1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 Google Inc.
7 * Copyright (c) 2015 Imagination Technologies Ltd.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Tests attachments unused by subpasses
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktRenderPassUnusedAttachmentTests.hpp"
27 #include "pipeline/vktPipelineImageUtil.hpp"
28 #include "vktRenderPassTestsUtil.hpp"
29 #include "vkBarrierUtil.hpp"
30 #include "vktTestCase.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkRef.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 #include "tcuImageCompare.hpp"
43 #include "tcuPlatform.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuVectorUtil.hpp"
47 #include "deStringUtil.hpp"
48 #include "deUniquePtr.hpp"
49 #include "deRandom.hpp"
50 #include <cstring>
51 #include <set>
52 #include <sstream>
53 #include <vector>
54
55 namespace vkt
56 {
57 namespace renderpass
58 {
59
60 using namespace vk;
61
62 namespace
63 {
64
65 struct TestParams
66 {
67 VkAttachmentLoadOp loadOp;
68 VkAttachmentStoreOp storeOp;
69 VkAttachmentLoadOp stencilLoadOp;
70 VkAttachmentStoreOp stencilStoreOp;
71 SharedGroupParams groupParams;
72 };
73
74 struct Vertex4RGBA
75 {
76 tcu::Vec4 position;
77 tcu::Vec4 color;
78 };
79
createQuad(void)80 std::vector<Vertex4RGBA> createQuad(void)
81 {
82 std::vector<Vertex4RGBA> vertices;
83
84 const float size = 0.8f;
85 const tcu::Vec4 color(0.2f, 0.3f, 0.1f, 1.0f);
86 const Vertex4RGBA lowerLeftVertex = {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
87 const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
88 const Vertex4RGBA upperLeftVertex = {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
89 const Vertex4RGBA upperRightVertex = {tcu::Vec4(size, size, 0.0f, 1.0f), color};
90
91 vertices.push_back(lowerLeftVertex);
92 vertices.push_back(lowerRightVertex);
93 vertices.push_back(upperLeftVertex);
94 vertices.push_back(upperLeftVertex);
95 vertices.push_back(lowerRightVertex);
96 vertices.push_back(upperRightVertex);
97
98 return vertices;
99 }
100
101 template <typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep,
102 typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice,const TestParams testParams)103 Move<VkRenderPass> createRenderPass(const DeviceInterface &vk, VkDevice vkDevice, const TestParams testParams)
104 {
105 const VkImageAspectFlags aspectMask =
106 testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
107 const AttachmentDesc attachmentDescriptions[] = {
108 // Result attachment
109 AttachmentDesc(DE_NULL, // const void* pNext
110 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
111 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format
112 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
113 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
114 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
115 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
116 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
117 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
118 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
119 ),
120 // Unused attachment
121 AttachmentDesc(DE_NULL, // const void* pNext
122 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
123 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format
124 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
125 testParams.loadOp, // VkAttachmentLoadOp loadOp
126 testParams.storeOp, // VkAttachmentStoreOp storeOp
127 testParams.stencilLoadOp, // VkAttachmentLoadOp stencilLoadOp
128 testParams.stencilStoreOp, // VkAttachmentStoreOp stencilStoreOp
129 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
130 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
131 ),
132 // Input attachment
133 AttachmentDesc(DE_NULL, // const void* pNext
134 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
135 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format
136 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
137 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
138 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
139 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
140 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
141 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
142 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
143 )};
144
145 // Note: Attachment 1 is not referenced by any subpass.
146 const AttachmentRef resultAttachmentRefSubpass0(
147 DE_NULL, // const void* pNext
148 2u, // uint32_t attachment
149 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
150 aspectMask // VkImageAspectFlags aspectMask
151 );
152
153 const AttachmentRef resultAttachmentRefSubpass1(
154 DE_NULL, // const void* pNext
155 0u, // uint32_t attachment
156 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
157 aspectMask // VkImageAspectFlags aspectMask
158 );
159
160 const AttachmentRef inputAttachmentRefSubpass1(
161 DE_NULL, // const void* pNext
162 2u, // uint32_t attachment
163 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout
164 aspectMask // VkImageAspectFlags aspectMask
165 );
166
167 const SubpassDesc subpassDescriptions[] = {
168 SubpassDesc(DE_NULL,
169 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
170 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
171 0u, // uint32_t viewMask
172 0u, // uint32_t inputAttachmentCount
173 DE_NULL, // const VkAttachmentReference* pInputAttachments
174 1u, // uint32_t colorAttachmentCount
175 &resultAttachmentRefSubpass0, // const VkAttachmentReference* pColorAttachments
176 DE_NULL, // const VkAttachmentReference* pResolveAttachments
177 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
178 0u, // uint32_t preserveAttachmentCount
179 DE_NULL // const uint32_t* pPreserveAttachments
180 ),
181 SubpassDesc(DE_NULL,
182 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
183 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
184 0u, // uint32_t viewMask
185 1u, // uint32_t inputAttachmentCount
186 &inputAttachmentRefSubpass1, // const VkAttachmentReference* pInputAttachments
187 1u, // uint32_t colorAttachmentCount
188 &resultAttachmentRefSubpass1, // const VkAttachmentReference* pColorAttachments
189 DE_NULL, // const VkAttachmentReference* pResolveAttachments
190 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
191 0u, // uint32_t preserveAttachmentCount
192 DE_NULL // const uint32_t* pPreserveAttachments
193 )};
194
195 const SubpassDep subpassDependency(
196 DE_NULL, // const void* pNext
197 0u, // uint32_t srcSubpass
198 1u, // uint32_t dstSubpass
199 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask
200 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask
201 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask
202 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask
203 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags
204 0u // int32_t viewOffset
205 );
206
207 const RenderPassCreateInfo renderPassInfo(DE_NULL, // const void* pNext
208 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
209 3u, // uint32_t attachmentCount
210 attachmentDescriptions, // const VkAttachmentDescription* pAttachments
211 2u, // uint32_t subpassCount
212 subpassDescriptions, // const VkSubpassDescription* pSubpasses
213 1u, // uint32_t dependencyCount
214 &subpassDependency, // const VkSubpassDependency* pDependencies
215 0u, // uint32_t correlatedViewMaskCount
216 DE_NULL // const uint32_t* pCorrelatedViewMasks
217 );
218
219 return renderPassInfo.createRenderPass(vk, vkDevice);
220 }
221
chooseInputImageLayout(const SharedGroupParams groupParams)222 VkImageLayout chooseInputImageLayout(const SharedGroupParams groupParams)
223 {
224 #ifndef CTS_USES_VULKANSC
225 if (groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
226 {
227 // use general layout for local reads for some tests
228 if (groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
229 return VK_IMAGE_LAYOUT_GENERAL;
230 return VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
231 }
232 #else
233 DE_UNREF(groupParams);
234 #endif
235 return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
236 }
237
238 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(const DeviceInterface & vk,VkCommandBuffer secCmdBuffer,const void * additionalInheritanceRenderingInfo)239 void beginSecondaryCmdBuffer(const DeviceInterface &vk, VkCommandBuffer secCmdBuffer,
240 const void *additionalInheritanceRenderingInfo)
241 {
242 VkCommandBufferUsageFlags usageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
243 const std::vector<VkFormat> colorAttachmentFormats(3, VK_FORMAT_R8G8B8A8_UNORM);
244
245 const VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
246 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
247 additionalInheritanceRenderingInfo, // const void* pNext;
248 0u, // VkRenderingFlagsKHR flags;
249 0u, // uint32_t viewMask;
250 3u, // uint32_t colorAttachmentCount;
251 colorAttachmentFormats.data(), // const VkFormat* pColorAttachmentFormats;
252 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
253 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
254 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
255 };
256 const VkCommandBufferInheritanceInfo bufferInheritanceInfo{
257 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
258 &inheritanceRenderingInfo, // const void* pNext;
259 DE_NULL, // VkRenderPass renderPass;
260 0u, // uint32_t subpass;
261 DE_NULL, // VkFramebuffer framebuffer;
262 VK_FALSE, // VkBool32 occlusionQueryEnable;
263 (VkQueryControlFlags)0u, // VkQueryControlFlags queryFlags;
264 (VkQueryPipelineStatisticFlags)0u // VkQueryPipelineStatisticFlags pipelineStatistics;
265 };
266 const VkCommandBufferBeginInfo commandBufBeginParams{
267 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
268 DE_NULL, // const void* pNext;
269 usageFlags, // VkCommandBufferUsageFlags flags;
270 &bufferInheritanceInfo // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
271 };
272 VK_CHECK(vk.beginCommandBuffer(secCmdBuffer, &commandBufBeginParams));
273 }
274 #endif // CTS_USES_VULKANSC
275
276 class UnusedAttachmentTest : public vkt::TestCase
277 {
278 public:
279 UnusedAttachmentTest(tcu::TestContext &testContext, const std::string &name, const TestParams &testParams);
280 virtual ~UnusedAttachmentTest(void) = default;
281 virtual void initPrograms(SourceCollections &sourceCollections) const;
282 virtual TestInstance *createInstance(Context &context) const;
283 void checkSupport(Context &context) const;
284
285 private:
286 const TestParams m_testParams;
287 };
288
289 class UnusedAttachmentTestInstance : public vkt::TestInstance
290 {
291 public:
292 UnusedAttachmentTestInstance(Context &context, const TestParams &testParams);
293 virtual ~UnusedAttachmentTestInstance(void) = default;
294 virtual tcu::TestStatus iterate(void);
295
296 protected:
297 template <typename RenderpassSubpass>
298 void createCommandBuffer(const DeviceInterface &vk, VkDevice vkDevice);
299 void createCommandBufferDynamicRendering(const DeviceInterface &vk, VkDevice vkDevice);
300
301 #ifndef CTS_USES_VULKANSC
302 void preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
303 void inbetweenRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
304 #endif // CTS_USES_VULKANSC
305 void drawFirstSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
306 void drawSecondSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
307
308 private:
309 tcu::TestStatus verifyImage(void);
310
311 const TestParams m_testParams;
312 const tcu::UVec2 m_renderSize;
313
314 Move<VkImage> m_colorImage;
315 de::MovePtr<Allocation> m_colorImageAlloc;
316 Move<VkImageView> m_colorAttachmentView;
317
318 Move<VkImage> m_unusedImage;
319 de::MovePtr<Allocation> m_unusedImageAlloc;
320 Move<VkImageView> m_unusedAttachmentView;
321
322 Move<VkImage> m_inputImage;
323 de::MovePtr<Allocation> m_inputImageAlloc;
324 Move<VkImageView> m_inputAttachmentView;
325 VkImageLayout m_inputImageReadLayout;
326
327 Move<VkDescriptorSetLayout> m_descriptorSetLayoutSubpass0;
328 Move<VkDescriptorSetLayout> m_descriptorSetLayoutSubpass1;
329 Move<VkDescriptorPool> m_descriptorPool;
330 Move<VkDescriptorSet> m_descriptorSetSubpass1;
331 Move<VkRenderPass> m_renderPass;
332 Move<VkFramebuffer> m_framebuffer;
333
334 ShaderWrapper m_vertexShaderModule;
335 ShaderWrapper m_fragmentShaderModuleSubpass0;
336 ShaderWrapper m_fragmentShaderModuleSubpass1;
337
338 Move<VkBuffer> m_vertexBuffer;
339 std::vector<Vertex4RGBA> m_vertices;
340 de::MovePtr<Allocation> m_vertexBufferAlloc;
341
342 Move<VkBuffer> m_backingBuffer;
343 de::MovePtr<Allocation> m_backingBufferAlloc;
344
345 PipelineLayoutWrapper m_pipelineLayoutSubpass0;
346 PipelineLayoutWrapper m_pipelineLayoutSubpass1;
347 GraphicsPipelineWrapper m_graphicsPipelineSubpass0;
348 GraphicsPipelineWrapper m_graphicsPipelineSubpass1;
349
350 Move<VkCommandPool> m_cmdPool;
351 Move<VkCommandBuffer> m_cmdBuffer;
352 Move<VkCommandBuffer> m_secCmdBuffer;
353 };
354
UnusedAttachmentTest(tcu::TestContext & testContext,const std::string & name,const TestParams & testParams)355 UnusedAttachmentTest::UnusedAttachmentTest(tcu::TestContext &testContext, const std::string &name,
356 const TestParams &testParams)
357 : vkt::TestCase(testContext, name)
358 , m_testParams(testParams)
359 {
360 }
361
createInstance(Context & context) const362 TestInstance *UnusedAttachmentTest::createInstance(Context &context) const
363 {
364 return new UnusedAttachmentTestInstance(context, m_testParams);
365 }
366
checkSupport(Context & context) const367 void UnusedAttachmentTest::checkSupport(Context &context) const
368 {
369 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
370 m_testParams.groupParams->pipelineConstructionType);
371 if (m_testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
372 context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
373 else if (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
374 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering_local_read");
375 }
376
initPrograms(SourceCollections & sourceCollections) const377 void UnusedAttachmentTest::initPrograms(SourceCollections &sourceCollections) const
378 {
379 std::ostringstream fragmentSource;
380
381 sourceCollections.glslSources.add("color_vert")
382 << glu::VertexSource("#version 450\n"
383 "layout(location = 0) in highp vec4 position;\n"
384 "layout(location = 1) in highp vec4 color;\n"
385 "layout(location = 0) out highp vec4 vtxColor;\n"
386 "void main (void)\n"
387 "{\n"
388 " gl_Position = position;\n"
389 " vtxColor = color;\n"
390 "}\n");
391
392 sourceCollections.glslSources.add("color_frag_sb0")
393 << glu::FragmentSource("#version 450\n"
394 "layout(location = 0) in highp vec4 vtxColor;\n"
395 "layout(location = 0) out highp vec4 fragColor;\n"
396 "void main (void)\n"
397 "{\n"
398 " fragColor = vtxColor;\n"
399 "}\n");
400
401 sourceCollections.glslSources.add("color_frag_sb1") << glu::FragmentSource(
402 "#version 450\n"
403 "layout(location = 0) in highp vec4 vtxColor;\n"
404 "layout(location = 0) out highp vec4 fragColor;\n"
405 "layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;"
406 "void main (void)\n"
407 "{\n"
408 " fragColor = subpassLoad(inputColor) + vtxColor;\n"
409 "}\n");
410 }
411
UnusedAttachmentTestInstance(Context & context,const TestParams & testParams)412 UnusedAttachmentTestInstance::UnusedAttachmentTestInstance(Context &context, const TestParams &testParams)
413 : vkt::TestInstance(context)
414 , m_testParams(testParams)
415 , m_renderSize(32u, 32u)
416 , m_inputImageReadLayout(chooseInputImageLayout(testParams.groupParams))
417 , m_vertices(createQuad())
418 , m_graphicsPipelineSubpass0(context.getInstanceInterface(), context.getDeviceInterface(),
419 context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(),
420 m_testParams.groupParams->pipelineConstructionType)
421 , m_graphicsPipelineSubpass1(context.getInstanceInterface(), context.getDeviceInterface(),
422 context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(),
423 m_testParams.groupParams->pipelineConstructionType)
424 {
425 const DeviceInterface &vk = m_context.getDeviceInterface();
426 const VkDevice vkDevice = m_context.getDevice();
427 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
428 SimpleAllocator memAlloc(
429 vk, vkDevice,
430 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
431 const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
432 VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
433
434 // Create color image
435 {
436 const VkImageCreateInfo colorImageParams = {
437 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
438 DE_NULL, // const void* pNext;
439 0u, // VkImageCreateFlags flags;
440 VK_IMAGE_TYPE_2D, // VkImageType imageType;
441 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
442 {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
443 1u, // uint32_t mipLevels;
444 1u, // uint32_t arrayLayers;
445 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
446 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
447 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
448 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
449 1u, // uint32_t queueFamilyIndexCount;
450 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
451 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
452 };
453
454 m_colorImage = createImage(vk, vkDevice, &colorImageParams);
455
456 // Allocate and bind color image memory
457 m_colorImageAlloc =
458 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
459 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(),
460 m_colorImageAlloc->getOffset()));
461 }
462
463 // Create image which is not used by any subpass
464 {
465 const VkImageCreateInfo unusedImageParams = {
466 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
467 DE_NULL, // const void* pNext;
468 0u, // VkImageCreateFlags flags;
469 VK_IMAGE_TYPE_2D, // VkImageType imageType;
470 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
471 {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
472 1u, // uint32_t mipLevels;
473 1u, // uint32_t arrayLayers;
474 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
475 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
476 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
477 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
478 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
479 1u, // uint32_t queueFamilyIndexCount;
480 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
481 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
482 };
483
484 m_unusedImage = createImage(vk, vkDevice, &unusedImageParams);
485
486 // Allocate and bind unused image memory
487 VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vk, vkDevice, *m_unusedImage);
488
489 m_unusedImageAlloc = memAlloc.allocate(memoryRequirements, MemoryRequirement::Any);
490 VK_CHECK(vk.bindImageMemory(vkDevice, *m_unusedImage, m_unusedImageAlloc->getMemory(),
491 m_unusedImageAlloc->getOffset()));
492
493 // Clear image with specific value to verify the contents don't change
494 {
495 const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
496 Move<VkCommandPool> cmdPool;
497 Move<VkCommandBuffer> cmdBuffer;
498
499 VkClearValue clearValue;
500 clearValue.color.float32[0] = 0.1f;
501 clearValue.color.float32[1] = 0.2f;
502 clearValue.color.float32[2] = 0.3f;
503 clearValue.color.float32[3] = 0.4f;
504
505 // Create command pool and buffer
506 cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
507 cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
508
509 const VkImageMemoryBarrier preImageBarrier = {
510 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
511 DE_NULL, // const void* pNext;
512 0u, // VkAccessFlags srcAccessMask;
513 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
514 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
515 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
516 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
517 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
518 *m_unusedImage, // VkImage image;
519 {
520 // VkImageSubresourceRange subresourceRange;
521 aspectMask, // VkImageAspect aspect;
522 0u, // uint32_t baseMipLevel;
523 1u, // uint32_t mipLevels;
524 0u, // uint32_t baseArraySlice;
525 1u // uint32_t arraySize;
526 }};
527
528 const VkImageMemoryBarrier postImageBarrier = {
529 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
530 DE_NULL, // const void* pNext;
531 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
532 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
533 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
534 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
535 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
536 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
537 *m_unusedImage, // VkImage image;
538 {
539 // VkImageSubresourceRange subresourceRange;
540 aspectMask, // VkImageAspect aspect;
541 0u, // uint32_t baseMipLevel;
542 1u, // uint32_t mipLevels;
543 0u, // uint32_t baseArraySlice;
544 1u // uint32_t arraySize;
545 }};
546
547 const VkImageSubresourceRange clearRange = {
548 aspectMask, // VkImageAspectFlags aspectMask;
549 0u, // uint32_t baseMipLevel;
550 1u, // uint32_t levelCount;
551 0u, // uint32_t baseArrayLayer;
552 1u // uint32_t layerCount;
553 };
554
555 // Clear image
556 beginCommandBuffer(vk, *cmdBuffer);
557 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
558 (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
559 (const VkBufferMemoryBarrier *)DE_NULL, 1, &preImageBarrier);
560 vk.cmdClearColorImage(*cmdBuffer, *m_unusedImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color,
561 1, &clearRange);
562 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
563 (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
564 (const VkBufferMemoryBarrier *)DE_NULL, 1, &postImageBarrier);
565 endCommandBuffer(vk, *cmdBuffer);
566
567 submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
568 }
569 }
570
571 // Create input image
572 {
573 const VkImageCreateInfo inputImageParams = {
574 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
575 DE_NULL, // const void* pNext;
576 0u, // VkImageCreateFlags flags;
577 VK_IMAGE_TYPE_2D, // VkImageType imageType;
578 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
579 {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
580 1u, // uint32_t mipLevels;
581 1u, // uint32_t arrayLayers;
582 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
583 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
584 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, // VkImageUsageFlags usage;
585 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
586 1u, // uint32_t queueFamilyIndexCount;
587 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
588 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
589 };
590
591 m_inputImage = createImage(vk, vkDevice, &inputImageParams);
592
593 // Allocate and bind input image memory
594 m_inputImageAlloc =
595 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_inputImage), MemoryRequirement::Any);
596 VK_CHECK(vk.bindImageMemory(vkDevice, *m_inputImage, m_inputImageAlloc->getMemory(),
597 m_inputImageAlloc->getOffset()));
598 }
599
600 // Create color attachment view
601 {
602 const VkImageViewCreateInfo colorAttachmentViewParams = {
603 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
604 DE_NULL, // const void* pNext;
605 0u, // VkImageViewCreateFlags flags;
606 *m_colorImage, // VkImage image;
607 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
608 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
609 componentMappingRGBA, // VkChannelMapping channels;
610 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
611 };
612
613 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
614 }
615
616 // Create unused attachment view
617 {
618 const VkImageViewCreateInfo unusedAttachmentViewParams = {
619 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
620 DE_NULL, // const void* pNext;
621 0u, // VkImageViewCreateFlags flags;
622 *m_unusedImage, // VkImage image;
623 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
624 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
625 componentMappingRGBA, // VkChannelMapping channels;
626 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
627 };
628
629 m_unusedAttachmentView = createImageView(vk, vkDevice, &unusedAttachmentViewParams);
630 }
631
632 // Create input attachment view
633 {
634 const VkImageViewCreateInfo inputAttachmentViewParams = {
635 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
636 DE_NULL, // const void* pNext;
637 0u, // VkImageViewCreateFlags flags;
638 *m_inputImage, // VkImage image;
639 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
640 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
641 componentMappingRGBA, // VkChannelMapping channels;
642 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
643 };
644
645 m_inputAttachmentView = createImageView(vk, vkDevice, &inputAttachmentViewParams);
646 }
647
648 // Create render pass
649 if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
650 m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1,
651 SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams);
652 else if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
653 m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2,
654 SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams);
655 else
656 m_renderPass = Move<VkRenderPass>();
657
658 // Create framebuffer if renderpass handle is valid
659 if (*m_renderPass != DE_NULL)
660 {
661 const VkImageView imageViews[] = {*m_colorAttachmentView, *m_unusedAttachmentView, *m_inputAttachmentView};
662
663 const VkFramebufferCreateInfo framebufferParams = {
664 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
665 DE_NULL, // const void* pNext;
666 0u, // VkFramebufferCreateFlags flags;
667 *m_renderPass, // VkRenderPass renderPass;
668 3u, // uint32_t attachmentCount;
669 imageViews, // const VkImageView* pAttachments;
670 (uint32_t)m_renderSize.x(), // uint32_t width;
671 (uint32_t)m_renderSize.y(), // uint32_t height;
672 1u // uint32_t layers;
673 };
674
675 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
676 }
677
678 // Create pipeline layout for subpass 0
679 {
680 const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams = {
681 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType
682 DE_NULL, // const void* pNext
683 0u, // VkDescriptorSetLayoutCreateFlags flags
684 0u, // uint32_t bindingCount
685 DE_NULL // const VkDescriptorSetLayoutBinding* pBindings
686 };
687 m_descriptorSetLayoutSubpass0 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
688 m_pipelineLayoutSubpass0 = PipelineLayoutWrapper(testParams.groupParams->pipelineConstructionType, vk, vkDevice,
689 *m_descriptorSetLayoutSubpass0);
690 }
691
692 // Create pipeline layout for subpass 1
693 {
694 const VkDescriptorSetLayoutBinding layoutBinding = {
695 0u, // uint32_t binding;
696 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType;
697 1u, // uint32_t descriptorCount;
698 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
699 DE_NULL // const VkSampler* pImmutableSamplers;
700 };
701
702 const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams = {
703 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType
704 DE_NULL, // const void* pNext
705 0u, // VkDescriptorSetLayoutCreateFlags flags
706 1u, // uint32_t bindingCount
707 &layoutBinding // const VkDescriptorSetLayoutBinding* pBindings
708 };
709 m_descriptorSetLayoutSubpass1 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
710 m_pipelineLayoutSubpass1 = PipelineLayoutWrapper(testParams.groupParams->pipelineConstructionType, vk, vkDevice,
711 *m_descriptorSetLayoutSubpass1);
712 }
713
714 // Update descriptor set
715 {
716 const VkDescriptorPoolSize descriptorPoolSize = {
717 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType type;
718 1u // uint32_t descriptorCount;
719 };
720
721 const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {
722 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType
723 DE_NULL, // const void* pNext
724 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags flags
725 1u, // uint32_t maxSets
726 1u, // uint32_t poolSizeCount
727 &descriptorPoolSize // const VkDescriptorPoolSize* pPoolSizes
728 };
729
730 m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
731
732 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
733 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType
734 DE_NULL, // const void* pNext
735 *m_descriptorPool, // VkDescriptorPool descriptorPool
736 1u, // uint32_t descriptorSetCount
737 &m_descriptorSetLayoutSubpass1.get(), // const VkDescriptorSetLayout* pSetLayouts
738 };
739
740 m_descriptorSetSubpass1 = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
741
742 const VkDescriptorImageInfo inputImageInfo = {
743 DE_NULL, // VkSampleri sampler;
744 *m_inputAttachmentView, // VkImageView imageView;
745 m_inputImageReadLayout // VkImageLayout imageLayout;
746 };
747
748 const VkWriteDescriptorSet descriptorWrite = {
749 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
750 DE_NULL, // const void* pNext;
751 *m_descriptorSetSubpass1, // VkDescriptorSet dstSet;
752 0u, // uint32_t dstBinding;
753 0u, // uint32_t dstArrayElement;
754 1u, // uint32_t descriptorCount;
755 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType;
756 &inputImageInfo, // const VkDescriptorImageInfo* pImageInfo;
757 DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo;
758 DE_NULL // const VkBufferView* pTexelBufferView;
759 };
760
761 vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
762 }
763
764 m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
765 m_fragmentShaderModuleSubpass0 =
766 ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb0"), 0);
767 m_fragmentShaderModuleSubpass1 =
768 ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb1"), 0);
769
770 // Create pipelines
771 {
772 const VkVertexInputBindingDescription vertexInputBindingDescription = {
773 0u, // uint32_t binding;
774 sizeof(Vertex4RGBA), // uint32_t strideInBytes;
775 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
776 };
777
778 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
779 {
780 0u, // uint32_t location;
781 0u, // uint32_t binding;
782 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
783 0u // uint32_t offset;
784 },
785 {
786 1u, // uint32_t location;
787 0u, // uint32_t binding;
788 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
789 (uint32_t)(sizeof(float) * 4), // uint32_t offset;
790 }};
791
792 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
793 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
794 DE_NULL, // const void* pNext;
795 0u, // VkPipelineVertexInputStateCreateFlags flags;
796 1u, // uint32_t vertexBindingDescriptionCount;
797 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
798 2u, // uint32_t vertexAttributeDescriptionCount;
799 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
800 };
801
802 VkPipelineColorBlendAttachmentState colorBlendAttachmentState;
803 deMemset(&colorBlendAttachmentState, 0x00, sizeof(VkPipelineColorBlendAttachmentState));
804 colorBlendAttachmentState.colorWriteMask = 0xF;
805
806 uint32_t colorAttachmentsCount = (*m_renderPass == DE_NULL) ? 3u : 1u;
807 const std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(colorAttachmentsCount,
808 colorBlendAttachmentState);
809 VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = initVulkanStructure();
810 colorBlendStateCreateInfo.attachmentCount = uint32_t(colorBlendAttachmentStates.size());
811 colorBlendStateCreateInfo.pAttachments = colorBlendAttachmentStates.data();
812
813 PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
814 RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfoWrapper;
815 RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfoWrapper;
816 const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
817 const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
818
819 #ifndef CTS_USES_VULKANSC
820 uint32_t colorAttachmentLocationsSubpass0[]{VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED, 0};
821 uint32_t colorAttachmentLocationsSubpass1[]{0, VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED};
822 VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo = initVulkanStructure();
823 renderingAttachmentLocationInfo.colorAttachmentCount = colorAttachmentsCount;
824 renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsSubpass0;
825
826 uint32_t colorAttachmentInputIndices[]{VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED, 0};
827 VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo{
828 VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR,
829 DE_NULL,
830 colorAttachmentsCount, // uint32_t colorAttachmentCount
831 colorAttachmentInputIndices, // const uint32_t* pColorAttachmentInputIndices
832 DE_NULL, // uint32_t depthInputAttachmentIndex
833 DE_NULL, // uint32_t stencilInputAttachmentIndex
834 };
835
836 const std::vector<VkFormat> colorAttachmentFormats(colorAttachmentsCount, VK_FORMAT_R8G8B8A8_UNORM);
837 VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
838 DE_NULL,
839 0u,
840 3u,
841 colorAttachmentFormats.data(),
842 VK_FORMAT_UNDEFINED,
843 VK_FORMAT_UNDEFINED};
844
845 if (*m_renderPass == DE_NULL)
846 {
847 renderingCreateInfoWrapper.ptr = &renderingCreateInfo;
848 renderingAttachmentLocationInfoWrapper.ptr = &renderingAttachmentLocationInfo;
849 renderingInputAttachmentIndexInfoWrapper.ptr = &renderingInputAttachmentIndexInfo;
850 }
851 #endif // CTS_USES_VULKANSC
852
853 m_graphicsPipelineSubpass0.setDefaultMultisampleState()
854 .setDefaultDepthStencilState()
855 .setDefaultRasterizationState()
856 .setupVertexInputState(&vertexInputStateParams)
857 .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayoutSubpass0, *m_renderPass, 0u,
858 m_vertexShaderModule, 0u, ShaderWrapper(), ShaderWrapper(),
859 ShaderWrapper(), DE_NULL, DE_NULL, renderingCreateInfoWrapper)
860 .setupFragmentShaderState(m_pipelineLayoutSubpass0, *m_renderPass, 0u, m_fragmentShaderModuleSubpass0)
861 .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateCreateInfo, 0, 0, {},
862 renderingAttachmentLocationInfoWrapper)
863 .setMonolithicPipelineLayout(m_pipelineLayoutSubpass0)
864 .buildPipeline();
865
866 #ifndef CTS_USES_VULKANSC
867 renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsSubpass1;
868 #endif // CTS_USES_VULKANSC
869
870 m_graphicsPipelineSubpass1.setDefaultMultisampleState()
871 .setDefaultDepthStencilState()
872 .setDefaultRasterizationState()
873 .setupVertexInputState(&vertexInputStateParams)
874 .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayoutSubpass1, *m_renderPass, 1u,
875 m_vertexShaderModule, 0u, ShaderWrapper(), ShaderWrapper(),
876 ShaderWrapper(), DE_NULL, DE_NULL, renderingCreateInfoWrapper)
877 .setupFragmentShaderState(m_pipelineLayoutSubpass1, *m_renderPass, 1u, m_fragmentShaderModuleSubpass1, 0, 0,
878 0, 0, {}, renderingInputAttachmentIndexInfoWrapper)
879 .setupFragmentOutputState(*m_renderPass, 1u, &colorBlendStateCreateInfo, 0, 0, {},
880 renderingAttachmentLocationInfoWrapper)
881 .setMonolithicPipelineLayout(m_pipelineLayoutSubpass1)
882 .buildPipeline();
883 }
884
885 // Create vertex buffer
886 {
887 const VkBufferCreateInfo vertexBufferParams = {
888 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
889 DE_NULL, // const void* pNext;
890 0u, // VkBufferCreateFlags flags;
891 (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
892 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
893 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
894 1u, // uint32_t queueFamilyIndexCount;
895 &queueFamilyIndex // const uint32_t* pQueueFamilyIndices;
896 };
897
898 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
899 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
900 MemoryRequirement::HostVisible);
901
902 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
903 m_vertexBufferAlloc->getOffset()));
904
905 // Upload vertex data
906 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
907 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
908 }
909
910 // Create command pool
911 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
912
913 // Create command buffer
914 if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
915 createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
916 else if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
917 createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
918 else
919 createCommandBufferDynamicRendering(vk, vkDevice);
920 }
921
922 template <typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)923 void UnusedAttachmentTestInstance::createCommandBuffer(const DeviceInterface &vk, VkDevice vkDevice)
924 {
925 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
926 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
927
928 const VkClearValue attachmentClearValues[] = {
929 makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f), // color
930 makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f), // unused
931 makeClearValueColorF32(0.5f, 0.2f, 0.1f, 1.0f) // input
932 };
933
934 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
935
936 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
937
938 const VkRenderPassBeginInfo renderPassBeginInfo{
939 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
940 DE_NULL, // const void* pNext;
941 *m_renderPass, // VkRenderPass renderPass;
942 *m_framebuffer, // VkFramebuffer framebuffer;
943 makeRect2D(m_renderSize), // VkRect2D renderArea;
944 3u, // uint32_t clearValueCount;
945 attachmentClearValues // const VkClearValue* pClearValues;
946 };
947 RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
948
949 drawFirstSubpass(vk, *m_cmdBuffer);
950 vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
951 drawSecondSubpass(vk, *m_cmdBuffer);
952
953 RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
954 endCommandBuffer(vk, *m_cmdBuffer);
955 }
956
createCommandBufferDynamicRendering(const DeviceInterface & vk,VkDevice vkDevice)957 void UnusedAttachmentTestInstance::createCommandBufferDynamicRendering(const DeviceInterface &vk, VkDevice vkDevice)
958 {
959 #ifndef CTS_USES_VULKANSC
960 uint32_t colorAttachmentLocationsSubpass0[]{VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED, 0};
961 uint32_t colorAttachmentLocationsSubpass1[]{0, VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED};
962 VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo = initVulkanStructure();
963 renderingAttachmentLocationInfo.colorAttachmentCount = 3u;
964 renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsSubpass0;
965
966 uint32_t colorAttachmentInputIndicesSubpass0[]{VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED};
967 uint32_t colorAttachmentInputIndicesSubpass1[]{VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED, 0};
968 VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo{
969 VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR,
970 DE_NULL,
971 3u, // uint32_t colorAttachmentCount
972 colorAttachmentInputIndicesSubpass1, // const uint32_t* pColorAttachmentInputIndices
973 DE_NULL, // uint32_t depthInputAttachmentIndex
974 DE_NULL, // uint32_t stencilInputAttachmentIndex
975 };
976
977 std::vector<VkRenderingAttachmentInfo> colorAttachments(
978 3u,
979 {
980 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
981 DE_NULL, // const void* pNext;
982 *m_colorAttachmentView, // VkImageView imageView;
983 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
984 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
985 DE_NULL, // VkImageView resolveImageView;
986 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
987 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
988 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
989 makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f) // VkClearValue clearValue;
990 });
991
992 colorAttachments[1].imageView = *m_unusedAttachmentView;
993 colorAttachments[1].loadOp = m_testParams.loadOp;
994 colorAttachments[1].storeOp = m_testParams.storeOp;
995 colorAttachments[2].imageView = *m_inputAttachmentView;
996 colorAttachments[2].imageLayout = m_inputImageReadLayout;
997 colorAttachments[2].clearValue = makeClearValueColorF32(0.5f, 0.2f, 0.1f, 1.0f);
998
999 VkRenderingInfo renderingInfo{
1000 VK_STRUCTURE_TYPE_RENDERING_INFO,
1001 DE_NULL,
1002 0, // VkRenderingFlagsKHR flags;
1003 makeRect2D(m_renderSize), // VkRect2D renderArea;
1004 1u, // uint32_t layerCount;
1005 0u, // uint32_t viewMask;
1006 3u, // uint32_t colorAttachmentCount;
1007 colorAttachments.data(), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
1008 DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
1009 DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
1010 };
1011
1012 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1013
1014 if (m_testParams.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1015 {
1016 m_secCmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
1017 VkCommandBuffer secCmdBuffer = *m_secCmdBuffer;
1018
1019 // record secondary command buffer
1020 renderingAttachmentLocationInfo.pNext = &renderingInputAttachmentIndexInfo;
1021 beginSecondaryCmdBuffer(vk, secCmdBuffer, &renderingAttachmentLocationInfo);
1022 vk.cmdBeginRendering(secCmdBuffer, &renderingInfo);
1023
1024 renderingAttachmentLocationInfo.pNext = DE_NULL;
1025 renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsSubpass0;
1026 renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices = colorAttachmentInputIndicesSubpass0;
1027 vk.cmdSetRenderingAttachmentLocationsKHR(secCmdBuffer, &renderingAttachmentLocationInfo);
1028 vk.cmdSetRenderingInputAttachmentIndicesKHR(secCmdBuffer, &renderingInputAttachmentIndexInfo);
1029 drawFirstSubpass(vk, secCmdBuffer);
1030 inbetweenRenderCommands(vk, secCmdBuffer);
1031
1032 renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsSubpass1;
1033 renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices = colorAttachmentInputIndicesSubpass1;
1034 vk.cmdSetRenderingAttachmentLocationsKHR(secCmdBuffer, &renderingAttachmentLocationInfo);
1035 vk.cmdSetRenderingInputAttachmentIndicesKHR(secCmdBuffer, &renderingInputAttachmentIndexInfo);
1036 drawSecondSubpass(vk, secCmdBuffer);
1037
1038 vk.cmdEndRendering(secCmdBuffer);
1039 endCommandBuffer(vk, secCmdBuffer);
1040
1041 // record primary command buffer
1042 beginCommandBuffer(vk, *m_cmdBuffer);
1043 preRenderCommands(vk, *m_cmdBuffer);
1044 vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &secCmdBuffer);
1045 endCommandBuffer(vk, *m_cmdBuffer);
1046 }
1047 else
1048 {
1049 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1050 preRenderCommands(vk, *m_cmdBuffer);
1051 vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
1052
1053 vk.cmdSetRenderingAttachmentLocationsKHR(*m_cmdBuffer, &renderingAttachmentLocationInfo);
1054 drawFirstSubpass(vk, *m_cmdBuffer);
1055 inbetweenRenderCommands(vk, *m_cmdBuffer);
1056
1057 renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsSubpass1;
1058 vk.cmdSetRenderingAttachmentLocationsKHR(*m_cmdBuffer, &renderingAttachmentLocationInfo);
1059 vk.cmdSetRenderingInputAttachmentIndicesKHR(*m_cmdBuffer, &renderingInputAttachmentIndexInfo);
1060 drawSecondSubpass(vk, *m_cmdBuffer);
1061
1062 vk.cmdEndRendering(*m_cmdBuffer);
1063 endCommandBuffer(vk, *m_cmdBuffer);
1064 }
1065 #else
1066 DE_UNREF(vk);
1067 DE_UNREF(vkDevice);
1068 #endif // CTS_USES_VULKANSC
1069 }
1070
1071 #ifndef CTS_USES_VULKANSC
preRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)1072 void UnusedAttachmentTestInstance::preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
1073 {
1074 const VkImageSubresourceRange subresourceRange(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1));
1075 const VkImageMemoryBarrier imageBarriers[]{
1076 makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1077 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *m_colorImage, subresourceRange),
1078 makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1079 m_inputImageReadLayout, *m_inputImage, subresourceRange),
1080 };
1081
1082 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1083 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1084 }
1085
inbetweenRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)1086 void UnusedAttachmentTestInstance::inbetweenRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
1087 {
1088 const VkImageSubresourceRange subresourceRange(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1));
1089 VkImageMemoryBarrier imageBarrier(
1090 makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
1091 m_inputImageReadLayout, m_inputImageReadLayout, *m_inputImage, subresourceRange));
1092 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1093 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0u, DE_NULL, 0u, DE_NULL,
1094 1u, &imageBarrier);
1095 }
1096 #endif // CTS_USES_VULKANSC
1097
drawFirstSubpass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)1098 void UnusedAttachmentTestInstance::drawFirstSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
1099 {
1100 const VkDeviceSize vertexBufferOffset = 0;
1101 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipelineSubpass0.getPipeline());
1102 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1103 vk.cmdDraw(cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
1104 }
1105
drawSecondSubpass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)1106 void UnusedAttachmentTestInstance::drawSecondSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
1107 {
1108 const VkDeviceSize vertexBufferOffset = 0;
1109 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipelineSubpass1.getPipeline());
1110 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1111 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutSubpass1, 0, 1,
1112 &m_descriptorSetSubpass1.get(), 0, DE_NULL);
1113 vk.cmdDraw(cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
1114 }
1115
iterate(void)1116 tcu::TestStatus UnusedAttachmentTestInstance::iterate(void)
1117 {
1118 const DeviceInterface &vk = m_context.getDeviceInterface();
1119 const VkDevice vkDevice = m_context.getDevice();
1120 const VkQueue queue = m_context.getUniversalQueue();
1121
1122 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1123
1124 return verifyImage();
1125 }
1126
verifyImage(void)1127 tcu::TestStatus UnusedAttachmentTestInstance::verifyImage(void)
1128 {
1129 const DeviceInterface &vk = m_context.getDeviceInterface();
1130 const VkDevice vkDevice = m_context.getDevice();
1131 const VkQueue queue = m_context.getUniversalQueue();
1132 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1133 SimpleAllocator allocator(
1134 vk, vkDevice,
1135 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1136 de::UniquePtr<tcu::TextureLevel> textureLevelResult(
1137 pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage,
1138 VK_FORMAT_R8G8B8A8_UNORM, m_renderSize)
1139 .release());
1140 const tcu::ConstPixelBufferAccess &resultAccess = textureLevelResult->getAccess();
1141 de::UniquePtr<tcu::TextureLevel> textureLevelUnused(
1142 pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_unusedImage,
1143 VK_FORMAT_R8G8B8A8_UNORM, m_renderSize)
1144 .release());
1145 const tcu::ConstPixelBufferAccess &unusedAccess = textureLevelUnused->getAccess();
1146 tcu::TestLog &log = m_context.getTestContext().getLog();
1147 tcu::Vec4 refColor(0.1f, 0.2f, 0.3f, 0.4f);
1148
1149 // Define helper lambda for checks if color is same as reference
1150 auto isColorValid = [](const tcu::Vec4 &color, const tcu::Vec4 &reference)
1151 { return tcu::boolAll(tcu::lessThan(tcu::absDiff(color, reference), tcu::Vec4(0.01f))); };
1152
1153 // Log images
1154 log << tcu::TestLog::ImageSet("Result", "Result images")
1155 << tcu::TestLog::Image("Rendered", "Rendered image", resultAccess)
1156 << tcu::TestLog::Image("Unused", "Unused image", unusedAccess) << tcu::TestLog::EndImageSet;
1157
1158 if ((m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) &&
1159 (m_testParams.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR))
1160 {
1161 // With renderpass object there could be attachment that is not listed as color attachment
1162 // for any subpass and in that case it would not be cleared even when op load clear is specified
1163 // in dynamic renderpass load operation will be done for all specified color attachments because we dont
1164 // know at vkCmdBeginRendering which color attachments are going to be used and which will be left unused
1165 if (m_testParams.storeOp == VK_ATTACHMENT_STORE_OP_STORE)
1166 refColor = tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f);
1167 else if (m_testParams.storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE)
1168 {
1169 // Unused attachment was cleared but we dont care if we store it or not and now two colors are valid.
1170 // If color at pixel (0, 0) is not refColor then we also should use clear color for verification.
1171 if (!isColorValid(unusedAccess.getPixel(0, 0), refColor))
1172 refColor = tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f);
1173 }
1174 }
1175
1176 // Check the unused image data.
1177 for (int y = 0; y < unusedAccess.getHeight(); y++)
1178 for (int x = 0; x < unusedAccess.getWidth(); x++)
1179 {
1180 if (!isColorValid(unusedAccess.getPixel(x, y), refColor))
1181 return tcu::TestStatus::fail("Unused image contents has changed.");
1182 }
1183
1184 // Check for rendered result. Just a quick check to see if correct color is found at the center of the quad.
1185 const tcu::Vec4 resultColor = resultAccess.getPixel(resultAccess.getWidth() / 2, resultAccess.getHeight() / 2);
1186 if (!isColorValid(resultColor, tcu::Vec4(0.4f, 0.6f, 0.2f, 1.0f)))
1187 return tcu::TestStatus::fail("Result image mismatch");
1188
1189 return tcu::TestStatus::pass("Pass");
1190 }
1191
loadOpToString(VkAttachmentLoadOp loadOp)1192 std::string loadOpToString(VkAttachmentLoadOp loadOp)
1193 {
1194 switch (loadOp)
1195 {
1196 case VK_ATTACHMENT_LOAD_OP_LOAD:
1197 return "load";
1198 case VK_ATTACHMENT_LOAD_OP_CLEAR:
1199 return "clear";
1200 case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
1201 return "dontcare";
1202 default:
1203 DE_FATAL("unexpected attachment load op");
1204 return "";
1205 }
1206 }
1207
storeOpToString(VkAttachmentStoreOp storeOp)1208 std::string storeOpToString(VkAttachmentStoreOp storeOp)
1209 {
1210 switch (storeOp)
1211 {
1212 case VK_ATTACHMENT_STORE_OP_STORE:
1213 return "store";
1214 case VK_ATTACHMENT_STORE_OP_DONT_CARE:
1215 return "dontcare";
1216 default:
1217 DE_FATAL("unexpected attachment store op");
1218 return "";
1219 }
1220 }
1221
1222 } // namespace
1223
createRenderPassUnusedAttachmentTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1224 tcu::TestCaseGroup *createRenderPassUnusedAttachmentTests(tcu::TestContext &testCtx,
1225 const SharedGroupParams groupParams)
1226 {
1227 // Unused attachment tests
1228 de::MovePtr<tcu::TestCaseGroup> unusedAttTests(new tcu::TestCaseGroup(testCtx, "unused_attachment"));
1229
1230 const VkAttachmentLoadOp loadOps[] = {VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR,
1231 VK_ATTACHMENT_LOAD_OP_DONT_CARE};
1232
1233 const VkAttachmentStoreOp storeOps[] = {VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_STORE_OP_DONT_CARE};
1234
1235 uint32_t stencilLoadOpStartIdx = 0;
1236 uint32_t stencilStoreOpStartIdx = 0;
1237 if (groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
1238 {
1239 // in dynamic rendering cases we dont_care about stencil load/store
1240 stencilLoadOpStartIdx = DE_LENGTH_OF_ARRAY(loadOps) - 1;
1241 stencilStoreOpStartIdx = DE_LENGTH_OF_ARRAY(storeOps) - 1;
1242 }
1243
1244 for (uint32_t loadOpIdx = 0; loadOpIdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpIdx++)
1245 {
1246 de::MovePtr<tcu::TestCaseGroup> loadOpGroup(
1247 new tcu::TestCaseGroup(testCtx, (std::string("loadop") + loadOpToString(loadOps[loadOpIdx])).c_str()));
1248
1249 for (uint32_t storeOpIdx = 0; storeOpIdx < DE_LENGTH_OF_ARRAY(storeOps); storeOpIdx++)
1250 {
1251 // for dynamic rendering we need to skip LOAD_OP_DONT_CARE+STORE_OP_STORE case
1252 // because some implementations in that case will write random data to unused attachments
1253 if ((groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) &&
1254 (loadOps[loadOpIdx] == VK_ATTACHMENT_LOAD_OP_DONT_CARE) &&
1255 (storeOps[storeOpIdx] == VK_ATTACHMENT_STORE_OP_STORE))
1256 {
1257 continue;
1258 }
1259
1260 de::MovePtr<tcu::TestCaseGroup> storeOpGroup(new tcu::TestCaseGroup(
1261 testCtx, (std::string("storeop") + storeOpToString(storeOps[storeOpIdx])).c_str()));
1262
1263 for (uint32_t stencilLoadOpIdx = stencilLoadOpStartIdx; stencilLoadOpIdx < DE_LENGTH_OF_ARRAY(loadOps);
1264 stencilLoadOpIdx++)
1265 {
1266 de::MovePtr<tcu::TestCaseGroup> stencilLoadOpGroup(new tcu::TestCaseGroup(
1267 testCtx, (std::string("stencilloadop") + loadOpToString(loadOps[stencilLoadOpIdx])).c_str()));
1268
1269 for (uint32_t stencilStoreOpIdx = stencilStoreOpStartIdx;
1270 stencilStoreOpIdx < DE_LENGTH_OF_ARRAY(storeOps); stencilStoreOpIdx++)
1271 {
1272 TestParams params;
1273 const std::string testName =
1274 std::string("stencilstoreop") + storeOpToString(storeOps[stencilStoreOpIdx]);
1275
1276 params.loadOp = loadOps[loadOpIdx];
1277 params.storeOp = storeOps[storeOpIdx];
1278 params.stencilLoadOp = loadOps[stencilLoadOpIdx];
1279 params.stencilStoreOp = storeOps[stencilStoreOpIdx];
1280 params.groupParams = groupParams;
1281
1282 stencilLoadOpGroup->addChild(new UnusedAttachmentTest(testCtx, testName, params));
1283 }
1284 storeOpGroup->addChild(stencilLoadOpGroup.release());
1285 }
1286 loadOpGroup->addChild(storeOpGroup.release());
1287 }
1288 unusedAttTests->addChild(loadOpGroup.release());
1289 }
1290
1291 return unusedAttTests.release();
1292 }
1293
1294 } // namespace renderpass
1295 } // namespace vkt
1296