1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 The Khronos Group Inc.
6 * Copyright (c) 2019 Valve Corporation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Tests vkCmdClearAttachments with unused attachments.
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktRenderPassUnusedClearAttachmentTests.hpp"
26 #include "pipeline/vktPipelineImageUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include <sstream>
34 #include <functional>
35 #include <vector>
36 #include <string>
37 #include <memory>
38
39 namespace vkt
40 {
41 namespace renderpass
42 {
43
44 namespace
45 {
46
47 constexpr size_t COLOR_ATTACHMENTS_NUMBER = 4; // maxColorAttachments is guaranteed to be at least 4.
48 constexpr VkFormat FORMAT_COLOR = VK_FORMAT_R8G8B8A8_UNORM;
49 constexpr VkFormat FORMAT_DEPTH = VK_FORMAT_D32_SFLOAT;
50 constexpr VkFormat FORMAT_STENCIL = VK_FORMAT_S8_UINT;
51 constexpr VkFormat FORMAT_DEPTH_STENCIL = VK_FORMAT_D32_SFLOAT_S8_UINT;
52 const deBool DE_BOOL_VALUES[] = { DE_FALSE, DE_TRUE };
53
54 enum DepthStencilType
55 {
56 DEPTH_STENCIL_NONE = 0,
57 DEPTH_STENCIL_DEPTH_ONLY = 1,
58 DEPTH_STENCIL_STENCIL_ONLY = 2,
59 DEPTH_STENCIL_BOTH = 3,
60 DEPTH_STENCIL_MAX_ENUM = 4
61 };
62
getFormatBriefName(VkFormat format)63 std::string getFormatBriefName (VkFormat format)
64 {
65 switch (format)
66 {
67 case VK_FORMAT_D32_SFLOAT: return "d32";
68 case VK_FORMAT_S8_UINT: return "s8";
69 case VK_FORMAT_D32_SFLOAT_S8_UINT: return "d32s8";
70 default: break;
71 }
72
73 return "";
74 }
75
depthStencilTypeName(DepthStencilType type,VkFormat format)76 std::string depthStencilTypeName (DepthStencilType type, VkFormat format)
77 {
78 DE_ASSERT(type >= DEPTH_STENCIL_NONE && type < DEPTH_STENCIL_MAX_ENUM);
79
80 const std::string formatName = getFormatBriefName(format);
81
82 switch (type)
83 {
84 case DEPTH_STENCIL_NONE: return "nods";
85 case DEPTH_STENCIL_DEPTH_ONLY: return "depthonly_" + formatName;
86 case DEPTH_STENCIL_STENCIL_ONLY: return "stencilonly_" + formatName;
87 case DEPTH_STENCIL_BOTH: return "depthstencil_" + formatName;
88 default: return "UNKNOWN"; // Unreachable.
89 }
90
91 return "UNKNOWN"; // Unreachable.
92 }
93
getClearAspectMask(DepthStencilType type)94 VkImageAspectFlags getClearAspectMask (DepthStencilType type)
95 {
96 VkImageAspectFlags aspectMask = 0u;
97
98 if (type == DEPTH_STENCIL_DEPTH_ONLY || type == DEPTH_STENCIL_BOTH)
99 aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
100
101 if (type == DEPTH_STENCIL_STENCIL_ONLY || type == DEPTH_STENCIL_BOTH)
102 aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
103
104 return aspectMask;
105 }
106
getFormatAspectMask(VkFormat format)107 VkImageAspectFlags getFormatAspectMask (VkFormat format)
108 {
109 const auto order = mapVkFormat(format).order;
110 VkImageAspectFlags aspectMask = 0u;
111
112 if (tcu::hasDepthComponent(order))
113 aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
114
115 if (tcu::hasStencilComponent(order))
116 aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
117
118 if (!aspectMask)
119 aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
120
121 return aspectMask;
122 }
123
getFormats(DepthStencilType type)124 std::vector<VkFormat> getFormats (DepthStencilType type)
125 {
126 DE_ASSERT(type >= DEPTH_STENCIL_NONE && type < DEPTH_STENCIL_MAX_ENUM);
127
128 std::vector<VkFormat> formats;
129
130 if (type != DEPTH_STENCIL_NONE)
131 formats.push_back(FORMAT_DEPTH_STENCIL);
132 else
133 formats.push_back(VK_FORMAT_UNDEFINED);
134
135 if (type == DEPTH_STENCIL_DEPTH_ONLY)
136 formats.push_back(FORMAT_DEPTH);
137 else if (type == DEPTH_STENCIL_STENCIL_ONLY)
138 formats.push_back(FORMAT_STENCIL);
139
140 return formats;
141 }
142
isDepthOnly(DepthStencilType type)143 bool isDepthOnly(DepthStencilType type)
144 {
145 return (type == DEPTH_STENCIL_DEPTH_ONLY);
146 }
147
isStencilOnly(DepthStencilType type)148 bool isStencilOnly(DepthStencilType type)
149 {
150 return (type == DEPTH_STENCIL_STENCIL_ONLY);
151 }
152
hasDepthStencil(DepthStencilType type)153 bool hasDepthStencil(DepthStencilType type)
154 {
155 return (type != DEPTH_STENCIL_NONE);
156 }
157
158 struct TestParams
159 {
TestParamsvkt::renderpass::__anon076e20c80111::TestParams160 TestParams(size_t numColorAttachments, DepthStencilType depthStencilType_, deBool depthStencilUsed_, VkFormat depthStencilFormat_, RenderPassType renderPassType_)
161 : colorUsed(numColorAttachments, DE_FALSE)
162 , depthStencilType(depthStencilType_)
163 , depthStencilUsed(depthStencilUsed_)
164 , depthStencilFormat(depthStencilFormat_)
165 , renderPassType(renderPassType_)
166 {}
167
168 std::vector<deBool> colorUsed;
169 DepthStencilType depthStencilType;
170 deBool depthStencilUsed;
171 VkFormat depthStencilFormat;
172 RenderPassType renderPassType;
173 };
174
175 class UnusedClearAttachmentTestInstance : public vkt::TestInstance
176 {
177 public:
178 UnusedClearAttachmentTestInstance (Context& context,
179 const TestParams& testParams);
~UnusedClearAttachmentTestInstance(void)180 virtual ~UnusedClearAttachmentTestInstance (void) {}
181 virtual tcu::TestStatus iterate (void);
182 template<typename RenderpassSubpass>
183 void createCommandBuffer (const DeviceInterface& vk,
184 VkDevice vkDevice);
185 private:
186 static constexpr deUint32 kImageWidth = 32;
187 static constexpr deUint32 kImageHeight = 32;
188 const tcu::UVec2 m_renderSize = { kImageWidth, kImageHeight };
189
190 VkClearValue m_initialColor;
191 VkClearValue m_initialColorDepth;
192 VkClearValue m_clearColor;
193 VkClearValue m_clearColorDepth;
194
195 const TestParams m_testParams;
196
197 std::vector<Move<VkImage>> m_colorImages;
198 std::vector<de::MovePtr<Allocation>> m_colorImageAllocs;
199 std::vector<Move<VkImageView>> m_colorAttachmentViews;
200
201 Move<VkImage> m_depthImage;
202 de::MovePtr<Allocation> m_depthImageAlloc;
203 Move<VkImageView> m_depthAttachmentView;
204
205 Move<VkRenderPass> m_renderPass;
206 Move<VkFramebuffer> m_framebuffer;
207 Move<VkShaderModule> m_vertexShaderModule;
208 Move<VkShaderModule> m_fragmentShaderModule;
209 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
210 Move<VkPipelineLayout> m_pipelineLayout;
211 Move<VkPipeline> m_graphicsPipeline;
212 Move<VkCommandPool> m_cmdPool;
213 Move<VkCommandBuffer> m_cmdBuffer;
214 };
215
216 class UnusedClearAttachmentTest : public vkt::TestCase
217 {
218 public:
UnusedClearAttachmentTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const TestParams & testParams)219 UnusedClearAttachmentTest (tcu::TestContext& testContext,
220 const std::string& name,
221 const std::string& description,
222 const TestParams& testParams)
223 : vkt::TestCase(testContext, name, description)
224 , m_testParams(testParams)
225 {}
~UnusedClearAttachmentTest(void)226 virtual ~UnusedClearAttachmentTest (void) {}
227 virtual void initPrograms (SourceCollections& sourceCollections) const;
228 virtual TestInstance* createInstance (Context& context) const;
229 virtual void checkSupport (Context& context) const;
230 private:
231 const TestParams m_testParams;
232 };
233
checkFormatSupported(Context & context,VkFormat format,VkImageUsageFlags usage)234 void checkFormatSupported(Context& context, VkFormat format, VkImageUsageFlags usage)
235 {
236 VkResult result;
237 VkImageFormatProperties properties;
238
239 result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
240 context.getPhysicalDevice(), format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, 0, &properties);
241
242 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
243 {
244 std::ostringstream msg;
245 msg << "Format " << format << " not supported for usage flags 0x" << std::hex << usage;
246 TCU_THROW(NotSupportedError, msg.str());
247 }
248
249 VK_CHECK(result);
250 }
251
checkSupport(Context & context) const252 void UnusedClearAttachmentTest::checkSupport (Context& context) const
253 {
254 // Check for renderpass2 extension if used
255 if (m_testParams.renderPassType == RENDERPASS_TYPE_RENDERPASS2)
256 context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
257
258 // Check support for the needed color, depth and stencil formats.
259 if (!m_testParams.colorUsed.empty())
260 checkFormatSupported(context, FORMAT_COLOR, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
261
262 if (hasDepthStencil(m_testParams.depthStencilType))
263 checkFormatSupported(context, m_testParams.depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
264 }
265
createInstance(Context & context) const266 TestInstance* UnusedClearAttachmentTest::createInstance (Context& context) const
267 {
268 return new UnusedClearAttachmentTestInstance(context, m_testParams);
269 }
270
271 // These shaders are needed to create the graphics pipeline, but they will not be actually used because we will not draw anything.
initPrograms(SourceCollections & sourceCollections) const272 void UnusedClearAttachmentTest::initPrograms (SourceCollections& sourceCollections) const
273 {
274 // Vertex shader.
275 sourceCollections.glslSources.add("vert_shader") << glu::VertexSource(
276 "#version 450\n"
277 "precision highp float;\n"
278 "layout(location = 0) in vec4 position;\n"
279 "layout(location = 0) out vec4 vtxColor;\n"
280 "void main (void)\n"
281 "{\n"
282 "\tgl_Position = position;\n"
283 "\tvtxColor = vec4(0.5, 0.5, 0.5, 1.0);\n"
284 "}\n");
285
286 // Fragment shader.
287 std::ostringstream fragmentSource;
288
289 fragmentSource << "#version 450\n"
290 << "precision highp float;\n"
291 << "layout(location = 0) in vec4 vtxColor;\n";
292
293 for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
294 {
295 if (m_testParams.colorUsed[i])
296 fragmentSource << "layout(location = " << i << ") out vec4 fragColor" << i << ";\n";
297 }
298
299 fragmentSource << "void main (void)\n"
300 << "{\n";
301
302 for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
303 {
304 if (m_testParams.colorUsed[i])
305 fragmentSource << "\tfragColor" << i << " = vtxColor;\n";
306 }
307
308 fragmentSource << "}\n";
309
310 sourceCollections.glslSources.add("frag_shader") << glu::FragmentSource(fragmentSource.str());
311 }
312
313 // Create a render pass for this use case.
314 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice,const TestParams testParams)315 Move<VkRenderPass> createRenderPass (const DeviceInterface& vk,
316 VkDevice vkDevice,
317 const TestParams testParams)
318 {
319 const VkImageAspectFlags colorAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
320 const VkImageAspectFlags dsClearAspectMask = getClearAspectMask(testParams.depthStencilType);
321 const bool isDepthStencil = hasDepthStencil(testParams.depthStencilType);
322
323 // Create attachment descriptions.
324 const AttachmentDesc attachmentDescription (
325 DE_NULL, // const void* pNext
326 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
327 FORMAT_COLOR, // VkFormat format
328 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
329 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp
330 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
331 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
332 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
333 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
334 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
335 );
336 std::vector<AttachmentDesc> attachmentDescriptions (testParams.colorUsed.size(), attachmentDescription);
337
338 if (isDepthStencil)
339 {
340 const bool depthOnly = isDepthOnly(testParams.depthStencilType);
341 const bool stencilOnly = isStencilOnly(testParams.depthStencilType);
342 const VkAttachmentLoadOp depthLoadOp = (stencilOnly ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD);
343 const VkAttachmentStoreOp depthStoreOp = (stencilOnly ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE);
344 const VkAttachmentLoadOp stencilLoadOp = (depthOnly ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD);
345 const VkAttachmentStoreOp stencilStoreOp = (depthOnly ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE);
346
347 attachmentDescriptions.emplace_back(
348 nullptr, // const void* pNext
349 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
350 testParams.depthStencilFormat, // VkFormat format
351 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
352 depthLoadOp, // VkAttachmentLoadOp loadOp
353 depthStoreOp, // VkAttachmentStoreOp storeOp
354 stencilLoadOp, // VkAttachmentLoadOp stencilLoadOp
355 stencilStoreOp, // VkAttachmentStoreOp stencilStoreOp
356 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
357 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
358 );
359 }
360
361 // Mark attachments as used or not depending on the test parameters.
362 std::vector<AttachmentRef> attachmentReferences;
363 for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
364 {
365 attachmentReferences.push_back(AttachmentRef(
366 DE_NULL, // const void* pNext
367 (testParams.colorUsed[i] ? static_cast<deUint32>(i) : VK_ATTACHMENT_UNUSED), // deUint32 attachment
368 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
369 colorAspectMask // VkImageAspectFlags aspectMask
370 ));
371 }
372
373 std::unique_ptr<AttachmentRef> depthAttachmentRef;
374 if (isDepthStencil)
375 {
376 depthAttachmentRef.reset(new AttachmentRef(
377 DE_NULL,
378 (testParams.depthStencilUsed ? static_cast<deUint32>(testParams.colorUsed.size()) : VK_ATTACHMENT_UNUSED),
379 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
380 dsClearAspectMask
381 ));
382 }
383
384 // Create subpass description with the previous color attachment references.
385 const SubpassDesc subpassDescription (
386 DE_NULL,
387 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
388 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
389 0u, // deUint32 viewMask
390 0u, // deUint32 inputAttachmentCount
391 DE_NULL, // const VkAttachmentReference* pInputAttachments
392 static_cast<deUint32>(attachmentReferences.size()), // deUint32 colorAttachmentCount
393 (attachmentReferences.empty() ? DE_NULL : attachmentReferences.data()), // const VkAttachmentReference* pColorAttachments
394 DE_NULL, // const VkAttachmentReference* pResolveAttachments
395 (depthAttachmentRef ? depthAttachmentRef.get() : DE_NULL), // const VkAttachmentReference* pDepthStencilAttachment
396 0u, // deUint32 preserveAttachmentCount
397 DE_NULL // const deUint32* pPreserveAttachments
398 );
399
400 const RenderPassCreateInfo renderPassInfo (
401 DE_NULL, // const void* pNext
402 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
403 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount
404 (attachmentDescriptions.empty() ? DE_NULL : attachmentDescriptions.data()), // const VkAttachmentDescription* pAttachments
405 1u, // deUint32 subpassCount
406 &subpassDescription, // const VkSubpassDescription* pSubpasses
407 0u, // deUint32 dependencyCount
408 DE_NULL, // const VkSubpassDependency* pDependencies
409 0u, // deUint32 correlatedViewMaskCount
410 DE_NULL // const deUint32* pCorrelatedViewMasks
411 );
412
413 return renderPassInfo.createRenderPass(vk, vkDevice);
414 }
415
UnusedClearAttachmentTestInstance(Context & context,const TestParams & testParams)416 UnusedClearAttachmentTestInstance::UnusedClearAttachmentTestInstance(Context& context,
417 const TestParams& testParams)
418 : vkt::TestInstance(context)
419 , m_testParams(testParams)
420 {
421 // Initial color for all images.
422 m_initialColor.color.float32[0] = 0.0f;
423 m_initialColor.color.float32[1] = 0.0f;
424 m_initialColor.color.float32[2] = 0.0f;
425 m_initialColor.color.float32[3] = 1.0f;
426
427 m_initialColorDepth.depthStencil.depth = 1.0f;
428 m_initialColorDepth.depthStencil.stencil = 0u;
429
430 // Clear color for used attachments.
431 m_clearColor.color.float32[0] = 1.0f;
432 m_clearColor.color.float32[1] = 1.0f;
433 m_clearColor.color.float32[2] = 1.0f;
434 m_clearColor.color.float32[3] = 1.0f;
435
436 m_clearColorDepth.depthStencil.depth = 0.0f;
437 m_clearColorDepth.depthStencil.stencil = 255u;
438
439 const DeviceInterface& vk = m_context.getDeviceInterface();
440 const VkDevice vkDevice = m_context.getDevice();
441 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
442 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
443 const VkComponentMapping componentMapping = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
444
445 // Create color images.
446 {
447 const VkImageCreateInfo colorImageParams =
448 {
449 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
450 DE_NULL, // const void* pNext;
451 0u, // VkImageCreateFlags flags;
452 VK_IMAGE_TYPE_2D, // VkImageType imageType;
453 FORMAT_COLOR, // VkFormat format;
454 { kImageWidth, kImageHeight, 1u }, // VkExtent3D extent;
455 1u, // deUint32 mipLevels;
456 1u, // deUint32 arrayLayers;
457 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
458 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
459 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
460 | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
461 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
462 1u, // deUint32 queueFamilyIndexCount;
463 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
464 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
465 };
466
467 const VkImageCreateInfo depthImageParams =
468 {
469 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
470 DE_NULL, // const void* pNext;
471 0u, // VkImageCreateFlags flags;
472 VK_IMAGE_TYPE_2D, // VkImageType imageType;
473 m_testParams.depthStencilFormat, // VkFormat format;
474 { kImageWidth, kImageHeight, 1u }, // VkExtent3D extent;
475 1u, // deUint32 mipLevels;
476 1u, // deUint32 arrayLayers;
477 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
478 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
479 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
480 | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
481 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
482 1u, // deUint32 queueFamilyIndexCount;
483 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
484 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
485 };
486
487 for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
488 {
489 // Create, allocate and bind image memory.
490 m_colorImages.emplace_back(createImage(vk, vkDevice, &colorImageParams));
491 m_colorImageAllocs.emplace_back(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImages.back()), MemoryRequirement::Any));
492 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImages.back(), m_colorImageAllocs.back()->getMemory(), m_colorImageAllocs.back()->getOffset()));
493
494 // Create image view.
495 {
496 const VkImageViewCreateInfo colorAttachmentViewParams =
497 {
498 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
499 DE_NULL, // const void* pNext;
500 0u, // VkImageViewCreateFlags flags;
501 *m_colorImages.back(), // VkImage image;
502 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
503 FORMAT_COLOR, // VkFormat format;
504 componentMapping, // VkChannelMapping channels;
505 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
506 };
507
508 m_colorAttachmentViews.emplace_back(createImageView(vk, vkDevice, &colorAttachmentViewParams));
509 }
510
511 // Clear image and leave it prepared to be used as a color attachment.
512 {
513 const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
514 Move<VkCommandPool> cmdPool;
515 Move<VkCommandBuffer> cmdBuffer;
516
517 // Create command pool and buffer
518 cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
519 cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
520
521 // From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
522 const VkImageMemoryBarrier preImageBarrier =
523 {
524 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
525 DE_NULL, // const void* pNext;
526 0u, // VkAccessFlags srcAccessMask;
527 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
528 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
529 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
530 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
531 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
532 *m_colorImages.back(), // VkImage image;
533 { // VkImageSubresourceRange subresourceRange;
534 aspectMask, // VkImageAspect aspect;
535 0u, // deUint32 baseMipLevel;
536 1u, // deUint32 mipLevels;
537 0u, // deUint32 baseArraySlice;
538 1u // deUint32 arraySize;
539 }
540 };
541
542 // From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
543 const VkImageMemoryBarrier postImageBarrier =
544 {
545 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
546 DE_NULL, // const void* pNext;
547 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
548 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
549 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
550 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
551 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
552 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
553 *m_colorImages.back(), // VkImage image;
554 { // VkImageSubresourceRange subresourceRange;
555 aspectMask, // VkImageAspect aspect;
556 0u, // deUint32 baseMipLevel;
557 1u, // deUint32 mipLevels;
558 0u, // deUint32 baseArraySlice;
559 1u // deUint32 arraySize;
560 }
561 };
562
563 const VkImageSubresourceRange clearRange =
564 {
565 aspectMask, // VkImageAspectFlags aspectMask;
566 0u, // deUint32 baseMipLevel;
567 1u, // deUint32 levelCount;
568 0u, // deUint32 baseArrayLayer;
569 1u // deUint32 layerCount;
570 };
571
572 // Clear image and transfer layout.
573 beginCommandBuffer(vk, *cmdBuffer);
574 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
575 vk.cmdClearColorImage(*cmdBuffer, *m_colorImages.back(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_initialColor.color, 1, &clearRange);
576 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
577 endCommandBuffer(vk, *cmdBuffer);
578
579 submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
580 }
581 }
582
583 if (hasDepthStencil(m_testParams.depthStencilType))
584 {
585 const VkImageAspectFlags clearAspectMask = getClearAspectMask(m_testParams.depthStencilType);
586 const VkImageAspectFlags formatAspectMask = getFormatAspectMask(m_testParams.depthStencilFormat);
587
588 // Create, allocate and bind image memory.
589 m_depthImage = createImage(vk, vkDevice, &depthImageParams);
590 m_depthImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthImage), MemoryRequirement::Any);
591 VK_CHECK(vk.bindImageMemory(vkDevice, *m_depthImage, m_depthImageAlloc->getMemory(), m_depthImageAlloc->getOffset()));
592
593 // Create image view.
594 {
595 const VkImageViewCreateInfo depthAttachmentViewParams =
596 {
597 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
598 DE_NULL, // const void* pNext;
599 0u, // VkImageViewCreateFlags flags;
600 *m_depthImage, // VkImage image;
601 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
602 m_testParams.depthStencilFormat, // VkFormat format;
603 componentMapping, // VkChannelMapping channels;
604 { clearAspectMask, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
605 };
606
607 m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
608 }
609
610 // Clear image and leave it prepared to be used as a depth/stencil attachment.
611 {
612 Move<VkCommandPool> cmdPool;
613 Move<VkCommandBuffer> cmdBuffer;
614
615 // Create command pool and buffer
616 cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
617 cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
618
619 // From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
620 const VkImageMemoryBarrier preImageBarrier =
621 {
622 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
623 DE_NULL, // const void* pNext;
624 0u, // VkAccessFlags srcAccessMask;
625 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
626 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
627 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
628 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
629 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
630 *m_depthImage, // VkImage image;
631 { // VkImageSubresourceRange subresourceRange;
632 formatAspectMask, // VkImageAspect aspect;
633 0u, // deUint32 baseMipLevel;
634 1u, // deUint32 mipLevels;
635 0u, // deUint32 baseArraySlice;
636 1u // deUint32 arraySize;
637 }
638 };
639
640 // From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL.
641 const VkImageMemoryBarrier postImageBarrier =
642 {
643 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
644 DE_NULL, // const void* pNext;
645 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
646 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
647 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
648 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
649 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
650 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
651 *m_depthImage, // VkImage image;
652 { // VkImageSubresourceRange subresourceRange;
653 formatAspectMask, // VkImageAspect aspect;
654 0u, // deUint32 baseMipLevel;
655 1u, // deUint32 mipLevels;
656 0u, // deUint32 baseArraySlice;
657 1u // deUint32 arraySize;
658 }
659 };
660
661 const VkImageSubresourceRange clearRange =
662 {
663 clearAspectMask, // VkImageAspectFlags aspectMask;
664 0u, // deUint32 baseMipLevel;
665 1u, // deUint32 levelCount;
666 0u, // deUint32 baseArrayLayer;
667 1u // deUint32 layerCount;
668 };
669
670 // Clear image and transfer layout.
671 beginCommandBuffer(vk, *cmdBuffer);
672 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
673 vk.cmdClearDepthStencilImage(*cmdBuffer, *m_depthImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_initialColorDepth.depthStencil, 1, &clearRange);
674 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
675 endCommandBuffer(vk, *cmdBuffer);
676
677 submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
678 }
679 }
680 }
681
682 // Create render pass.
683 if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
684 m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams);
685 else
686 m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams);
687
688 // Create framebuffer
689 {
690 std::vector<VkImageView> imageViews;
691
692 for (auto& movePtr : m_colorAttachmentViews)
693 imageViews.push_back(movePtr.get());
694
695 if (hasDepthStencil(m_testParams.depthStencilType))
696 imageViews.push_back(m_depthAttachmentView.get());
697
698 const VkFramebufferCreateInfo framebufferParams =
699 {
700 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
701 DE_NULL, // const void* pNext;
702 0u, // VkFramebufferCreateFlags flags;
703 *m_renderPass, // VkRenderPass renderPass;
704 static_cast<deUint32>(imageViews.size()), // deUint32 attachmentCount;
705 (imageViews.empty() ? DE_NULL : imageViews.data()), // const VkImageView* pAttachments;
706 kImageWidth, // deUint32 width;
707 kImageHeight, // deUint32 height;
708 1u // deUint32 layers;
709 };
710
711 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
712 }
713
714 // Create pipeline layout for subpass 0.
715 {
716 const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams =
717 {
718 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType
719 DE_NULL, // const void* pNext
720 0u, // VkDescriptorSetLayoutCreateFlags flags
721 0u, // deUint32 bindingCount
722 DE_NULL // const VkDescriptorSetLayoutBinding* pBindings
723 };
724 m_descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
725
726 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
727 {
728 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
729 DE_NULL, // const void* pNext;
730 0u, // VkPipelineLayoutCreateFlags flags;
731 1u, // deUint32 setLayoutCount;
732 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
733 0u, // deUint32 pushConstantRangeCount;
734 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
735 };
736
737 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
738 }
739
740 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert_shader"), 0);
741 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag_shader"), 0);
742
743 // Create pipeline.
744 {
745 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize));
746 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
747
748 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
749 {
750 VK_FALSE, // VkBool32 blendEnable
751 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
752 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
753 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
754 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
755 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
756 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
757 VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
758 | VK_COLOR_COMPONENT_G_BIT
759 | VK_COLOR_COMPONENT_B_BIT
760 | VK_COLOR_COMPONENT_A_BIT
761 };
762
763 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
764 for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
765 colorBlendAttachmentStates.push_back(colorBlendAttachmentState);
766
767 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
768 {
769 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
770 DE_NULL, // const void* pNext
771 0u, // VkPipelineColorBlendStateCreateFlags flags
772 VK_FALSE, // VkBool32 logicOpEnable
773 VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp
774 static_cast<deUint32>(colorBlendAttachmentStates.size()), // deUint32 attachmentCount
775 (colorBlendAttachmentStates.empty() ? DE_NULL : colorBlendAttachmentStates.data()), // const VkPipelineColorBlendAttachmentState* pAttachments
776 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
777 };
778
779 m_graphicsPipeline = makeGraphicsPipeline(vk, // const DeviceInterface& vk
780 vkDevice, // const VkDevice device
781 *m_pipelineLayout, // const VkPipelineLayout pipelineLayout
782 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
783 DE_NULL, // const VkShaderModule tessellationControlModule
784 DE_NULL, // const VkShaderModule tessellationEvalModule
785 DE_NULL, // const VkShaderModule geometryShaderModule
786 *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
787 *m_renderPass, // const VkRenderPass renderPass
788 viewports, // const std::vector<VkViewport>& viewports
789 scissors, // const std::vector<VkRect2D>& scissors
790 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
791 0u, // const deUint32 subpass
792 0u, // const deUint32 patchControlPoints
793 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
794 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
795 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
796 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
797 &colorBlendStateCreateInfo); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
798 }
799
800 // Create command pool
801 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
802
803 // Create command buffer
804 if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
805 createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
806 else
807 createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
808 }
809
810 template <typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)811 void UnusedClearAttachmentTestInstance::createCommandBuffer (const DeviceInterface& vk,
812 VkDevice vkDevice)
813 {
814 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo (DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
815 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo (DE_NULL);
816
817 const VkRenderPassBeginInfo renderPassBeginInfo =
818 {
819 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
820 DE_NULL, // const void* pNext;
821 *m_renderPass, // VkRenderPass renderPass;
822 *m_framebuffer, // VkFramebuffer framebuffer;
823 makeRect2D(m_renderSize), // VkRect2D renderArea;
824 0u, // uint32_t clearValueCount;
825 DE_NULL // const VkClearValue* pClearValues;
826 };
827
828 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
829
830 const VkClearRect clearRect =
831 {
832 { // VkRect2D rect;
833 { 0, 0, }, // VkOffset2D offset;
834 { kImageWidth, kImageHeight } // VkExtent2D extent;
835 },
836 0u, // uint32_t baseArrayLayer;
837 1u // uint32_t layerCount;
838 };
839
840 std::vector<VkClearAttachment> clearAttachments;
841 for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
842 {
843 const VkClearAttachment clearAttachment = {
844 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
845 static_cast<deUint32>(i), // uint32_t colorAttachment;
846 m_clearColor // VkClearValue clearValue;
847 };
848 clearAttachments.push_back(clearAttachment);
849 }
850
851 if (hasDepthStencil(m_testParams.depthStencilType))
852 {
853 const VkClearAttachment clearAttachment = {
854 getClearAspectMask(m_testParams.depthStencilType), // VkImageAspectFlags aspectMask;
855 0u, // uint32_t colorAttachment;
856 m_clearColorDepth // VkClearValue clearValue;
857 };
858 clearAttachments.push_back(clearAttachment);
859 }
860
861 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
862 RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
863 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
864 vk.cmdClearAttachments(*m_cmdBuffer, static_cast<deUint32>(clearAttachments.size()), (clearAttachments.empty() ? DE_NULL : clearAttachments.data()), 1u, &clearRect);
865 RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
866 endCommandBuffer(vk, *m_cmdBuffer);
867 }
868
iterate(void)869 tcu::TestStatus UnusedClearAttachmentTestInstance::iterate (void)
870 {
871 const DeviceInterface& vk = m_context.getDeviceInterface();
872 const VkDevice vkDevice = m_context.getDevice();
873 const VkQueue queue = m_context.getUniversalQueue();
874 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
875 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
876
877 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
878
879 // Read result images.
880 std::vector<de::MovePtr<tcu::TextureLevel>> imagePixels;
881 for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
882 imagePixels.emplace_back(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImages[i], FORMAT_COLOR, m_renderSize).release());
883
884 // Verify pixel colors match.
885 for (size_t i = 0; i < imagePixels.size(); ++i)
886 {
887 const tcu::ConstPixelBufferAccess& imageAccess = imagePixels[i]->getAccess();
888 const float* refColor = (m_testParams.colorUsed[i] ? m_clearColor.color.float32 : m_initialColor.color.float32);
889
890 for (int y = 0; y < imageAccess.getHeight(); ++y)
891 for (int x = 0; x < imageAccess.getWidth(); ++x)
892 {
893 const tcu::Vec4 color = imageAccess.getPixel(x, y);
894
895 for (deUint32 cpnt = 0; cpnt < 4; ++cpnt)
896 if (de::abs(color[cpnt] - refColor[cpnt]) > 0.01f)
897 {
898 std::ostringstream msg;
899
900 msg << "Attachment " << i << " with mismatched pixel (" << x << ", " << y << "): expecting pixel value [";
901 for (deUint32 j = 0; j < 4; ++j)
902 msg << ((j == 0) ? "" : ", ") << refColor[j];
903 msg << "] and found [";
904 for (deUint32 j = 0; j < 4; ++j)
905 msg << ((j == 0) ? "" : ", ") << color[j];
906 msg << "]";
907
908 return tcu::TestStatus::fail(msg.str());
909 }
910 }
911 }
912
913 if (hasDepthStencil(m_testParams.depthStencilType))
914 {
915 const bool depthOnly = isDepthOnly(m_testParams.depthStencilType);
916 const bool stencilOnly = isStencilOnly(m_testParams.depthStencilType);
917
918 if (!stencilOnly)
919 {
920 de::MovePtr<tcu::TextureLevel> depthPixels = pipeline::readDepthAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_testParams.depthStencilFormat, m_renderSize);
921 const tcu::ConstPixelBufferAccess& depthAccess = depthPixels->getAccess();
922 const float refDepth = (m_testParams.depthStencilUsed ? m_clearColorDepth.depthStencil.depth : m_initialColorDepth.depthStencil.depth);
923
924 for (int y = 0; y < depthAccess.getHeight(); ++y)
925 for (int x = 0; x < depthAccess.getWidth(); ++x)
926 {
927 const float value = depthAccess.getPixDepth(x, y);
928 if (de::abs(value - refDepth) > 0.001f)
929 {
930 std::ostringstream msg;
931
932 msg << "Depth/stencil attachment with mismatched depth value at pixel ("
933 << x << ", " << y << "): expected value " << refDepth << " and found " << value;
934 return tcu::TestStatus::fail(msg.str());
935 }
936 }
937 }
938
939 if (!depthOnly)
940 {
941 // Note read*Attachment leaves the attachment in the VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL layout, so the current layout
942 // depends on if we have previously read the depth aspect or not.
943 const VkImageLayout currentLayout = (stencilOnly ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
944 de::MovePtr<tcu::TextureLevel> stencilPixels = pipeline::readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_testParams.depthStencilFormat, m_renderSize, currentLayout);
945 const tcu::ConstPixelBufferAccess& stencilAccess = stencilPixels->getAccess();
946 const deUint32 refStencil = (m_testParams.depthStencilUsed ? m_clearColorDepth.depthStencil.stencil : m_initialColorDepth.depthStencil.stencil);
947
948 for (int y = 0; y < stencilAccess.getHeight(); ++y)
949 for (int x = 0; x < stencilAccess.getWidth(); ++x)
950 {
951 const int value = stencilAccess.getPixStencil(x, y);
952 if (value < 0 || static_cast<deUint32>(value) != refStencil)
953 {
954 std::ostringstream msg;
955
956 msg << "Depth/stencil attachment with mismatched stencil value at pixel ("
957 << x << ", " << y << "): expected value " << refStencil << " and found " << value;
958 return tcu::TestStatus::fail(msg.str());
959 }
960 }
961 }
962 }
963
964 return tcu::TestStatus::pass("Pass");
965 }
966
967
968 using CallbackFunction = std::function<void(const std::vector<deBool>&)>;
969
runCallbackOnCombination(std::vector<deBool> & array,size_t current_index,CallbackFunction callback)970 void runCallbackOnCombination(std::vector<deBool>& array, size_t current_index, CallbackFunction callback)
971 {
972 DE_ASSERT(current_index < array.size());
973 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(DE_BOOL_VALUES); ++i)
974 {
975 array[current_index] = DE_BOOL_VALUES[i];
976 if (current_index == array.size() - 1)
977 callback(array);
978 else
979 runCallbackOnCombination(array, current_index + 1, callback);
980 }
981 }
982
runCallbackOnCombination(std::vector<deBool> & array,CallbackFunction callback)983 void runCallbackOnCombination(std::vector<deBool>& array, CallbackFunction callback)
984 {
985 runCallbackOnCombination(array, 0, callback);
986 }
987
getUsed(deBool value)988 std::string getUsed(deBool value)
989 {
990 return (value ? "used" : "unused");
991 }
992
getCombName(const std::vector<deBool> & array)993 std::string getCombName(const std::vector<deBool>& array)
994 {
995 std::ostringstream name;
996 for (size_t i = 0; i < array.size(); ++i)
997 name << ((i == 0)? "" : "_") << "color" << getUsed(array[i]);
998 return name.str();
999 }
1000
1001 } // anonymous
1002
1003
createRenderPassUnusedClearAttachmentTests(tcu::TestContext & testCtx,const RenderPassType renderPassType)1004 tcu::TestCaseGroup* createRenderPassUnusedClearAttachmentTests (tcu::TestContext& testCtx, const RenderPassType renderPassType)
1005 {
1006 de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "unused_clear_attachments", "Unused attachments with vkCmdClearAttachments"));
1007
1008 for (int depthStencilType = 0; depthStencilType < DEPTH_STENCIL_MAX_ENUM; ++depthStencilType)
1009 {
1010 const DepthStencilType dsType = static_cast<DepthStencilType>(depthStencilType);
1011 const auto dsFormats = getFormats(dsType);
1012
1013 for (const auto dsFormat : dsFormats)
1014 {
1015 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(DE_BOOL_VALUES); ++i)
1016 {
1017 const deBool depthStencilUse = DE_BOOL_VALUES[i];
1018 const std::string dsCase = depthStencilTypeName(dsType, dsFormat);
1019 std::vector<TestParams> testTypes;
1020
1021 if (hasDepthStencil(dsType))
1022 testTypes.emplace_back(0, dsType, depthStencilUse, dsFormat, renderPassType); // No color attachments.
1023 testTypes.emplace_back(1, dsType, depthStencilUse, dsFormat, renderPassType); // Single color attachment.
1024 testTypes.emplace_back(COLOR_ATTACHMENTS_NUMBER, dsType, depthStencilUse, dsFormat, renderPassType); // Multiple color attachments.
1025
1026 for (auto& params : testTypes)
1027 {
1028 if (!params.colorUsed.empty())
1029 {
1030 runCallbackOnCombination(params.colorUsed, [&](const std::vector<deBool>& array) {
1031 std::string name = getCombName(array) + "_" + dsCase;
1032 if (hasDepthStencil(dsType))
1033 name += std::string("_") + getUsed(depthStencilUse);
1034 testGroup->addChild(new UnusedClearAttachmentTest(testCtx, name, "", params));
1035 });
1036 }
1037 else
1038 {
1039 std::string name = dsCase + "_" + getUsed(depthStencilUse);
1040 testGroup->addChild(new UnusedClearAttachmentTest(testCtx, name, "", params));
1041 }
1042
1043 }
1044
1045 if (!hasDepthStencil(dsType))
1046 break;
1047 }
1048 }
1049 }
1050
1051 return testGroup.release();
1052 }
1053
1054 } // renderpass
1055 } // vkt
1056