1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2023 LunarG, Inc.
7  * Copyright (c) 2023 Nintendo
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 for VK_EXT_multisampled_render_to_single_sampled
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktPipelineMultisampledRenderToSingleSampledTests.hpp"
27 #include "vktPipelineMakeUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestCaseUtil.hpp"
30 #include "vktTestGroupUtil.hpp"
31 
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkBuilderUtil.hpp"
40 #include "vkPrograms.hpp"
41 #include "vkImageUtil.hpp"
42 #include "vkPipelineConstructionUtil.hpp"
43 
44 #include "deUniquePtr.hpp"
45 #include "deSharedPtr.hpp"
46 #include "deRandom.hpp"
47 #include "deMath.h"
48 
49 #include "tcuVector.hpp"
50 #include "tcuTestLog.hpp"
51 #include "tcuImageCompare.hpp"
52 #include "tcuTextureUtil.hpp"
53 #include "tcuRGBA.hpp"
54 
55 #include <string>
56 #include <vector>
57 
58 // For testing, logs
59 #define DEBUG_LOGS 0
60 
61 #if DEBUG_LOGS
62 #define DBG(...) fprintf(stderr, __VA_ARGS__)
63 #else
64 #define DBG(...) ((void)0)
65 #endif
66 
67 namespace vkt
68 {
69 namespace pipeline
70 {
71 namespace
72 {
73 using namespace vk;
74 using de::MovePtr;
75 using de::SharedPtr;
76 using de::UniquePtr;
77 using tcu::IVec2;
78 using tcu::IVec4;
79 using tcu::UVec2;
80 using tcu::UVec4;
81 using tcu::Vec2;
82 using tcu::Vec4;
83 
getDepthStencilAspectFlags(const VkFormat format)84 VkImageAspectFlags getDepthStencilAspectFlags(const VkFormat format)
85 {
86     const tcu::TextureFormat tcuFormat = mapVkFormat(format);
87 
88     if (tcuFormat.order == tcu::TextureFormat::DS)
89         return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
90     else if (tcuFormat.order == tcu::TextureFormat::D)
91         return VK_IMAGE_ASPECT_DEPTH_BIT;
92     else if (tcuFormat.order == tcu::TextureFormat::S)
93         return VK_IMAGE_ASPECT_STENCIL_BIT;
94 
95     DE_ASSERT(false);
96     return 0u;
97 }
98 
isDepthFormat(const VkFormat format)99 inline bool isDepthFormat(const VkFormat format)
100 {
101     return (getDepthStencilAspectFlags(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
102 }
103 
isStencilFormat(const VkFormat format)104 inline bool isStencilFormat(const VkFormat format)
105 {
106     return (getDepthStencilAspectFlags(format) & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
107 }
108 
109 using PipelineSp = SharedPtr<Unique<VkPipeline>>;
110 
111 // How many regions to render to in multi-pass tests
112 constexpr uint32_t RegionCount = 4;
113 
114 struct DrawPushConstants
115 {
116     Vec4 color1Data[2];
117     Vec4 color2Data[2];
118     IVec4 color3Data[2];
119     Vec2 depthData;
120 };
121 
122 struct VerifyPushConstants
123 {
124     Vec4 color1Data[2]   = {Vec4(0, 0, 0, 0), Vec4(0, 0, 0, 0)};
125     Vec4 color2Data[2]   = {Vec4(0, 0, 0, 0), Vec4(0, 0, 0, 0)};
126     IVec4 color3Data[2]  = {IVec4(0, 0, 0, 0), IVec4(0, 0, 0, 0)};
127     float depthData      = 0;
128     uint32_t stencilData = 0;
129 };
130 
131 struct VerificationResults
132 {
133     uint32_t color1Verification;
134     uint32_t color2Verification;
135     uint32_t color3Verification;
136     uint32_t depthVerification;
137     uint32_t stencilVerification;
138 };
139 
140 struct VerifySingleFloatPushConstants
141 {
142     UVec4 area;
143     Vec4 color;
144     uint32_t attachmentNdx;
145 };
146 
147 struct VerifySingleIntPushConstants
148 {
149     UVec4 area;
150     IVec4 color;
151     uint32_t attachmentNdx;
152 };
153 
154 struct VerifySingleDepthPushConstants
155 {
156     UVec4 area;
157     float depthData;
158 };
159 
160 struct VerifySingleStencilPushConstants
161 {
162     UVec4 area;
163     uint32_t stencilData;
164 };
165 
166 //! The parameters that define a test case
167 struct TestParams
168 {
169     VkSampleCountFlagBits numFloatColor1Samples;  //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
170     VkSampleCountFlagBits numFloatColor2Samples;  //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
171     VkSampleCountFlagBits numIntColorSamples;     //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
172     VkSampleCountFlagBits numDepthStencilSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
173 
174     VkFormat floatColor1Format;  //!< Color attachment format
175     VkFormat floatColor2Format;  //!< Color attachment format
176     VkFormat intColorFormat;     //!< Color attachment format
177     VkFormat depthStencilFormat; //!< D/S attachment format. Will test both aspects if it's a mixed format
178 
179     VkClearValue clearValues[4];
180 
181     VerifyPushConstants verifyConstants[RegionCount];
182 
183     bool
184         isMultisampledRenderToSingleSampled; //!< Whether the test should use VK_EXT_multisampled_render_to_single_sampled or normal multisampling
185     bool
186         clearBeforeRenderPass; //!< Whether loadOp=CLEAR should be used, or clear is done before render pass and loadOp=LOAD is used
187     bool renderToWholeFramebuffer; //!< Whether the test should render to the whole framebuffer.
188     bool
189         testBlendsColors; //!< Whether the test blends colors or overwrites them.  Tests don't adapt to this automatically, it's informative for shader generation.
190     bool dynamicRendering;     //!< Whether the test should use dynamic rendering.
191     bool useGarbageAttachment; //!< Whether the test uses garbage attachments.
192     bool
193         renderToAttachment; //!< Whether the test renders to input attachment in previous subpass or if it's initialize outside of render pass
194 
195     struct PerPass
196     {
197         VkSampleCountFlagBits numSamples; //!< Pipeline samples
198 
199         int32_t floatColor1Location;
200         int32_t floatColor2Location;
201         int32_t intColorLocation;
202         bool hasDepthStencil;
203 
204         bool resolveFloatColor1;
205         bool resolveFloatColor2;
206         bool resolveIntColor;
207         bool resolveDepthStencil;
208 
209         VkResolveModeFlagBits depthStencilResolveMode;
210 
211         DrawPushConstants drawConstantsWithDepthWrite[RegionCount];
212         DrawPushConstants drawConstantsWithDepthTest[RegionCount];
213     };
214 
215     std::vector<PerPass> perPass;
216 
217     // Used to carry forward the rng seed from test generation to test run.
218     uint32_t rngSeed;
219 
220     PipelineConstructionType pipelineConstructionType;
221 
TestParamsvkt::pipeline::__anonc9ecde940111::TestParams222     TestParams()
223         : numFloatColor1Samples{}
224         , numFloatColor2Samples{}
225         , numIntColorSamples{}
226         , numDepthStencilSamples{}
227         , floatColor1Format{}
228         , floatColor2Format{}
229         , intColorFormat{}
230         , depthStencilFormat{}
231         , clearValues{}
232     {
233     }
234 
usesColor1InPassvkt::pipeline::__anonc9ecde940111::TestParams235     bool usesColor1InPass(const size_t passNdx) const
236     {
237         return perPass[passNdx].floatColor1Location >= 0;
238     }
usesColor2InPassvkt::pipeline::__anonc9ecde940111::TestParams239     bool usesColor2InPass(const size_t passNdx) const
240     {
241         return perPass[passNdx].floatColor2Location >= 0;
242     }
usesColor3InPassvkt::pipeline::__anonc9ecde940111::TestParams243     bool usesColor3InPass(const size_t passNdx) const
244     {
245         return perPass[passNdx].intColorLocation >= 0;
246     }
usesDepthStencilInPassvkt::pipeline::__anonc9ecde940111::TestParams247     bool usesDepthStencilInPass(const size_t passNdx) const
248     {
249         return perPass[passNdx].hasDepthStencil;
250     }
251 };
252 
253 struct Image
254 {
255     Move<VkImage> image;
256     MovePtr<Allocation> alloc;
257     Move<VkImageView> view;
258 
259     void allocate(const DeviceInterface &vk, const VkDevice device, const MovePtr<Allocator> &allocator,
260                   const VkFormat format, const UVec2 &size, const VkSampleCountFlagBits samples,
261                   const VkImageUsageFlags usage, const VkImageAspectFlags aspect, const uint32_t layerCount,
262                   const bool usedForMSRTSS);
263     Move<VkImageView> makeView(const DeviceInterface &vk, const VkDevice device, const VkFormat format,
264                                const VkImageAspectFlags aspect, const uint32_t layerCount);
265 };
266 
267 //! Common data used by the test
268 struct WorkingData
269 {
270     UVec2 framebufferSize; //!< Size of the framebuffer
271     UVec4 renderArea;      //!< Render area
272 
273     Move<VkBuffer> vertexBuffer;                 //!< Contains a fullscreen triangle
274     MovePtr<Allocation> vertexBufferAlloc;       //!< Storage for vertexBuffer
275     Move<VkBuffer> verificationBuffer;           //!< Buffer used for validation
276     MovePtr<Allocation> verificationBufferAlloc; //!< Storage for verificationBuffer
277     Move<VkBuffer> singleVerificationBuffer;     //!< Buffer used for validation of attachments outside the render area
278     MovePtr<Allocation> singleVerificationBufferAlloc; //!< Storage for singleVerificationBuffer
279 
280     //!< Color and depth/stencil attachments
281     Image floatColor1;
282     Image floatColor2;
283     Image intColor;
284     Image depthStencil;
285     Move<VkImageView> depthOnlyImageView;
286     Move<VkImageView> stencilOnlyImageView;
287 
288     // Use when not rendering directly to input attachment
289     Image dataColor1;
290     Move<VkBuffer> dataBuffer;
291     MovePtr<Allocation> dataBufferAlloc;
292 
293     //!< Resolve attachments
294     Image floatResolve1;
295     Image floatResolve2;
296     Image intResolve;
297     Image depthStencilResolve;
298     Move<VkImageView> depthOnlyResolveImageView;
299     Move<VkImageView> stencilOnlyResolveImageView;
300 
301     //!< Verification results for logging (an array of 5 to avoid hitting maxPerStageDescriptorStorageImages limit of 4.
302     Image verify;
303 
WorkingDatavkt::pipeline::__anonc9ecde940111::WorkingData304     WorkingData(void)
305     {
306     }
307 
getResolvedFloatColorImage1vkt::pipeline::__anonc9ecde940111::WorkingData308     Move<VkImage> &getResolvedFloatColorImage1(const TestParams &params)
309     {
310         return params.numFloatColor1Samples != VK_SAMPLE_COUNT_1_BIT ? floatResolve1.image : floatColor1.image;
311     }
getResolvedFloatColorImage2vkt::pipeline::__anonc9ecde940111::WorkingData312     Move<VkImage> &getResolvedFloatColorImage2(const TestParams &params)
313     {
314         return params.numFloatColor2Samples != VK_SAMPLE_COUNT_1_BIT ? floatResolve2.image : floatColor2.image;
315     }
getResolvedIntColorImagevkt::pipeline::__anonc9ecde940111::WorkingData316     Move<VkImage> &getResolvedIntColorImage(const TestParams &params)
317     {
318         return params.numIntColorSamples != VK_SAMPLE_COUNT_1_BIT ? intResolve.image : intColor.image;
319     }
getResolvedDepthStencilImagevkt::pipeline::__anonc9ecde940111::WorkingData320     Move<VkImage> &getResolvedDepthStencilImage(const TestParams &params)
321     {
322         return params.numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT ? depthStencilResolve.image : depthStencil.image;
323     }
324 
getResolvedFloatColorImage1Viewvkt::pipeline::__anonc9ecde940111::WorkingData325     Move<VkImageView> &getResolvedFloatColorImage1View(const TestParams &params)
326     {
327         return params.numFloatColor1Samples != VK_SAMPLE_COUNT_1_BIT ? floatResolve1.view : floatColor1.view;
328     }
getResolvedFloatColorImage2Viewvkt::pipeline::__anonc9ecde940111::WorkingData329     Move<VkImageView> &getResolvedFloatColorImage2View(const TestParams &params)
330     {
331         return params.numFloatColor2Samples != VK_SAMPLE_COUNT_1_BIT ? floatResolve2.view : floatColor2.view;
332     }
getResolvedIntColorImageViewvkt::pipeline::__anonc9ecde940111::WorkingData333     Move<VkImageView> &getResolvedIntColorImageView(const TestParams &params)
334     {
335         return params.numIntColorSamples != VK_SAMPLE_COUNT_1_BIT ? intResolve.view : intColor.view;
336     }
getResolvedDepthOnlyImageViewvkt::pipeline::__anonc9ecde940111::WorkingData337     Move<VkImageView> &getResolvedDepthOnlyImageView(const TestParams &params)
338     {
339         // If no depth aspect, return the stencil view just to have something bound in the desc set
340         if (!isDepthFormat(params.depthStencilFormat))
341             return getResolvedStencilOnlyImageView(params);
342         return params.numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT ? depthOnlyResolveImageView : depthOnlyImageView;
343     }
getResolvedStencilOnlyImageViewvkt::pipeline::__anonc9ecde940111::WorkingData344     Move<VkImageView> &getResolvedStencilOnlyImageView(const TestParams &params)
345     {
346         // If no stencil aspect, return the depth view just to have something bound in the desc set
347         if (!isStencilFormat(params.depthStencilFormat))
348             return getResolvedDepthOnlyImageView(params);
349         return params.numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT ? stencilOnlyResolveImageView :
350                                                                         stencilOnlyImageView;
351     }
352 };
353 
354 // Accumulate objects throughout the test to avoid them getting deleted before the command buffer is submitted and waited on.
355 // Speeds up the test by avoiding making multiple submissions and waits.
356 class TestObjects
357 {
358 public:
359     TestObjects(Context &contextIn);
360 
361     void beginCommandBuffer();
362     void submitCommandsAndWait();
363 
364     const Unique<VkCommandPool> cmdPool;
365     const Unique<VkCommandBuffer> cmdBuffer;
366     std::vector<PipelineSp> computePipelines;
367     std::vector<MovePtr<GraphicsPipelineWrapper>> graphicsPipelines;
368     std::vector<Move<VkDescriptorPool>> descriptorPools;
369     std::vector<Move<VkDescriptorSet>> descriptorSets;
370     std::vector<RenderPassWrapper> renderPassFramebuffers;
371     RenderPassWrapper dataRenderPassFramebuffer;
372 
373 private:
374     Context &context;
375 };
376 
377 const VkImageUsageFlags commonImageUsageFlags =
378     VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
379 const VkImageUsageFlags colorImageUsageFlags =
380     commonImageUsageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
381 const VkImageUsageFlags depthStencilImageUsageFlags =
382     commonImageUsageFlags | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
383 
makeImage(const DeviceInterface & vk,const VkDevice device,const VkFormat format,const UVec2 & size,const uint32_t layerCount,const VkSampleCountFlagBits samples,const VkImageUsageFlags usage,const bool usedForMSRTSS)384 Move<VkImage> makeImage(const DeviceInterface &vk, const VkDevice device, const VkFormat format, const UVec2 &size,
385                         const uint32_t layerCount, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage,
386                         const bool usedForMSRTSS)
387 {
388     const VkImageCreateFlags createFlags = samples == VK_SAMPLE_COUNT_1_BIT && usedForMSRTSS ?
389                                                VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT :
390                                                0;
391 
392     const VkImageCreateInfo imageParams = {
393         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
394         DE_NULL,                             // const void* pNext;
395         createFlags,                         // VkImageCreateFlags flags;
396         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
397         format,                              // VkFormat format;
398         makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
399         1u,                                  // uint32_t mipLevels;
400         layerCount,                          // uint32_t arrayLayers;
401         samples,                             // VkSampleCountFlagBits samples;
402         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
403         usage,                               // VkImageUsageFlags usage;
404         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
405         0u,                                  // uint32_t queueFamilyIndexCount;
406         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
407         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
408     };
409     return createImage(vk, device, &imageParams);
410 }
411 
allocate(const DeviceInterface & vk,const VkDevice device,const MovePtr<Allocator> & allocator,const VkFormat format,const UVec2 & size,const VkSampleCountFlagBits samples,const VkImageUsageFlags usage,const VkImageAspectFlags aspect,const uint32_t layerCount,const bool usedForMSRTSS)412 void Image::allocate(const DeviceInterface &vk, const VkDevice device, const MovePtr<Allocator> &allocator,
413                      const VkFormat format, const UVec2 &size, const VkSampleCountFlagBits samples,
414                      const VkImageUsageFlags usage, const VkImageAspectFlags aspect, const uint32_t layerCount,
415                      const bool usedForMSRTSS)
416 {
417     image = makeImage(vk, device, format, size, layerCount, samples, usage, usedForMSRTSS);
418     alloc = bindImage(vk, device, *allocator, *image, MemoryRequirement::Any);
419     view  = makeView(vk, device, format, aspect, layerCount);
420 }
421 
makeView(const DeviceInterface & vk,const VkDevice device,const VkFormat format,const VkImageAspectFlags aspect,const uint32_t layerCount)422 Move<VkImageView> Image::makeView(const DeviceInterface &vk, const VkDevice device, const VkFormat format,
423                                   const VkImageAspectFlags aspect, const uint32_t layerCount)
424 {
425     return makeImageView(vk, device, *image, layerCount > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
426                          format, makeImageSubresourceRange(aspect, 0u, 1u, 0u, layerCount));
427 }
428 
429 //! Create a test-specific MSAA pipeline
makeGraphicsPipeline(const InstanceInterface & vki,const DeviceInterface & vk,const VkPhysicalDevice physicalDevice,const VkDevice device,const std::vector<std::string> & deviceExtensions,const PipelineConstructionType pipelineConstructionType,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,VkPipelineRenderingCreateInfoKHR * pipelineRenderingCreateInfo,const ShaderWrapper vertexModule,const ShaderWrapper fragmentModule,const bool enableBlend,const bool enableDepthStencilWrite,const bool enableDepthTest,const uint32_t intWriteMask,const uint32_t subpassNdx,const int32_t integerAttachmentLocation,const UVec4 & viewportIn,const UVec4 & scissorIn,const VkSampleCountFlagBits numSamples,const bool garbageAttachment,const bool singleAttachment=false)430 MovePtr<GraphicsPipelineWrapper> makeGraphicsPipeline(
431     const InstanceInterface &vki, const DeviceInterface &vk, const VkPhysicalDevice physicalDevice,
432     const VkDevice device, const std::vector<std::string> &deviceExtensions,
433     const PipelineConstructionType pipelineConstructionType, const PipelineLayoutWrapper &pipelineLayout,
434     const VkRenderPass renderPass, VkPipelineRenderingCreateInfoKHR *pipelineRenderingCreateInfo,
435     const ShaderWrapper vertexModule, const ShaderWrapper fragmentModule, const bool enableBlend,
436     const bool enableDepthStencilWrite, const bool enableDepthTest, const uint32_t intWriteMask,
437     const uint32_t subpassNdx, const int32_t integerAttachmentLocation, const UVec4 &viewportIn, const UVec4 &scissorIn,
438     const VkSampleCountFlagBits numSamples, const bool garbageAttachment, const bool singleAttachment = false)
439 {
440     std::vector<VkVertexInputBindingDescription> vertexInputBindingDescriptions;
441     std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions;
442 
443     // Vertex attributes: position
444     vertexInputBindingDescriptions.push_back(
445         makeVertexInputBindingDescription(0u, sizeof(Vec4), VK_VERTEX_INPUT_RATE_VERTEX));
446     vertexInputAttributeDescriptions.push_back(
447         makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u));
448 
449     const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {
450         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,    // VkStructureType sType;
451         DE_NULL,                                                      // const void* pNext;
452         (VkPipelineVertexInputStateCreateFlags)0,                     // VkPipelineVertexInputStateCreateFlags flags;
453         static_cast<uint32_t>(vertexInputBindingDescriptions.size()), // uint32_t vertexBindingDescriptionCount;
454         dataOrNullPtr(
455             vertexInputBindingDescriptions), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
456         static_cast<uint32_t>(vertexInputAttributeDescriptions.size()), // uint32_t vertexAttributeDescriptionCount;
457         dataOrNullPtr(
458             vertexInputAttributeDescriptions), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
459     };
460 
461     const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = {
462         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
463         DE_NULL,                                                     // const void* pNext;
464         (VkPipelineInputAssemblyStateCreateFlags)0,                  // VkPipelineInputAssemblyStateCreateFlags flags;
465         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                         // VkPrimitiveTopology topology;
466         VK_FALSE,                                                    // VkBool32 primitiveRestartEnable;
467     };
468 
469     const std::vector<VkViewport> viewports{{
470         static_cast<float>(viewportIn.x()), static_cast<float>(viewportIn.y()), // x, y
471         static_cast<float>(viewportIn.z()), static_cast<float>(viewportIn.w()), // width, height
472         0.0f, 1.0f                                                              // minDepth, maxDepth
473     }};
474 
475     const std::vector<VkRect2D> scissors = {{
476         makeOffset2D(scissorIn.x(), scissorIn.y()),
477         makeExtent2D(scissorIn.z(), scissorIn.w()),
478     }};
479 
480     const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = {
481         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
482         DE_NULL,                                                    // const void* pNext;
483         (VkPipelineRasterizationStateCreateFlags)0,                 // VkPipelineRasterizationStateCreateFlags flags;
484         VK_FALSE,                                                   // VkBool32 depthClampEnable;
485         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
486         VK_POLYGON_MODE_FILL,                                       // VkPolygonMode polygonMode;
487         VK_CULL_MODE_NONE,                                          // VkCullModeFlags cullMode;
488         VK_FRONT_FACE_COUNTER_CLOCKWISE,                            // VkFrontFace frontFace;
489         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
490         0.0f,                                                       // float depthBiasConstantFactor;
491         0.0f,                                                       // float depthBiasClamp;
492         0.0f,                                                       // float depthBiasSlopeFactor;
493         1.0f,                                                       // float lineWidth;
494     };
495 
496     VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = {
497         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
498         DE_NULL,                                                  // const void* pNext;
499         (VkPipelineMultisampleStateCreateFlags)0,                 // VkPipelineMultisampleStateCreateFlags flags;
500         numSamples,                                               // VkSampleCountFlagBits rasterizationSamples;
501         VK_TRUE,                                                  // VkBool32 sampleShadingEnable;
502         1.0f,                                                     // float minSampleShading;
503         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
504         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
505         VK_FALSE                                                  // VkBool32 alphaToOneEnable;
506     };
507 
508     // Simply increment the buffer
509     const VkStencilOpState stencilOpState =
510         makeStencilOpState(VK_STENCIL_OP_KEEP,                // stencil fail
511                            VK_STENCIL_OP_INCREMENT_AND_CLAMP, // depth & stencil pass
512                            VK_STENCIL_OP_KEEP,                // depth only fail
513                            VK_COMPARE_OP_ALWAYS,              // compare op
514                            ~0u,                               // compare mask
515                            ~0u,                               // write mask
516                            0u);                               // reference
517 
518     // Enable depth write and test if needed
519     VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = {
520         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType sType;
521         DE_NULL,                                                        // const void* pNext;
522         (VkPipelineDepthStencilStateCreateFlags)0,                      // VkPipelineDepthStencilStateCreateFlags flags;
523         VK_TRUE,                                                        // VkBool32 depthTestEnable;
524         enableDepthStencilWrite,                                        // VkBool32 depthWriteEnable;
525         enableDepthTest ? VK_COMPARE_OP_GREATER : VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
526         VK_FALSE,                                                       // VkBool32 depthBoundsTestEnable;
527         VK_TRUE,                                                        // VkBool32 stencilTestEnable;
528         stencilOpState,                                                 // VkStencilOpState front;
529         stencilOpState,                                                 // VkStencilOpState back;
530         0.0f,                                                           // float minDepthBounds;
531         1.0f,                                                           // float maxDepthBounds;
532     };
533 
534     // Always blend by addition.  This is used to verify the combination of multiple draw calls.
535     const VkColorComponentFlags colorComponentsAll =
536         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
537     VkPipelineColorBlendAttachmentState defaultBlendAttachmentState = {
538         enableBlend ? VK_TRUE : VK_FALSE, // VkBool32 blendEnable;
539         VK_BLEND_FACTOR_ONE,              // VkBlendFactor srcColorBlendFactor;
540         VK_BLEND_FACTOR_ONE,              // VkBlendFactor dstColorBlendFactor;
541         VK_BLEND_OP_ADD,                  // VkBlendOp colorBlendOp;
542         VK_BLEND_FACTOR_ONE,              // VkBlendFactor srcAlphaBlendFactor;
543         VK_BLEND_FACTOR_ONE,              // VkBlendFactor dstAlphaBlendFactor;
544         VK_BLEND_OP_ADD,                  // VkBlendOp alphaBlendOp;
545         colorComponentsAll,               // VkColorComponentFlags colorWriteMask;
546     };
547 
548     VkPipelineColorBlendAttachmentState blendAttachmentStates[4] = {
549         defaultBlendAttachmentState,
550         defaultBlendAttachmentState,
551         defaultBlendAttachmentState,
552         defaultBlendAttachmentState,
553     };
554 
555     if (enableBlend && integerAttachmentLocation >= 0)
556     {
557         // Disable blend for the integer attachment unconditionally
558         blendAttachmentStates[integerAttachmentLocation].blendEnable = VK_FALSE;
559         // But emulate it by outputting to one channel only.
560         blendAttachmentStates[integerAttachmentLocation].colorWriteMask =
561             ((intWriteMask & 1) != 0 ? VK_COLOR_COMPONENT_R_BIT : 0) |
562             ((intWriteMask & 2) != 0 ? VK_COLOR_COMPONENT_G_BIT : 0) |
563             ((intWriteMask & 4) != 0 ? VK_COLOR_COMPONENT_B_BIT : 0) |
564             ((intWriteMask & 8) != 0 ? VK_COLOR_COMPONENT_A_BIT : 0);
565         DE_ASSERT(blendAttachmentStates[integerAttachmentLocation].colorWriteMask != 0);
566     }
567 
568     const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = {
569         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
570         DE_NULL,                                                  // const void* pNext;
571         (VkPipelineColorBlendStateCreateFlags)0,                  // VkPipelineColorBlendStateCreateFlags flags;
572         VK_FALSE,                                                 // VkBool32 logicOpEnable;
573         VK_LOGIC_OP_COPY,                                         // VkLogicOp logicOp;
574         singleAttachment ? 1u : 4u,                               // uint32_t attachmentCount;
575         blendAttachmentStates,    // const VkPipelineColorBlendAttachmentState* pAttachments;
576         {0.0f, 0.0f, 0.0f, 0.0f}, // float blendConstants[4];
577     };
578 
579     VkPipelineRenderingCreateInfo pipelineRenderingCreateInfoWithGarbage;
580     std::vector<VkFormat> garbageFormats;
581 
582     if (garbageAttachment)
583     {
584         DE_ASSERT(pipelineRenderingCreateInfo);
585 
586         for (int i = 0; i < 10; i++)
587             garbageFormats.push_back(VK_FORMAT_UNDEFINED);
588 
589         pipelineRenderingCreateInfoWithGarbage = *pipelineRenderingCreateInfo;
590         // Just set a bunch of VK_FORMAT_UNDEFINED for garbage_color_attachment tests to make the validation happy.
591         pipelineRenderingCreateInfoWithGarbage.colorAttachmentCount    = static_cast<uint32_t>(garbageFormats.size());
592         pipelineRenderingCreateInfoWithGarbage.pColorAttachmentFormats = garbageFormats.data();
593     }
594 
595     MovePtr<GraphicsPipelineWrapper> graphicsPipeline = MovePtr<GraphicsPipelineWrapper>(
596         new GraphicsPipelineWrapper(vki, vk, physicalDevice, device, deviceExtensions, pipelineConstructionType, 0u));
597     graphicsPipeline.get()
598         ->setMonolithicPipelineLayout(pipelineLayout)
599         .setupVertexInputState(&vertexInputStateInfo, &pipelineInputAssemblyStateInfo)
600         .setupPreRasterizationShaderState(
601             viewports, scissors, pipelineLayout, renderPass, subpassNdx, vertexModule, &pipelineRasterizationStateInfo,
602             ShaderWrapper(), ShaderWrapper(), ShaderWrapper(), DE_NULL, nullptr,
603             garbageAttachment ? &pipelineRenderingCreateInfoWithGarbage : pipelineRenderingCreateInfo)
604         .setupFragmentShaderState(pipelineLayout, renderPass, subpassNdx, fragmentModule,
605                                   &pipelineDepthStencilStateInfo, &pipelineMultisampleStateInfo)
606         .setRenderingColorAttachmentsInfo(pipelineRenderingCreateInfo)
607         .setupFragmentOutputState(renderPass, subpassNdx, &pipelineColorBlendStateInfo, &pipelineMultisampleStateInfo)
608         .buildPipeline();
609 
610     return graphicsPipeline;
611 }
612 
logTestImages(Context & context,const TestParams & params,WorkingData & wd,const bool drawsToColor1,const bool drawsToColor2,const bool drawsToColor3,const bool drawsToDepthStencil)613 void logTestImages(Context &context, const TestParams &params, WorkingData &wd, const bool drawsToColor1,
614                    const bool drawsToColor2, const bool drawsToColor3, const bool drawsToDepthStencil)
615 {
616     const DeviceInterface &vk    = context.getDeviceInterface();
617     const VkDevice device        = context.getDevice();
618     MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(
619         vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
620     tcu::TestLog &log            = context.getTestContext().getLog();
621 
622     const VkDeviceSize bufferSize[4] = {
623         wd.framebufferSize.x() * wd.framebufferSize.y() * tcu::getPixelSize(mapVkFormat(params.floatColor1Format)),
624         wd.framebufferSize.x() * wd.framebufferSize.y() * tcu::getPixelSize(mapVkFormat(params.floatColor2Format)),
625         wd.framebufferSize.x() * wd.framebufferSize.y() * tcu::getPixelSize(mapVkFormat(params.intColorFormat)),
626         wd.framebufferSize.x() * wd.framebufferSize.y() * tcu::getPixelSize(mapVkFormat(params.depthStencilFormat)),
627     };
628     const Move<VkBuffer> buffer[5] = {
629         makeBuffer(vk, device, bufferSize[0], VK_BUFFER_USAGE_TRANSFER_DST_BIT),
630         makeBuffer(vk, device, bufferSize[1], VK_BUFFER_USAGE_TRANSFER_DST_BIT),
631         makeBuffer(vk, device, bufferSize[2], VK_BUFFER_USAGE_TRANSFER_DST_BIT),
632         makeBuffer(vk, device, bufferSize[3], VK_BUFFER_USAGE_TRANSFER_DST_BIT),
633         makeBuffer(vk, device, bufferSize[3], VK_BUFFER_USAGE_TRANSFER_DST_BIT),
634     };
635     const MovePtr<Allocation> bufferAlloc[5] = {
636         bindBuffer(vk, device, *allocator, *buffer[0], MemoryRequirement::HostVisible),
637         bindBuffer(vk, device, *allocator, *buffer[1], MemoryRequirement::HostVisible),
638         bindBuffer(vk, device, *allocator, *buffer[2], MemoryRequirement::HostVisible),
639         bindBuffer(vk, device, *allocator, *buffer[3], MemoryRequirement::HostVisible),
640         bindBuffer(vk, device, *allocator, *buffer[4], MemoryRequirement::HostVisible),
641     };
642 
643     for (uint32_t bufferNdx = 0; bufferNdx < 5; ++bufferNdx)
644         invalidateAlloc(vk, device, *bufferAlloc[bufferNdx]);
645 
646     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
647                                                           context.getUniversalQueueFamilyIndex()));
648     const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
649 
650     beginCommandBuffer(vk, *cmdBuffer);
651 
652     const IVec2 size(wd.framebufferSize.x(), wd.framebufferSize.y());
653     {
654         if (drawsToColor1)
655             copyImageToBuffer(vk, *cmdBuffer, *wd.getResolvedFloatColorImage1(params), *buffer[0], size,
656                               VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
657         if (drawsToColor2)
658             copyImageToBuffer(vk, *cmdBuffer, *wd.getResolvedFloatColorImage2(params), *buffer[1], size,
659                               VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
660         if (drawsToColor3)
661             copyImageToBuffer(vk, *cmdBuffer, *wd.getResolvedIntColorImage(params), *buffer[2], size,
662                               VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
663 
664         VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
665         if (drawsToDepthStencil && isDepthFormat(params.depthStencilFormat))
666         {
667             copyImageToBuffer(vk, *cmdBuffer, *wd.getResolvedDepthStencilImage(params), *buffer[3], size,
668                               VK_ACCESS_SHADER_WRITE_BIT, depthStencilLayout, 1,
669                               getDepthStencilAspectFlags(params.depthStencilFormat), VK_IMAGE_ASPECT_DEPTH_BIT);
670             depthStencilLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
671         }
672         if (drawsToDepthStencil && isStencilFormat(params.depthStencilFormat))
673         {
674             copyImageToBuffer(vk, *cmdBuffer, *wd.getResolvedDepthStencilImage(params), *buffer[4], size,
675                               VK_ACCESS_SHADER_WRITE_BIT, depthStencilLayout, 1,
676                               getDepthStencilAspectFlags(params.depthStencilFormat), VK_IMAGE_ASPECT_STENCIL_BIT);
677         }
678     }
679 
680     endCommandBuffer(vk, *cmdBuffer);
681     submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
682 
683     // For the D32 depth formats, we specify the texture format directly as tcu::getEffectiveDepthStencilAccess assumes stencil data is interleaved.
684     // For the D24 format however, we have to use tcu::getEffectiveDepthStencilAccess to correctly account for the 8-bit padding.
685     const tcu::TextureFormat copiedDepthFormat = tcu::TextureFormat(
686         tcu::TextureFormat::D,
687         params.depthStencilFormat == VK_FORMAT_D16_UNORM ? tcu::TextureFormat::UNORM_INT16 : tcu::TextureFormat::FLOAT);
688     const tcu::TextureFormat copiedStencilFormat =
689         tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
690 
691     const tcu::ConstPixelBufferAccess testImageData[5] = {
692         {mapVkFormat(params.floatColor1Format), size.x(), size.y(), 1, bufferAlloc[0]->getHostPtr()},
693         {mapVkFormat(params.floatColor2Format), size.x(), size.y(), 1, bufferAlloc[1]->getHostPtr()},
694         {mapVkFormat(params.intColorFormat), size.x(), size.y(), 1, bufferAlloc[2]->getHostPtr()},
695         {copiedDepthFormat, size.x(), size.y(), 1, bufferAlloc[3]->getHostPtr()},
696         {copiedStencilFormat, size.x(), size.y(), 1, bufferAlloc[4]->getHostPtr()},
697     };
698 
699     const tcu::ConstPixelBufferAccess testImageDataD24 = tcu::getEffectiveDepthStencilAccess(
700         tcu::ConstPixelBufferAccess(mapVkFormat(params.depthStencilFormat), size.x(), size.y(), 1,
701                                     bufferAlloc[3]->getHostPtr()),
702         tcu::Sampler::MODE_DEPTH);
703 
704     log << tcu::TestLog::ImageSet("attachments", "attachments");
705     if (drawsToColor1)
706         log << tcu::TestLog::Image("Color attachment 1", "Color attachment 1", testImageData[0]);
707     if (drawsToColor2)
708         log << tcu::TestLog::Image("Color attachment 2", "Color attachment 2", testImageData[1]);
709     if (drawsToColor3)
710         log << tcu::TestLog::Image("Color attachment 3", "Color attachment 3", testImageData[2]);
711     if (isDepthFormat(params.depthStencilFormat))
712         log << tcu::TestLog::Image("Depth attachment", "Depth attachment",
713                                    params.depthStencilFormat == VK_FORMAT_D24_UNORM_S8_UINT ? testImageDataD24 :
714                                                                                               testImageData[3]);
715     if (isStencilFormat(params.depthStencilFormat))
716         log << tcu::TestLog::Image("Stencil attachment", "Stencil attachment", testImageData[4]);
717     log << tcu::TestLog::EndImageSet;
718 }
719 
logVerifyImages(Context & context,const TestParams & params,WorkingData & wd,const bool drawsToColor1,const bool drawsToColor2,const bool drawsToColor3,const bool drawsToDepthStencil)720 void logVerifyImages(Context &context, const TestParams &params, WorkingData &wd, const bool drawsToColor1,
721                      const bool drawsToColor2, const bool drawsToColor3, const bool drawsToDepthStencil)
722 {
723     const DeviceInterface &vk    = context.getDeviceInterface();
724     const VkDevice device        = context.getDevice();
725     MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(
726         vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
727     tcu::TestLog &log            = context.getTestContext().getLog();
728 
729     const VkDeviceSize bufferSize =
730         wd.framebufferSize.x() * wd.framebufferSize.y() * 5 * tcu::getPixelSize(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
731     const Move<VkBuffer> buffer           = makeBuffer(vk, device, bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
732     const MovePtr<Allocation> bufferAlloc = bindBuffer(vk, device, *allocator, *buffer, MemoryRequirement::HostVisible);
733 
734     invalidateAlloc(vk, device, *bufferAlloc);
735 
736     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
737                                                           context.getUniversalQueueFamilyIndex()));
738     const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
739 
740     beginCommandBuffer(vk, *cmdBuffer);
741 
742     copyImageToBuffer(vk, *cmdBuffer, *wd.verify.image, *buffer, IVec2(wd.framebufferSize.x(), wd.framebufferSize.y()),
743                       VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, 5);
744 
745     endCommandBuffer(vk, *cmdBuffer);
746     submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
747 
748     const tcu::ConstPixelBufferAccess verifyImageData(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), wd.framebufferSize.x(),
749                                                       wd.framebufferSize.y(), 5, bufferAlloc->getHostPtr());
750 
751     log << tcu::TestLog::ImageSet("attachment error mask", "attachment error mask");
752     if (drawsToColor1)
753         log << tcu::TestLog::Image(
754             "ErrorMask color attachment 1", "Error mask color attachment 1",
755             tcu::getSubregion(verifyImageData, 0, 0, 0, wd.framebufferSize.x(), wd.framebufferSize.y(), 1));
756     if (drawsToColor2)
757         log << tcu::TestLog::Image(
758             "ErrorMask color attachment 2", "Error mask color attachment 2",
759             tcu::getSubregion(verifyImageData, 0, 0, 1, wd.framebufferSize.x(), wd.framebufferSize.y(), 1));
760     if (drawsToColor3)
761         log << tcu::TestLog::Image(
762             "ErrorMask color attachment 3", "Error mask color attachment 3",
763             tcu::getSubregion(verifyImageData, 0, 0, 2, wd.framebufferSize.x(), wd.framebufferSize.y(), 1));
764     if (drawsToDepthStencil && isDepthFormat(params.depthStencilFormat))
765         log << tcu::TestLog::Image(
766             "ErrorMask depth attachment", "Error mask depth attachment",
767             tcu::getSubregion(verifyImageData, 0, 0, 3, wd.framebufferSize.x(), wd.framebufferSize.y(), 1));
768     if (drawsToDepthStencil && isStencilFormat(params.depthStencilFormat))
769         log << tcu::TestLog::Image(
770             "ErrorMask stencil attachment", "Error mask stencil attachment",
771             tcu::getSubregion(verifyImageData, 0, 0, 4, wd.framebufferSize.x(), wd.framebufferSize.y(), 1));
772     log << tcu::TestLog::EndImageSet;
773 }
774 
checkAndReportError(Context & context,const uint32_t verifiedPixelCount,const uint32_t expectedPixelCount,const std::string & attachment)775 bool checkAndReportError(Context &context, const uint32_t verifiedPixelCount, const uint32_t expectedPixelCount,
776                          const std::string &attachment)
777 {
778     tcu::TestLog &log = context.getTestContext().getLog();
779 
780     bool passed = verifiedPixelCount == expectedPixelCount;
781 
782     if (passed)
783         log << tcu::TestLog::Message << "Verification passed for " << attachment << tcu::TestLog::EndMessage;
784     else
785         log << tcu::TestLog::Message << "Verification failed for " << attachment << " for "
786             << (expectedPixelCount - verifiedPixelCount) << " pixel(s)" << tcu::TestLog::EndMessage;
787 
788     return passed;
789 }
790 
checkSampleRequirements(Context & context,const VkSampleCountFlagBits numSamples,const bool checkColor,const bool checkDepth,const bool checkStencil)791 void checkSampleRequirements(Context &context, const VkSampleCountFlagBits numSamples, const bool checkColor,
792                              const bool checkDepth, const bool checkStencil)
793 {
794     const VkPhysicalDeviceLimits &limits = context.getDeviceProperties().limits;
795 
796     if (checkColor && (limits.framebufferColorSampleCounts & numSamples) == 0u)
797         TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
798 
799     if (checkDepth && (limits.framebufferDepthSampleCounts & numSamples) == 0u)
800         TCU_THROW(NotSupportedError, "framebufferDepthSampleCounts: sample count not supported");
801 
802     if (checkStencil && (limits.framebufferStencilSampleCounts & numSamples) == 0u)
803         TCU_THROW(NotSupportedError, "framebufferStencilSampleCounts: sample count not supported");
804 }
805 
checkImageRequirements(Context & context,const VkFormat format,const VkFormatFeatureFlags requiredFeatureFlags,const VkImageUsageFlags requiredUsageFlags,const VkSampleCountFlagBits requiredSampleCount,VkImageFormatProperties & imageProperties)806 void checkImageRequirements(Context &context, const VkFormat format, const VkFormatFeatureFlags requiredFeatureFlags,
807                             const VkImageUsageFlags requiredUsageFlags, const VkSampleCountFlagBits requiredSampleCount,
808                             VkImageFormatProperties &imageProperties)
809 {
810     const InstanceInterface &vki          = context.getInstanceInterface();
811     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
812 
813     const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
814 
815     if ((formatProperties.optimalTilingFeatures & requiredFeatureFlags) != requiredFeatureFlags)
816         TCU_THROW(NotSupportedError, (de::toString(format) + ": format features not supported").c_str());
817 
818     const VkImageCreateFlags createFlags = requiredSampleCount == VK_SAMPLE_COUNT_1_BIT ?
819                                                VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT :
820                                                0;
821 
822     const VkResult result =
823         vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
824                                                    requiredUsageFlags, createFlags, &imageProperties);
825 
826     if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
827         TCU_THROW(NotSupportedError, (de::toString(format) + ": format not supported").c_str());
828 
829     if ((imageProperties.sampleCounts & requiredSampleCount) != requiredSampleCount)
830         TCU_THROW(NotSupportedError, (de::toString(format) + ": sample count not supported").c_str());
831 }
832 
TestObjects(Context & contextIn)833 TestObjects::TestObjects(Context &contextIn)
834     : cmdPool(createCommandPool(contextIn.getDeviceInterface(), contextIn.getDevice(),
835                                 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
836                                 contextIn.getUniversalQueueFamilyIndex()))
837     , cmdBuffer(makeCommandBuffer(contextIn.getDeviceInterface(), contextIn.getDevice(), *cmdPool))
838     , context(contextIn)
839 {
840 }
841 
beginCommandBuffer()842 void TestObjects::beginCommandBuffer()
843 {
844     const DeviceInterface &vk = context.getDeviceInterface();
845 
846     vk::beginCommandBuffer(vk, *cmdBuffer);
847 }
848 
submitCommandsAndWait()849 void TestObjects::submitCommandsAndWait()
850 {
851     const DeviceInterface &vk = context.getDeviceInterface();
852     const VkDevice device     = context.getDevice();
853 
854     VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
855     vk::submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
856 }
857 
initializeAttachments(const TestParams & params,WorkingData & wd,std::vector<VkImage> & images,std::vector<VkImageView> & attachments,const size_t passNdx,int32_t attachmentNdxes[8])858 void initializeAttachments(const TestParams &params, WorkingData &wd, std::vector<VkImage> &images,
859                            std::vector<VkImageView> &attachments, const size_t passNdx, int32_t attachmentNdxes[8])
860 {
861     const bool includeAll = passNdx >= params.perPass.size();
862     int32_t currentNdx    = 0;
863 
864     // Output attachments
865     if (includeAll || params.usesColor1InPass(passNdx))
866     {
867         images.push_back(wd.floatColor1.image.get());
868         attachments.push_back(wd.floatColor1.view.get());
869         attachmentNdxes[0] = currentNdx++;
870     }
871     if (includeAll || params.usesColor2InPass(passNdx))
872     {
873         images.push_back(wd.floatColor2.image.get());
874         attachments.push_back(wd.floatColor2.view.get());
875         attachmentNdxes[1] = currentNdx++;
876     }
877     if (includeAll || params.usesColor3InPass(passNdx))
878     {
879         images.push_back(wd.intColor.image.get());
880         attachments.push_back(wd.intColor.view.get());
881         attachmentNdxes[2] = currentNdx++;
882     }
883     if (includeAll || params.usesDepthStencilInPass(passNdx))
884     {
885         images.push_back(wd.depthStencil.image.get());
886         attachments.push_back(wd.depthStencil.view.get());
887         attachmentNdxes[3] = currentNdx++;
888     }
889 
890     // Resolve attachments
891     if (params.numFloatColor1Samples != VK_SAMPLE_COUNT_1_BIT && (includeAll || params.usesColor1InPass(passNdx)))
892     {
893         images.push_back(wd.floatResolve1.image.get());
894         attachments.push_back(wd.floatResolve1.view.get());
895         attachmentNdxes[4] = currentNdx++;
896     }
897     if (params.numFloatColor2Samples != VK_SAMPLE_COUNT_1_BIT && (includeAll || params.usesColor2InPass(passNdx)))
898     {
899         images.push_back(wd.floatResolve2.image.get());
900         attachments.push_back(wd.floatResolve2.view.get());
901         attachmentNdxes[5] = currentNdx++;
902     }
903     if (params.numIntColorSamples != VK_SAMPLE_COUNT_1_BIT && (includeAll || params.usesColor3InPass(passNdx)))
904     {
905         images.push_back(wd.intResolve.image.get());
906         attachments.push_back(wd.intResolve.view.get());
907         attachmentNdxes[6] = currentNdx++;
908     }
909     if (params.numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT &&
910         (includeAll || params.usesDepthStencilInPass(passNdx)))
911     {
912         images.push_back(wd.depthStencilResolve.image.get());
913         attachments.push_back(wd.depthStencilResolve.view.get());
914         attachmentNdxes[7] = currentNdx++;
915     }
916 }
917 
initializeAttachmentDescriptions(const TestParams & params,std::vector<VkAttachmentDescription2> & descs,const bool preCleared,const int32_t attachmentNdxes[8],uint32_t & attachmentUseMask)918 void initializeAttachmentDescriptions(const TestParams &params, std::vector<VkAttachmentDescription2> &descs,
919                                       const bool preCleared, const int32_t attachmentNdxes[8],
920                                       uint32_t &attachmentUseMask)
921 {
922     // The attachments are either cleared already or should be cleared now.  If an attachment was used in a previous render pass,
923     // it will override these values to always LOAD and use the SHADER_READ_ONLY layout.  It's SHADER_READ_ONLY because final layout
924     // is always that for simplicity.
925     const VkAttachmentLoadOp loadOp   = preCleared ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
926     const VkImageLayout initialLayout = preCleared ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
927 
928     // Output attachments
929     if (attachmentNdxes[0] >= 0)
930     {
931         descs.push_back(VkAttachmentDescription2{
932             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                  sType;
933             DE_NULL,                                    // const void*                      pNext;
934             (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags flags;
935             params.floatColor1Format,                   // VkFormat format;
936             params.numFloatColor1Samples,               // VkSampleCountFlagBits samples;
937             (attachmentUseMask & (1 << 0)) != 0 ? VK_ATTACHMENT_LOAD_OP_LOAD : loadOp, // VkAttachmentLoadOp loadOp;
938             VK_ATTACHMENT_STORE_OP_STORE,                                              // VkAttachmentStoreOp storeOp;
939             VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // VkAttachmentLoadOp stencilLoadOp;
940             VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
941             (attachmentUseMask & (1 << 0)) != 0 ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
942                                                   initialLayout, // VkImageLayout initialLayout;
943             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL             // VkImageLayout finalLayout;
944         });
945         attachmentUseMask |= 1 << 0;
946     }
947 
948     if (attachmentNdxes[1] >= 0)
949     {
950         descs.push_back(VkAttachmentDescription2{
951             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                  sType;
952             DE_NULL,                                    // const void*                      pNext;
953             (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags flags;
954             params.floatColor2Format,                   // VkFormat format;
955             params.numFloatColor2Samples,               // VkSampleCountFlagBits samples;
956             (attachmentUseMask & (1 << 1)) != 0 ? VK_ATTACHMENT_LOAD_OP_LOAD : loadOp, // VkAttachmentLoadOp loadOp;
957             VK_ATTACHMENT_STORE_OP_STORE,                                              // VkAttachmentStoreOp storeOp;
958             VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // VkAttachmentLoadOp stencilLoadOp;
959             VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
960             (attachmentUseMask & (1 << 1)) != 0 ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
961                                                   initialLayout, // VkImageLayout initialLayout;
962             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL             // VkImageLayout finalLayout;
963         });
964         attachmentUseMask |= 1 << 1;
965     }
966 
967     if (attachmentNdxes[2] >= 0)
968     {
969         descs.push_back(VkAttachmentDescription2{
970             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                  sType;
971             DE_NULL,                                    // const void*                      pNext;
972             (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags flags;
973             params.intColorFormat,                      // VkFormat format;
974             params.numIntColorSamples,                  // VkSampleCountFlagBits samples;
975             (attachmentUseMask & (1 << 2)) != 0 ? VK_ATTACHMENT_LOAD_OP_LOAD : loadOp, // VkAttachmentLoadOp loadOp;
976             VK_ATTACHMENT_STORE_OP_STORE,                                              // VkAttachmentStoreOp storeOp;
977             VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // VkAttachmentLoadOp stencilLoadOp;
978             VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
979             (attachmentUseMask & (1 << 2)) != 0 ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
980                                                   initialLayout, // VkImageLayout initialLayout;
981             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL             // VkImageLayout finalLayout;
982         });
983         attachmentUseMask |= 1 << 2;
984     }
985 
986     if (attachmentNdxes[3] >= 0)
987     {
988         descs.push_back(VkAttachmentDescription2{
989             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                  sType;
990             DE_NULL,                                    // const void*                      pNext;
991             (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags flags;
992             params.depthStencilFormat,                  // VkFormat format;
993             params.numDepthStencilSamples,              // VkSampleCountFlagBits samples;
994             (attachmentUseMask & (1 << 3)) != 0 ? VK_ATTACHMENT_LOAD_OP_LOAD : loadOp, // VkAttachmentLoadOp loadOp;
995             VK_ATTACHMENT_STORE_OP_STORE,                                              // VkAttachmentStoreOp storeOp;
996             (attachmentUseMask & (1 << 3)) != 0 ? VK_ATTACHMENT_LOAD_OP_LOAD :
997                                                   loadOp, // VkAttachmentLoadOp stencilLoadOp;
998             VK_ATTACHMENT_STORE_OP_STORE,                 // VkAttachmentStoreOp stencilStoreOp;
999             (attachmentUseMask & (1 << 3)) != 0 ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL :
1000                                                   initialLayout, // VkImageLayout initialLayout;
1001             VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL      // VkImageLayout finalLayout;
1002         });
1003         attachmentUseMask |= 1 << 3;
1004     }
1005 
1006     // Resolve attachments
1007     if (attachmentNdxes[4] >= 0)
1008         descs.push_back(VkAttachmentDescription2{
1009             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                  sType;
1010             DE_NULL,                                    // const void*                      pNext;
1011             (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags flags;
1012             params.floatColor1Format,                   // VkFormat format;
1013             VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
1014             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp loadOp;
1015             VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp storeOp;
1016             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp stencilLoadOp;
1017             VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp stencilStoreOp;
1018             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout initialLayout;
1019             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL    // VkImageLayout finalLayout;
1020         });
1021 
1022     if (attachmentNdxes[5] >= 0)
1023         descs.push_back(VkAttachmentDescription2{
1024             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                  sType;
1025             DE_NULL,                                    // const void*                      pNext;
1026             (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags flags;
1027             params.floatColor2Format,                   // VkFormat format;
1028             VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
1029             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp loadOp;
1030             VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp storeOp;
1031             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp stencilLoadOp;
1032             VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp stencilStoreOp;
1033             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout initialLayout;
1034             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL    // VkImageLayout finalLayout;
1035         });
1036 
1037     if (attachmentNdxes[6] >= 0)
1038         descs.push_back(VkAttachmentDescription2{
1039             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                  sType;
1040             DE_NULL,                                    // const void*                      pNext;
1041             (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags flags;
1042             params.intColorFormat,                      // VkFormat format;
1043             VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
1044             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp loadOp;
1045             VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp storeOp;
1046             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp stencilLoadOp;
1047             VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp stencilStoreOp;
1048             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout initialLayout;
1049             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL    // VkImageLayout finalLayout;
1050         });
1051 
1052     if (attachmentNdxes[7] >= 0)
1053         descs.push_back(VkAttachmentDescription2{
1054             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,     // VkStructureType                  sType;
1055             DE_NULL,                                        // const void*                      pNext;
1056             (VkAttachmentDescriptionFlags)0,                // VkAttachmentDescriptionFlags flags;
1057             params.depthStencilFormat,                      // VkFormat format;
1058             VK_SAMPLE_COUNT_1_BIT,                          // VkSampleCountFlagBits samples;
1059             VK_ATTACHMENT_LOAD_OP_DONT_CARE,                // VkAttachmentLoadOp loadOp;
1060             VK_ATTACHMENT_STORE_OP_STORE,                   // VkAttachmentStoreOp storeOp;
1061             VK_ATTACHMENT_LOAD_OP_DONT_CARE,                // VkAttachmentLoadOp stencilLoadOp;
1062             VK_ATTACHMENT_STORE_OP_STORE,                   // VkAttachmentStoreOp stencilStoreOp;
1063             VK_IMAGE_LAYOUT_UNDEFINED,                      // VkImageLayout initialLayout;
1064             VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL // VkImageLayout finalLayout;
1065         });
1066 }
1067 
initializeRenderingAttachmentInfos(const TestParams & params,WorkingData & wd,std::vector<VkRenderingAttachmentInfo> & colorAttachmentInfos,VkRenderingAttachmentInfo & depthStencilAttachmentInfo,std::vector<VkFormat> & colorAttachmentFormats,const int32_t attachmentNdxes[8],uint32_t & attachmentUseMask,uint32_t passNdx)1068 void initializeRenderingAttachmentInfos(const TestParams &params, WorkingData &wd,
1069                                         std::vector<VkRenderingAttachmentInfo> &colorAttachmentInfos,
1070                                         VkRenderingAttachmentInfo &depthStencilAttachmentInfo,
1071                                         std::vector<VkFormat> &colorAttachmentFormats, const int32_t attachmentNdxes[8],
1072                                         uint32_t &attachmentUseMask, uint32_t passNdx)
1073 {
1074     // The attachments are either cleared already or should be cleared now. If an attachment was used in a previous render pass,
1075     // it will override these values to always LOAD and use the SHADER_READ_ONLY layout. It's SHADER_READ_ONLY because final layout
1076     // is always that for simplicity.
1077     const VkAttachmentLoadOp loadOp =
1078         params.clearBeforeRenderPass ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
1079     const TestParams::PerPass &perPass = params.perPass[passNdx];
1080 
1081     const VkRenderingAttachmentInfo emptyRenderingAttachmentInfo = {
1082         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType            sType
1083         DE_NULL,                                     // const void*                pNext
1084         DE_NULL,                                     // VkImageView                imageView
1085         VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout            imageLayout
1086         VK_RESOLVE_MODE_NONE,                        // VkResolveModeFlagBits    resolveMode
1087         DE_NULL,                                     // VkImageView                resolveImageView
1088         VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout            resolveImageLayout
1089         VK_ATTACHMENT_LOAD_OP_DONT_CARE,             // VkAttachmentLoadOp        loadOp
1090         VK_ATTACHMENT_STORE_OP_DONT_CARE,            // VkAttachmentStoreOp        storeOp
1091         params.clearValues[0]                        // VkClearValue                clearValue
1092     };
1093 
1094     for (auto &colorAttachmentInfo : colorAttachmentInfos)
1095     {
1096         colorAttachmentInfo = emptyRenderingAttachmentInfo;
1097     }
1098 
1099     // Output attachments
1100     if (attachmentNdxes[0] >= 0)
1101     {
1102         VkRenderingAttachmentInfo renderingAttachmentInfo = {
1103             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType            sType
1104             DE_NULL,                                     // const void*                pNext
1105             wd.floatColor1.view.get(),                   // VkImageView                imageView
1106             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,    // VkImageLayout            imageLayout
1107             VK_RESOLVE_MODE_NONE,                        // VkResolveModeFlagBits    resolveMode
1108             DE_NULL,                                     // VkImageView                resolveImageView
1109             VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout            resolveImageLayout
1110             (attachmentUseMask & (1 << 0)) != 0 ? VK_ATTACHMENT_LOAD_OP_LOAD :
1111                                                   loadOp, // VkAttachmentLoadOp        loadOp
1112             VK_ATTACHMENT_STORE_OP_STORE,                 // VkAttachmentStoreOp        storeOp
1113             params.clearValues[0]                         // VkClearValue                clearValue
1114         };
1115 
1116         // Enable resolve image if it's used.
1117         if (attachmentNdxes[4] >= 0)
1118         {
1119             renderingAttachmentInfo.resolveMode        = VK_RESOLVE_MODE_AVERAGE_BIT;
1120             renderingAttachmentInfo.resolveImageView   = wd.floatResolve1.view.get();
1121             renderingAttachmentInfo.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1122         }
1123         else if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
1124         {
1125             renderingAttachmentInfo.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
1126         }
1127 
1128         colorAttachmentInfos[perPass.floatColor1Location]   = renderingAttachmentInfo;
1129         colorAttachmentFormats[perPass.floatColor1Location] = params.floatColor1Format;
1130         attachmentUseMask |= 1 << 0;
1131     }
1132 
1133     if (attachmentNdxes[1] >= 0)
1134     {
1135         VkRenderingAttachmentInfo renderingAttachmentInfo = {
1136             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType            sType
1137             DE_NULL,                                     // const void*                pNext
1138             wd.floatColor2.view.get(),                   // VkImageView                imageView
1139             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,    // VkImageLayout            imageLayout
1140             VK_RESOLVE_MODE_NONE,                        // VkResolveModeFlagBits    resolveMode
1141             DE_NULL,                                     // VkImageView                resolveImageView
1142             VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout            resolveImageLayout
1143             (attachmentUseMask & (1 << 1)) != 0 ? VK_ATTACHMENT_LOAD_OP_LOAD :
1144                                                   loadOp, // VkAttachmentLoadOp        loadOp
1145             VK_ATTACHMENT_STORE_OP_STORE,                 // VkAttachmentStoreOp        storeOp
1146             params.clearValues[1]                         // VkClearValue                clearValue
1147         };
1148 
1149         if (attachmentNdxes[5] >= 0)
1150         {
1151             renderingAttachmentInfo.resolveMode        = VK_RESOLVE_MODE_AVERAGE_BIT;
1152             renderingAttachmentInfo.resolveImageView   = wd.floatResolve2.view.get();
1153             renderingAttachmentInfo.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1154         }
1155         else if (params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT)
1156         {
1157             renderingAttachmentInfo.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
1158         }
1159 
1160         colorAttachmentInfos[perPass.floatColor2Location]   = renderingAttachmentInfo;
1161         colorAttachmentFormats[perPass.floatColor2Location] = params.floatColor2Format;
1162         attachmentUseMask |= 1 << 1;
1163     }
1164 
1165     if (attachmentNdxes[2] >= 0)
1166     {
1167         VkRenderingAttachmentInfo renderingAttachmentInfo = {
1168             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType            sType
1169             DE_NULL,                                     // const void*                pNext
1170             wd.intColor.view.get(),                      // VkImageView                imageView
1171             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,    // VkImageLayout            imageLayout
1172             VK_RESOLVE_MODE_NONE,                        // VkResolveModeFlagBits    resolveMode
1173             DE_NULL,                                     // VkImageView                resolveImageView
1174             VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout            resolveImageLayout
1175             (attachmentUseMask & (1 << 2)) != 0 ? VK_ATTACHMENT_LOAD_OP_LOAD :
1176                                                   loadOp, // VkAttachmentLoadOp        loadOp
1177             VK_ATTACHMENT_STORE_OP_STORE,                 // VkAttachmentStoreOp        storeOp
1178             params.clearValues[2]                         // VkClearValue                clearValue
1179         };
1180 
1181         if (attachmentNdxes[6] >= 0)
1182         {
1183             renderingAttachmentInfo.resolveMode        = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1184             renderingAttachmentInfo.resolveImageView   = wd.intResolve.view.get();
1185             renderingAttachmentInfo.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1186         }
1187         else if (params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT)
1188         {
1189             renderingAttachmentInfo.resolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1190         }
1191 
1192         colorAttachmentInfos[perPass.intColorLocation]   = renderingAttachmentInfo;
1193         colorAttachmentFormats[perPass.intColorLocation] = params.intColorFormat;
1194         attachmentUseMask |= 1 << 2;
1195     }
1196 
1197     if (attachmentNdxes[3] >= 0)
1198     {
1199 
1200         VkRenderingAttachmentInfo renderingAttachmentInfo = {
1201             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,      // VkStructureType            sType
1202             DE_NULL,                                          // const void*                pNext
1203             wd.depthStencil.view.get(),                       // VkImageView                imageView
1204             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout            imageLayout
1205             VK_RESOLVE_MODE_NONE,                             // VkResolveModeFlagBits    resolveMode
1206             DE_NULL,                                          // VkImageView                resolveImageView
1207             VK_IMAGE_LAYOUT_UNDEFINED,                        // VkImageLayout            resolveImageLayout
1208             (attachmentUseMask & (1 << 3)) != 0 ? VK_ATTACHMENT_LOAD_OP_LOAD :
1209                                                   loadOp, // VkAttachmentLoadOp        loadOp
1210             VK_ATTACHMENT_STORE_OP_STORE,                 // VkAttachmentStoreOp        storeOp
1211             params.clearValues[3]                         // VkClearValue                clearValue
1212         };
1213 
1214         if (attachmentNdxes[7] >= 0)
1215         {
1216             renderingAttachmentInfo.resolveMode        = params.perPass[passNdx].depthStencilResolveMode;
1217             renderingAttachmentInfo.resolveImageView   = wd.depthStencilResolve.view.get();
1218             renderingAttachmentInfo.resolveImageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1219         }
1220         else if (params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT)
1221         {
1222             renderingAttachmentInfo.resolveMode = params.perPass[passNdx].depthStencilResolveMode;
1223         }
1224 
1225         depthStencilAttachmentInfo = renderingAttachmentInfo;
1226         attachmentUseMask |= 1 << 3;
1227     }
1228 }
1229 
initResolveImageLayouts(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)1230 void initResolveImageLayouts(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects)
1231 {
1232     const DeviceInterface &vk                       = context.getDeviceInterface();
1233     const VkImageMemoryBarrier imageBarrierTemplate = {
1234         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType
1235         DE_NULL,                                // const void*                pNext
1236         0,                                      // VkAccessFlags            srcAccessMask
1237         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1238             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags            dstAccessMask
1239         VK_IMAGE_LAYOUT_UNDEFINED,                        // VkImageLayout            oldLayout
1240         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,         // VkImageLayout            newLayout
1241         VK_QUEUE_FAMILY_IGNORED,                          // uint32_t                    srcQueueFamilyIndex
1242         VK_QUEUE_FAMILY_IGNORED,                          // uint32_t                    dstQueueFamilyIndex
1243         0,                                                // VkImage                    image
1244         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,
1245                                   1u), // VkImageSubresourceRange    subresourceRange
1246     };
1247 
1248     std::vector<VkImageMemoryBarrier> barriers;
1249 
1250     if (wd.floatResolve1.image)
1251     {
1252         barriers.push_back(imageBarrierTemplate);
1253         barriers.back().image = *wd.floatResolve1.image;
1254     }
1255 
1256     if (wd.floatResolve2.image)
1257     {
1258         barriers.push_back(imageBarrierTemplate);
1259         barriers.back().image = *wd.floatResolve2.image;
1260     }
1261 
1262     if (wd.intResolve.image)
1263     {
1264         barriers.push_back(imageBarrierTemplate);
1265         barriers.back().image = *wd.intResolve.image;
1266     }
1267 
1268     if (wd.depthStencilResolve.image)
1269     {
1270         barriers.push_back(imageBarrierTemplate);
1271         barriers.back().image                       = *wd.depthStencilResolve.image;
1272         barriers.back().newLayout                   = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1273         barriers.back().subresourceRange.aspectMask = getDepthStencilAspectFlags(params.depthStencilFormat);
1274     }
1275 
1276     if (!barriers.empty())
1277     {
1278         vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1279                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1280                               0u, 0u, DE_NULL, 0u, DE_NULL, static_cast<uint32_t>(barriers.size()), barriers.data());
1281     }
1282 }
1283 
preRenderingImageLayoutTransition(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)1284 void preRenderingImageLayoutTransition(Context &context, const TestParams &params, WorkingData &wd,
1285                                        TestObjects &testObjects)
1286 {
1287     const DeviceInterface &vk = context.getDeviceInterface();
1288     const bool preCleared     = params.clearBeforeRenderPass;
1289 
1290     const VkImageMemoryBarrier imageBarrierTemplate = {
1291         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType;
1292         DE_NULL,                                // const void*                pNext;
1293         preCleared ? (VkAccessFlags)VK_ACCESS_TRANSFER_WRITE_BIT :
1294                      (VkAccessFlags)0, // VkAccessFlags              srcAccessMask;
1295         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1296             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags              dstAccessMask;
1297         preCleared ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL :
1298                      VK_IMAGE_LAYOUT_UNDEFINED,   // VkImageLayout              oldLayout;
1299         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout              newLayout;
1300         VK_QUEUE_FAMILY_IGNORED,                  // uint32_t                   srcQueueFamilyIndex;
1301         VK_QUEUE_FAMILY_IGNORED,                  // uint32_t                   dstQueueFamilyIndex;
1302         0,                                        // VkImage                    image;
1303         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,
1304                                   1u), // VkImageSubresourceRange    subresourceRange;
1305     };
1306 
1307     VkImageMemoryBarrier barriers[4] = {imageBarrierTemplate, imageBarrierTemplate, imageBarrierTemplate,
1308                                         imageBarrierTemplate};
1309     barriers[0].image                = *wd.floatColor1.image;
1310     barriers[1].image                = *wd.floatColor2.image;
1311     barriers[2].image                = *wd.intColor.image;
1312     barriers[3].image                = *wd.depthStencil.image;
1313     barriers[3].dstAccessMask =
1314         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1315     barriers[3].newLayout                   = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1316     barriers[3].subresourceRange.aspectMask = getDepthStencilAspectFlags(params.depthStencilFormat);
1317 
1318     vk.cmdPipelineBarrier(*testObjects.cmdBuffer,
1319                           preCleared ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1320                           VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
1321                               VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1322                           0u, 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1323 }
1324 
postRenderingResolveImageLayoutTransition(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)1325 void postRenderingResolveImageLayoutTransition(Context &context, const TestParams &params, WorkingData &wd,
1326                                                TestObjects &testObjects)
1327 {
1328     const DeviceInterface &vk                       = context.getDeviceInterface();
1329     const VkImageMemoryBarrier imageBarrierTemplate = {
1330         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType
1331         DE_NULL,                                // const void*                pNext
1332         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1333             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags            srcAccessMask
1334         VK_ACCESS_SHADER_READ_BIT,                        // VkAccessFlags            dstAccessMask
1335         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,         // VkImageLayout            oldLayout
1336         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,         // VkImageLayout            newLayout
1337         VK_QUEUE_FAMILY_IGNORED,                          // uint32_t                    srcQueueFamilyIndex
1338         VK_QUEUE_FAMILY_IGNORED,                          // uint32_t                    dstQueueFamilyIndex
1339         0,                                                // VkImage                    image
1340         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,
1341                                   1u), // VkImageSubresourceRange    subresourceRange
1342     };
1343 
1344     std::vector<VkImageMemoryBarrier> barriers;
1345 
1346     if (wd.floatResolve1.image)
1347     {
1348         barriers.push_back(imageBarrierTemplate);
1349         barriers.back().image = *wd.floatResolve1.image;
1350     }
1351 
1352     if (wd.floatResolve2.image)
1353     {
1354         barriers.push_back(imageBarrierTemplate);
1355         barriers.back().image = *wd.floatResolve2.image;
1356     }
1357 
1358     if (wd.intResolve.image)
1359     {
1360         barriers.push_back(imageBarrierTemplate);
1361         barriers.back().image = *wd.intResolve.image;
1362     }
1363 
1364     if (wd.depthStencilResolve.image)
1365     {
1366         barriers.push_back(imageBarrierTemplate);
1367         barriers.back().image                       = *wd.depthStencilResolve.image;
1368         barriers.back().oldLayout                   = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1369         barriers.back().newLayout                   = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
1370         barriers.back().subresourceRange.aspectMask = getDepthStencilAspectFlags(params.depthStencilFormat);
1371     }
1372 
1373     if (!barriers.empty())
1374     {
1375         vk.cmdPipelineBarrier(*testObjects.cmdBuffer,
1376                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1377                               VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
1378                               static_cast<uint32_t>(barriers.size()), barriers.data());
1379     }
1380 }
1381 
preinitializeAttachmentReferences(std::vector<VkAttachmentReference2> & references,const uint32_t count)1382 void preinitializeAttachmentReferences(std::vector<VkAttachmentReference2> &references, const uint32_t count)
1383 {
1384     references.resize(count, VkAttachmentReference2{
1385                                  VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType       sType;
1386                                  DE_NULL,                                  // const void*           pNext;
1387                                  VK_ATTACHMENT_UNUSED,                     // uint32_t              attachment;
1388                                  VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout         layout;
1389                                  0,                                        // VkImageAspectFlags    aspectMask;
1390                              });
1391 }
1392 
initializeAttachmentReference(VkAttachmentReference2 & reference,uint32_t attachment,const VkFormat depthStencilFormat,const bool isInputAttachment)1393 void initializeAttachmentReference(VkAttachmentReference2 &reference, uint32_t attachment,
1394                                    const VkFormat depthStencilFormat, const bool isInputAttachment)
1395 {
1396     const bool isColor = depthStencilFormat == VK_FORMAT_UNDEFINED;
1397 
1398     reference.attachment = attachment;
1399     reference.layout     = isInputAttachment ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
1400                            isColor           ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL :
1401                                                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1402     reference.aspectMask =
1403         isColor ? VkImageAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT) : getDepthStencilAspectFlags(depthStencilFormat);
1404 }
1405 
isInAttachmentReferences(const std::vector<VkAttachmentReference2> & references,const int32_t attachment)1406 bool isInAttachmentReferences(const std::vector<VkAttachmentReference2> &references, const int32_t attachment)
1407 {
1408     for (const VkAttachmentReference2 &reference : references)
1409         if (reference.attachment == static_cast<uint32_t>(attachment))
1410             return true;
1411 
1412     return false;
1413 }
1414 
addSubpassDescription(const TestParams & params,const uint32_t passNdx,std::vector<VkAttachmentReference2> & attachmentReferences,std::vector<VkAttachmentReference2> & resolveAttachmentReferences,VkSubpassDescriptionDepthStencilResolve & depthStencilResolve,std::vector<uint32_t> * preserveAttachments,VkMultisampledRenderToSingleSampledInfoEXT & msrtss,std::vector<VkSubpassDescription2> & subpasses,const std::vector<VkAttachmentReference2> & inputAttachmentReferences,const int32_t attachmentNdxes[8])1415 void addSubpassDescription(
1416     const TestParams &params, const uint32_t passNdx, std::vector<VkAttachmentReference2> &attachmentReferences,
1417     std::vector<VkAttachmentReference2> &resolveAttachmentReferences,
1418     VkSubpassDescriptionDepthStencilResolve &depthStencilResolve, std::vector<uint32_t> *preserveAttachments,
1419     VkMultisampledRenderToSingleSampledInfoEXT &msrtss, std::vector<VkSubpassDescription2> &subpasses,
1420     const std::vector<VkAttachmentReference2> &inputAttachmentReferences, const int32_t attachmentNdxes[8])
1421 {
1422     const TestParams::PerPass &perPass   = params.perPass[passNdx];
1423     bool anySingleSampledAttachmentsUsed = false;
1424 
1425     // Maximum 4 attachment references for color and 1 for depth
1426     preinitializeAttachmentReferences(attachmentReferences, 5);
1427     preinitializeAttachmentReferences(resolveAttachmentReferences, 5);
1428 
1429     if (!params.renderToAttachment && passNdx == 0)
1430     {
1431         attachmentReferences[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1432     }
1433 
1434     if (perPass.floatColor1Location >= 0)
1435     {
1436         initializeAttachmentReference(attachmentReferences[perPass.floatColor1Location], attachmentNdxes[0],
1437                                       VK_FORMAT_UNDEFINED, false);
1438         anySingleSampledAttachmentsUsed =
1439             anySingleSampledAttachmentsUsed || params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT;
1440     }
1441     else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[0]))
1442     {
1443         if (attachmentNdxes[0] != -1)
1444             preserveAttachments->push_back(attachmentNdxes[0]);
1445     }
1446     if (perPass.floatColor2Location >= 0)
1447     {
1448         initializeAttachmentReference(attachmentReferences[perPass.floatColor2Location], attachmentNdxes[1],
1449                                       VK_FORMAT_UNDEFINED, false);
1450         anySingleSampledAttachmentsUsed =
1451             anySingleSampledAttachmentsUsed || params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT;
1452     }
1453     else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[1]))
1454     {
1455         if (attachmentNdxes[1] != -1)
1456             preserveAttachments->push_back(attachmentNdxes[1]);
1457     }
1458     if (perPass.intColorLocation >= 0)
1459     {
1460         initializeAttachmentReference(attachmentReferences[perPass.intColorLocation], attachmentNdxes[2],
1461                                       VK_FORMAT_UNDEFINED, false);
1462         anySingleSampledAttachmentsUsed =
1463             anySingleSampledAttachmentsUsed || params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT;
1464     }
1465     else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[2]))
1466     {
1467         if (attachmentNdxes[2] != -1)
1468             preserveAttachments->push_back(attachmentNdxes[2]);
1469     }
1470     if (perPass.hasDepthStencil)
1471     {
1472         initializeAttachmentReference(attachmentReferences.back(), attachmentNdxes[3], params.depthStencilFormat,
1473                                       false);
1474         anySingleSampledAttachmentsUsed =
1475             anySingleSampledAttachmentsUsed || params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT;
1476     }
1477     else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[3]))
1478     {
1479         if (attachmentNdxes[3] != -1)
1480             preserveAttachments->push_back(attachmentNdxes[3]);
1481     }
1482 
1483     // Resolve attachments
1484     if (perPass.resolveFloatColor1)
1485     {
1486         initializeAttachmentReference(resolveAttachmentReferences[perPass.floatColor1Location], attachmentNdxes[4],
1487                                       VK_FORMAT_UNDEFINED, false);
1488     }
1489     else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[4]))
1490     {
1491         if (attachmentNdxes[4] != -1)
1492             preserveAttachments->push_back(attachmentNdxes[4]);
1493     }
1494     if (perPass.resolveFloatColor2)
1495     {
1496         initializeAttachmentReference(resolveAttachmentReferences[perPass.floatColor2Location], attachmentNdxes[5],
1497                                       VK_FORMAT_UNDEFINED, false);
1498     }
1499     else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[5]))
1500     {
1501         if (attachmentNdxes[5] != -1)
1502             preserveAttachments->push_back(attachmentNdxes[5]);
1503     }
1504     if (perPass.resolveIntColor)
1505     {
1506         initializeAttachmentReference(resolveAttachmentReferences[perPass.intColorLocation], attachmentNdxes[6],
1507                                       VK_FORMAT_UNDEFINED, false);
1508     }
1509     else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[6]))
1510     {
1511         if (attachmentNdxes[6] != -1)
1512             preserveAttachments->push_back(attachmentNdxes[6]);
1513     }
1514 
1515     // Account for single-sampled attachments in input attachments as well.
1516     if (!inputAttachmentReferences.empty())
1517     {
1518         if (attachmentNdxes[0] >= 0 && isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[0]))
1519             anySingleSampledAttachmentsUsed =
1520                 anySingleSampledAttachmentsUsed || params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT;
1521         if (attachmentNdxes[1] >= 0 && isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[1]))
1522             anySingleSampledAttachmentsUsed =
1523                 anySingleSampledAttachmentsUsed || params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT;
1524         if (attachmentNdxes[2] >= 0 && isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[2]))
1525             anySingleSampledAttachmentsUsed =
1526                 anySingleSampledAttachmentsUsed || params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT;
1527         if (attachmentNdxes[3] >= 0 && isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[3]))
1528             anySingleSampledAttachmentsUsed =
1529                 anySingleSampledAttachmentsUsed || params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT;
1530     }
1531 
1532     const bool needsMsrtss = anySingleSampledAttachmentsUsed && perPass.numSamples != VK_SAMPLE_COUNT_1_BIT;
1533     const bool needsDepthStencilResolve =
1534         perPass.resolveDepthStencil ||
1535         (needsMsrtss && params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT && perPass.hasDepthStencil);
1536 
1537     if (needsDepthStencilResolve)
1538     {
1539         if (perPass.resolveDepthStencil)
1540         {
1541             initializeAttachmentReference(resolveAttachmentReferences.back(), attachmentNdxes[7],
1542                                           params.depthStencilFormat, false);
1543         }
1544         depthStencilResolve = VkSubpassDescriptionDepthStencilResolve{
1545             VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, // VkStructureType                  sType;
1546             DE_NULL,                                                     // const void*                      pNext;
1547             perPass.depthStencilResolveMode, // VkResolveModeFlagBits            depthResolveMode;
1548             perPass.depthStencilResolveMode, // VkResolveModeFlagBits            stencilResolveMode;
1549             perPass.resolveDepthStencil ? &resolveAttachmentReferences.back() :
1550                                           nullptr, // const VkAttachmentReference2*    pDepthStencilResolveAttachment;
1551         };
1552     }
1553     else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[7]))
1554     {
1555         if (attachmentNdxes[7] != -1)
1556             preserveAttachments->push_back(attachmentNdxes[7]);
1557     }
1558 
1559     VkSubpassDescription2 subpassDescription = {
1560         VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,                   // VkStructureType                 sType;
1561         needsDepthStencilResolve ? &depthStencilResolve : DE_NULL, // const void*                     pNext;
1562         (VkSubpassDescriptionFlags)0,                              // VkSubpassDescriptionFlags       flags;
1563         VK_PIPELINE_BIND_POINT_GRAPHICS,                           // VkPipelineBindPoint             pipelineBindPoint;
1564         0u,                                                        // uint32_t                        viewMask;
1565         static_cast<uint32_t>(
1566             inputAttachmentReferences.size()),      // uint32_t                        inputAttachmentCount;
1567         dataOrNullPtr(inputAttachmentReferences),   // const VkAttachmentReference2*   pInputAttachments;
1568         4u,                                         // uint32_t                        colorAttachmentCount;
1569         dataOrNullPtr(attachmentReferences),        // const VkAttachmentReference2*   pColorAttachments;
1570         dataOrNullPtr(resolveAttachmentReferences), // const VkAttachmentReference2*   pResolveAttachments;
1571         perPass.hasDepthStencil ? &attachmentReferences.back() :
1572                                   DE_NULL, // const VkAttachmentReference2*   pDepthStencilAttachment;
1573         preserveAttachments ? static_cast<uint32_t>(preserveAttachments->size()) :
1574                               0, // uint32_t                        preserveAttachmentCount;
1575         preserveAttachments ? dataOrNullPtr(*preserveAttachments) :
1576                               nullptr, // const uint32_t*                 pPreserveAttachments;
1577     };
1578 
1579     // Append MSRTSS to subpass desc
1580     msrtss = VkMultisampledRenderToSingleSampledInfoEXT{
1581         VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT, // VkStructureType            sType
1582         subpassDescription.pNext,                                         // const void*                pNext
1583         VK_TRUE,            // VkBool32                    multisampledRenderToSingleSampledEnable
1584         perPass.numSamples, // VkSampleCountFlagBits    rasterizationSamples
1585     };
1586     if (needsMsrtss)
1587         subpassDescription.pNext = &msrtss;
1588 
1589     subpasses.push_back(subpassDescription);
1590 }
1591 
addSubpassDependency(const uint32_t subpassNdx,std::vector<VkSubpassDependency2> & subpassDependencies)1592 void addSubpassDependency(const uint32_t subpassNdx, std::vector<VkSubpassDependency2> &subpassDependencies)
1593 {
1594     subpassDependencies.push_back(VkSubpassDependency2{
1595         VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, // VkStructureType         sType;
1596         DE_NULL,                                // const void*             pNext;
1597         subpassNdx - 1,                         // uint32_t                srcSubpass;
1598         subpassNdx,                             // uint32_t                dstSubpass;
1599 
1600         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1601             VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags    srcStageMask;
1602 
1603         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1604             VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags    dstStageMask;
1605 
1606         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1607             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags           srcAccessMask;
1608 
1609         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1610             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
1611             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, // VkAccessFlags           dstAccessMask;
1612 
1613         VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags       dependencyFlags;
1614         0,                           // int32_t                 viewOffset;
1615     });
1616 }
1617 
createRenderPassAndFramebuffer(Context & context,WorkingData & wd,TestObjects & testObjects,const PipelineConstructionType pipelineConstructionType,const std::vector<VkImage> & images,const std::vector<VkImageView> & attachments,const std::vector<VkAttachmentDescription2> & attachmentDescriptions,const std::vector<VkSubpassDescription2> & subpasses,const std::vector<VkSubpassDependency2> & subpassDependencies)1618 void createRenderPassAndFramebuffer(Context &context, WorkingData &wd, TestObjects &testObjects,
1619                                     const PipelineConstructionType pipelineConstructionType,
1620                                     const std::vector<VkImage> &images, const std::vector<VkImageView> &attachments,
1621                                     const std::vector<VkAttachmentDescription2> &attachmentDescriptions,
1622                                     const std::vector<VkSubpassDescription2> &subpasses,
1623                                     const std::vector<VkSubpassDependency2> &subpassDependencies)
1624 {
1625     const DeviceInterface &vk = context.getDeviceInterface();
1626     const VkDevice device     = context.getDevice();
1627 
1628     const VkRenderPassCreateInfo2 renderPassInfo = {
1629         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,          // VkStructureType sType;
1630         DE_NULL,                                              // const void* pNext;
1631         (VkRenderPassCreateFlags)0,                           // VkRenderPassCreateFlags flags;
1632         static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t attachmentCount;
1633         dataOrNullPtr(attachmentDescriptions),                // const VkAttachmentDescription2* pAttachments;
1634         static_cast<uint32_t>(subpasses.size()),              // uint32_t subpassCount;
1635         dataOrNullPtr(subpasses),                             // const VkSubpassDescription2* pSubpasses;
1636         static_cast<uint32_t>(subpassDependencies.size()),    // uint32_t dependencyCount;
1637         dataOrNullPtr(subpassDependencies),                   // const VkSubpassDependency2* pDependencies;
1638         0u,      // uint32_t                         correlatedViewMaskCount;
1639         DE_NULL, // const uint32_t*                  pCorrelatedViewMasks;
1640     };
1641 
1642     testObjects.renderPassFramebuffers.emplace_back(
1643         RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo));
1644     testObjects.renderPassFramebuffers.back().createFramebuffer(vk, device, static_cast<uint32_t>(attachments.size()),
1645                                                                 dataOrNullPtr(images), dataOrNullPtr(attachments),
1646                                                                 wd.framebufferSize.x(), wd.framebufferSize.y());
1647 }
1648 
createWorkingData(Context & context,const TestParams & params,WorkingData & wd)1649 void createWorkingData(Context &context, const TestParams &params, WorkingData &wd)
1650 {
1651     const DeviceInterface &vk    = context.getDeviceInterface();
1652     const VkDevice device        = context.getDevice();
1653     MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(
1654         vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1655 
1656     // Create images
1657     {
1658         // TODO: change image types to be nonuniform, for example: mip 1 of 2D image, mip 2/level 3 of 2D array image, etc.
1659         wd.floatColor1.allocate(vk, device, allocator, params.floatColor1Format, wd.framebufferSize,
1660                                 params.numFloatColor1Samples, colorImageUsageFlags, VK_IMAGE_ASPECT_COLOR_BIT, 1, true);
1661         wd.floatColor2.allocate(vk, device, allocator, params.floatColor2Format, wd.framebufferSize,
1662                                 params.numFloatColor2Samples, colorImageUsageFlags, VK_IMAGE_ASPECT_COLOR_BIT, 1, true);
1663         wd.intColor.allocate(vk, device, allocator, params.intColorFormat, wd.framebufferSize,
1664                              params.numIntColorSamples, colorImageUsageFlags, VK_IMAGE_ASPECT_COLOR_BIT, 1, true);
1665         wd.depthStencil.allocate(vk, device, allocator, params.depthStencilFormat, wd.framebufferSize,
1666                                  params.numDepthStencilSamples, depthStencilImageUsageFlags,
1667                                  getDepthStencilAspectFlags(params.depthStencilFormat), 1, true);
1668 
1669         if (!params.renderToAttachment)
1670         {
1671             wd.dataColor1.allocate(vk, device, allocator, params.floatColor1Format, wd.framebufferSize,
1672                                    params.numFloatColor1Samples, colorImageUsageFlags, VK_IMAGE_ASPECT_COLOR_BIT, 1,
1673                                    true);
1674             VkDeviceSize bufferSize = static_cast<VkDeviceSize>(wd.framebufferSize.x() * wd.framebufferSize.y() * 4u);
1675             wd.dataBuffer =
1676                 makeBuffer(vk, device, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1677             wd.dataBufferAlloc = bindBuffer(vk, device, *allocator, *wd.dataBuffer, MemoryRequirement::HostVisible);
1678         }
1679 
1680         if (isDepthFormat(params.depthStencilFormat))
1681             wd.depthOnlyImageView =
1682                 wd.depthStencil.makeView(vk, device, params.depthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
1683 
1684         if (isStencilFormat(params.depthStencilFormat))
1685             wd.stencilOnlyImageView =
1686                 wd.depthStencil.makeView(vk, device, params.depthStencilFormat, VK_IMAGE_ASPECT_STENCIL_BIT, 1);
1687 
1688         if (params.numFloatColor1Samples != VK_SAMPLE_COUNT_1_BIT)
1689         {
1690             wd.floatResolve1.allocate(vk, device, allocator, params.floatColor1Format, wd.framebufferSize,
1691                                       VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags, VK_IMAGE_ASPECT_COLOR_BIT, 1, false);
1692         }
1693 
1694         if (params.numFloatColor2Samples != VK_SAMPLE_COUNT_1_BIT)
1695         {
1696             wd.floatResolve2.allocate(vk, device, allocator, params.floatColor2Format, wd.framebufferSize,
1697                                       VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags, VK_IMAGE_ASPECT_COLOR_BIT, 1, false);
1698         }
1699 
1700         if (params.numIntColorSamples != VK_SAMPLE_COUNT_1_BIT)
1701         {
1702             wd.intResolve.allocate(vk, device, allocator, params.intColorFormat, wd.framebufferSize,
1703                                    VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags, VK_IMAGE_ASPECT_COLOR_BIT, 1, false);
1704         }
1705 
1706         if (params.numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT)
1707         {
1708             wd.depthStencilResolve.allocate(vk, device, allocator, params.depthStencilFormat, wd.framebufferSize,
1709                                             VK_SAMPLE_COUNT_1_BIT, depthStencilImageUsageFlags,
1710                                             getDepthStencilAspectFlags(params.depthStencilFormat), 1, false);
1711 
1712             if (isDepthFormat(params.depthStencilFormat))
1713                 wd.depthOnlyResolveImageView = wd.depthStencilResolve.makeView(vk, device, params.depthStencilFormat,
1714                                                                                VK_IMAGE_ASPECT_DEPTH_BIT, 1);
1715 
1716             if (isStencilFormat(params.depthStencilFormat))
1717                 wd.stencilOnlyResolveImageView = wd.depthStencilResolve.makeView(vk, device, params.depthStencilFormat,
1718                                                                                  VK_IMAGE_ASPECT_STENCIL_BIT, 1);
1719         }
1720 
1721         wd.verify.allocate(vk, device, allocator, VK_FORMAT_R8G8B8A8_UNORM, wd.framebufferSize, VK_SAMPLE_COUNT_1_BIT,
1722                            VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1723                                VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1724                            VK_IMAGE_ASPECT_COLOR_BIT, 5, false);
1725     }
1726 
1727     // Create vertex and verification buffers
1728     {
1729         // A fullscreen triangle
1730         const std::vector<Vec4> vertices = {
1731             Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
1732             Vec4(3.0f, -1.0f, 0.0f, 1.0f),
1733             Vec4(-1.0f, 3.0f, 0.0f, 1.0f),
1734         };
1735 
1736         const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1737         wd.vertexBuffer      = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1738         wd.vertexBufferAlloc = bindBuffer(vk, device, *allocator, *wd.vertexBuffer, MemoryRequirement::HostVisible);
1739 
1740         deMemcpy(wd.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices),
1741                  static_cast<std::size_t>(vertexBufferSize));
1742         flushMappedMemoryRange(vk, device, wd.vertexBufferAlloc->getMemory(), wd.vertexBufferAlloc->getOffset(),
1743                                VK_WHOLE_SIZE);
1744 
1745         // Initialize the verification data with 0.
1746         const VerificationResults results = {};
1747 
1748         wd.verificationBuffer = makeBuffer(vk, device, sizeof(results), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1749         wd.verificationBufferAlloc =
1750             bindBuffer(vk, device, *allocator, *wd.verificationBuffer, MemoryRequirement::HostVisible);
1751 
1752         deMemcpy(wd.verificationBufferAlloc->getHostPtr(), &results, sizeof(results));
1753         flushMappedMemoryRange(vk, device, wd.verificationBufferAlloc->getMemory(),
1754                                wd.verificationBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1755 
1756         wd.singleVerificationBuffer = makeBuffer(vk, device, sizeof(results), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1757         wd.singleVerificationBufferAlloc =
1758             bindBuffer(vk, device, *allocator, *wd.singleVerificationBuffer, MemoryRequirement::HostVisible);
1759 
1760         deMemcpy(wd.singleVerificationBufferAlloc->getHostPtr(), &results, sizeof(results));
1761         flushMappedMemoryRange(vk, device, wd.singleVerificationBufferAlloc->getMemory(),
1762                                wd.singleVerificationBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1763     }
1764 }
1765 
checkRequirements(Context & context,TestParams params)1766 void checkRequirements(Context &context, TestParams params)
1767 {
1768     const VkPhysicalDevice physicalDevice          = context.getPhysicalDevice();
1769     const vk::InstanceInterface &instanceInterface = context.getInstanceInterface();
1770 
1771     checkPipelineConstructionRequirements(instanceInterface, physicalDevice, params.pipelineConstructionType);
1772 
1773     context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
1774     context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
1775 
1776     if (params.dynamicRendering)
1777         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1778 
1779     if (params.isMultisampledRenderToSingleSampled)
1780     {
1781         context.requireDeviceFunctionality("VK_EXT_multisampled_render_to_single_sampled");
1782 
1783         // Check extension feature
1784         {
1785             VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT msrtssFeatures = {
1786                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT,
1787                 DE_NULL,
1788                 VK_FALSE,
1789             };
1790             VkPhysicalDeviceFeatures2 physicalDeviceFeatures = {
1791                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
1792                 &msrtssFeatures,
1793                 {},
1794             };
1795 
1796             instanceInterface.getPhysicalDeviceFeatures2(physicalDevice, &physicalDeviceFeatures);
1797 
1798             if (msrtssFeatures.multisampledRenderToSingleSampled != VK_TRUE)
1799             {
1800                 TCU_THROW(NotSupportedError, "multisampledRenderToSingleSampled not supported");
1801             }
1802         }
1803     }
1804 
1805     // Check whether formats are supported with the requested usage and sample counts.
1806     {
1807         VkImageFormatProperties imageProperties;
1808         checkImageRequirements(context, params.floatColor1Format,
1809                                VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT |
1810                                    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1811                                colorImageUsageFlags, params.numFloatColor1Samples, imageProperties);
1812         if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
1813             for (const TestParams::PerPass &perPass : params.perPass)
1814                 if (perPass.floatColor1Location >= 0 &&
1815                     (imageProperties.sampleCounts & perPass.numSamples) != perPass.numSamples)
1816                     TCU_THROW(NotSupportedError,
1817                               (de::toString(params.floatColor1Format) + ": sample count not supported").c_str());
1818     }
1819     {
1820         VkImageFormatProperties imageProperties;
1821         checkImageRequirements(context, params.floatColor2Format,
1822                                VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT |
1823                                    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1824                                colorImageUsageFlags, params.numFloatColor2Samples, imageProperties);
1825         if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
1826             for (const TestParams::PerPass &perPass : params.perPass)
1827                 if (perPass.floatColor2Location >= 0 &&
1828                     (imageProperties.sampleCounts & perPass.numSamples) != perPass.numSamples)
1829                     TCU_THROW(NotSupportedError,
1830                               (de::toString(params.floatColor2Format) + ": sample count not supported").c_str());
1831     }
1832     {
1833         VkImageFormatProperties imageProperties;
1834         checkImageRequirements(context, params.intColorFormat,
1835                                VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1836                                colorImageUsageFlags, params.numIntColorSamples, imageProperties);
1837         if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
1838             for (const TestParams::PerPass &perPass : params.perPass)
1839                 if (perPass.intColorLocation >= 0 &&
1840                     (imageProperties.sampleCounts & perPass.numSamples) != perPass.numSamples)
1841                     TCU_THROW(NotSupportedError,
1842                               (de::toString(params.intColorFormat) + ": sample count not supported").c_str());
1843     }
1844     {
1845         VkImageFormatProperties imageProperties;
1846         checkImageRequirements(context, params.depthStencilFormat,
1847                                VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1848                                depthStencilImageUsageFlags, params.numDepthStencilSamples, imageProperties);
1849         if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
1850             for (const TestParams::PerPass &perPass : params.perPass)
1851                 if (perPass.hasDepthStencil &&
1852                     (imageProperties.sampleCounts & perPass.numSamples) != perPass.numSamples)
1853                     TCU_THROW(NotSupportedError,
1854                               (de::toString(params.depthStencilFormat) + ": sample count not supported").c_str());
1855     }
1856 
1857     // Perform query to get supported depth/stencil resolve modes.
1858     VkPhysicalDeviceDepthStencilResolveProperties dsResolveProperties = {};
1859     dsResolveProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
1860 
1861     VkPhysicalDeviceProperties2 deviceProperties = {};
1862     deviceProperties.sType                       = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1863     deviceProperties.pNext                       = &dsResolveProperties;
1864 
1865     instanceInterface.getPhysicalDeviceProperties2(physicalDevice, &deviceProperties);
1866 
1867     for (const TestParams::PerPass &perPass : params.perPass)
1868     {
1869         // Check whether sample counts used for rendering are acceptable
1870         const bool checkColor =
1871             perPass.floatColor1Location >= 0 || perPass.floatColor2Location >= 0 || perPass.intColorLocation >= 0;
1872         const bool checkDepth   = perPass.hasDepthStencil && isDepthFormat(params.depthStencilFormat);
1873         const bool checkStencil = perPass.hasDepthStencil && isStencilFormat(params.depthStencilFormat);
1874         checkSampleRequirements(context, perPass.numSamples, checkColor, checkDepth, checkStencil);
1875 
1876         // Check whether depth/stencil resolve mode is supported
1877         if (perPass.depthStencilResolveMode != VK_RESOLVE_MODE_NONE &&
1878             ((dsResolveProperties.supportedDepthResolveModes & perPass.depthStencilResolveMode) == 0 ||
1879              (dsResolveProperties.supportedStencilResolveModes & perPass.depthStencilResolveMode) == 0))
1880         {
1881             TCU_THROW(NotSupportedError, "Depth/stencil resolve mode not supported");
1882         }
1883     }
1884 
1885     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1886 }
1887 
checkHasMsrtss(Context & context,VkFormat)1888 void checkHasMsrtss(Context &context, VkFormat)
1889 {
1890     context.requireDeviceFunctionality("VK_EXT_multisampled_render_to_single_sampled");
1891 }
1892 
generateRandomClearValues(de::Random & rng,const TestParams & params,VkClearValue clearValues[4],bool smallValues)1893 void generateRandomClearValues(de::Random &rng, const TestParams &params, VkClearValue clearValues[4], bool smallValues)
1894 {
1895     const bool usesSignedIntFormat = params.intColorFormat == VK_FORMAT_R16G16B16A16_SINT;
1896 
1897     const float minFloatValue      = 0.05f;
1898     const float maxFloatValue      = smallValues ? 0.1f : 0.95f;
1899     const uint32_t minIntValue     = smallValues ? 20 : 5000;
1900     const uint32_t maxIntValue     = smallValues ? 100 : 10000;
1901     const float minDepthValue      = 0.05f;
1902     const float maxDepthValue      = smallValues ? 0.1f : 0.5f;
1903     const uint32_t minStencilValue = 0x10;
1904     const uint32_t maxStencilValue = 0x20;
1905 
1906     clearValues[0].color.float32[0]     = rng.getFloat(minFloatValue, maxFloatValue);
1907     clearValues[0].color.float32[1]     = rng.getFloat(minFloatValue, maxFloatValue);
1908     clearValues[0].color.float32[2]     = rng.getFloat(minFloatValue, maxFloatValue);
1909     clearValues[0].color.float32[3]     = rng.getFloat(minFloatValue, maxFloatValue);
1910     clearValues[1].color.float32[0]     = rng.getFloat(minFloatValue, maxFloatValue);
1911     clearValues[1].color.float32[1]     = rng.getFloat(minFloatValue, maxFloatValue);
1912     clearValues[1].color.float32[2]     = rng.getFloat(minFloatValue, maxFloatValue);
1913     clearValues[1].color.float32[3]     = rng.getFloat(minFloatValue, maxFloatValue);
1914     clearValues[2].color.int32[0]       = (usesSignedIntFormat ? -1 : 1) * rng.getInt(minIntValue, maxIntValue);
1915     clearValues[2].color.int32[1]       = (usesSignedIntFormat ? -1 : 1) * rng.getInt(minIntValue, maxIntValue);
1916     clearValues[2].color.int32[2]       = (usesSignedIntFormat ? -1 : 1) * rng.getInt(minIntValue, maxIntValue);
1917     clearValues[2].color.int32[3]       = (usesSignedIntFormat ? -1 : 1) * rng.getInt(minIntValue, maxIntValue);
1918     clearValues[3].depthStencil.depth   = rng.getFloat(minDepthValue, maxDepthValue);
1919     clearValues[3].depthStencil.stencil = rng.getInt(minStencilValue, maxStencilValue);
1920 }
1921 
clearImagesBeforeDraw(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)1922 void clearImagesBeforeDraw(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects)
1923 {
1924     const DeviceInterface &vk = context.getDeviceInterface();
1925 
1926     const VkImageMemoryBarrier imageBarrierTemplate = {
1927         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType;
1928         DE_NULL,                                // const void*                pNext;
1929         0,                                      // VkAccessFlags              srcAccessMask;
1930         VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags              dstAccessMask;
1931         VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout              oldLayout;
1932         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout              newLayout;
1933         VK_QUEUE_FAMILY_IGNORED,                // uint32_t                   srcQueueFamilyIndex;
1934         VK_QUEUE_FAMILY_IGNORED,                // uint32_t                   dstQueueFamilyIndex;
1935         0,                                      // VkImage                    image;
1936         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,
1937                                   1u), // VkImageSubresourceRange    subresourceRange;
1938     };
1939 
1940     VkImage firstImage = params.renderToAttachment ? *wd.floatColor1.image : *wd.dataColor1.image;
1941 
1942     VkImageMemoryBarrier preClearBarriers[4]        = {imageBarrierTemplate, imageBarrierTemplate, imageBarrierTemplate,
1943                                                        imageBarrierTemplate};
1944     preClearBarriers[0].image                       = firstImage;
1945     preClearBarriers[1].image                       = *wd.floatColor2.image;
1946     preClearBarriers[2].image                       = *wd.intColor.image;
1947     preClearBarriers[3].image                       = *wd.depthStencil.image;
1948     preClearBarriers[3].subresourceRange.aspectMask = getDepthStencilAspectFlags(params.depthStencilFormat);
1949 
1950     vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1951                           0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(preClearBarriers), preClearBarriers);
1952 
1953     vk.cmdClearColorImage(*testObjects.cmdBuffer, firstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1954                           &params.clearValues[0].color, 1, &preClearBarriers[0].subresourceRange);
1955     vk.cmdClearColorImage(*testObjects.cmdBuffer, *wd.floatColor2.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1956                           &params.clearValues[1].color, 1, &preClearBarriers[1].subresourceRange);
1957     vk.cmdClearColorImage(*testObjects.cmdBuffer, *wd.intColor.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1958                           &params.clearValues[2].color, 1, &preClearBarriers[2].subresourceRange);
1959     vk.cmdClearDepthStencilImage(*testObjects.cmdBuffer, *wd.depthStencil.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1960                                  &params.clearValues[3].depthStencil, 1, &preClearBarriers[3].subresourceRange);
1961 
1962     const VkMemoryBarrier postClearBarrier = {
1963         VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType    sType;
1964         DE_NULL,                          // const void*        pNext;
1965         VK_ACCESS_TRANSFER_WRITE_BIT,     // VkAccessFlags      srcAccessMask;
1966         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1967             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1968             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags      dstAccessMask;
1969     };
1970 
1971     vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1972                           VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
1973                               VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1974                           0u, 1u, &postClearBarrier, 0u, DE_NULL, 0u, DE_NULL);
1975 }
1976 
getDrawRegions(WorkingData & wd,UVec4 regions[RegionCount])1977 void getDrawRegions(WorkingData &wd, UVec4 regions[RegionCount])
1978 {
1979     static_assert(RegionCount == 4, "Update this function to generate the correct number of regions");
1980 
1981     UVec2 oneThirdRenderAreaSize(wd.renderArea.z() / 3, wd.renderArea.w() / 3);
1982     UVec2 twoThirdsRenderAreaSize(wd.renderArea.z() - oneThirdRenderAreaSize.x(),
1983                                   wd.renderArea.w() - oneThirdRenderAreaSize.y());
1984     UVec2 renderAreaSplit(wd.renderArea.x() + oneThirdRenderAreaSize.x(),
1985                           wd.renderArea.y() + oneThirdRenderAreaSize.y());
1986 
1987     regions[0] = UVec4(wd.renderArea.x(), wd.renderArea.y(), oneThirdRenderAreaSize.x(), oneThirdRenderAreaSize.y());
1988     regions[1] = UVec4(renderAreaSplit.x(), wd.renderArea.y(), twoThirdsRenderAreaSize.x(), oneThirdRenderAreaSize.y());
1989     regions[2] = UVec4(wd.renderArea.x(), renderAreaSplit.y(), oneThirdRenderAreaSize.x(), twoThirdsRenderAreaSize.y());
1990     regions[3] =
1991         UVec4(renderAreaSplit.x(), renderAreaSplit.y(), twoThirdsRenderAreaSize.x(), twoThirdsRenderAreaSize.y());
1992 }
1993 
startRenderPass(Context & context,WorkingData & wd,TestObjects & testObjects,const uint32_t clearValueCount,const VkClearValue * clearValues)1994 void startRenderPass(Context &context, WorkingData &wd, TestObjects &testObjects, const uint32_t clearValueCount,
1995                      const VkClearValue *clearValues)
1996 {
1997     const DeviceInterface &vk = context.getDeviceInterface();
1998 
1999     const VkRect2D renderArea = {{static_cast<int32_t>(wd.renderArea.x()), static_cast<int32_t>(wd.renderArea.y())},
2000                                  {wd.renderArea.z(), wd.renderArea.w()}};
2001 
2002     testObjects.renderPassFramebuffers.back().begin(vk, *testObjects.cmdBuffer, renderArea, clearValueCount,
2003                                                     clearValues);
2004 }
2005 
startRendering(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects,uint32_t colorAttachmentCount,std::vector<VkRenderingAttachmentInfo> & colorAttachmentInfos,VkRenderingAttachmentInfo & depthStencilAttachmentInfo,uint32_t renderPassNdx)2006 void startRendering(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects,
2007                     uint32_t colorAttachmentCount, std::vector<VkRenderingAttachmentInfo> &colorAttachmentInfos,
2008                     VkRenderingAttachmentInfo &depthStencilAttachmentInfo, uint32_t renderPassNdx)
2009 {
2010     const DeviceInterface &vk          = context.getDeviceInterface();
2011     const TestParams::PerPass &perPass = params.perPass[renderPassNdx];
2012 
2013     bool anySingleSampledAttachmentsUsed = false;
2014     if (perPass.floatColor1Location >= 0)
2015     {
2016         anySingleSampledAttachmentsUsed =
2017             anySingleSampledAttachmentsUsed || params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT;
2018     }
2019     if (perPass.floatColor2Location >= 0)
2020     {
2021         anySingleSampledAttachmentsUsed =
2022             anySingleSampledAttachmentsUsed || params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT;
2023     }
2024     if (perPass.intColorLocation >= 0)
2025     {
2026         anySingleSampledAttachmentsUsed =
2027             anySingleSampledAttachmentsUsed || params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT;
2028     }
2029     if (perPass.hasDepthStencil)
2030     {
2031         anySingleSampledAttachmentsUsed =
2032             anySingleSampledAttachmentsUsed || params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT;
2033     }
2034 
2035     // Append MSRTSS to subpass desc
2036     VkMultisampledRenderToSingleSampledInfoEXT msrtss = {
2037         VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT, // VkStructureType            sType
2038         DE_NULL,                                                          // const void*                pNext
2039         VK_TRUE,           // VkBool32                    multisampledRenderToSingleSampledEnable
2040         perPass.numSamples // VkSampleCountFlagBits    rasterizationSamples
2041     };
2042 
2043     const VkRect2D renderArea = {{static_cast<int32_t>(wd.renderArea.x()), static_cast<int32_t>(wd.renderArea.y())},
2044                                  {wd.renderArea.z(), wd.renderArea.w()}};
2045 
2046     const bool useDepthStencil = params.usesDepthStencilInPass(renderPassNdx);
2047 
2048     VkRenderingInfo renderingInfo = {
2049         VK_STRUCTURE_TYPE_RENDERING_INFO, // VkStructureType                        sType
2050         DE_NULL,                          // const void*                            pNext
2051         (VkRenderingFlags)0,              // VkRenderingFlags                        flags
2052         renderArea,                       // VkRect2D                                renderArea
2053         1u,                               // uint32_t                                layerCount
2054         0u,                               // uint32_t                                viewMask
2055         colorAttachmentCount,             // uint32_t                                colorAttachmentCount
2056         colorAttachmentInfos.data(),      // const VkRenderingAttachmentInfo*        pColorAttachments
2057         useDepthStencil && isDepthFormat(params.depthStencilFormat) ?
2058             &depthStencilAttachmentInfo :
2059             DE_NULL, // const VkRenderingAttachmentInfo*        pDepthAttachment
2060         useDepthStencil && isStencilFormat(params.depthStencilFormat) ?
2061             &depthStencilAttachmentInfo :
2062             DE_NULL // const VkRenderingAttachmentInfo*        pStencilAttachment
2063     };
2064 
2065     if (anySingleSampledAttachmentsUsed && perPass.numSamples != VK_SAMPLE_COUNT_1_BIT)
2066         renderingInfo.pNext = &msrtss;
2067 
2068     vk.cmdBeginRendering(*testObjects.cmdBuffer, &renderingInfo);
2069 }
2070 
postDrawBarrier(Context & context,TestObjects & testObjects)2071 void postDrawBarrier(Context &context, TestObjects &testObjects)
2072 {
2073     const DeviceInterface &vk = context.getDeviceInterface();
2074 
2075     const VkMemoryBarrier barrier = {
2076         VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType    sType;
2077         DE_NULL,                          // const void*        pNext;
2078         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2079             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags      srcAccessMask;
2080         VK_ACCESS_SHADER_READ_BIT,                        // VkAccessFlags      dstAccessMask;
2081     };
2082 
2083     vk.cmdPipelineBarrier(*testObjects.cmdBuffer,
2084                           VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
2085                               VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
2086                           VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
2087 }
2088 
setupVerifyDescriptorSetAndPipeline(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects,const VkPushConstantRange * pushConstantRange,Move<VkPipelineLayout> & verifyPipelineLayout)2089 void setupVerifyDescriptorSetAndPipeline(Context &context, const TestParams &params, WorkingData &wd,
2090                                          TestObjects &testObjects, const VkPushConstantRange *pushConstantRange,
2091                                          Move<VkPipelineLayout> &verifyPipelineLayout)
2092 {
2093     const DeviceInterface &vk = context.getDeviceInterface();
2094     const VkDevice device     = context.getDevice();
2095 
2096     const Unique<VkDescriptorSetLayout> descriptorSetLayout(
2097         DescriptorSetLayoutBuilder()
2098             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
2099             .addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2100             .addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2101             .addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2102             .addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2103             .addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2104             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2105             .build(vk, device));
2106 
2107     testObjects.descriptorPools.emplace_back(
2108         DescriptorPoolBuilder()
2109             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
2110             .addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 5u)
2111             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
2112             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
2113 
2114     testObjects.descriptorSets.emplace_back(
2115         makeDescriptorSet(vk, device, *testObjects.descriptorPools.back(), *descriptorSetLayout));
2116 
2117     const VkDescriptorBufferInfo resultBufferInfo =
2118         makeDescriptorBufferInfo(*wd.verificationBuffer, 0ull, sizeof(VerificationResults));
2119     const VkDescriptorImageInfo color1ImageInfo = makeDescriptorImageInfo(
2120         DE_NULL, *wd.getResolvedFloatColorImage1View(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2121     const VkDescriptorImageInfo color2ImageInfo = makeDescriptorImageInfo(
2122         DE_NULL, *wd.getResolvedFloatColorImage2View(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2123     const VkDescriptorImageInfo color3ImageInfo = makeDescriptorImageInfo(
2124         DE_NULL, *wd.getResolvedIntColorImageView(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2125     const VkDescriptorImageInfo depthImageInfo = makeDescriptorImageInfo(
2126         DE_NULL, *wd.getResolvedDepthOnlyImageView(params), VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
2127     const VkDescriptorImageInfo stencilImageInfo = makeDescriptorImageInfo(
2128         DE_NULL, *wd.getResolvedStencilOnlyImageView(params), VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
2129     const VkDescriptorImageInfo verifyImageInfo =
2130         makeDescriptorImageInfo(DE_NULL, *wd.verify.view, VK_IMAGE_LAYOUT_GENERAL);
2131 
2132     DescriptorSetUpdateBuilder builder;
2133 
2134     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(0u),
2135                         VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo);
2136     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(1u),
2137                         VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &color1ImageInfo);
2138     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(2u),
2139                         VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &color2ImageInfo);
2140     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(3u),
2141                         VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &color3ImageInfo);
2142     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(4u),
2143                         VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &depthImageInfo);
2144     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(5u),
2145                         VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &stencilImageInfo);
2146     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(6u),
2147                         VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &verifyImageInfo);
2148 
2149     builder.update(vk, device);
2150 
2151     const Unique<VkShaderModule> verifyModule(
2152         createShaderModule(vk, device, context.getBinaryCollection().get("comp"), 0u));
2153 
2154     verifyPipelineLayout = makePipelineLayout(vk, device, 1, &*descriptorSetLayout, 1, pushConstantRange);
2155 
2156     testObjects.computePipelines.push_back(
2157         PipelineSp(new Unique<VkPipeline>(makeComputePipeline(vk, device, *verifyPipelineLayout, *verifyModule))));
2158 
2159     vk.cmdBindPipeline(*testObjects.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, **testObjects.computePipelines.back());
2160     vk.cmdBindDescriptorSets(*testObjects.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *verifyPipelineLayout, 0u, 1u,
2161                              &testObjects.descriptorSets.back().get(), 0u, DE_NULL);
2162 }
2163 
postVerifyBarrier(Context & context,TestObjects & testObjects,const Move<VkBuffer> & verificationBuffer)2164 void postVerifyBarrier(Context &context, TestObjects &testObjects, const Move<VkBuffer> &verificationBuffer)
2165 {
2166     const DeviceInterface &vk = context.getDeviceInterface();
2167 
2168     const VkBufferMemoryBarrier barrier = {
2169         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType    sType;
2170         DE_NULL,                                 // const void*        pNext;
2171         VK_ACCESS_SHADER_WRITE_BIT,              // VkAccessFlags      srcAccessMask;
2172         VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags      dstAccessMask;
2173         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           srcQueueFamilyIndex;
2174         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           dstQueueFamilyIndex;
2175         *verificationBuffer,                     // VkBuffer           buffer;
2176         0ull,                                    // VkDeviceSize       offset;
2177         VK_WHOLE_SIZE,                           // VkDeviceSize       size;
2178     };
2179 
2180     vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
2181                           0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
2182 }
2183 
dispatchVerifyConstantColor(Context & context,TestObjects & testObjects,const Move<VkImageView> & imageView,const VkImageLayout layout,const Move<VkImageView> & verifyImageView,const Move<VkBuffer> & verificationBuffer,const uint32_t pushConstantSize,const void * pushConstants,const std::string & shaderName)2184 void dispatchVerifyConstantColor(Context &context, TestObjects &testObjects, const Move<VkImageView> &imageView,
2185                                  const VkImageLayout layout, const Move<VkImageView> &verifyImageView,
2186                                  const Move<VkBuffer> &verificationBuffer, const uint32_t pushConstantSize,
2187                                  const void *pushConstants, const std::string &shaderName)
2188 {
2189     const DeviceInterface &vk = context.getDeviceInterface();
2190     const VkDevice device     = context.getDevice();
2191 
2192     // Set up descriptor set
2193     const Unique<VkDescriptorSetLayout> descriptorSetLayout(
2194         DescriptorSetLayoutBuilder()
2195             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
2196             .addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2197             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2198             .build(vk, device));
2199 
2200     testObjects.descriptorPools.emplace_back(
2201         DescriptorPoolBuilder()
2202             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
2203             .addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1u)
2204             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
2205             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
2206 
2207     testObjects.descriptorSets.emplace_back(
2208         makeDescriptorSet(vk, device, *testObjects.descriptorPools.back(), *descriptorSetLayout));
2209 
2210     const VkDescriptorBufferInfo resultBufferInfo =
2211         makeDescriptorBufferInfo(*verificationBuffer, 0ull, sizeof(VerificationResults));
2212     const VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, layout);
2213     const VkDescriptorImageInfo verifyImageInfo =
2214         makeDescriptorImageInfo(DE_NULL, *verifyImageView, VK_IMAGE_LAYOUT_GENERAL);
2215 
2216     DescriptorSetUpdateBuilder builder;
2217 
2218     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(0u),
2219                         VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo);
2220     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(1u),
2221                         VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
2222     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(2u),
2223                         VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &verifyImageInfo);
2224 
2225     builder.update(vk, device);
2226 
2227     // Setup pipeline
2228     const VkPushConstantRange &verifyPushConstantRange = {
2229         VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags    stageFlags;
2230         0,                           // uint32_t              offset;
2231         pushConstantSize,            // uint32_t              size;
2232     };
2233 
2234     const Unique<VkShaderModule> verifyModule(
2235         createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u));
2236     const Unique<VkPipelineLayout> verifyPipelineLayout(
2237         makePipelineLayout(vk, device, 1, &*descriptorSetLayout, 1, &verifyPushConstantRange));
2238 
2239     testObjects.computePipelines.push_back(
2240         PipelineSp(new Unique<VkPipeline>(makeComputePipeline(vk, device, *verifyPipelineLayout, *verifyModule))));
2241 
2242     vk.cmdBindPipeline(*testObjects.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, **testObjects.computePipelines.back());
2243     vk.cmdBindDescriptorSets(*testObjects.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *verifyPipelineLayout, 0u, 1u,
2244                              &testObjects.descriptorSets.back().get(), 0u, DE_NULL);
2245 
2246     const VkMemoryBarrier preVerifyBarrier = {
2247         VK_STRUCTURE_TYPE_MEMORY_BARRIER,                       // VkStructureType    sType;
2248         DE_NULL,                                                // const void*        pNext;
2249         VK_ACCESS_SHADER_WRITE_BIT,                             // VkAccessFlags      srcAccessMask;
2250         VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags      dstAccessMask;
2251     };
2252 
2253     vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2254                           VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 1u, &preVerifyBarrier, 0u,
2255                           DE_NULL, 0u, DE_NULL);
2256 
2257     // Area is always the first uvec4
2258     const UVec4 *area = static_cast<const UVec4 *>(pushConstants);
2259 
2260     vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, pushConstantSize,
2261                         pushConstants);
2262     vk.cmdDispatch(*testObjects.cmdBuffer, (area->z() + 7) / 8, (area->w() + 7) / 8, 1);
2263 
2264     postVerifyBarrier(context, testObjects, verificationBuffer);
2265 }
2266 
testStart(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)2267 void testStart(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects)
2268 {
2269     de::Random rng(params.rngSeed);
2270 
2271     wd.framebufferSize = UVec2(rng.getInt(60, 80), rng.getInt(48, 64));
2272     wd.renderArea      = UVec4(0, 0, wd.framebufferSize.x(), wd.framebufferSize.y());
2273     if (!params.renderToWholeFramebuffer)
2274     {
2275         wd.renderArea.x() += rng.getInt(5, 15);
2276         wd.renderArea.y() += rng.getInt(5, 15);
2277         wd.renderArea.z() -= wd.renderArea.x() + rng.getInt(2, 12);
2278         wd.renderArea.w() -= wd.renderArea.y() + rng.getInt(2, 12);
2279     }
2280 
2281     createWorkingData(context, params, wd);
2282 
2283     testObjects.beginCommandBuffer();
2284 
2285     const DeviceInterface &vk = context.getDeviceInterface();
2286 
2287     // Clear verify image
2288     {
2289         VkImageMemoryBarrier clearBarrier = {
2290             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType;
2291             DE_NULL,                                // const void*                pNext;
2292             0,                                      // VkAccessFlags              srcAccessMask;
2293             VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags              dstAccessMask;
2294             VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout              oldLayout;
2295             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout              newLayout;
2296             VK_QUEUE_FAMILY_IGNORED,                // uint32_t                   srcQueueFamilyIndex;
2297             VK_QUEUE_FAMILY_IGNORED,                // uint32_t                   dstQueueFamilyIndex;
2298             *wd.verify.image,                       // VkImage                    image;
2299             makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,
2300                                       5u), // VkImageSubresourceRange    subresourceRange;
2301         };
2302 
2303         vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2304                               0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &clearBarrier);
2305 
2306         VkClearColorValue clearToBlack;
2307         clearToBlack.float32[0] = 0;
2308         clearToBlack.float32[1] = 0;
2309         clearToBlack.float32[2] = 0;
2310         clearToBlack.float32[3] = 1.0;
2311         vk.cmdClearColorImage(*testObjects.cmdBuffer, *wd.verify.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2312                               &clearToBlack, 1, &clearBarrier.subresourceRange);
2313     }
2314 
2315     // Transition it to GENERAL
2316     {
2317         VkImageMemoryBarrier verifyBarrier = {
2318             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType;
2319             DE_NULL,                                // const void*                pNext;
2320             VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags              srcAccessMask;
2321             VK_ACCESS_SHADER_WRITE_BIT,             // VkAccessFlags              dstAccessMask;
2322             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout              oldLayout;
2323             VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout              newLayout;
2324             VK_QUEUE_FAMILY_IGNORED,                // uint32_t                   srcQueueFamilyIndex;
2325             VK_QUEUE_FAMILY_IGNORED,                // uint32_t                   dstQueueFamilyIndex;
2326             *wd.verify.image,                       // VkImage                    image;
2327             makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,
2328                                       5u), // VkImageSubresourceRange    subresourceRange;
2329         };
2330 
2331         vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
2332                               VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &verifyBarrier);
2333     }
2334 }
2335 
testEnd(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)2336 void testEnd(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects)
2337 {
2338     // If not rendering to the whole framebuffer and the images were cleared before the render pass, verify that the area outside the render pass is untouched.
2339     const bool verifyOutsideRenderArea = params.clearBeforeRenderPass && !params.renderToWholeFramebuffer;
2340     if (verifyOutsideRenderArea)
2341     {
2342         const DeviceInterface &vk = context.getDeviceInterface();
2343         const VkDevice device     = context.getDevice();
2344 
2345         const UVec4 verifyAreas[] = {
2346             UVec4(0, 0, wd.framebufferSize.x(), wd.renderArea.y()),
2347             UVec4(0, wd.renderArea.y(), wd.renderArea.x(), wd.renderArea.w()),
2348             UVec4(wd.renderArea.x() + wd.renderArea.z(), wd.renderArea.y(),
2349                   wd.framebufferSize.x() - wd.renderArea.x() - wd.renderArea.z(), wd.renderArea.w()),
2350             UVec4(0, wd.renderArea.y() + wd.renderArea.w(), wd.framebufferSize.x(),
2351                   wd.framebufferSize.y() - wd.renderArea.y() - wd.renderArea.w()),
2352         };
2353 
2354         for (uint32_t areaNdx = 0; areaNdx < DE_LENGTH_OF_ARRAY(verifyAreas); ++areaNdx)
2355         {
2356             if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
2357             {
2358                 const VerifySingleFloatPushConstants verifyColor1 = {
2359                     verifyAreas[areaNdx],
2360                     Vec4(params.clearValues[0].color.float32[0], params.clearValues[0].color.float32[1],
2361                          params.clearValues[0].color.float32[2], params.clearValues[0].color.float32[3]),
2362                     0,
2363                 };
2364                 dispatchVerifyConstantColor(context, testObjects, wd.getResolvedFloatColorImage1View(params),
2365                                             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view,
2366                                             wd.singleVerificationBuffer, static_cast<uint32_t>(sizeof(verifyColor1)),
2367                                             &verifyColor1, "comp_singleFloat");
2368             }
2369 
2370             if (params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT)
2371             {
2372                 const VerifySingleFloatPushConstants verifyColor2 = {
2373                     verifyAreas[areaNdx],
2374                     Vec4(params.clearValues[1].color.float32[0], params.clearValues[1].color.float32[1],
2375                          params.clearValues[1].color.float32[2], params.clearValues[1].color.float32[3]),
2376                     1,
2377                 };
2378                 dispatchVerifyConstantColor(context, testObjects, wd.getResolvedFloatColorImage2View(params),
2379                                             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view,
2380                                             wd.singleVerificationBuffer, static_cast<uint32_t>(sizeof(verifyColor2)),
2381                                             &verifyColor2, "comp_singleFloat");
2382             }
2383 
2384             if (params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT)
2385             {
2386                 const VerifySingleIntPushConstants verifyColor3 = {
2387                     verifyAreas[areaNdx],
2388                     IVec4(params.clearValues[2].color.int32[0], params.clearValues[2].color.int32[1],
2389                           params.clearValues[2].color.int32[2], params.clearValues[2].color.int32[3]),
2390                     2,
2391                 };
2392                 dispatchVerifyConstantColor(context, testObjects, wd.getResolvedIntColorImageView(params),
2393                                             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view,
2394                                             wd.singleVerificationBuffer, static_cast<uint32_t>(sizeof(verifyColor3)),
2395                                             &verifyColor3, "comp_singleInt");
2396             }
2397 
2398             if (params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT && isDepthFormat(params.depthStencilFormat))
2399             {
2400                 const VerifySingleDepthPushConstants verifyDepth = {
2401                     verifyAreas[areaNdx],
2402                     params.clearValues[3].depthStencil.depth,
2403                 };
2404                 dispatchVerifyConstantColor(context, testObjects, wd.getResolvedDepthOnlyImageView(params),
2405                                             VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, wd.verify.view,
2406                                             wd.singleVerificationBuffer, static_cast<uint32_t>(sizeof(verifyDepth)),
2407                                             &verifyDepth, "comp_singleDepth");
2408             }
2409 
2410             if (params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT && isStencilFormat(params.depthStencilFormat))
2411             {
2412                 const VerifySingleStencilPushConstants verifyStencil = {
2413                     verifyAreas[areaNdx],
2414                     params.clearValues[3].depthStencil.stencil,
2415                 };
2416                 dispatchVerifyConstantColor(context, testObjects, wd.getResolvedStencilOnlyImageView(params),
2417                                             VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, wd.verify.view,
2418                                             wd.singleVerificationBuffer, static_cast<uint32_t>(sizeof(verifyStencil)),
2419                                             &verifyStencil, "comp_singleStencil");
2420             }
2421         }
2422 
2423         invalidateAlloc(vk, device, *wd.singleVerificationBufferAlloc);
2424     }
2425 
2426     testObjects.submitCommandsAndWait();
2427 }
2428 
verify(Context & context,const TestParams & params,WorkingData & wd)2429 tcu::TestStatus verify(Context &context, const TestParams &params, WorkingData &wd)
2430 {
2431     bool drawsToColor1       = false;
2432     bool drawsToColor2       = false;
2433     bool drawsToColor3       = false;
2434     bool drawsToDepthStencil = false;
2435     for (const TestParams::PerPass &perPass : params.perPass)
2436     {
2437         if (perPass.floatColor1Location >= 0)
2438             drawsToColor1 = true;
2439         if (perPass.floatColor2Location >= 0)
2440             drawsToColor2 = true;
2441         if (perPass.intColorLocation >= 0)
2442             drawsToColor3 = true;
2443         if (perPass.hasDepthStencil)
2444             drawsToDepthStencil = true;
2445     }
2446 
2447     logTestImages(context, params, wd, drawsToColor1, drawsToColor2, drawsToColor3, drawsToDepthStencil);
2448 
2449     // Verify draw call results
2450     {
2451         const VerificationResults *const results =
2452             static_cast<const VerificationResults *>(wd.verificationBufferAlloc->getHostPtr());
2453         const uint32_t totalPixels = wd.renderArea.z() * wd.renderArea.w();
2454         bool allOk                 = true;
2455         const char *errorDelim     = "";
2456         std::string errorMsg       = "Incorrect multisampled rendering for ";
2457 
2458         if (drawsToColor1)
2459             if (!checkAndReportError(context, results->color1Verification, totalPixels, "color attachment 1"))
2460             {
2461                 errorMsg += errorDelim;
2462                 errorMsg += "color attachment 1";
2463                 errorDelim = ", ";
2464                 allOk      = false;
2465             }
2466 
2467         if (drawsToColor2)
2468             if (!checkAndReportError(context, results->color2Verification, totalPixels, "color attachment 2"))
2469             {
2470                 errorMsg += errorDelim;
2471                 errorMsg += "color attachment 2";
2472                 errorDelim = ", ";
2473                 allOk      = false;
2474             }
2475 
2476         if (drawsToColor3)
2477             if (!checkAndReportError(context, results->color3Verification, totalPixels, "color attachment 3"))
2478             {
2479                 errorMsg += errorDelim;
2480                 errorMsg += "color attachment 3";
2481                 errorDelim = ", ";
2482                 allOk      = false;
2483             }
2484 
2485         if (drawsToDepthStencil && isDepthFormat(params.depthStencilFormat))
2486             if (!checkAndReportError(context, results->depthVerification, totalPixels, "depth attachment"))
2487             {
2488                 errorMsg += errorDelim;
2489                 errorMsg += "depth attachment";
2490                 errorDelim = ", ";
2491                 allOk      = false;
2492             }
2493 
2494         if (drawsToDepthStencil && isStencilFormat(params.depthStencilFormat))
2495             if (!checkAndReportError(context, results->stencilVerification, totalPixels, "stencil attachment"))
2496             {
2497                 errorMsg += errorDelim;
2498                 errorMsg += "stencil attachment";
2499                 errorDelim = ", ";
2500                 allOk      = false;
2501             }
2502 
2503         if (!allOk)
2504         {
2505             logVerifyImages(context, params, wd, drawsToColor1, drawsToColor2, drawsToColor3, drawsToDepthStencil);
2506             return tcu::TestStatus::fail(errorMsg);
2507         }
2508     }
2509 
2510     const bool verifyOutsideRenderArea = params.clearBeforeRenderPass && !params.renderToWholeFramebuffer;
2511     if (verifyOutsideRenderArea)
2512     {
2513         const VerificationResults *const results =
2514             static_cast<const VerificationResults *>(wd.singleVerificationBufferAlloc->getHostPtr());
2515         const uint32_t totalPixels =
2516             wd.framebufferSize.x() * wd.framebufferSize.y() - wd.renderArea.z() * wd.renderArea.w();
2517         bool allOk = true;
2518 
2519         if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
2520             allOk = checkAndReportError(context, results->color1Verification, totalPixels,
2521                                         "color attachment 1 (outside render area)") &&
2522                     allOk;
2523         if (params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT)
2524             allOk = checkAndReportError(context, results->color2Verification, totalPixels,
2525                                         "color attachment 2 (outside render area)") &&
2526                     allOk;
2527         if (params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT)
2528             allOk = checkAndReportError(context, results->color3Verification, totalPixels,
2529                                         "color attachment 3 (outside render area)") &&
2530                     allOk;
2531         if (params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT && isDepthFormat(params.depthStencilFormat))
2532             allOk = checkAndReportError(context, results->depthVerification, totalPixels,
2533                                         "depth attachment (outside render area)") &&
2534                     allOk;
2535         if (params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT && isStencilFormat(params.depthStencilFormat))
2536             allOk = checkAndReportError(context, results->stencilVerification, totalPixels,
2537                                         "stencil attachment (outside render area)") &&
2538                     allOk;
2539 
2540         if (!allOk)
2541         {
2542             logVerifyImages(context, params, wd, drawsToColor1, drawsToColor2, drawsToColor3, drawsToDepthStencil);
2543             return tcu::TestStatus::fail("Detected corruption outside render area");
2544         }
2545     }
2546 
2547     return tcu::TestStatus::pass("Pass");
2548 }
2549 
initConstantColorVerifyPrograms(SourceCollections & programCollection,const TestParams params)2550 void initConstantColorVerifyPrograms(SourceCollections &programCollection, const TestParams params)
2551 {
2552     const bool usesSignedIntFormat = params.intColorFormat == VK_FORMAT_R16G16B16A16_SINT;
2553 
2554     // Compute shader - Verify outside render area is intact (float colors)
2555     {
2556         std::ostringstream src;
2557         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2558             << "#extension GL_EXT_samplerless_texture_functions : require\n"
2559             << "\n"
2560             << "layout(push_constant) uniform PushConstants {\n"
2561             << "    uvec4 area;\n"
2562             << "    vec4 color;\n"
2563             << "    uint attachmentNdx;\n"
2564             << "} params;\n"
2565             << "\n"
2566             << "layout(local_size_x = 8, local_size_y = 8) in;\n"
2567             << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
2568             << "    uint colorVerification[3];\n"
2569             << "    uint depthVerification;\n"
2570             << "    uint stencilVerification;\n"
2571             << "} sb_out;\n"
2572             << "layout(set = 0, binding = 1) uniform texture2D colorImage;\n"
2573             << "layout(set = 0, binding = 2, rgba8) uniform writeonly image2DArray verify;\n"
2574             << "\n"
2575             << "bool v4matches(vec4 a, vec4 b, float error)\n"
2576             << "{\n"
2577             << "    return all(lessThan(abs(a - b), vec4(error)));\n"
2578             << "}\n"
2579             << "\n"
2580             << "void main (void)\n"
2581             << "{\n"
2582             << "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
2583             << "        return;\n"
2584             << "\n"
2585             << "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
2586             << "\n"
2587             << "    vec4 result = vec4(1, 0, 0, 1);\n"
2588             << "    vec4 color = texelFetch(colorImage, ivec2(coords), 0);\n"
2589             << "    if (v4matches(color, params.color, 0.01))\n"
2590             << "    {\n"
2591             << "        atomicAdd(sb_out.colorVerification[params.attachmentNdx], 1);\n"
2592             << "        result = vec4(0, 1, 0, 1);\n"
2593             << "    }\n"
2594             << "    imageStore(verify, ivec3(coords, params.attachmentNdx), result);\n"
2595             << "}\n";
2596 
2597         programCollection.glslSources.add("comp_singleFloat") << glu::ComputeSource(src.str());
2598     }
2599 
2600     // Compute shader - Verify outside render area is intact (int colors)
2601     {
2602         std::ostringstream src;
2603         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2604             << "#extension GL_EXT_samplerless_texture_functions : require\n"
2605             << "\n"
2606             << "layout(push_constant) uniform PushConstants {\n"
2607             << "    uvec4 area;\n"
2608             << "    ivec4 color;\n"
2609             << "    uint attachmentNdx;\n"
2610             << "} params;\n"
2611             << "\n"
2612             << "layout(local_size_x = 8, local_size_y = 8) in;\n"
2613             << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
2614             << "    uint colorVerification[3];\n"
2615             << "    uint depthVerification;\n"
2616             << "    uint stencilVerification;\n"
2617             << "} sb_out;\n"
2618             << "layout(set = 0, binding = 1) uniform " << (usesSignedIntFormat ? "i" : "u") << "texture2D colorImage;\n"
2619             << "layout(set = 0, binding = 2, rgba8) uniform writeonly image2DArray verify;\n"
2620             << "\n"
2621             << "bool i4matches(ivec4 a, ivec4 b, int error)\n"
2622             << "{\n"
2623             << "    return all(lessThanEqual(abs(a - b), ivec4(error)));\n"
2624             << "}\n"
2625             << "\n"
2626             << "void main (void)\n"
2627             << "{\n"
2628             << "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
2629             << "        return;\n"
2630             << "\n"
2631             << "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
2632             << "\n"
2633             << "    vec4 result = vec4(1, 0, 0, 1);\n"
2634             << "    ivec4 color = ivec4(texelFetch(colorImage, ivec2(coords), 0));\n"
2635             << "    if (i4matches(color, params.color, 0))\n"
2636             << "    {\n"
2637             << "        atomicAdd(sb_out.colorVerification[params.attachmentNdx], 1);\n"
2638             << "        result = vec4(0, 1, 0, 1);\n"
2639             << "    }\n"
2640             << "    imageStore(verify, ivec3(coords, params.attachmentNdx), result);\n"
2641             << "}\n";
2642 
2643         programCollection.glslSources.add("comp_singleInt") << glu::ComputeSource(src.str());
2644     }
2645 
2646     // Compute shader - Verify outside render area is intact (depth)
2647     {
2648         std::ostringstream src;
2649         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2650             << "#extension GL_EXT_samplerless_texture_functions : require\n"
2651             << "\n"
2652             << "layout(push_constant) uniform PushConstants {\n"
2653             << "    uvec4 area;\n"
2654             << "    float depthData;\n"
2655             << "} params;\n"
2656             << "\n"
2657             << "layout(local_size_x = 8, local_size_y = 8) in;\n"
2658             << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
2659             << "    uint colorVerification[3];\n"
2660             << "    uint depthVerification;\n"
2661             << "    uint stencilVerification;\n"
2662             << "} sb_out;\n"
2663             << "layout(set = 0, binding = 1) uniform texture2D depthImage;\n"
2664             << "layout(set = 0, binding = 2, rgba8) uniform writeonly image2DArray verify;\n"
2665             << "\n"
2666             << "bool fmatches(float a, float b, float error)\n"
2667             << "{\n"
2668             << "    return abs(a - b) < error;\n"
2669             << "}\n"
2670             << "\n"
2671             << "void main (void)\n"
2672             << "{\n"
2673             << "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
2674             << "        return;\n"
2675             << "\n"
2676             << "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
2677             << "\n"
2678             << "    vec4 result = vec4(1, 0, 0, 1);\n"
2679             << "    float depth  = texelFetch(depthImage, ivec2(coords), 0).r;\n"
2680             << "    if (fmatches(depth, params.depthData, 0.01))\n"
2681             << "    {\n"
2682             << "        atomicAdd(sb_out.depthVerification, 1);\n"
2683             << "        result = vec4(0, 1, 0, 1);\n"
2684             << "    }\n"
2685             << "    imageStore(verify, ivec3(coords, 3), result);\n"
2686             << "}\n";
2687 
2688         programCollection.glslSources.add("comp_singleDepth") << glu::ComputeSource(src.str());
2689     }
2690 
2691     // Compute shader - Verify outside render area is intact (stencil)
2692     {
2693         std::ostringstream src;
2694         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2695             << "#extension GL_EXT_samplerless_texture_functions : require\n"
2696             << "\n"
2697             << "layout(push_constant) uniform PushConstants {\n"
2698             << "    uvec4 area;\n"
2699             << "    uint stencilData;\n"
2700             << "} params;\n"
2701             << "\n"
2702             << "layout(local_size_x = 8, local_size_y = 8) in;\n"
2703             << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
2704             << "    uint colorVerification[3];\n"
2705             << "    uint depthVerification;\n"
2706             << "    uint stencilVerification;\n"
2707             << "} sb_out;\n"
2708             << "layout(set = 0, binding = 1) uniform utexture2D stencilImage;\n"
2709             << "layout(set = 0, binding = 2, rgba8) uniform writeonly image2DArray verify;\n"
2710             << "\n"
2711             << "bool umatches(uint a, uint b, uint error)\n"
2712             << "{\n"
2713             << "    return abs(a - b) <= error;\n"
2714             << "}\n"
2715             << "\n"
2716             << "void main (void)\n"
2717             << "{\n"
2718             << "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
2719             << "        return;\n"
2720             << "\n"
2721             << "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
2722             << "\n"
2723             << "    vec4 result = vec4(1, 0, 0, 1);\n"
2724             << "    uint stencil = texelFetch(stencilImage, ivec2(coords), 0).r;\n"
2725             << "    if (umatches(stencil, params.stencilData, 0))\n"
2726             << "    {\n"
2727             << "        atomicAdd(sb_out.stencilVerification, 1);\n"
2728             << "        result = vec4(0, 1, 0, 1);\n"
2729             << "    }\n"
2730             << "    imageStore(verify, ivec3(coords, 4), result);\n"
2731             << "}\n";
2732 
2733         programCollection.glslSources.add("comp_singleStencil") << glu::ComputeSource(src.str());
2734     }
2735 }
2736 
initBasicPrograms(SourceCollections & programCollection,const TestParams params)2737 void initBasicPrograms(SourceCollections &programCollection, const TestParams params)
2738 {
2739     // Vertex shader - position
2740     {
2741         std::ostringstream src;
2742         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2743             << "\n"
2744             << "layout(location = 0) in  vec4 in_position;\n"
2745             << "\n"
2746             << "out gl_PerVertex {\n"
2747             << "    vec4 gl_Position;\n"
2748             << "};\n"
2749             << "\n"
2750             << "void main(void)\n"
2751             << "{\n"
2752             << "    gl_Position = in_position;\n"
2753             << "}\n";
2754 
2755         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2756     }
2757 
2758     const bool usesSignedIntFormat = params.intColorFormat == VK_FORMAT_R16G16B16A16_SINT;
2759     const char *intTypePrefix      = usesSignedIntFormat ? "i" : "u";
2760 
2761     // The framebuffer contains four attachments with the same number of samples.
2762     // The fragment shader outputs a different color per sample (in a gradient) to verify that the multisampled image actually has that many samples:
2763     //
2764     // - For samples [4s, 4s+3), the shader outputs:
2765     //
2766     //     Vec4(0, v, v, v),
2767     //     Vec4(v, 0, v, v),
2768     //     Vec4(v, v, 0, v),
2769     //     Vec4(v, v, v, 0),
2770     //
2771     //   for float attachments where v = 1-s*0.2. For sample s, it outputs:
2772     //
2773     //     UVec4(v, v + 1, v + 2, v + 3),
2774     //
2775     //   for the int attachment where v = (s+1)*(s+1)*10.
2776     //
2777     // Additionally, the fragment shader outputs depth based on the sample index as well.  For sample s, it outputs 1 - (s^1)/16.
2778     // Note that ^1 ensures VK_RESOLVE_MODE_SAMPLE_ZERO_BIT and VK_RESOLVE_MODE_MAX_BIT produce different values.
2779     {
2780         const TestParams::PerPass &perPass = params.perPass[0];
2781 
2782         // The shader outputs up to 16 samples
2783         const uint32_t numSamples = static_cast<uint32_t>(perPass.numSamples);
2784 
2785         DE_ASSERT(numSamples <= 16);
2786 
2787         std::ostringstream src;
2788         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2789             << "\n"
2790             << "layout(location = " << perPass.floatColor1Location << ") out vec4 o_color1;\n"
2791             << "layout(location = " << perPass.floatColor2Location << ") out vec4 o_color2;\n"
2792             << "layout(location = " << perPass.intColorLocation << ") out " << intTypePrefix << "vec4 o_color3;\n"
2793             << "\n"
2794             << "layout(push_constant) uniform PushConstants {\n"
2795             << "    uvec4 area;\n"
2796             << "} params;\n"
2797             << "\n"
2798             << "void main(void)\n"
2799             << "{\n"
2800             << "    vec2 uv = (gl_FragCoord.xy - vec2(params.area.xy)) / vec2(params.area.zw);\n";
2801         for (uint32_t sampleID = 0; sampleID < numSamples; ++sampleID)
2802         {
2803             const char *uvComponent = sampleID % 2 == 0 ? "uv.x" : "uv.y";
2804 
2805             const float floatValue  = 1 - static_cast<float>(sampleID / 4) * 0.2f;
2806             const uint32_t intValue = (sampleID + 1) * (sampleID + 1) * 10;
2807             const float depthValue  = 1 - static_cast<float>(sampleID ^ 1) / 16.0f;
2808 
2809             const Vec4 floatChannels(sampleID % 4 == 0 ? 0 : floatValue, sampleID % 4 == 1 ? 0 : floatValue,
2810                                      sampleID % 4 == 2 ? 0 : floatValue, sampleID % 4 == 3 ? 0 : floatValue);
2811             const UVec4 intChannels(intValue, intValue + 1, intValue + 2, intValue + 3);
2812 
2813             src << "    " << (sampleID == 0 ? "" : "else ") << "if (gl_SampleID == " << sampleID << ")\n"
2814                 << "    {\n"
2815                 << "        o_color1 = vec4(" << floatChannels.x() << ", " << floatChannels.y() << ", "
2816                 << floatChannels.z() << ", " << floatChannels.w() << ") * " << uvComponent << ";\n"
2817                 << "        o_color2 = vec4(" << floatChannels.x() << ", " << floatChannels.y() << ", "
2818                 << floatChannels.z() << ", " << floatChannels.w() << ") * " << uvComponent << ";\n"
2819                 << "        o_color3 = " << intTypePrefix << "vec4(vec4(" << intChannels.x() << ", " << intChannels.y()
2820                 << ", " << intChannels.z() << ", " << intChannels.w() << ") * " << uvComponent << ");\n"
2821                 << "        gl_FragDepth = " << depthValue << ";\n"
2822                 << "    }\n";
2823         }
2824         src << "}\n";
2825 
2826         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2827     }
2828 
2829     // Compute shader - verify the results of rendering
2830     //
2831     // Take the formulas used for the fragment shader.  Note the following:
2832     //
2833     //    n-1
2834     //    sum(1 - s*0.2)
2835     //     0                 n - (n*(n-1))/2 * 0.2
2836     //  ----------------- = ----------------------- = 1 - (n-1)*0.1
2837     //          n                    n
2838     //
2839     // When rendering is done to every sample and the attachment is resolved, we expect:
2840     //
2841     // - For float attachments, average of:
2842     //   * Horizontal gradient:
2843     //
2844     //       Vec4(0, 1, 1, 1)            if 2 samples
2845     //       Vec4(0.5v, v, 0.5v, v)        o.w. where v = 1 - (n - 1)*0.1 where n = floor(sampleCount / 4).
2846     //
2847     //   * Vertical gradient:
2848     //
2849     //       Vec4(1, 0, 1, 1)            if 2 samples
2850     //       Vec4(v, 0.5v, v, 0.5v)        o.w. where v = 1 - (n - 1)*0.1 where n = floor(sampleCount / 4).
2851     //
2852     // - For the int attachments, any of UVec4(v, v + 1, v + 2, v + 3) where v = (s+1)*(s+1)*10
2853     // - For the depth attachment, either 1 or 1-1/16 based on whether MAX or SAMPLE_ZERO resolve modes are selected respectively.
2854     // - For the stencil attachment, expect the clear value + 1.
2855     {
2856         const TestParams::PerPass &perPass = params.perPass[0];
2857 
2858         // The shader outputs up to 16 samples
2859         const uint32_t numSamples = static_cast<uint32_t>(perPass.numSamples);
2860 
2861         const float floatValue = 1 - static_cast<float>((numSamples / 4) - 1) * 0.1f;
2862 
2863         const Vec4 floatExpectHorizontal =
2864             numSamples == 2 ? Vec4(0, 1, 1, 1) : Vec4(0.5f * floatValue, floatValue, 0.5f * floatValue, floatValue);
2865         const Vec4 floatExpectVertical =
2866             numSamples == 2 ? Vec4(1, 0, 1, 1) : Vec4(floatValue, 0.5f * floatValue, floatValue, 0.5f * floatValue);
2867 
2868         std::ostringstream src;
2869         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2870             << "#extension GL_EXT_samplerless_texture_functions : require\n"
2871             << "\n"
2872             << "layout(push_constant) uniform PushConstants {\n"
2873             << "    uvec4 area;\n"
2874             << "    uint stencilExpect;\n"
2875             << "} params;\n"
2876             << "\n"
2877             << "layout(local_size_x = 8, local_size_y = 8) in;\n"
2878             << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
2879             << "    uint colorVerification[3];\n"
2880             << "    uint depthVerification;\n"
2881             << "    uint stencilVerification;\n"
2882             << "} sb_out;\n"
2883             << "layout(set = 0, binding = 1) uniform texture2D color1Image;\n"
2884             << "layout(set = 0, binding = 2) uniform texture2D color2Image;\n"
2885             << "layout(set = 0, binding = 3) uniform " << (usesSignedIntFormat ? "i" : "u")
2886             << "texture2D color3Image;\n";
2887         if (isDepthFormat(params.depthStencilFormat))
2888             src << "layout(set = 0, binding = 4) uniform texture2D depthImage;\n";
2889         if (isStencilFormat(params.depthStencilFormat))
2890             src << "layout(set = 0, binding = 5) uniform utexture2D stencilImage;\n";
2891         src << "layout(set = 0, binding = 6, rgba8) uniform writeonly image2DArray verify;\n"
2892             << "\n"
2893             << "bool fmatches(float a, float b, float error)\n"
2894             << "{\n"
2895             << "    return abs(a - b) < error;\n"
2896             << "}\n"
2897             << "bool umatches(uint a, uint b, uint error)\n"
2898             << "{\n"
2899             << "    return abs(a - b) <= error;\n"
2900             << "}\n"
2901             << "bool v4matches(vec4 a, vec4 b, vec4 error)\n"
2902             << "{\n"
2903             << "    return all(lessThan(abs(a - b), error));\n"
2904             << "}\n"
2905             << "bool i4matchesEither(ivec4 a, ivec4 b, ivec4 c, int errorB, int errorC)\n"
2906             << "{\n"
2907             << "    return all(lessThanEqual(abs(a - b), ivec4(errorB))) || all(lessThanEqual(abs(a - c), "
2908                "ivec4(errorC)));\n"
2909             << "}\n"
2910             << "\n"
2911             << "void main (void)\n"
2912             << "{\n"
2913             << "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
2914             << "        return;\n"
2915             << "\n"
2916             << "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
2917             << "    vec2 uv = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5)) / vec2(params.area.zw);\n"
2918             << "\n"
2919             << "    vec4 result1 = vec4(1, 0, 0, 1);\n"
2920             << "    vec4 color1 = texelFetch(color1Image, ivec2(coords), 0);\n"
2921             << "    vec4 expected1H = vec4(" << floatExpectHorizontal.x() << ", " << floatExpectHorizontal.y() << ", "
2922             << floatExpectHorizontal.z() << ", " << floatExpectHorizontal.w() << ");\n"
2923             << "    vec4 expected1V = vec4(" << floatExpectVertical.x() << ", " << floatExpectVertical.y() << ", "
2924             << floatExpectVertical.z() << ", " << floatExpectVertical.w() << ");\n"
2925             << "    vec4 expected1 = (expected1H * uv.x + expected1V * uv.y) / 2.0;\n"
2926             // Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
2927             << "    if (v4matches(color1, expected1, max(expected1H / float(params.area.z), expected1V / "
2928                "float(params.area.w)) + 2.0/255.0))\n"
2929             << "    {\n"
2930             << "        atomicAdd(sb_out.colorVerification[0], 1);\n"
2931             << "        result1 = vec4(0, 1, 0, 1);\n"
2932             << "    }\n"
2933             << "    imageStore(verify, ivec3(coords, 0), result1);\n"
2934             << "\n"
2935             << "    vec4 result2 = vec4(1, 0, 0, 1);\n"
2936             << "    vec4 color2 = texelFetch(color2Image, ivec2(coords), 0);\n"
2937             // Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
2938             << "    if (v4matches(color2, expected1, max(expected1H / float(params.area.z), expected1V / "
2939                "float(params.area.w)) + 2.0/1024.0))\n"
2940             << "    {\n"
2941             << "        atomicAdd(sb_out.colorVerification[1], 1);\n"
2942             << "        result2 = vec4(0, 1, 0, 1);\n"
2943             << "    }\n"
2944             << "    imageStore(verify, ivec3(coords, 1), result2);\n"
2945             << "\n"
2946             << "    vec4 result3 = vec4(1, 0, 0, 1);\n"
2947             << "    ivec4 color3 = ivec4(texelFetch(color3Image, ivec2(coords), 0));\n"
2948             << "    if (";
2949         for (uint32_t sampleID = 0; sampleID < numSamples; ++sampleID)
2950         {
2951             const uint32_t intValue = (sampleID + 1) * (sampleID + 1) * 10;
2952             const UVec4 intExpect(intValue, intValue + 1, intValue + 2, intValue + 3);
2953 
2954             src << (sampleID == 0 ? "" : "        || ") << "i4matchesEither(color3, ivec4(vec4(" << intExpect.x()
2955                 << ", " << intExpect.y() << ", " << intExpect.z() << ", " << intExpect.w() << ") * uv.x), "
2956                 << "ivec4(vec4(" << intExpect.x() << ", " << intExpect.y() << ", " << intExpect.z() << ", "
2957                 << intExpect.w()
2958                 << ") * uv.y), "
2959                 // Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
2960                 << intValue << " / int(params.area.z) + 1, " << intValue << " / int(params.area.w) + 1)"
2961                 << (sampleID == numSamples - 1 ? ")" : "") << "\n";
2962         }
2963         src << "    {\n"
2964             << "        atomicAdd(sb_out.colorVerification[2], 1);\n"
2965             << "        result3 = vec4(0, 1, 0, 1);\n"
2966             << "    }\n"
2967             << "    imageStore(verify, ivec3(coords, 2), result3);\n"
2968             << "\n";
2969         if (isDepthFormat(params.depthStencilFormat))
2970         {
2971             const float expect =
2972                 perPass.depthStencilResolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT ? 1 - 1 / 16.0f : 1.0f;
2973 
2974             src << "    vec4 resultDepth = vec4(1, 0, 0, 1);\n"
2975                 << "    float depth  = texelFetch(depthImage, ivec2(coords), 0).r;\n"
2976                 << "    if (fmatches(depth, " << expect << ", 0.01))\n"
2977                 << "    {\n"
2978                 << "        atomicAdd(sb_out.depthVerification, 1);\n"
2979                 << "        resultDepth = vec4(0, 1, 0, 1);\n"
2980                 << "    }\n"
2981                 << "    imageStore(verify, ivec3(coords, 3), resultDepth);\n";
2982         }
2983         if (isStencilFormat(params.depthStencilFormat))
2984         {
2985             src << "    vec4 resultStencil = vec4(1, 0, 0, 1);\n"
2986                 << "    uint stencil = texelFetch(stencilImage, ivec2(coords), 0).r;\n"
2987                 << "    if (umatches(stencil, params.stencilExpect, 0))\n"
2988                 << "    {\n"
2989                 << "        atomicAdd(sb_out.stencilVerification, 1);\n"
2990                 << "        resultStencil = vec4(0, 1, 0, 1);\n"
2991                 << "    }\n"
2992                 << "    imageStore(verify, ivec3(coords, 4), resultStencil);\n";
2993         }
2994         src << "}\n";
2995 
2996         programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
2997     }
2998 
2999     // Always generate constant-color checks as they are used by vkCmdClearAttachments tests
3000     initConstantColorVerifyPrograms(programCollection, params);
3001 }
3002 
dispatchVerifyBasic(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)3003 void dispatchVerifyBasic(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects)
3004 {
3005     const DeviceInterface &vk = context.getDeviceInterface();
3006     const VkDevice device     = context.getDevice();
3007 
3008     postDrawBarrier(context, testObjects);
3009 
3010     const VkPushConstantRange &verifyPushConstantRange = {
3011         VK_SHADER_STAGE_COMPUTE_BIT,                             // VkShaderStageFlags    stageFlags;
3012         0,                                                       // uint32_t              offset;
3013         static_cast<uint32_t>(sizeof(UVec4) + sizeof(uint32_t)), // uint32_t              size;
3014     };
3015 
3016     Move<VkPipelineLayout> verifyPipelineLayout;
3017     setupVerifyDescriptorSetAndPipeline(context, params, wd, testObjects, &verifyPushConstantRange,
3018                                         verifyPipelineLayout);
3019 
3020     const uint32_t stencilExpect = params.clearValues[3].depthStencil.stencil + 1;
3021 
3022     vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(UVec4),
3023                         &wd.renderArea);
3024     vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, sizeof(UVec4),
3025                         sizeof(uint32_t), &stencilExpect);
3026     vk.cmdDispatch(*testObjects.cmdBuffer, (wd.renderArea.z() + 7) / 8, (wd.renderArea.w() + 7) / 8, 1);
3027 
3028     postVerifyBarrier(context, testObjects, wd.verificationBuffer);
3029 
3030     invalidateAlloc(vk, device, *wd.verificationBufferAlloc);
3031 }
3032 
drawBasic(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)3033 void drawBasic(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects)
3034 {
3035     const InstanceInterface &vki          = context.getInstanceInterface();
3036     const DeviceInterface &vk             = context.getDeviceInterface();
3037     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
3038     const VkDevice device                 = context.getDevice();
3039     VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo;
3040     std::vector<VkFormat> colorAttachmentFormats = {VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED,
3041                                                     VK_FORMAT_UNDEFINED};
3042     std::vector<VkRenderingAttachmentInfo> colorAttachmentInfos(4u);
3043     VkRenderingAttachmentInfo depthStencilAttachmentInfo;
3044 
3045     DE_ASSERT(params.perPass.size() == 1);
3046 
3047     if (params.clearBeforeRenderPass)
3048     {
3049         clearImagesBeforeDraw(context, params, wd, testObjects);
3050     }
3051 
3052     if (params.dynamicRendering)
3053     {
3054         preRenderingImageLayoutTransition(context, params, wd, testObjects);
3055         initResolveImageLayouts(context, params, wd, testObjects);
3056     }
3057 
3058     // Create a render pass and a framebuffer
3059     {
3060         std::vector<VkSubpassDescription2> subpasses;
3061         std::vector<VkImage> images;
3062         std::vector<VkImageView> attachments;
3063         std::vector<VkAttachmentDescription2> attachmentDescriptions;
3064         std::vector<VkAttachmentReference2> attachmentReferences;
3065         std::vector<VkAttachmentReference2> resolveAttachmentReferences;
3066         VkMultisampledRenderToSingleSampledInfoEXT msrtss;
3067         VkSubpassDescriptionDepthStencilResolve depthStencilResolve;
3068         int32_t attachmentNdxes[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
3069         uint32_t attachmentUseMask = 0;
3070 
3071         initializeAttachments(params, wd, images, attachments, 0, attachmentNdxes);
3072 
3073         if (params.dynamicRendering)
3074         {
3075             initializeRenderingAttachmentInfos(params, wd, colorAttachmentInfos, depthStencilAttachmentInfo,
3076                                                colorAttachmentFormats, attachmentNdxes, attachmentUseMask, 0u);
3077 
3078             pipelineRenderingCreateInfo = {
3079                 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,     // VkStructureType    sType
3080                 DE_NULL,                                              // const void*        pNext
3081                 0u,                                                   // uint32_t            viewMask
3082                 static_cast<uint32_t>(colorAttachmentFormats.size()), // uint32_t            colorAttachmentCount
3083                 colorAttachmentFormats.data(),                        // const VkFormat*    pColorAttachmentFormats
3084                 VK_FORMAT_UNDEFINED,                                  // VkFormat            depthAttachmentFormat
3085                 VK_FORMAT_UNDEFINED                                   // VkFormat            stencilAttachmentFormat
3086             };
3087 
3088             if (params.usesDepthStencilInPass(0))
3089             {
3090                 if (isDepthFormat(params.depthStencilFormat))
3091                     pipelineRenderingCreateInfo.depthAttachmentFormat = params.depthStencilFormat;
3092                 if (isStencilFormat(params.depthStencilFormat))
3093                     pipelineRenderingCreateInfo.stencilAttachmentFormat = params.depthStencilFormat;
3094             }
3095         }
3096         else
3097         {
3098             initializeAttachmentDescriptions(params, attachmentDescriptions, params.clearBeforeRenderPass,
3099                                              attachmentNdxes, attachmentUseMask);
3100 
3101             addSubpassDescription(params, 0, attachmentReferences, resolveAttachmentReferences, depthStencilResolve,
3102                                   nullptr, msrtss, subpasses, {}, attachmentNdxes);
3103 
3104             createRenderPassAndFramebuffer(context, wd, testObjects, params.pipelineConstructionType, images,
3105                                            attachments, attachmentDescriptions, subpasses, {});
3106         }
3107     }
3108 
3109     {
3110         const VkPushConstantRange &pushConstantRange = {
3111             VK_SHADER_STAGE_FRAGMENT_BIT,         // VkShaderStageFlags    stageFlags;
3112             0,                                    // uint32_t              offset;
3113             static_cast<uint32_t>(sizeof(UVec4)), // uint32_t              size;
3114         };
3115 
3116         const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
3117         const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
3118         const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device, 0, DE_NULL, 1,
3119                                                    &pushConstantRange);
3120 
3121         testObjects.graphicsPipelines.push_back(pipeline::makeGraphicsPipeline(
3122             vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType,
3123             pipelineLayout, params.dynamicRendering ? DE_NULL : *testObjects.renderPassFramebuffers.back(),
3124             params.dynamicRendering ? &pipelineRenderingCreateInfo : DE_NULL, vertexModule, fragmentModule, false, true,
3125             false, 0, 0, params.perPass[0].intColorLocation, wd.renderArea, wd.renderArea, params.perPass[0].numSamples,
3126             params.useGarbageAttachment));
3127 
3128         if (params.dynamicRendering)
3129         {
3130             startRendering(context, params, wd, testObjects, static_cast<uint32_t>(colorAttachmentFormats.size()),
3131                            colorAttachmentInfos, depthStencilAttachmentInfo, 0u);
3132         }
3133         else
3134         {
3135             startRenderPass(context, wd, testObjects, DE_LENGTH_OF_ARRAY(params.clearValues), params.clearValues);
3136         }
3137 
3138         const VkDeviceSize vertexBufferOffset = 0;
3139         vk.cmdBindVertexBuffers(*testObjects.cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
3140 
3141         vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4),
3142                             &wd.renderArea);
3143         (*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
3144         vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
3145 
3146         if (params.dynamicRendering)
3147         {
3148             vk.cmdEndRendering(*testObjects.cmdBuffer);
3149         }
3150         else
3151         {
3152             testObjects.renderPassFramebuffers.back().end(vk, *testObjects.cmdBuffer);
3153         }
3154     }
3155 
3156     if (params.dynamicRendering)
3157     {
3158         postRenderingResolveImageLayoutTransition(context, params, wd, testObjects);
3159     }
3160 
3161     // Verify results
3162     dispatchVerifyBasic(context, params, wd, testObjects);
3163 }
3164 
3165 //! Verify multisampled rendering is done with the exact number of samples.
testBasic(Context & context,const TestParams params)3166 tcu::TestStatus testBasic(Context &context, const TestParams params)
3167 {
3168     WorkingData wd;
3169     TestObjects testObjects(context);
3170     testStart(context, params, wd, testObjects);
3171 
3172     drawBasic(context, params, wd, testObjects);
3173 
3174     testEnd(context, params, wd, testObjects);
3175     return verify(context, params, wd);
3176 }
3177 
generateBasicTest(de::Random & rng,TestParams & params,const VkSampleCountFlagBits sampleCount,const VkResolveModeFlagBits resolveMode,const bool renderToWholeFramebuffer)3178 void generateBasicTest(de::Random &rng, TestParams &params, const VkSampleCountFlagBits sampleCount,
3179                        const VkResolveModeFlagBits resolveMode, const bool renderToWholeFramebuffer)
3180 {
3181     params.perPass.resize(1);
3182 
3183     TestParams::PerPass &perPass = params.perPass[0];
3184 
3185     // Set the sample count for attachments.
3186     if (params.isMultisampledRenderToSingleSampled)
3187     {
3188         params.numFloatColor1Samples  = VK_SAMPLE_COUNT_1_BIT;
3189         params.numFloatColor2Samples  = VK_SAMPLE_COUNT_1_BIT;
3190         params.numIntColorSamples     = VK_SAMPLE_COUNT_1_BIT;
3191         params.numDepthStencilSamples = VK_SAMPLE_COUNT_1_BIT;
3192 
3193         perPass.resolveFloatColor1  = false;
3194         perPass.resolveFloatColor2  = false;
3195         perPass.resolveIntColor     = false;
3196         perPass.resolveDepthStencil = false;
3197     }
3198     else
3199     {
3200         params.numFloatColor1Samples  = sampleCount;
3201         params.numFloatColor2Samples  = sampleCount;
3202         params.numIntColorSamples     = sampleCount;
3203         params.numDepthStencilSamples = sampleCount;
3204 
3205         perPass.resolveFloatColor1  = true;
3206         perPass.resolveFloatColor2  = true;
3207         perPass.resolveIntColor     = true;
3208         perPass.resolveDepthStencil = true;
3209     }
3210     perPass.depthStencilResolveMode = resolveMode;
3211 
3212     perPass.numSamples = sampleCount;
3213 
3214     // Set locations for the color attachments.
3215     perPass.floatColor1Location = 0;
3216     perPass.floatColor2Location = 1;
3217     perPass.intColorLocation    = 2;
3218 
3219     // Depth/stencil is always used
3220     perPass.hasDepthStencil = true;
3221 
3222     // Always clear before render pass so outside render area can be verified.
3223     params.clearBeforeRenderPass    = true;
3224     params.renderToWholeFramebuffer = renderToWholeFramebuffer;
3225     params.testBlendsColors         = false;
3226 
3227     // Set random clear values.
3228     generateRandomClearValues(rng, params, params.clearValues, false);
3229 
3230     params.rngSeed = rng.getUint32();
3231 }
3232 
dispatchVerifyClearAttachments(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects,const UVec4 regions[RegionCount],const VkClearValue clearValues[RegionCount-1][4])3233 void dispatchVerifyClearAttachments(Context &context, const TestParams &params, WorkingData &wd,
3234                                     TestObjects &testObjects, const UVec4 regions[RegionCount],
3235                                     const VkClearValue clearValues[RegionCount - 1][4])
3236 {
3237     const DeviceInterface &vk = context.getDeviceInterface();
3238     const VkDevice device     = context.getDevice();
3239 
3240     postDrawBarrier(context, testObjects);
3241 
3242     const VkPushConstantRange &verifyPushConstantRange = {
3243         VK_SHADER_STAGE_COMPUTE_BIT,                             // VkShaderStageFlags    stageFlags;
3244         0,                                                       // uint32_t              offset;
3245         static_cast<uint32_t>(sizeof(UVec4) + sizeof(uint32_t)), // uint32_t              size;
3246     };
3247 
3248     Move<VkPipelineLayout> verifyPipelineLayout;
3249     setupVerifyDescriptorSetAndPipeline(context, params, wd, testObjects, &verifyPushConstantRange,
3250                                         verifyPipelineLayout);
3251 
3252     const uint32_t stencilExpect[2] = {
3253         // For region 0, there's a single draw that increments the cleared stencil
3254         params.clearValues[3].depthStencil.stencil + 1,
3255         // For region 1, there's a vkCmdClearAttachments followed by a draw that increments that stencil value
3256         clearValues[0][3].depthStencil.stencil + 1,
3257     };
3258 
3259     // Verify regions 0 and 1 have gradient colors.
3260     for (uint32_t regionNdx = 0; regionNdx < 2; ++regionNdx)
3261     {
3262         vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
3263                             sizeof(UVec4), &regions[regionNdx]);
3264         vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, sizeof(UVec4),
3265                             sizeof(uint32_t), &stencilExpect[regionNdx]);
3266         vk.cmdDispatch(*testObjects.cmdBuffer, (regions[regionNdx].z() + 7) / 8, (regions[regionNdx].w() + 7) / 8, 1);
3267 
3268         postVerifyBarrier(context, testObjects, wd.verificationBuffer);
3269     }
3270 
3271     // Verify the rest of the regions have clear values.  Note that clearValues[0] is unused as it's overriden with a draw call to region 1.
3272     for (uint32_t regionNdx = 2; regionNdx < RegionCount; ++regionNdx)
3273     {
3274         const VkClearValue *regionClearValues = clearValues[regionNdx - 1];
3275         const UVec4 &region                   = regions[regionNdx];
3276 
3277         {
3278             const VerifySingleFloatPushConstants verifyColor1 = {
3279                 region,
3280                 Vec4(regionClearValues[0].color.float32[0], regionClearValues[0].color.float32[1],
3281                      regionClearValues[0].color.float32[2], regionClearValues[0].color.float32[3]),
3282                 0,
3283             };
3284             dispatchVerifyConstantColor(context, testObjects, wd.getResolvedFloatColorImage1View(params),
3285                                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view, wd.verificationBuffer,
3286                                         static_cast<uint32_t>(sizeof(verifyColor1)), &verifyColor1, "comp_singleFloat");
3287         }
3288 
3289         {
3290             const VerifySingleFloatPushConstants verifyColor2 = {
3291                 region,
3292                 Vec4(regionClearValues[1].color.float32[0], regionClearValues[1].color.float32[1],
3293                      regionClearValues[1].color.float32[2], regionClearValues[1].color.float32[3]),
3294                 1,
3295             };
3296             dispatchVerifyConstantColor(context, testObjects, wd.getResolvedFloatColorImage2View(params),
3297                                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view, wd.verificationBuffer,
3298                                         static_cast<uint32_t>(sizeof(verifyColor2)), &verifyColor2, "comp_singleFloat");
3299         }
3300 
3301         {
3302             const VerifySingleIntPushConstants verifyColor3 = {
3303                 region,
3304                 IVec4(regionClearValues[2].color.int32[0], regionClearValues[2].color.int32[1],
3305                       regionClearValues[2].color.int32[2], regionClearValues[2].color.int32[3]),
3306                 2,
3307             };
3308             dispatchVerifyConstantColor(context, testObjects, wd.getResolvedIntColorImageView(params),
3309                                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view, wd.verificationBuffer,
3310                                         static_cast<uint32_t>(sizeof(verifyColor3)), &verifyColor3, "comp_singleInt");
3311         }
3312 
3313         if (isDepthFormat(params.depthStencilFormat))
3314         {
3315             const VerifySingleDepthPushConstants verifyDepth = {
3316                 region,
3317                 regionClearValues[3].depthStencil.depth,
3318             };
3319             dispatchVerifyConstantColor(context, testObjects, wd.getResolvedDepthOnlyImageView(params),
3320                                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, wd.verify.view,
3321                                         wd.verificationBuffer, static_cast<uint32_t>(sizeof(verifyDepth)), &verifyDepth,
3322                                         "comp_singleDepth");
3323         }
3324 
3325         if (isStencilFormat(params.depthStencilFormat))
3326         {
3327             const VerifySingleStencilPushConstants verifyStencil = {
3328                 region,
3329                 regionClearValues[3].depthStencil.stencil,
3330             };
3331             dispatchVerifyConstantColor(context, testObjects, wd.getResolvedStencilOnlyImageView(params),
3332                                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, wd.verify.view,
3333                                         wd.verificationBuffer, static_cast<uint32_t>(sizeof(verifyStencil)),
3334                                         &verifyStencil, "comp_singleStencil");
3335         }
3336     }
3337 
3338     invalidateAlloc(vk, device, *wd.verificationBufferAlloc);
3339 }
3340 
drawClearAttachments(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)3341 void drawClearAttachments(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects)
3342 {
3343     const InstanceInterface &vki          = context.getInstanceInterface();
3344     const DeviceInterface &vk             = context.getDeviceInterface();
3345     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
3346     const VkDevice device                 = context.getDevice();
3347     VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo;
3348     std::vector<VkFormat> colorAttachmentFormats = {VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED,
3349                                                     VK_FORMAT_UNDEFINED};
3350     std::vector<VkRenderingAttachmentInfo> colorAttachmentInfos(4u);
3351     VkRenderingAttachmentInfo depthStencilAttachmentInfo;
3352 
3353     DE_ASSERT(params.perPass.size() == 1);
3354 
3355     if (params.clearBeforeRenderPass)
3356     {
3357         clearImagesBeforeDraw(context, params, wd, testObjects);
3358     }
3359 
3360     if (params.dynamicRendering)
3361     {
3362         preRenderingImageLayoutTransition(context, params, wd, testObjects);
3363         initResolveImageLayouts(context, params, wd, testObjects);
3364     }
3365 
3366     // Create a render pass and a framebuffer
3367     {
3368         std::vector<VkSubpassDescription2> subpasses;
3369         std::vector<VkImage> images;
3370         std::vector<VkImageView> attachments;
3371         std::vector<VkAttachmentDescription2> attachmentDescriptions;
3372         std::vector<VkAttachmentReference2> attachmentReferences;
3373         std::vector<VkAttachmentReference2> resolveAttachmentReferences;
3374         VkMultisampledRenderToSingleSampledInfoEXT msrtss;
3375         VkSubpassDescriptionDepthStencilResolve depthStencilResolve;
3376         int32_t attachmentNdxes[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
3377         uint32_t attachmentUseMask = 0;
3378 
3379         initializeAttachments(params, wd, images, attachments, 0, attachmentNdxes);
3380 
3381         if (params.dynamicRendering)
3382         {
3383             initializeRenderingAttachmentInfos(params, wd, colorAttachmentInfos, depthStencilAttachmentInfo,
3384                                                colorAttachmentFormats, attachmentNdxes, attachmentUseMask, 0u);
3385 
3386             pipelineRenderingCreateInfo = {
3387                 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,     // VkStructureType    sType
3388                 DE_NULL,                                              // const void*        pNext
3389                 0u,                                                   // uint32_t            viewMask
3390                 static_cast<uint32_t>(colorAttachmentFormats.size()), // uint32_t            colorAttachmentCount
3391                 colorAttachmentFormats.data(),                        // const VkFormat*    pColorAttachmentFormats
3392                 VK_FORMAT_UNDEFINED,                                  // VkFormat            depthAttachmentFormat
3393                 VK_FORMAT_UNDEFINED                                   // VkFormat            stencilAttachmentFormat
3394             };
3395 
3396             if (params.usesDepthStencilInPass(0))
3397             {
3398                 if (isDepthFormat(params.depthStencilFormat))
3399                     pipelineRenderingCreateInfo.depthAttachmentFormat = params.depthStencilFormat;
3400                 if (isStencilFormat(params.depthStencilFormat))
3401                     pipelineRenderingCreateInfo.stencilAttachmentFormat = params.depthStencilFormat;
3402             }
3403         }
3404         else
3405         {
3406             initializeAttachmentDescriptions(params, attachmentDescriptions, params.clearBeforeRenderPass,
3407                                              attachmentNdxes, attachmentUseMask);
3408 
3409             addSubpassDescription(params, 0, attachmentReferences, resolveAttachmentReferences, depthStencilResolve,
3410                                   nullptr, msrtss, subpasses, {}, attachmentNdxes);
3411 
3412             createRenderPassAndFramebuffer(context, wd, testObjects, params.pipelineConstructionType, images,
3413                                            attachments, attachmentDescriptions, subpasses, {});
3414         }
3415     }
3416 
3417     UVec4 regions[RegionCount];
3418     getDrawRegions(wd, regions);
3419 
3420     VkClearValue clearValues[RegionCount - 1][4];
3421     de::Random rng(params.rngSeed);
3422     for (uint32_t regionNdx = 0; regionNdx < RegionCount - 1; ++regionNdx)
3423         generateRandomClearValues(rng, params, clearValues[regionNdx], false);
3424 
3425     {
3426         const VkPushConstantRange &pushConstantRange = {
3427             VK_SHADER_STAGE_FRAGMENT_BIT,         // VkShaderStageFlags    stageFlags;
3428             0,                                    // uint32_t              offset;
3429             static_cast<uint32_t>(sizeof(UVec4)), // uint32_t              size;
3430         };
3431 
3432         const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
3433         const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
3434         const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device, 0, DE_NULL, 1,
3435                                                    &pushConstantRange);
3436 
3437         if (params.dynamicRendering)
3438         {
3439             startRendering(context, params, wd, testObjects, static_cast<uint32_t>(colorAttachmentFormats.size()),
3440                            colorAttachmentInfos, depthStencilAttachmentInfo, 0u);
3441         }
3442         else
3443         {
3444             startRenderPass(context, wd, testObjects, DE_LENGTH_OF_ARRAY(params.clearValues), params.clearValues);
3445         }
3446 
3447         // Draw to region[0]
3448         testObjects.graphicsPipelines.push_back(pipeline::makeGraphicsPipeline(
3449             vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType,
3450             pipelineLayout, params.dynamicRendering ? DE_NULL : *testObjects.renderPassFramebuffers.back(),
3451             params.dynamicRendering ? &pipelineRenderingCreateInfo : DE_NULL, vertexModule, fragmentModule, false, true,
3452             false, 0, 0, params.perPass[0].intColorLocation, regions[0], regions[0], params.perPass[0].numSamples,
3453             params.useGarbageAttachment));
3454 
3455         const VkDeviceSize vertexBufferOffset = 0;
3456         vk.cmdBindVertexBuffers(*testObjects.cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
3457 
3458         vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4),
3459                             &regions[0]);
3460         (*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
3461         vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
3462 
3463         // Clear all regions except region 0
3464         {
3465             for (uint32_t regionNdx = 0; regionNdx < RegionCount - 1; ++regionNdx)
3466             {
3467                 const VkClearAttachment attachments[4] = {
3468                     {
3469                         VK_IMAGE_ASPECT_COLOR_BIT,
3470                         static_cast<uint32_t>(params.perPass[0].floatColor1Location),
3471                         clearValues[regionNdx][0],
3472                     },
3473                     {
3474                         VK_IMAGE_ASPECT_COLOR_BIT,
3475                         static_cast<uint32_t>(params.perPass[0].floatColor2Location),
3476                         clearValues[regionNdx][1],
3477                     },
3478                     {
3479                         VK_IMAGE_ASPECT_COLOR_BIT,
3480                         static_cast<uint32_t>(params.perPass[0].intColorLocation),
3481                         clearValues[regionNdx][2],
3482                     },
3483                     {
3484                         getDepthStencilAspectFlags(params.depthStencilFormat),
3485                         0,
3486                         clearValues[regionNdx][3],
3487                     },
3488                 };
3489                 const UVec4 &region            = regions[regionNdx + 1];
3490                 const VkClearRect clearRegions = {
3491                     {{static_cast<int32_t>(region.x()), static_cast<int32_t>(region.y())}, {region.z(), region.w()}},
3492                     0,
3493                     1};
3494 
3495                 vk.cmdClearAttachments(*testObjects.cmdBuffer, 4, attachments, 1, &clearRegions);
3496             }
3497         }
3498 
3499         // Draw to region[1], overriding the clear value
3500         testObjects.graphicsPipelines.push_back(makeGraphicsPipeline(
3501             vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType,
3502             pipelineLayout, params.dynamicRendering ? DE_NULL : *testObjects.renderPassFramebuffers.back(),
3503             params.dynamicRendering ? &pipelineRenderingCreateInfo : DE_NULL, vertexModule, fragmentModule, false, true,
3504             false, 0, 0, params.perPass[0].intColorLocation, regions[1], regions[1], params.perPass[0].numSamples,
3505             params.useGarbageAttachment));
3506 
3507         vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4),
3508                             &regions[1]);
3509         (*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
3510         vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
3511 
3512         if (params.dynamicRendering)
3513         {
3514             vk.cmdEndRendering(*testObjects.cmdBuffer);
3515         }
3516         else
3517         {
3518             testObjects.renderPassFramebuffers.back().end(vk, *testObjects.cmdBuffer);
3519         }
3520     }
3521 
3522     if (params.dynamicRendering)
3523     {
3524         postRenderingResolveImageLayoutTransition(context, params, wd, testObjects);
3525     }
3526 
3527     // Verify results
3528     dispatchVerifyClearAttachments(context, params, wd, testObjects, regions, clearValues);
3529 }
3530 
3531 //! Verify vkCmdClearAttachments works.
testClearAttachments(Context & context,const TestParams params)3532 tcu::TestStatus testClearAttachments(Context &context, const TestParams params)
3533 {
3534     WorkingData wd;
3535     TestObjects testObjects(context);
3536     testStart(context, params, wd, testObjects);
3537 
3538     drawClearAttachments(context, params, wd, testObjects);
3539 
3540     testEnd(context, params, wd, testObjects);
3541     return verify(context, params, wd);
3542 }
3543 
drawOnePass(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects,const ShaderWrapper & vertexModule,const PipelineLayoutWrapper & pipelineLayout,const uint32_t passNdx,const uint32_t subpassNdx,UVec4 regions[RegionCount],VkPipelineRenderingCreateInfo * pipelineRenderingCreateInfo)3544 void drawOnePass(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects,
3545                  const ShaderWrapper &vertexModule, const PipelineLayoutWrapper &pipelineLayout, const uint32_t passNdx,
3546                  const uint32_t subpassNdx, UVec4 regions[RegionCount],
3547                  VkPipelineRenderingCreateInfo *pipelineRenderingCreateInfo)
3548 {
3549     const InstanceInterface &vki          = context.getInstanceInterface();
3550     const DeviceInterface &vk             = context.getDeviceInterface();
3551     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
3552     const VkDevice device                 = context.getDevice();
3553 
3554     const VkDeviceSize vertexBufferOffset = 0;
3555     vk.cmdBindVertexBuffers(*testObjects.cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
3556 
3557     const TestParams::PerPass &perPass = params.perPass[passNdx];
3558 
3559     // Each subpass performs 4 sets of one or two draw calls.  Two if there is depth/stencil and one if not.
3560     // When depth/stencil is present, the first draw call writes to depth, while the second draw call does a depth test.
3561     // The four sets are draw calls with scissors dividing the render area in four:
3562     //
3563     // +--------+---------------+
3564     // |        |               |
3565     // |   1    |       2       |
3566     // |        |               |
3567     // +--------+---------------+
3568     // |        |               |
3569     // |        |               |
3570     // |   3    |       4       |
3571     // |        |               |
3572     // |        |               |
3573     // +--------+---------------+
3574     //
3575 
3576     std::ostringstream fragName;
3577     fragName << "frag_" << passNdx;
3578     const ShaderWrapper fragmentModule(
3579         ShaderWrapper(vk, device, context.getBinaryCollection().get(fragName.str().c_str()), 0u));
3580 
3581     for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
3582     {
3583         testObjects.graphicsPipelines.push_back(pipeline::makeGraphicsPipeline(
3584             vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType,
3585             pipelineLayout, params.dynamicRendering ? DE_NULL : *testObjects.renderPassFramebuffers.back(),
3586             params.dynamicRendering ? pipelineRenderingCreateInfo : DE_NULL, vertexModule, fragmentModule, true, true,
3587             false, 1 << passNdx, subpassNdx, perPass.intColorLocation, regions[regionNdx], regions[regionNdx],
3588             perPass.numSamples, params.useGarbageAttachment));
3589 
3590         vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4),
3591                             &regions[regionNdx]);
3592         vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UVec4),
3593                             sizeof(perPass.drawConstantsWithDepthWrite[regionNdx]),
3594                             &perPass.drawConstantsWithDepthWrite[regionNdx]);
3595         (*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
3596         vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
3597 
3598         if (perPass.hasDepthStencil)
3599         {
3600             testObjects.graphicsPipelines.push_back(pipeline::makeGraphicsPipeline(
3601                 vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType,
3602                 pipelineLayout, params.dynamicRendering ? DE_NULL : *testObjects.renderPassFramebuffers.back(),
3603                 params.dynamicRendering ? pipelineRenderingCreateInfo : DE_NULL, vertexModule, fragmentModule, true,
3604                 false, true, 1 << passNdx, subpassNdx, perPass.intColorLocation, regions[regionNdx], regions[regionNdx],
3605                 perPass.numSamples, params.useGarbageAttachment));
3606 
3607             vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4),
3608                                 &regions[regionNdx]);
3609             vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UVec4),
3610                                 sizeof(perPass.drawConstantsWithDepthTest[regionNdx]),
3611                                 &perPass.drawConstantsWithDepthTest[regionNdx]);
3612             (*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
3613             vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
3614         }
3615     }
3616 }
3617 
dispatchVerifyMultiPassRendering(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects,UVec4 regions[RegionCount])3618 void dispatchVerifyMultiPassRendering(Context &context, const TestParams &params, WorkingData &wd,
3619                                       TestObjects &testObjects, UVec4 regions[RegionCount])
3620 {
3621     const DeviceInterface &vk = context.getDeviceInterface();
3622     const VkDevice device     = context.getDevice();
3623 
3624     postDrawBarrier(context, testObjects);
3625 
3626     const VkPushConstantRange &verifyPushConstantRange = {
3627         VK_SHADER_STAGE_COMPUTE_BIT,                                        // VkShaderStageFlags    stageFlags;
3628         0,                                                                  // uint32_t              offset;
3629         static_cast<uint32_t>(sizeof(UVec4) + sizeof(VerifyPushConstants)), // uint32_t              size;
3630     };
3631 
3632     Move<VkPipelineLayout> verifyPipelineLayout;
3633     setupVerifyDescriptorSetAndPipeline(context, params, wd, testObjects, &verifyPushConstantRange,
3634                                         verifyPipelineLayout);
3635 
3636     for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
3637     {
3638         if (regionNdx != 0)
3639         {
3640             const VkMemoryBarrier preVerifyBarrier = {
3641                 VK_STRUCTURE_TYPE_MEMORY_BARRIER,                       // VkStructureType    sType;
3642                 DE_NULL,                                                // const void*        pNext;
3643                 VK_ACCESS_SHADER_WRITE_BIT,                             // VkAccessFlags      srcAccessMask;
3644                 VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags      dstAccessMask;
3645             };
3646 
3647             vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3648                                   VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 1u, &preVerifyBarrier, 0u,
3649                                   DE_NULL, 0u, DE_NULL);
3650         }
3651 
3652         vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
3653                             sizeof(UVec4), &regions[regionNdx]);
3654         vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, sizeof(UVec4),
3655                             sizeof(params.verifyConstants[regionNdx]), &params.verifyConstants[regionNdx]);
3656         vk.cmdDispatch(*testObjects.cmdBuffer, (regions[regionNdx].z() + 7) / 8, (regions[regionNdx].w() + 7) / 8, 1);
3657     }
3658 
3659     postVerifyBarrier(context, testObjects, wd.verificationBuffer);
3660 
3661     invalidateAlloc(vk, device, *wd.verificationBufferAlloc);
3662 }
3663 
drawSingleRenderPass(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)3664 void drawSingleRenderPass(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects)
3665 {
3666     const DeviceInterface &vk   = context.getDeviceInterface();
3667     const VkDevice device       = context.getDevice();
3668     const uint32_t numSubpasses = static_cast<uint32_t>(params.perPass.size());
3669 
3670     if (params.clearBeforeRenderPass)
3671     {
3672         clearImagesBeforeDraw(context, params, wd, testObjects);
3673     }
3674 
3675     // Create a render pass and a framebuffer
3676     {
3677         std::vector<VkSubpassDescription2> subpasses;
3678         std::vector<VkImage> images;
3679         std::vector<VkImageView> attachments;
3680         std::vector<VkAttachmentDescription2> attachmentDescriptions;
3681         std::vector<std::vector<VkAttachmentReference2>> attachmentReferences(numSubpasses);
3682         std::vector<std::vector<VkAttachmentReference2>> resolveAttachmentReferences(numSubpasses);
3683         std::vector<std::vector<uint32_t>> preserveAttachments(numSubpasses);
3684         std::vector<VkSubpassDependency2> subpassDependencies;
3685         std::vector<VkMultisampledRenderToSingleSampledInfoEXT> msrtss(numSubpasses);
3686         std::vector<VkSubpassDescriptionDepthStencilResolve> depthStencilResolve(numSubpasses);
3687         int32_t attachmentNdxes[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
3688         uint32_t attachmentUseMask = 0;
3689 
3690         initializeAttachments(params, wd, images, attachments, params.perPass.size(), attachmentNdxes);
3691         initializeAttachmentDescriptions(params, attachmentDescriptions, params.clearBeforeRenderPass, attachmentNdxes,
3692                                          attachmentUseMask);
3693 
3694         for (uint32_t passNdx = 0; passNdx < numSubpasses; ++passNdx)
3695         {
3696             addSubpassDescription(params, passNdx, attachmentReferences[passNdx], resolveAttachmentReferences[passNdx],
3697                                   depthStencilResolve[passNdx], &preserveAttachments[passNdx], msrtss[passNdx],
3698                                   subpasses, {}, attachmentNdxes);
3699 
3700             if (passNdx > 0)
3701                 addSubpassDependency(passNdx, subpassDependencies);
3702         }
3703 
3704         createRenderPassAndFramebuffer(context, wd, testObjects, params.pipelineConstructionType, images, attachments,
3705                                        attachmentDescriptions, subpasses, subpassDependencies);
3706     }
3707 
3708     const VkPushConstantRange &pushConstantRange = {
3709         VK_SHADER_STAGE_FRAGMENT_BIT,                                     // VkShaderStageFlags    stageFlags;
3710         0,                                                                // uint32_t              offset;
3711         static_cast<uint32_t>(sizeof(UVec4) + sizeof(DrawPushConstants)), // uint32_t              size;
3712     };
3713 
3714     const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
3715     const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device, 0, DE_NULL, 1,
3716                                                &pushConstantRange);
3717 
3718     UVec4 regions[RegionCount];
3719     getDrawRegions(wd, regions);
3720 
3721     startRenderPass(context, wd, testObjects, DE_LENGTH_OF_ARRAY(params.clearValues), params.clearValues);
3722 
3723     for (uint32_t passNdx = 0; passNdx < numSubpasses; ++passNdx)
3724     {
3725         if (passNdx != 0)
3726             testObjects.renderPassFramebuffers.back().nextSubpass(vk, *testObjects.cmdBuffer,
3727                                                                   VK_SUBPASS_CONTENTS_INLINE);
3728 
3729         drawOnePass(context, params, wd, testObjects, vertexModule, pipelineLayout, passNdx, passNdx, regions, DE_NULL);
3730     }
3731 
3732     testObjects.renderPassFramebuffers.back().end(vk, *testObjects.cmdBuffer);
3733 
3734     // Verify results
3735     dispatchVerifyMultiPassRendering(context, params, wd, testObjects, regions);
3736 }
3737 
3738 //! Verify multisampled rendering in subpasses
testSingleRenderPass(Context & context,const TestParams params)3739 tcu::TestStatus testSingleRenderPass(Context &context, const TestParams params)
3740 {
3741     WorkingData wd;
3742     TestObjects testObjects(context);
3743     testStart(context, params, wd, testObjects);
3744 
3745     drawSingleRenderPass(context, params, wd, testObjects);
3746 
3747     testEnd(context, params, wd, testObjects);
3748     return verify(context, params, wd);
3749 }
3750 
drawMultiRenderPass(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)3751 void drawMultiRenderPass(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects)
3752 {
3753     const DeviceInterface &vk      = context.getDeviceInterface();
3754     const VkDevice device          = context.getDevice();
3755     const uint32_t numRenderPasses = static_cast<uint32_t>(params.perPass.size());
3756 
3757     if (params.clearBeforeRenderPass)
3758     {
3759         clearImagesBeforeDraw(context, params, wd, testObjects);
3760     }
3761 
3762     if (params.dynamicRendering)
3763     {
3764         preRenderingImageLayoutTransition(context, params, wd, testObjects);
3765         initResolveImageLayouts(context, params, wd, testObjects);
3766     }
3767 
3768     const VkPushConstantRange &pushConstantRange = {
3769         VK_SHADER_STAGE_FRAGMENT_BIT,                                     // VkShaderStageFlags    stageFlags;
3770         0,                                                                // uint32_t              offset;
3771         static_cast<uint32_t>(sizeof(UVec4) + sizeof(DrawPushConstants)), // uint32_t              size;
3772     };
3773 
3774     const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
3775     const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device, 0, DE_NULL, 1,
3776                                                &pushConstantRange);
3777 
3778     UVec4 regions[RegionCount];
3779     getDrawRegions(wd, regions);
3780 
3781     uint32_t attachmentUseMask = 0;
3782 
3783     for (uint32_t renderPassNdx = 0; renderPassNdx < numRenderPasses; ++renderPassNdx)
3784     {
3785         // Create a render pass and a framebuffer
3786         std::vector<VkSubpassDescription2> subpasses;
3787         std::vector<VkImage> images;
3788         std::vector<VkImageView> attachments;
3789         std::vector<VkAttachmentDescription2> attachmentDescriptions;
3790         std::vector<VkAttachmentReference2> attachmentReferences;
3791         std::vector<VkAttachmentReference2> resolveAttachmentReferences;
3792         VkMultisampledRenderToSingleSampledInfoEXT msrtss;
3793         VkSubpassDescriptionDepthStencilResolve depthStencilResolve;
3794         int32_t attachmentNdxes[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
3795         VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo;
3796         std::vector<VkFormat> colorAttachmentFormats = {VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED,
3797                                                         VK_FORMAT_UNDEFINED};
3798         std::vector<VkRenderingAttachmentInfo> colorAttachmentInfos(4u);
3799         VkRenderingAttachmentInfo depthStencilAttachmentInfo;
3800 
3801         std::vector<VkClearValue> clearValues;
3802 
3803         initializeAttachments(params, wd, images, attachments, renderPassNdx, attachmentNdxes);
3804         if (params.dynamicRendering)
3805         {
3806             initializeRenderingAttachmentInfos(params, wd, colorAttachmentInfos, depthStencilAttachmentInfo,
3807                                                colorAttachmentFormats, attachmentNdxes, attachmentUseMask,
3808                                                renderPassNdx);
3809 
3810             pipelineRenderingCreateInfo = {
3811                 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,     // VkStructureType    sType
3812                 DE_NULL,                                              // const void*        pNext
3813                 0u,                                                   // uint32_t            viewMask
3814                 static_cast<uint32_t>(colorAttachmentFormats.size()), // uint32_t            colorAttachmentCount
3815                 colorAttachmentFormats.data(),                        // const VkFormat*    pColorAttachmentFormats
3816                 VK_FORMAT_UNDEFINED,                                  // VkFormat            depthAttachmentFormat
3817                 VK_FORMAT_UNDEFINED                                   // VkFormat            stencilAttachmentFormat
3818             };
3819 
3820             if (params.usesDepthStencilInPass(renderPassNdx))
3821             {
3822                 if (isDepthFormat(params.depthStencilFormat))
3823                     pipelineRenderingCreateInfo.depthAttachmentFormat = params.depthStencilFormat;
3824                 if (isStencilFormat(params.depthStencilFormat))
3825                     pipelineRenderingCreateInfo.stencilAttachmentFormat = params.depthStencilFormat;
3826             }
3827         }
3828         else
3829         {
3830             initializeAttachmentDescriptions(params, attachmentDescriptions, params.clearBeforeRenderPass,
3831                                              attachmentNdxes, attachmentUseMask);
3832 
3833             addSubpassDescription(params, renderPassNdx, attachmentReferences, resolveAttachmentReferences,
3834                                   depthStencilResolve, nullptr, msrtss, subpasses, {}, attachmentNdxes);
3835 
3836             createRenderPassAndFramebuffer(context, wd, testObjects, params.pipelineConstructionType, images,
3837                                            attachments, attachmentDescriptions, subpasses, {});
3838 
3839             // Init clear values
3840             if (attachmentNdxes[0] >= 0)
3841                 clearValues.push_back(params.clearValues[0]);
3842             if (attachmentNdxes[1] >= 0)
3843                 clearValues.push_back(params.clearValues[1]);
3844             if (attachmentNdxes[2] >= 0)
3845                 clearValues.push_back(params.clearValues[2]);
3846             if (attachmentNdxes[3] >= 0)
3847                 clearValues.push_back(params.clearValues[3]);
3848         }
3849 
3850         if (renderPassNdx > 0)
3851         {
3852             const VkMemoryBarrier interRenderPassBarrier = {
3853                 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType    sType;
3854                 DE_NULL,                          // const void*        pNext;
3855                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
3856                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags      srcAccessMask;
3857                 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
3858                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
3859                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags      dstAccessMask;
3860             };
3861 
3862             vk.cmdPipelineBarrier(
3863                 *testObjects.cmdBuffer,
3864                 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
3865                     VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
3866                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
3867                     VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
3868                 0u, 1u, &interRenderPassBarrier, 0u, DE_NULL, 0u, DE_NULL);
3869         }
3870 
3871         if (params.dynamicRendering)
3872         {
3873             startRendering(context, params, wd, testObjects, static_cast<uint32_t>(colorAttachmentFormats.size()),
3874                            colorAttachmentInfos, depthStencilAttachmentInfo, renderPassNdx);
3875         }
3876         else
3877         {
3878             startRenderPass(context, wd, testObjects, static_cast<uint32_t>(clearValues.size()),
3879                             dataOrNullPtr(clearValues));
3880         }
3881 
3882         drawOnePass(context, params, wd, testObjects, vertexModule, pipelineLayout, renderPassNdx, 0, regions,
3883                     &pipelineRenderingCreateInfo);
3884 
3885         if (params.dynamicRendering)
3886         {
3887             vk.cmdEndRendering(*testObjects.cmdBuffer);
3888         }
3889         else
3890         {
3891             testObjects.renderPassFramebuffers.back().end(vk, *testObjects.cmdBuffer);
3892         }
3893     }
3894 
3895     if (params.dynamicRendering)
3896     {
3897         postRenderingResolveImageLayoutTransition(context, params, wd, testObjects);
3898     }
3899 
3900     // Verify results
3901     dispatchVerifyMultiPassRendering(context, params, wd, testObjects, regions);
3902 }
3903 
3904 //! Verify multisampled rendering in multiple render passes
testMultiRenderPass(Context & context,const TestParams params)3905 tcu::TestStatus testMultiRenderPass(Context &context, const TestParams params)
3906 {
3907     WorkingData wd;
3908     TestObjects testObjects(context);
3909     testStart(context, params, wd, testObjects);
3910 
3911     drawMultiRenderPass(context, params, wd, testObjects);
3912 
3913     testEnd(context, params, wd, testObjects);
3914     return verify(context, params, wd);
3915 }
3916 
generateMultiPassTest(de::Random & rng,TestParams & params)3917 void generateMultiPassTest(de::Random &rng, TestParams &params)
3918 {
3919     const VkSampleCountFlagBits sampleRange[] = {
3920         // 4x multisampling is always supported.  A higher chance is given to that to avoid too many tests being skipped.
3921         VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT,
3922         VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT,
3923     };
3924 
3925     const VkResolveModeFlagBits depthStencilResolveModeRange[] = {
3926         // SAMPLE_ZERO is always supported, while MAX may not be.  A higher chance is given to SAMPLE_ZERO to avoid too many tests being skipped.
3927         VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
3928         VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
3929         VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
3930         VK_RESOLVE_MODE_MAX_BIT,
3931     };
3932 
3933     // Generate a random number of passes (either subpass or render pass)
3934     const uint32_t passCount = rng.getInt(1, 4);
3935 
3936     params.perPass.resize(passCount);
3937 
3938     std::vector<uint32_t> passAttachments;
3939 
3940     uint32_t usedAttachmentMask = 0;
3941     if (params.isMultisampledRenderToSingleSampled)
3942     {
3943         // Decide which attachments will be used in which pass.  This is a bit mask.
3944         for (uint32_t passNdx = 0; passNdx < passCount; ++passNdx)
3945         {
3946             passAttachments.push_back(rng.getInt(1, 15));
3947             usedAttachmentMask |= passAttachments.back();
3948         }
3949     }
3950     else
3951     {
3952         passAttachments.push_back(15); // Make sure all attachments have the same sample count
3953         for (uint32_t passNdx = 1; passNdx < passCount; ++passNdx)
3954             passAttachments.push_back(rng.getInt(1, 15));
3955     }
3956 
3957     // Decide which attachments will be single-sampled.  This is a bit mask.
3958     // Include any attachment that is not used in any subpass just to make all attachments valid.
3959     const uint32_t singleSampledAttachmentsMask =
3960         params.isMultisampledRenderToSingleSampled ? rng.getInt(1, 15) | (~usedAttachmentMask & 0xF) : 0;
3961 
3962     DBG("Generating test for %u passes\n", passCount);
3963 
3964     // Set the sample count for attachments.  Multisampled attachments that are used in the same pass will get the same number of samples.
3965     if ((singleSampledAttachmentsMask & 1) != 0)
3966         params.numFloatColor1Samples = VK_SAMPLE_COUNT_1_BIT;
3967     if ((singleSampledAttachmentsMask & 2) != 0)
3968         params.numFloatColor2Samples = VK_SAMPLE_COUNT_1_BIT;
3969     if ((singleSampledAttachmentsMask & 4) != 0)
3970         params.numIntColorSamples = VK_SAMPLE_COUNT_1_BIT;
3971     if ((singleSampledAttachmentsMask & 8) != 0)
3972         params.numDepthStencilSamples = VK_SAMPLE_COUNT_1_BIT;
3973 
3974     for (uint32_t passNdx = 0; passNdx < passCount; ++passNdx)
3975     {
3976         TestParams::PerPass &perPass = params.perPass[passNdx];
3977 
3978         const uint32_t multisampledAttachments        = passAttachments[passNdx] & ~singleSampledAttachmentsMask;
3979         const VkSampleCountFlagBits randomSampleCount = sampleRange[rng.getInt(0, DE_LENGTH_OF_ARRAY(sampleRange) - 1)];
3980         DBG("  + random samples: %d, multisampled attachments: %#x\n", randomSampleCount, multisampledAttachments);
3981 
3982         if (multisampledAttachments == 0)
3983         {
3984             // If all attachments are single-sampled, choose a random number of samples for the render pass.
3985             perPass.numSamples = randomSampleCount;
3986         }
3987         else
3988         {
3989             // Otherwise see if any of the attachments has already been decided what number of samples it has.
3990             VkSampleCountFlagBits sampleCount =
3991                 (multisampledAttachments & 1) != 0 && params.numFloatColor1Samples != 0 ?
3992                     params.numFloatColor1Samples :
3993                 (multisampledAttachments & 2) != 0 && params.numFloatColor2Samples != 0 ?
3994                     params.numFloatColor2Samples :
3995                 (multisampledAttachments & 4) != 0 && params.numIntColorSamples != 0 ?
3996                     params.numIntColorSamples :
3997                 (multisampledAttachments & 8) != 0 && params.numDepthStencilSamples != 0 ?
3998                     params.numDepthStencilSamples
3999                     // If none of the attachments already have a defined sample, generate a random sample count to use for all of them.
4000                     :
4001                     randomSampleCount;
4002             DBG("   + sample count from attachments or random: %d (already: %d %d %d %d)\n", sampleCount,
4003                 params.numFloatColor1Samples, params.numFloatColor2Samples, params.numIntColorSamples,
4004                 params.numDepthStencilSamples);
4005 
4006             perPass.numSamples = sampleCount;
4007 
4008             // Make all multisampled attachments used in the pass have the same number of samples.  Additionally, make all the multisampled attachments
4009             // used in conjunction with the these ones in future passes also have the same number of samples.
4010             for (uint32_t followingPassNdx = passNdx; followingPassNdx < passCount; ++followingPassNdx)
4011             {
4012                 const uint32_t followingMultisampledAttachments =
4013                     passAttachments[followingPassNdx] & ~singleSampledAttachmentsMask;
4014 
4015                 if ((followingMultisampledAttachments & 1) != 0)
4016                     params.numFloatColor1Samples = sampleCount;
4017                 if ((followingMultisampledAttachments & 2) != 0)
4018                     params.numFloatColor2Samples = sampleCount;
4019                 if ((followingMultisampledAttachments & 4) != 0)
4020                     params.numIntColorSamples = sampleCount;
4021                 if ((followingMultisampledAttachments & 8) != 0)
4022                     params.numDepthStencilSamples = sampleCount;
4023             }
4024         }
4025 
4026         // Generate random locations for the color attachments.
4027         int32_t locations[] = {0, 1, 2, 3};
4028         for (int i = 0; i < 3; ++i)
4029         {
4030             int j = rng.getInt(i, 3);
4031             std::swap(locations[i], locations[j]);
4032         }
4033         size_t nextLocation         = 0;
4034         perPass.floatColor1Location = (passAttachments[passNdx] & 1) != 0 ? locations[nextLocation++] : -1;
4035         perPass.floatColor2Location = (passAttachments[passNdx] & 2) != 0 ? locations[nextLocation++] : -1;
4036         perPass.intColorLocation    = (passAttachments[passNdx] & 4) != 0 ? locations[nextLocation++] : -1;
4037 
4038         // Specify if depth/stencil is used
4039         perPass.hasDepthStencil = (passAttachments[passNdx] & 8) != 0;
4040 
4041         perPass.resolveFloatColor1      = false;
4042         perPass.resolveFloatColor2      = false;
4043         perPass.resolveIntColor         = false;
4044         perPass.resolveDepthStencil     = false;
4045         perPass.depthStencilResolveMode = VK_RESOLVE_MODE_NONE;
4046 
4047         DBG(" - %u samples, locations: %d %d %d has D/S? %d\n", perPass.numSamples, perPass.floatColor1Location,
4048             perPass.floatColor2Location, perPass.intColorLocation, perPass.hasDepthStencil);
4049     }
4050 
4051     DBG(" Sample counts: %u %u %u %u\n", params.numFloatColor1Samples, params.numFloatColor2Samples,
4052         params.numIntColorSamples, params.numDepthStencilSamples);
4053 
4054     // Assert that generated passes are valid
4055     for (uint32_t passNdx = 0; passNdx < passCount; ++passNdx)
4056     {
4057         const VkSampleCountFlagBits sampleCounts[4] = {params.numFloatColor1Samples, params.numFloatColor2Samples,
4058                                                        params.numIntColorSamples, params.numDepthStencilSamples};
4059         VkSampleCountFlagBits subpassSampleCount    = VK_SAMPLE_COUNT_1_BIT;
4060 
4061         for (uint32_t attachmentNdx = 0; attachmentNdx < 4; ++attachmentNdx)
4062         {
4063             if ((passAttachments[passNdx] & (1 << attachmentNdx)) == 0)
4064                 continue;
4065 
4066             const VkSampleCountFlagBits attachmentSampleCount = sampleCounts[attachmentNdx] == VK_SAMPLE_COUNT_1_BIT ?
4067                                                                     params.perPass[passNdx].numSamples :
4068                                                                     sampleCounts[attachmentNdx];
4069 
4070             if (subpassSampleCount == VK_SAMPLE_COUNT_1_BIT)
4071                 subpassSampleCount = attachmentSampleCount;
4072 
4073             DE_ASSERT(subpassSampleCount == attachmentSampleCount);
4074         }
4075     }
4076 
4077     // Determine when multisampled attachments should resolve.
4078     uint32_t resolvedAttachmentsMask = singleSampledAttachmentsMask;
4079     for (uint32_t passNdx = passCount; passNdx > 0; --passNdx)
4080     {
4081         TestParams::PerPass &perPass         = params.perPass[passNdx - 1];
4082         const uint32_t unresolvedAttachments = passAttachments[passNdx - 1] & ~resolvedAttachmentsMask;
4083 
4084         // Make every multisampled attachment resolve in the last pass it's used.
4085         if ((unresolvedAttachments & 1) != 0)
4086             perPass.resolveFloatColor1 = true;
4087         if ((unresolvedAttachments & 2) != 0)
4088             perPass.resolveFloatColor2 = true;
4089         if ((unresolvedAttachments & 4) != 0)
4090             perPass.resolveIntColor = true;
4091         if ((unresolvedAttachments & 8) != 0)
4092             perPass.resolveDepthStencil = true;
4093 
4094         if (perPass.resolveDepthStencil || params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT)
4095             perPass.depthStencilResolveMode =
4096                 depthStencilResolveModeRange[rng.getInt(0, DE_LENGTH_OF_ARRAY(depthStencilResolveModeRange) - 1)];
4097 
4098         resolvedAttachmentsMask |= unresolvedAttachments;
4099 
4100         DBG(" - Resolved 0x%x in pass %u\n", unresolvedAttachments, passNdx - 1);
4101     }
4102 
4103     // Decide whether clear should be done as part of the render pass.  Tests loadOp=CLEAR vs loadOp=LOAD.
4104     params.clearBeforeRenderPass = rng.getBool();
4105     // Decide whether should render to the whole framebuffer or a subarea.
4106     params.renderToWholeFramebuffer = rng.getBool();
4107     // These tests blend color so they can verify the results all at once at the end.
4108     params.testBlendsColors = true;
4109 
4110     // Set random clear values.  Use small values as draw calls do additive blending.
4111     generateRandomClearValues(rng, params, params.clearValues, true);
4112 
4113     // Decide DrawPushConstants
4114     for (uint32_t passNdx = 0; passNdx < passCount; ++passNdx)
4115     {
4116         TestParams::PerPass &perPass = params.perPass[passNdx];
4117 
4118         for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4119         {
4120             perPass.drawConstantsWithDepthWrite[regionNdx] = DrawPushConstants{
4121                 {Vec4(rng.getFloat(0.05f, 0.1f), 0, rng.getFloat(0.05f, 0.1f), 0),
4122                  Vec4(0, rng.getFloat(0.05f, 0.1f), 0, rng.getFloat(0.05f, 0.1f))},
4123                 {Vec4(rng.getFloat(0.05f, 0.1f), rng.getFloat(0.05f, 0.1f), 0, 0),
4124                  Vec4(0, 0, rng.getFloat(0.05f, 0.1f), rng.getFloat(0.05f, 0.1f))},
4125                 {IVec4(0, 0, 0, 0), IVec4(0, 0, 0, 0)},
4126                 // Use quantized values to avoid values that are too close and may cause precision issues
4127                 Vec2(0.1f * static_cast<float>(rng.getInt(2, 9)), 0.1f * static_cast<float>(rng.getInt(2, 9))),
4128             };
4129 
4130             perPass.drawConstantsWithDepthTest[regionNdx] = DrawPushConstants{
4131                 {Vec4(rng.getFloat(0.05f, 0.1f), 0, rng.getFloat(0.05f, 0.1f), 0),
4132                  Vec4(0, rng.getFloat(0.05f, 0.1f), 0, rng.getFloat(0.05f, 0.1f))},
4133                 {Vec4(rng.getFloat(0.05f, 0.1f), rng.getFloat(0.05f, 0.1f), 0, 0),
4134                  Vec4(0, 0, rng.getFloat(0.05f, 0.1f), rng.getFloat(0.05f, 0.1f))},
4135                 {IVec4(0, 0, 0, 0), IVec4(0, 0, 0, 0)},
4136                 Vec2(0.1f * static_cast<float>(rng.getInt(2, 9)) + 0.05f,
4137                      0.1f * static_cast<float>(rng.getInt(2, 8)) + 0.05f),
4138             };
4139 
4140             // Integer resolve may choose any sample, so we modify only one channel per pass (hence the maximum of 4 passes).  This way, the verification
4141             // shader can accept two values per channel.
4142             perPass.drawConstantsWithDepthWrite[regionNdx].color3Data[0][passNdx] = rng.getInt(1000, 5000);
4143             perPass.drawConstantsWithDepthWrite[regionNdx].color3Data[1][passNdx] = rng.getInt(1000, 5000);
4144             perPass.drawConstantsWithDepthTest[regionNdx].color3Data[0][passNdx]  = rng.getInt(1000, 5000);
4145             perPass.drawConstantsWithDepthTest[regionNdx].color3Data[1][passNdx]  = rng.getInt(1000, 5000);
4146         }
4147     }
4148 
4149     // Calculate VerifyPushConstants.  Walk through the passes and emulate what the draw calls would produce.
4150     // Note: Color clear value is not applied and is added by the verification shader.  This is because the verification shader interpolates colors with black,
4151     // so the baseline (clear value) is added afterwards.
4152     Vec2 depthResult[RegionCount];
4153     UVec2 stencilResult[RegionCount];
4154     for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4155     {
4156         depthResult[regionNdx] =
4157             Vec2(params.clearValues[3].depthStencil.depth, params.clearValues[3].depthStencil.depth);
4158         stencilResult[regionNdx] =
4159             UVec2(params.clearValues[3].depthStencil.stencil, params.clearValues[3].depthStencil.stencil);
4160     }
4161 
4162     for (uint32_t passNdx = 0; passNdx < passCount; ++passNdx)
4163     {
4164         TestParams::PerPass &perPass = params.perPass[passNdx];
4165 
4166         for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4167         {
4168             // Apply the draw call output to enabled attachments.  Note that the tests always do additive blending, and when depth test succeeds, stencil is incremented.
4169 
4170             // First draw call overwrites depth and always succeeds.
4171             // Second draw call overwrites only the samples that pass the depth test (which is GREATER).
4172             const bool evenSamplesPassDepthTest =
4173                 perPass.hasDepthStencil && (!isDepthFormat(params.depthStencilFormat) ||
4174                                             perPass.drawConstantsWithDepthTest[regionNdx].depthData[0] >
4175                                                 perPass.drawConstantsWithDepthWrite[regionNdx].depthData[0]);
4176             const bool oddSamplesPassDepthTest =
4177                 perPass.hasDepthStencil && (!isDepthFormat(params.depthStencilFormat) ||
4178                                             perPass.drawConstantsWithDepthTest[regionNdx].depthData[1] >
4179                                                 perPass.drawConstantsWithDepthWrite[regionNdx].depthData[1]);
4180 
4181             if (perPass.floatColor1Location >= 0)
4182             {
4183                 params.verifyConstants[regionNdx].color1Data[0] +=
4184                     perPass.drawConstantsWithDepthWrite[regionNdx].color1Data[0];
4185                 params.verifyConstants[regionNdx].color1Data[1] +=
4186                     perPass.drawConstantsWithDepthWrite[regionNdx].color1Data[1];
4187                 if (evenSamplesPassDepthTest)
4188                     params.verifyConstants[regionNdx].color1Data[0] +=
4189                         perPass.drawConstantsWithDepthTest[regionNdx].color1Data[0];
4190                 if (oddSamplesPassDepthTest)
4191                     params.verifyConstants[regionNdx].color1Data[1] +=
4192                         perPass.drawConstantsWithDepthTest[regionNdx].color1Data[1];
4193             }
4194             if (perPass.floatColor2Location >= 0)
4195             {
4196                 params.verifyConstants[regionNdx].color2Data[0] +=
4197                     perPass.drawConstantsWithDepthWrite[regionNdx].color2Data[0];
4198                 params.verifyConstants[regionNdx].color2Data[1] +=
4199                     perPass.drawConstantsWithDepthWrite[regionNdx].color2Data[1];
4200                 if (evenSamplesPassDepthTest)
4201                     params.verifyConstants[regionNdx].color2Data[0] +=
4202                         perPass.drawConstantsWithDepthTest[regionNdx].color2Data[0];
4203                 if (oddSamplesPassDepthTest)
4204                     params.verifyConstants[regionNdx].color2Data[1] +=
4205                         perPass.drawConstantsWithDepthTest[regionNdx].color2Data[1];
4206             }
4207             if (perPass.intColorLocation >= 0)
4208             {
4209                 // Note that integer formats don't blend, so always take the last value that's written.  Each pass writes to only one channel, and color mask is used
4210                 // to emulate the effect of blending.
4211                 if (evenSamplesPassDepthTest)
4212                     params.verifyConstants[regionNdx].color3Data[0] +=
4213                         perPass.drawConstantsWithDepthTest[regionNdx].color3Data[0];
4214                 else
4215                     params.verifyConstants[regionNdx].color3Data[0] +=
4216                         perPass.drawConstantsWithDepthWrite[regionNdx].color3Data[0];
4217 
4218                 if (oddSamplesPassDepthTest)
4219                     params.verifyConstants[regionNdx].color3Data[1] +=
4220                         perPass.drawConstantsWithDepthTest[regionNdx].color3Data[1];
4221                 else
4222                     params.verifyConstants[regionNdx].color3Data[1] +=
4223                         perPass.drawConstantsWithDepthWrite[regionNdx].color3Data[1];
4224             }
4225             if (perPass.hasDepthStencil)
4226             {
4227                 depthResult[regionNdx] = perPass.drawConstantsWithDepthWrite[regionNdx].depthData;
4228                 stencilResult[regionNdx] += UVec2(1);
4229 
4230                 if (evenSamplesPassDepthTest)
4231                     ++stencilResult[regionNdx][0];
4232                 if (oddSamplesPassDepthTest)
4233                     ++stencilResult[regionNdx][1];
4234             }
4235 
4236             // There is no need to resolve color attachments between passes.  For float formats, the additive nature of blend and resolve means we can continue adding to
4237             // the two color vectors and get the same result in the end, no matter when and how often resolve happens.  For the integer formats this is not true (because resolve
4238             // does not average), so the test makes sure every channel is written to in only one pass, which again means there's no need to perform a resolve in between passes.
4239             // Depth/stencil needs to resolve though, either if multisampled and requested or if it's single sampled.
4240             if (perPass.resolveDepthStencil || params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT)
4241             {
4242                 DE_ASSERT(perPass.depthStencilResolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT ||
4243                           perPass.depthStencilResolveMode == VK_RESOLVE_MODE_MAX_BIT);
4244                 if (perPass.depthStencilResolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
4245                 {
4246                     params.verifyConstants[regionNdx].depthData   = depthResult[regionNdx][0];
4247                     params.verifyConstants[regionNdx].stencilData = stencilResult[regionNdx][0];
4248                 }
4249                 else
4250                 {
4251                     params.verifyConstants[regionNdx].depthData =
4252                         std::max(depthResult[regionNdx][0], depthResult[regionNdx][1]);
4253                     params.verifyConstants[regionNdx].stencilData =
4254                         std::max(stencilResult[regionNdx][0], stencilResult[regionNdx][1]);
4255                 }
4256 
4257                 // If depth/stencil is single-sampled, prepare the data for the next pass.  If multisampled, it will no longer be used after the resolve.
4258                 depthResult[regionNdx][0] = depthResult[regionNdx][1] = params.verifyConstants[regionNdx].depthData;
4259                 stencilResult[regionNdx][0]                           = stencilResult[regionNdx][1] =
4260                     params.verifyConstants[regionNdx].stencilData;
4261             }
4262         }
4263     }
4264 
4265     params.rngSeed = rng.getUint32();
4266 
4267     // Note: formats are decided outside this function
4268 }
4269 
initMultipassPrograms(SourceCollections & programCollection,const TestParams params)4270 void initMultipassPrograms(SourceCollections &programCollection, const TestParams params)
4271 {
4272     // Vertex shader - position
4273     {
4274         std::ostringstream src;
4275         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4276             << "\n"
4277             << "layout(location = 0) in  vec4 in_position;\n"
4278             << "\n"
4279             << "out gl_PerVertex {\n"
4280             << "    vec4 gl_Position;\n"
4281             << "};\n"
4282             << "\n"
4283             << "void main(void)\n"
4284             << "{\n"
4285             << "    gl_Position = in_position;\n"
4286             << "}\n";
4287 
4288         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
4289     }
4290 
4291     const bool usesSignedIntFormat = params.intColorFormat == VK_FORMAT_R16G16B16A16_SINT;
4292     const char *intTypePrefix      = usesSignedIntFormat ? "i" : "u";
4293 
4294     // Fragment shader - output color based on sample index and push constants
4295     size_t count = params.perPass.size();
4296     if (!params.renderToAttachment)
4297         ++count;
4298     for (size_t passNdx = 0; passNdx < count; ++passNdx)
4299     {
4300         const TestParams::PerPass &perPass = params.perPass[passNdx % params.perPass.size()];
4301 
4302         // The framebuffer contains four attachments with a mixture of samples.  A subpass can only contain a mixture of 1x and Nx samples with the pipelines configured at Nx multisampled rendering.
4303         // The fragment shader is adjusted based on which of these attachments are used in the subpass.  The output of the fragment shader is determined by push constants
4304         // as such (2 colors specified per output in uniform data):
4305         //
4306         // - For even samples, output color is interpolation of color 0 and transparent black from left to right
4307         // - For odd samples, output color is interpolation of color 1 and transparent black from top to bottom
4308         //
4309         // Additionally, the fragment shader outputs depth based on the sample index as well.
4310         //
4311         std::ostringstream src;
4312         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4313             << "\n";
4314 
4315         if (perPass.floatColor1Location >= 0)
4316             src << "layout(location = " << perPass.floatColor1Location << ") out vec4 o_color1;\n";
4317         else if (passNdx == params.perPass.size())
4318             src << "layout(location = 0) out vec4 o_color1;\n";
4319         if (perPass.floatColor2Location >= 0)
4320             src << "layout(location = " << perPass.floatColor2Location << ") out vec4 o_color2;\n";
4321         if (perPass.intColorLocation >= 0)
4322             src << "layout(location = " << perPass.intColorLocation << ") out " << intTypePrefix << "vec4 o_color3;\n";
4323 
4324         src << "\n"
4325             << "layout(push_constant) uniform PushConstants {\n"
4326             << "    uvec4 area;\n"
4327             << "    vec4 color1Data[2];\n"
4328             << "    vec4 color2Data[2];\n"
4329             << "    ivec4 color3Data[2];\n"
4330             << "    vec2 depthData;\n"
4331             << "} params;\n"
4332             << "\n"
4333             << "void main(void)\n"
4334             << "{\n"
4335             << "    vec2 uv = (gl_FragCoord.xy - vec2(params.area.xy)) / vec2(params.area.zw);\n"
4336             << "    if (gl_SampleID % 2 == 0)\n"
4337             << "    {\n";
4338 
4339         if (perPass.floatColor1Location >= 0 || passNdx == params.perPass.size())
4340             src << "        o_color1 = params.color1Data[0] * uv.x;\n";
4341         if (perPass.floatColor2Location >= 0)
4342             src << "        o_color2 = params.color2Data[0] * uv.x;\n";
4343         if (perPass.intColorLocation >= 0)
4344             src << "        o_color3 = " << intTypePrefix << "vec4(vec4(params.color3Data[0]) * uv.x);\n";
4345         if (perPass.hasDepthStencil)
4346             src << "        gl_FragDepth = params.depthData.x;\n";
4347 
4348         src << "    }\n"
4349             << "    else\n"
4350             << "    {\n";
4351 
4352         if (perPass.floatColor1Location >= 0 || passNdx == params.perPass.size())
4353             src << "        o_color1 = params.color1Data[1] * uv.y;\n";
4354         if (perPass.floatColor2Location >= 0)
4355             src << "        o_color2 = params.color2Data[1] * uv.y;\n";
4356         if (perPass.intColorLocation >= 0)
4357             src << "        o_color3 = " << intTypePrefix << "vec4(vec4(params.color3Data[1]) * uv.y);\n";
4358         if (perPass.hasDepthStencil)
4359             src << "        gl_FragDepth = params.depthData.y;\n";
4360 
4361         src << "    }\n"
4362             << "}\n";
4363 
4364         std::ostringstream name;
4365         name << "frag_" << passNdx;
4366 
4367         programCollection.glslSources.add(name.str()) << glu::FragmentSource(src.str());
4368     }
4369 
4370     // Compute shader - verify the results of rendering
4371     {
4372         // The images are cleared and rendered to, possibly multiple times with blend, by blending between one color and black horizontally and another color and black vertically for every other sample.
4373         // Once resolved, the resulting image is verified by interpolating one color and black horizontally, another color and black vertically, averaging them and adding in the clear color.  For integer
4374         // formats, instead of averaging the two interpolated colors, either of the colors is accepted as integer resolves selects any sample.  A comparison threshold is used to avoid precision issues.
4375         // Each pixel that passes the test atomically increments an integer in the output buffer.  The test passes if the final number in the output buffer is the same as the number of pixels in the area being verified.
4376 
4377         std::ostringstream src;
4378         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4379             << "#extension GL_EXT_samplerless_texture_functions : require\n"
4380             << "\n"
4381             << "layout(push_constant) uniform PushConstants {\n"
4382             << "    uvec4 area;\n"
4383             << "    vec4 color1Data[2];\n"
4384             << "    vec4 color2Data[2];\n"
4385             << "    ivec4 color3Data[2];\n"
4386             << "    float depthData;\n"
4387             << "    uint stencilData;\n"
4388             << "} params;\n"
4389             << "\n"
4390             << "layout(local_size_x = 8, local_size_y = 8) in;\n"
4391             << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
4392             << "    uint colorVerification[3];\n"
4393             << "    uint depthVerification;\n"
4394             << "    uint stencilVerification;\n"
4395             << "} sb_out;\n"
4396             << "layout(set = 0, binding = 1) uniform texture2D color1Image;\n"
4397             << "layout(set = 0, binding = 2) uniform texture2D color2Image;\n"
4398             << "layout(set = 0, binding = 3) uniform " << (usesSignedIntFormat ? "i" : "u")
4399             << "texture2D color3Image;\n";
4400         if (isDepthFormat(params.depthStencilFormat))
4401             src << "layout(set = 0, binding = 4) uniform texture2D depthImage;\n";
4402         if (isStencilFormat(params.depthStencilFormat))
4403             src << "layout(set = 0, binding = 5) uniform utexture2D stencilImage;\n";
4404         src << "layout(set = 0, binding = 6, rgba8) uniform writeonly image2DArray verify;\n"
4405             << "\n"
4406             << "bool fmatches(float a, float b, float error)\n"
4407             << "{\n"
4408             << "    return abs(a - b) < error;\n"
4409             << "}\n"
4410             << "bool umatches(uint a, uint b, uint error)\n"
4411             << "{\n"
4412             << "    return abs(a - b) <= error;\n"
4413             << "}\n"
4414             << "bool v4matches(vec4 a, vec4 b, vec4 error)\n"
4415             << "{\n"
4416             << "    return all(lessThan(abs(a - b), error));\n"
4417             << "}\n"
4418             << "bool i4matchesEither(ivec4 a, ivec4 b, ivec4 c, ivec4 errorB, ivec4 errorC)\n"
4419             << "{\n"
4420             << "    const bvec4 bMatches = lessThanEqual(abs(a - b), errorB);\n"
4421             << "    const bvec4 cMatches = lessThanEqual(abs(a - c), errorC);\n"
4422             << "    return all(bvec4(bMatches.x || cMatches.x, bMatches.y || cMatches.y, bMatches.z || cMatches.z, "
4423                "bMatches.w || cMatches.w));\n"
4424             << "}\n"
4425             << "\n"
4426             << "void main (void)\n"
4427             << "{\n"
4428             << "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
4429             << "        return;\n"
4430             << "\n"
4431             << "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
4432             << "    vec2 uv = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5)) / vec2(params.area.zw);\n"
4433             << "\n"
4434             << "    vec4 result1 = vec4(1, 0, 0, 1);\n"
4435             << "    vec4 color1 = texelFetch(color1Image, ivec2(coords), 0);\n"
4436             << "    vec4 expected1 = (params.color1Data[0] * uv.x + params.color1Data[1] * uv.y) / 2.0";
4437         if (params.testBlendsColors)
4438             src << " + vec4(" << params.clearValues[0].color.float32[0] << ", "
4439                 << params.clearValues[0].color.float32[1] << ", " << params.clearValues[0].color.float32[2] << ", "
4440                 << params.clearValues[0].color.float32[3] << ")";
4441         src << ";\n"
4442             // Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
4443             << "    if (v4matches(color1, expected1, max(params.color1Data[0] / float(params.area.z), "
4444                "params.color1Data[1] / float(params.area.w)) + 2.0/255.0))\n"
4445             << "    {\n"
4446             << "        atomicAdd(sb_out.colorVerification[0], 1);\n"
4447             << "        result1 = vec4(0, 1, 0, 1);\n"
4448             << "    }\n"
4449             << "    imageStore(verify, ivec3(coords, 0), result1);\n"
4450             << "\n"
4451             << "    vec4 result2 = vec4(1, 0, 0, 1);\n"
4452             << "    vec4 color2 = texelFetch(color2Image, ivec2(coords), 0);\n"
4453             << "    vec4 expected2 = (params.color2Data[0] * uv.x + params.color2Data[1] * uv.y) / 2.0";
4454         if (params.testBlendsColors)
4455             src << " + vec4(" << params.clearValues[1].color.float32[0] << ", "
4456                 << params.clearValues[1].color.float32[1] << ", " << params.clearValues[1].color.float32[2] << ", "
4457                 << params.clearValues[1].color.float32[3] << ")";
4458         src << ";\n"
4459             // Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
4460             << "    if (v4matches(color2, expected2, max(params.color2Data[0] / float(params.area.z), "
4461                "params.color2Data[1] / float(params.area.w)) + 2.0/1024.0))\n"
4462             << "    {\n"
4463             << "        atomicAdd(sb_out.colorVerification[1], 1);\n"
4464             << "        result2 = vec4(0, 1, 0, 1);\n"
4465             << "    }\n"
4466             << "    imageStore(verify, ivec3(coords, 1), result2);\n"
4467             << "\n"
4468             << "    vec4 result3 = vec4(1, 0, 0, 1);\n"
4469             << "    ivec4 color3 = ivec4(texelFetch(color3Image, ivec2(coords), 0));\n";
4470         // Note that integer formats don't blend, so clear values are discarded, except for channels that are never written to.  Each pass
4471         // outputs only to one channel.
4472         if (params.testBlendsColors)
4473             src << "    ivec4 clearValue3 = ivec4("
4474                 << (params.perPass[0].intColorLocation < 0 ? params.clearValues[2].color.int32[0] : 0) << ", "
4475                 << (params.perPass.size() < 2 || params.perPass[1].intColorLocation < 0 ?
4476                         params.clearValues[2].color.int32[1] :
4477                         0)
4478                 << ", "
4479                 << (params.perPass.size() < 3 || params.perPass[2].intColorLocation < 0 ?
4480                         params.clearValues[2].color.int32[2] :
4481                         0)
4482                 << ", "
4483                 << (params.perPass.size() < 4 || params.perPass[3].intColorLocation < 0 ?
4484                         params.clearValues[2].color.int32[3] :
4485                         0)
4486                 << ")"
4487                 << ";\n";
4488         else
4489             src << "    ivec4 clearValue3 = ivec4(0);\n";
4490         src << "    ivec4 expected3_0 = ivec4(params.color3Data[0] * uv.x) + clearValue3;\n"
4491             << "    ivec4 expected3_1 = ivec4(params.color3Data[1] * uv.y) + clearValue3;\n"
4492             // Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
4493             << "    if (i4matchesEither(color3, expected3_0, expected3_1, params.color3Data[0] / int(params.area.z), "
4494                "params.color3Data[1] / int(params.area.w)))\n"
4495             << "    {\n"
4496             << "        atomicAdd(sb_out.colorVerification[2], 1);\n"
4497             << "        result3 = vec4(0, 1, 0, 1);\n"
4498             << "    }\n"
4499             << "    imageStore(verify, ivec3(coords, 2), result3);\n"
4500             << "\n";
4501         if (isDepthFormat(params.depthStencilFormat))
4502             src << "    vec4 resultDepth = vec4(1, 0, 0, 1);\n"
4503                 << "    float depth  = texelFetch(depthImage, ivec2(coords), 0).r;\n"
4504                 << "    if (fmatches(depth, params.depthData, 0.01))\n"
4505                 << "    {\n"
4506                 << "        atomicAdd(sb_out.depthVerification, 1);\n"
4507                 << "        resultDepth = vec4(0, 1, 0, 1);\n"
4508                 << "    }\n"
4509                 << "    imageStore(verify, ivec3(coords, 3), resultDepth);\n";
4510         if (isStencilFormat(params.depthStencilFormat))
4511             src << "    vec4 resultStencil = vec4(1, 0, 0, 1);\n"
4512                 << "    uint stencil = texelFetch(stencilImage, ivec2(coords), 0).r;\n"
4513                 << "    if (umatches(stencil, params.stencilData, 0))\n"
4514                 << "    {\n"
4515                 << "        atomicAdd(sb_out.stencilVerification, 1);\n"
4516                 << "        resultStencil = vec4(0, 1, 0, 1);\n"
4517                 << "    }\n"
4518                 << "    imageStore(verify, ivec3(coords, 4), resultStencil);\n";
4519         src << "}\n";
4520 
4521         programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
4522     }
4523 
4524     const bool verifyOutsideRenderArea = params.clearBeforeRenderPass && !params.renderToWholeFramebuffer;
4525     if (verifyOutsideRenderArea)
4526         initConstantColorVerifyPrograms(programCollection, params);
4527 }
4528 
copyToInputAttachment(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects,const PipelineLayoutWrapper & pipelineLayout,const ShaderWrapper & vertexModule,const UVec4 * regions)4529 void copyToInputAttachment(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects,
4530                            const PipelineLayoutWrapper &pipelineLayout, const ShaderWrapper &vertexModule,
4531                            const UVec4 *regions)
4532 {
4533     const InstanceInterface &vki          = context.getInstanceInterface();
4534     const DeviceInterface &vk             = context.getDeviceInterface();
4535     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
4536     const VkDevice device                 = context.getDevice();
4537 
4538     const ShaderWrapper fragmentModule2(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag_2"), 0u));
4539 
4540     const VkRect2D renderArea = {{static_cast<int32_t>(wd.renderArea.x()), static_cast<int32_t>(wd.renderArea.y())},
4541                                  {wd.renderArea.z(), wd.renderArea.w()}};
4542 
4543     vk::VkAttachmentDescription2 attachmentDescription{
4544         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
4545         DE_NULL,                                    // const void* pNext;
4546         (VkAttachmentDescriptionFlags)0u,           // VkAttachmentDescriptionFlags flags;
4547         params.floatColor1Format,                   // VkFormat format;
4548         params.numFloatColor1Samples,               // VkSampleCountFlagBits samples;
4549         VK_ATTACHMENT_LOAD_OP_CLEAR,                // VkAttachmentLoadOp loadOp;
4550         VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp storeOp;
4551         VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp stencilLoadOp;
4552         VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp stencilStoreOp;
4553         VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout initialLayout;
4554         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout finalLayout;
4555     };
4556 
4557     vk::VkAttachmentReference2 attachmentReference{
4558         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
4559         DE_NULL,                                  // const void* pNext;
4560         0u,                                       // uint32_t attachment;
4561         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
4562         VK_IMAGE_ASPECT_COLOR_BIT,                // VkImageAspectFlags aspectMask;
4563     };
4564 
4565     VkMultisampledRenderToSingleSampledInfoEXT msrtss = {
4566         VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT, // VkStructureType            sType
4567         DE_NULL,                                                          // const void*                pNext
4568         VK_TRUE,                      // VkBool32                    multisampledRenderToSingleSampledEnable
4569         params.perPass[0].numSamples, // VkSampleCountFlagBits    rasterizationSamples
4570     };
4571 
4572     vk::VkSubpassDescription2 subpass = {
4573         VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, // VkStructureType                 sType;
4574         &msrtss,                                 // const void*                     pNext;
4575         (VkSubpassDescriptionFlags)0,            // VkSubpassDescriptionFlags       flags;
4576         VK_PIPELINE_BIND_POINT_GRAPHICS,         // VkPipelineBindPoint             pipelineBindPoint;
4577         0u,                                      // uint32_t                        viewMask;
4578         0u,                                      // uint32_t                        inputAttachmentCount;
4579         DE_NULL,                                 // const VkAttachmentReference2*   pInputAttachments;
4580         1u,                                      // uint32_t                        colorAttachmentCount;
4581         &attachmentReference,                    // const VkAttachmentReference2*   pColorAttachments;
4582         0u,                                      // const VkAttachmentReference2*   pResolveAttachments;
4583         DE_NULL,                                 // const VkAttachmentReference2*   pDepthStencilAttachment;
4584         0u,                                      // uint32_t                        preserveAttachmentCount;
4585         DE_NULL,                                 // const uint32_t*                 pPreserveAttachments;
4586     };
4587 
4588     const VkRenderPassCreateInfo2 renderPassInfo = {
4589         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, // VkStructureType sType;
4590         DE_NULL,                                     // const void* pNext;
4591         (VkRenderPassCreateFlags)0,                  // VkRenderPassCreateFlags flags;
4592         1u,                                          // uint32_t attachmentCount;
4593         &attachmentDescription,                      // const VkAttachmentDescription2* pAttachments;
4594         1u,                                          // uint32_t subpassCount;
4595         &subpass,                                    // const VkSubpassDescription2* pSubpasses;
4596         0u,                                          // uint32_t dependencyCount;
4597         DE_NULL,                                     // const VkSubpassDependency2* pDependencies;
4598         0u,                                          // uint32_t                         correlatedViewMaskCount;
4599         DE_NULL,                                     // const uint32_t*                  pCorrelatedViewMasks;
4600     };
4601 
4602     testObjects.dataRenderPassFramebuffer =
4603         RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo);
4604     testObjects.dataRenderPassFramebuffer.createFramebuffer(vk, device, *wd.dataColor1.image, *wd.dataColor1.view,
4605                                                             wd.framebufferSize.x(), wd.framebufferSize.y());
4606 
4607     testObjects.dataRenderPassFramebuffer.begin(vk, *testObjects.cmdBuffer, renderArea, 1u, params.clearValues);
4608 
4609     // start render pass and end after
4610     const VkDeviceSize vertexBufferOffset = 0;
4611     vk.cmdBindVertexBuffers(*testObjects.cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
4612 
4613     // First draw call outputs to color attachment 1 and depth/stencil.  It doesn't blend with clear for simplicity of the verification code.
4614     for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4615     {
4616         testObjects.graphicsPipelines.push_back(pipeline::makeGraphicsPipeline(
4617             vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType,
4618             pipelineLayout, *testObjects.dataRenderPassFramebuffer, DE_NULL, vertexModule, fragmentModule2, false, true,
4619             false, 0, 0, 0, regions[regionNdx], regions[regionNdx], params.perPass[0].numSamples,
4620             params.useGarbageAttachment, true));
4621 
4622         vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4),
4623                             &regions[regionNdx]);
4624         vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UVec4),
4625                             sizeof(params.perPass[0].drawConstantsWithDepthWrite[regionNdx]),
4626                             &params.perPass[0].drawConstantsWithDepthWrite[regionNdx]);
4627         (*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
4628         vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
4629     }
4630 
4631     testObjects.dataRenderPassFramebuffer.end(vk, *testObjects.cmdBuffer);
4632 
4633     vk::VkBufferImageCopy copy = {
4634         0u,                                      // VkDeviceSize                         bufferOffset;
4635         0u,                                      // uint32_t                                     bufferRowLength;
4636         0u,                                      // uint32_t                                     bufferImageHeight;
4637         {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u}, // VkImageSubresourceLayers     imageSubresource;
4638         {0u, 0u, 0u},                            // VkOffset3D                           imageOffset;
4639         {wd.framebufferSize.x(), wd.framebufferSize.y(), 1u} // VkExtent3D                           imageExtent;
4640     };
4641 
4642     vk::VkImageMemoryBarrier dataBarrier = {
4643         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // VkStructureType sType;
4644         DE_NULL,                                    // const void* pNext;
4645         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags srcAccessMask;
4646         VK_ACCESS_TRANSFER_READ_BIT,                // VkAccessFlags dstAccessMask;
4647         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout oldLayout;
4648         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,       // VkImageLayout newLayout;
4649         0u,                                         // uint32_t srcQueueFamilyIndex;
4650         0u,                                         // uint32_t dstQueueFamilyIndex;
4651         *wd.dataColor1.image,                       // VkImage image;
4652         {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
4653     };
4654     vk::VkImageMemoryBarrier preBarrier = {
4655         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // VkStructureType sType;
4656         DE_NULL,                                    // const void* pNext;
4657         VK_ACCESS_NONE,                             // VkAccessFlags srcAccessMask;
4658         VK_ACCESS_TRANSFER_WRITE_BIT,               // VkAccessFlags dstAccessMask;
4659         VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout oldLayout;
4660         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,       // VkImageLayout newLayout;
4661         0u,                                         // uint32_t srcQueueFamilyIndex;
4662         0u,                                         // uint32_t dstQueueFamilyIndex;
4663         *wd.floatColor1.image,                      // VkImage image;
4664         {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
4665     };
4666     vk::VkImageMemoryBarrier postBarrier = {
4667         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // VkStructureType sType;
4668         DE_NULL,                                    // const void* pNext;
4669         VK_ACCESS_TRANSFER_WRITE_BIT,               // VkAccessFlags srcAccessMask;
4670         VK_ACCESS_SHADER_READ_BIT,                  // VkAccessFlags dstAccessMask;
4671         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,       // VkImageLayout oldLayout;
4672         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,       // VkImageLayout newLayout;
4673         0u,                                         // uint32_t srcQueueFamilyIndex;
4674         0u,                                         // uint32_t dstQueueFamilyIndex;
4675         *wd.floatColor1.image,                      // VkImage image;
4676         {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
4677     };
4678     VkDeviceSize bufferSize = static_cast<VkDeviceSize>(wd.framebufferSize.x() * wd.framebufferSize.y() * 4u);
4679     vk::VkBufferMemoryBarrier bufferBarrier = {
4680         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
4681         DE_NULL,                                 // const void* pNext;
4682         VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags srcAccessMask;
4683         VK_ACCESS_TRANSFER_READ_BIT,             // VkAccessFlags dstAccessMask;
4684         0u,                                      // uint32_t srcQueueFamilyIndex;
4685         0u,                                      // uint32_t dstQueueFamilyIndex;
4686         *wd.dataBuffer,                          // VkBuffer buffer;
4687         0u,                                      // VkDeviceSize offset;
4688         bufferSize                               // VkDeviceSize size;
4689     };
4690     vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
4691                           VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dataBarrier);
4692     vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_NONE, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
4693                           DE_NULL, 0u, DE_NULL, 1u, &preBarrier);
4694     vk.cmdCopyImageToBuffer(*testObjects.cmdBuffer, *wd.dataColor1.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4695                             *wd.dataBuffer, 1u, &copy);
4696     vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
4697                           0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
4698     vk.cmdCopyBufferToImage(*testObjects.cmdBuffer, *wd.dataBuffer, *wd.floatColor1.image,
4699                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copy);
4700     vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
4701                           0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &postBarrier);
4702 }
4703 
drawInputAttachments(Context & context,const TestParams & params,WorkingData & wd,TestObjects & testObjects)4704 void drawInputAttachments(Context &context, const TestParams &params, WorkingData &wd, TestObjects &testObjects)
4705 {
4706     const InstanceInterface &vki          = context.getInstanceInterface();
4707     const DeviceInterface &vk             = context.getDeviceInterface();
4708     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
4709     const VkDevice device                 = context.getDevice();
4710     const uint32_t numSubpasses           = static_cast<uint32_t>(params.perPass.size());
4711 
4712     if (params.clearBeforeRenderPass)
4713     {
4714         clearImagesBeforeDraw(context, params, wd, testObjects);
4715     }
4716 
4717     // Create a render pass and a framebuffer
4718     {
4719         std::vector<VkSubpassDescription2> subpasses;
4720         std::vector<VkImage> images;
4721         std::vector<VkImageView> attachments;
4722         std::vector<VkAttachmentDescription2> attachmentDescriptions;
4723         std::vector<std::vector<VkAttachmentReference2>> attachmentReferences(numSubpasses);
4724         std::vector<std::vector<VkAttachmentReference2>> resolveAttachmentReferences(numSubpasses);
4725         std::vector<std::vector<uint32_t>> preserveAttachments(numSubpasses);
4726         std::vector<VkAttachmentReference2> inputAttachmentReferences;
4727         std::vector<VkSubpassDependency2> subpassDependencies;
4728         std::vector<VkMultisampledRenderToSingleSampledInfoEXT> msrtss(numSubpasses);
4729         std::vector<VkSubpassDescriptionDepthStencilResolve> depthStencilResolve(numSubpasses);
4730         int32_t attachmentNdxes[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
4731         uint32_t attachmentUseMask = 0;
4732 
4733         initializeAttachments(params, wd, images, attachments, params.perPass.size(), attachmentNdxes);
4734         initializeAttachmentDescriptions(params, attachmentDescriptions, params.clearBeforeRenderPass, attachmentNdxes,
4735                                          attachmentUseMask);
4736 
4737         DE_ASSERT(numSubpasses == 2);
4738         inputAttachmentReferences.resize(2,
4739                                          VkAttachmentReference2{
4740                                              VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType       sType;
4741                                              DE_NULL,                                  // const void*           pNext;
4742                                              VK_ATTACHMENT_UNUSED,      // uint32_t              attachment;
4743                                              VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout         layout;
4744                                              0,                         // VkImageAspectFlags    aspectMask;
4745                                          });
4746         // Color attachment 1 and depth/stencil attachment are used as input attachments in subpass 1.
4747         initializeAttachmentReference(inputAttachmentReferences[0], attachmentNdxes[0], VK_FORMAT_UNDEFINED, true);
4748         initializeAttachmentReference(inputAttachmentReferences[1], attachmentNdxes[3], params.depthStencilFormat,
4749                                       true);
4750 
4751         for (uint32_t passNdx = 0; passNdx < numSubpasses; ++passNdx)
4752         {
4753             const std::vector<VkAttachmentReference2> noInputAttachments;
4754 
4755             addSubpassDescription(params, passNdx, attachmentReferences[passNdx], resolveAttachmentReferences[passNdx],
4756                                   depthStencilResolve[passNdx], &preserveAttachments[passNdx], msrtss[passNdx],
4757                                   subpasses, passNdx == 0 ? noInputAttachments : inputAttachmentReferences,
4758                                   attachmentNdxes);
4759         }
4760 
4761         subpassDependencies.push_back(VkSubpassDependency2{
4762             VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, // VkStructureType         sType;
4763             DE_NULL,                                // const void*             pNext;
4764             0,                                      // uint32_t                srcSubpass;
4765             1,                                      // uint32_t                dstSubpass;
4766 
4767             VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
4768                 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags    srcStageMask;
4769 
4770             VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags    dstStageMask;
4771 
4772             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
4773                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags           srcAccessMask;
4774 
4775             VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags           dstAccessMask;
4776 
4777             VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags       dependencyFlags;
4778             0,                           // int32_t                 viewOffset;
4779         });
4780 
4781         createRenderPassAndFramebuffer(context, wd, testObjects, params.pipelineConstructionType, images, attachments,
4782                                        attachmentDescriptions, subpasses, subpassDependencies);
4783     }
4784 
4785     const VkPushConstantRange &pushConstantRange = {
4786         VK_SHADER_STAGE_FRAGMENT_BIT,                                     // VkShaderStageFlags    stageFlags;
4787         0,                                                                // uint32_t              offset;
4788         static_cast<uint32_t>(sizeof(UVec4) + sizeof(DrawPushConstants)), // uint32_t              size;
4789     };
4790 
4791     const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
4792     const ShaderWrapper fragmentModule0(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag_0"), 0u));
4793     const ShaderWrapper fragmentModule1(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag_1"), 0u));
4794     const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device, 0, DE_NULL, 1,
4795                                                &pushConstantRange);
4796 
4797     // Descriptor set and layout for the draw call that uses input attachments
4798     const Unique<VkDescriptorSetLayout> descriptorSetLayout(
4799         DescriptorSetLayoutBuilder()
4800             .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
4801             .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
4802             .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
4803             .build(vk, device));
4804 
4805     testObjects.descriptorPools.emplace_back(
4806         DescriptorPoolBuilder()
4807             .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u)
4808             .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u)
4809             .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u)
4810             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
4811 
4812     testObjects.descriptorSets.emplace_back(
4813         makeDescriptorSet(vk, device, *testObjects.descriptorPools.back(), *descriptorSetLayout));
4814 
4815     const VkDescriptorImageInfo color1Info =
4816         makeDescriptorImageInfo(DE_NULL, *wd.floatColor1.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4817     const VkDescriptorImageInfo depthInfo = makeDescriptorImageInfo(
4818         DE_NULL, isDepthFormat(params.depthStencilFormat) ? *wd.depthOnlyImageView : *wd.stencilOnlyImageView,
4819         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4820     const VkDescriptorImageInfo stencilInfo = makeDescriptorImageInfo(
4821         DE_NULL, isStencilFormat(params.depthStencilFormat) ? *wd.stencilOnlyImageView : *wd.depthOnlyImageView,
4822         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4823 
4824     DescriptorSetUpdateBuilder builder;
4825 
4826     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(0u),
4827                         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &color1Info);
4828     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(1u),
4829                         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &depthInfo);
4830     builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(2u),
4831                         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &stencilInfo);
4832 
4833     builder.update(vk, device);
4834 
4835     const VkPushConstantRange &inputPushConstantRange = {
4836         VK_SHADER_STAGE_FRAGMENT_BIT,         // VkShaderStageFlags    stageFlags;
4837         0,                                    // uint32_t              offset;
4838         static_cast<uint32_t>(sizeof(UVec4)), // uint32_t              size;
4839     };
4840 
4841     const ShaderWrapper fragmentModuleIn(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag_in"), 0u));
4842     const PipelineLayoutWrapper inputPipelineLayout(params.pipelineConstructionType, vk, device, 1,
4843                                                     &*descriptorSetLayout, 1, &inputPushConstantRange);
4844 
4845     UVec4 regions[RegionCount];
4846     getDrawRegions(wd, regions);
4847 
4848     if (!params.renderToAttachment)
4849     {
4850         copyToInputAttachment(context, params, wd, testObjects, pipelineLayout, vertexModule, regions);
4851     }
4852 
4853     startRenderPass(context, wd, testObjects, DE_LENGTH_OF_ARRAY(params.clearValues), params.clearValues);
4854 
4855     {
4856         DE_ASSERT(numSubpasses == 2);
4857 
4858         const VkDeviceSize vertexBufferOffset = 0;
4859         vk.cmdBindVertexBuffers(*testObjects.cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
4860 
4861         // First draw call outputs to color attachment 1 and depth/stencil.  It doesn't blend with clear for simplicity of the verification code.
4862         for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4863         {
4864             testObjects.graphicsPipelines.push_back(pipeline::makeGraphicsPipeline(
4865                 vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType,
4866                 pipelineLayout, *testObjects.renderPassFramebuffers.back(), DE_NULL, vertexModule, fragmentModule0,
4867                 false, true, false, 0, 0, params.perPass[0].intColorLocation, regions[regionNdx], regions[regionNdx],
4868                 params.perPass[0].numSamples, params.useGarbageAttachment));
4869 
4870             vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4),
4871                                 &regions[regionNdx]);
4872             vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UVec4),
4873                                 sizeof(params.perPass[0].drawConstantsWithDepthWrite[regionNdx]),
4874                                 &params.perPass[0].drawConstantsWithDepthWrite[regionNdx]);
4875             (*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
4876             vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
4877         }
4878 
4879         // Next subpass initializes color attachments 2 and 3 from color attachment 1 and depth/stencil, then issues a draw call that modifies those attachments.
4880         testObjects.renderPassFramebuffers.back().nextSubpass(vk, *testObjects.cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
4881 
4882         for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4883         {
4884             testObjects.graphicsPipelines.push_back(pipeline::makeGraphicsPipeline(
4885                 vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType,
4886                 inputPipelineLayout, *testObjects.renderPassFramebuffers.back(), DE_NULL, vertexModule,
4887                 fragmentModuleIn, false, false, false, 0, 1, params.perPass[1].intColorLocation, regions[regionNdx],
4888                 regions[regionNdx], params.perPass[1].numSamples, params.useGarbageAttachment));
4889 
4890             vk.cmdPushConstants(*testObjects.cmdBuffer, *inputPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4891                                 sizeof(UVec4), &regions[regionNdx]);
4892             (*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
4893             vk.cmdBindDescriptorSets(*testObjects.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *inputPipelineLayout, 0u,
4894                                      1u, &testObjects.descriptorSets.back().get(), 0u, DE_NULL);
4895             vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
4896         }
4897 
4898         for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4899         {
4900             testObjects.graphicsPipelines.push_back(pipeline::makeGraphicsPipeline(
4901                 vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType,
4902                 pipelineLayout, *testObjects.renderPassFramebuffers.back(), DE_NULL, vertexModule, fragmentModule1,
4903                 true, false, false, 0xC, 1, params.perPass[1].intColorLocation, regions[regionNdx], regions[regionNdx],
4904                 params.perPass[1].numSamples, params.useGarbageAttachment));
4905 
4906             vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4),
4907                                 &regions[regionNdx]);
4908             vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UVec4),
4909                                 sizeof(params.perPass[1].drawConstantsWithDepthWrite[regionNdx]),
4910                                 &params.perPass[1].drawConstantsWithDepthWrite[regionNdx]);
4911             (*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
4912             vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
4913         }
4914     }
4915 
4916     testObjects.renderPassFramebuffers.back().end(vk, *testObjects.cmdBuffer);
4917 
4918     // Verify results
4919     dispatchVerifyMultiPassRendering(context, params, wd, testObjects, regions);
4920 }
4921 
4922 //! Verify input attachments and multisampled rendering interact correctly.
testInputAttachments(Context & context,const TestParams params)4923 tcu::TestStatus testInputAttachments(Context &context, const TestParams params)
4924 {
4925     WorkingData wd;
4926     TestObjects testObjects(context);
4927     testStart(context, params, wd, testObjects);
4928 
4929     drawInputAttachments(context, params, wd, testObjects);
4930 
4931     testEnd(context, params, wd, testObjects);
4932 
4933     return verify(context, params, wd);
4934 }
4935 
generateInputAttachmentsTest(de::Random & rng,TestParams & params,const VkSampleCountFlagBits sampleCount,const VkResolveModeFlagBits resolveMode,const bool renderToWholeFramebuffer,const bool renderToAttachment)4936 void generateInputAttachmentsTest(de::Random &rng, TestParams &params, const VkSampleCountFlagBits sampleCount,
4937                                   const VkResolveModeFlagBits resolveMode, const bool renderToWholeFramebuffer,
4938                                   const bool renderToAttachment)
4939 {
4940     params.perPass.resize(2);
4941 
4942     // Set the sample count for attachments.
4943     if (params.isMultisampledRenderToSingleSampled)
4944     {
4945         params.numFloatColor1Samples  = VK_SAMPLE_COUNT_1_BIT;
4946         params.numFloatColor2Samples  = VK_SAMPLE_COUNT_1_BIT;
4947         params.numIntColorSamples     = VK_SAMPLE_COUNT_1_BIT;
4948         params.numDepthStencilSamples = VK_SAMPLE_COUNT_1_BIT;
4949 
4950         params.perPass[0].resolveFloatColor1  = false;
4951         params.perPass[0].resolveDepthStencil = false;
4952 
4953         params.perPass[1].resolveFloatColor2 = false;
4954         params.perPass[1].resolveIntColor    = false;
4955     }
4956     else
4957     {
4958         params.numFloatColor1Samples  = sampleCount;
4959         params.numFloatColor2Samples  = sampleCount;
4960         params.numIntColorSamples     = sampleCount;
4961         params.numDepthStencilSamples = sampleCount;
4962 
4963         params.perPass[0].resolveFloatColor1  = true;
4964         params.perPass[0].resolveDepthStencil = true;
4965 
4966         params.perPass[1].resolveFloatColor2 = true;
4967         params.perPass[1].resolveIntColor    = true;
4968     }
4969 
4970     // Subpass 0 renders to color1 and depth/stencil only.  They are resolved at the end of the pass.
4971     params.perPass[0].resolveFloatColor2      = false;
4972     params.perPass[0].resolveIntColor         = false;
4973     params.perPass[0].depthStencilResolveMode = resolveMode;
4974 
4975     params.perPass[0].numSamples = sampleCount;
4976 
4977     params.perPass[0].floatColor1Location = renderToAttachment ? 0 : -1;
4978     params.perPass[0].floatColor2Location = -1;
4979     params.perPass[0].intColorLocation    = -1;
4980     params.perPass[0].hasDepthStencil     = true;
4981 
4982     // Subpass 1 uses color1 and depth/stencil as input attachments and outputs to color2 and color3.
4983     params.perPass[1].resolveFloatColor1  = false;
4984     params.perPass[1].resolveDepthStencil = false;
4985 
4986     params.perPass[1].numSamples = params.isMultisampledRenderToSingleSampled ? VK_SAMPLE_COUNT_1_BIT : sampleCount;
4987 
4988     params.perPass[1].floatColor1Location = -1;
4989     params.perPass[1].floatColor2Location = 3;
4990     params.perPass[1].intColorLocation    = 2;
4991     params.perPass[1].hasDepthStencil     = false;
4992 
4993     // Always clear before render pass so outside render area can be verified.
4994     params.clearBeforeRenderPass    = true;
4995     params.renderToWholeFramebuffer = renderToWholeFramebuffer;
4996     params.testBlendsColors         = false;
4997 
4998     // Set random clear values.
4999     generateRandomClearValues(rng, params, params.clearValues, true);
5000 
5001     // Decide DrawPushConstants
5002     for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
5003     {
5004         // Subpass 0 writes to color 1, depth and stencil.
5005         params.perPass[0].drawConstantsWithDepthWrite[regionNdx] = DrawPushConstants{
5006             {Vec4(rng.getFloat(0.2f, 0.4f), 0, rng.getFloat(0.2f, 0.4f), 0),
5007              Vec4(0, rng.getFloat(0.2f, 0.4f), 0, rng.getFloat(0.2f, 0.4f))},
5008             {Vec4(0, 0, 0, 0), Vec4(0, 0, 0, 0)},
5009             {IVec4(0, 0, 0, 0), IVec4(0, 0, 0, 0)},
5010             // Use quantized values to avoid values that are too close and may cause precision issues
5011             Vec2(0.025f * static_cast<float>(rng.getInt(2, 38)), 0.025f * static_cast<float>(rng.getInt(2, 38))),
5012         };
5013 
5014         // Subpass 1 writes to color 2 and color 3.
5015         params.perPass[1].drawConstantsWithDepthWrite[regionNdx] = DrawPushConstants{
5016             {Vec4(0, 0, 0, 0), Vec4(0, 0, 0, 0)},
5017             {Vec4(rng.getFloat(0.2f, 0.4f), rng.getFloat(0.2f, 0.4f), 0, 0),
5018              Vec4(0, 0, rng.getFloat(0.2f, 0.4f), rng.getFloat(0.2f, 0.4f))},
5019             {IVec4(0, 0, 0, 0), IVec4(0, 0, 0, 0)},
5020             // Use quantized values to avoid values that are too close and may cause precision issues
5021             Vec2(0, 0),
5022         };
5023 
5024         // Integer resolve may choose any sample, so we modify only one channel.  This way, the verification
5025         // shader can accept two values per channel.
5026         params.perPass[0].drawConstantsWithDepthWrite[regionNdx].color3Data[0][0] = rng.getInt(1000, 5000);
5027         params.perPass[0].drawConstantsWithDepthWrite[regionNdx].color3Data[1][1] = rng.getInt(1000, 5000);
5028         params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color3Data[0][2] = rng.getInt(1000, 5000);
5029         params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color3Data[1][3] = rng.getInt(1000, 5000);
5030     }
5031 
5032     // Calculate VerifyPushConstants.  Walk through the passes and emulate what the draw calls would produce.
5033     for (uint32_t regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
5034     {
5035         // First, subpass[0]'s data is written to every sample of color1 and depth/stencil.
5036         params.verifyConstants[regionNdx].color1Data[0] =
5037             params.perPass[0].drawConstantsWithDepthWrite[regionNdx].color1Data[0];
5038         params.verifyConstants[regionNdx].color1Data[1] =
5039             params.perPass[0].drawConstantsWithDepthWrite[regionNdx].color1Data[1];
5040 
5041         // Then depth/stencil is resolved
5042         DE_ASSERT(resolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT || resolveMode == VK_RESOLVE_MODE_MAX_BIT);
5043         if (resolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
5044         {
5045             params.verifyConstants[regionNdx].depthData =
5046                 params.perPass[0].drawConstantsWithDepthWrite[regionNdx].depthData[0];
5047         }
5048         else
5049         {
5050             params.verifyConstants[regionNdx].depthData =
5051                 std::max(params.perPass[0].drawConstantsWithDepthWrite[regionNdx].depthData[0],
5052                          params.perPass[0].drawConstantsWithDepthWrite[regionNdx].depthData[1]);
5053         }
5054         params.verifyConstants[regionNdx].stencilData = params.clearValues[3].depthStencil.stencil + 1;
5055 
5056         // Then subpass 1 initializes color2 and color3 based on the previous subpass' color1 and depth/stencil values.
5057         params.verifyConstants[regionNdx].color2Data[0] = params.verifyConstants[regionNdx].color1Data[0];
5058         params.verifyConstants[regionNdx].color2Data[1] = params.verifyConstants[regionNdx].color1Data[1];
5059 
5060         if (isDepthFormat(params.depthStencilFormat))
5061         {
5062             if (params.isMultisampledRenderToSingleSampled)
5063             {
5064                 params.verifyConstants[regionNdx].color3Data[0][0] =
5065                     int32_t(10000 * params.verifyConstants[regionNdx].depthData);
5066                 params.verifyConstants[regionNdx].color3Data[1][0] =
5067                     int32_t(10000 * params.verifyConstants[regionNdx].depthData);
5068             }
5069             else
5070             {
5071                 params.verifyConstants[regionNdx].color3Data[0][0] =
5072                     int32_t(10000 * params.perPass[0].drawConstantsWithDepthWrite[regionNdx].depthData[0]);
5073                 params.verifyConstants[regionNdx].color3Data[1][0] =
5074                     int32_t(10000 * params.perPass[0].drawConstantsWithDepthWrite[regionNdx].depthData[1]);
5075             }
5076         }
5077 
5078         if (isStencilFormat(params.depthStencilFormat))
5079         {
5080             params.verifyConstants[regionNdx].color3Data[0][1] = 100 * params.verifyConstants[regionNdx].stencilData;
5081             params.verifyConstants[regionNdx].color3Data[1][1] = 100 * params.verifyConstants[regionNdx].stencilData;
5082         }
5083 
5084         // Finally, a draw call in subpass 1 blends on top of those values.
5085         if (params.isMultisampledRenderToSingleSampled)
5086         {
5087             // If subpass 1 is single-sampled, there's only one sample to write to which is interpolated along X.  Additionally, there's no resolve.
5088             // The verification code expects the following:
5089             //
5090             //     color@uv = (color_even_samples*u + color_odd_samples*v) / 2
5091             //
5092             // In this case, we want color@uv to be color_even_samples*u.  We can have the verification shader arrive at this value
5093             // by providing color_even_samples twice what it should be and zero for color_odd_samples:
5094             //
5095             //     color@uv = (color_even_samples*2*u + 0*v) / 2 = color_even_samples*u
5096             params.verifyConstants[regionNdx].color2Data[0] +=
5097                 params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color2Data[0] * Vec4(2, 2, 2, 2);
5098         }
5099         else
5100         {
5101             params.verifyConstants[regionNdx].color2Data[0] +=
5102                 params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color2Data[0];
5103             params.verifyConstants[regionNdx].color2Data[1] +=
5104                 params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color2Data[1];
5105         }
5106 
5107         params.verifyConstants[regionNdx].color3Data[0] +=
5108             params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color3Data[0];
5109         params.verifyConstants[regionNdx].color3Data[1] +=
5110             params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color3Data[1];
5111     }
5112 
5113     params.rngSeed = rng.getUint32();
5114 }
5115 
initInputAttachmentsPrograms(SourceCollections & programCollection,const TestParams params)5116 void initInputAttachmentsPrograms(SourceCollections &programCollection, const TestParams params)
5117 {
5118     // This test reuses the same programs as the multipass tests for rendering and verification.
5119     initMultipassPrograms(programCollection, params);
5120 
5121     const bool usesSignedIntFormat = params.intColorFormat == VK_FORMAT_R16G16B16A16_SINT;
5122     const char *intTypePrefix      = usesSignedIntFormat ? "i" : "u";
5123     const char *subpassInputSuffix = params.perPass[1].numSamples == VK_SAMPLE_COUNT_1_BIT ? "" : "MS";
5124     const char *subpassLoadParam   = params.perPass[1].numSamples == VK_SAMPLE_COUNT_1_BIT ? "" : ", gl_SampleID";
5125 
5126     // Fragment shader - initialize color attachments 2 and 3 with data from color attachments 1 and depth/stencil
5127     {
5128         const TestParams::PerPass &perPass = params.perPass[1];
5129 
5130         // Data from color attachment 1 is replicated in color attachment 2.  Data from the depth/stencil attachment is replicated in the red and green
5131         // channels of color attachment 3.  Depth is multiplied by 10000 and interpolated along x and stencil by 100 and interpolated along y.  This makes
5132         // the result look like the other draw calls that produce a gradient and simplifies the verification code.
5133         std::ostringstream src;
5134         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
5135             << "\n"
5136             << "layout(location = " << perPass.floatColor2Location << ") out vec4 o_color2;\n"
5137             << "layout(location = " << perPass.intColorLocation << ") out " << intTypePrefix << "vec4 o_color3;\n"
5138             << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput" << subpassInputSuffix
5139             << " i_color1;\n";
5140         if (isDepthFormat(params.depthStencilFormat))
5141             src << "layout(input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput" << subpassInputSuffix
5142                 << " i_depth;\n";
5143         if (isStencilFormat(params.depthStencilFormat))
5144             src << "layout(input_attachment_index = 1, set = 0, binding = 2) uniform usubpassInput"
5145                 << subpassInputSuffix << " i_stencil;\n";
5146         src << "\n"
5147             << "layout(push_constant) uniform PushConstants {\n"
5148             << "    uvec4 area;\n"
5149             << "} params;\n"
5150             << "\n"
5151             << "void main(void)\n"
5152             << "{\n"
5153             << "    vec2 uv = (gl_FragCoord.xy - vec2(params.area.xy)) / vec2(params.area.zw);\n"
5154             << "    o_color2 = subpassLoad(i_color1" << subpassLoadParam << ");\n"
5155             << "    if (gl_SampleID % 2 != 0)\n"
5156             << "        uv.xy = uv.yx;\n"
5157             << "    uvec4 color3Value = uvec4(0);\n";
5158         if (isDepthFormat(params.depthStencilFormat))
5159             src << "    color3Value.x = uint(subpassLoad(i_depth" << subpassLoadParam << ").x * 10000 * uv.x);\n";
5160         if (isStencilFormat(params.depthStencilFormat))
5161             src << "    color3Value.y = uint(subpassLoad(i_stencil" << subpassLoadParam << ").x * 100 * uv.y);\n";
5162         src << "    o_color3 = " << intTypePrefix << "vec4(color3Value);\n"
5163             << "}\n";
5164 
5165         programCollection.glslSources.add("frag_in") << glu::FragmentSource(src.str());
5166     }
5167 }
5168 
5169 //! Verify that subpass resolve perf query works.
testPerfQuery(Context & context,VkFormat format)5170 tcu::TestStatus testPerfQuery(Context &context, VkFormat format)
5171 {
5172     const InstanceInterface &vki                  = context.getInstanceInterface();
5173     const VkPhysicalDevice physicalDevice         = context.getPhysicalDevice();
5174     VkFormatProperties2 formatProperties          = {};
5175     VkSubpassResolvePerformanceQueryEXT perfQuery = {};
5176 
5177     perfQuery.sType   = VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT;
5178     perfQuery.optimal = 0xDEADBEEF;
5179 
5180     formatProperties.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
5181     formatProperties.pNext = &perfQuery;
5182 
5183     vki.getPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProperties);
5184 
5185     // There is actually nothing to verify other than that the above query was successful.
5186     // Regardless of optimal resolve or not, the operations must succeed.  We'll just make sure
5187     // the driver did produce a valid response.
5188     if (perfQuery.optimal != VK_FALSE && perfQuery.optimal != VK_TRUE)
5189     {
5190         std::string errorMsg = "VkSubpassResolvePerformanceQueryEXT::optimal is not populated after query";
5191         return tcu::TestStatus::fail(errorMsg);
5192     }
5193 
5194     return tcu::TestStatus::pass("Pass");
5195 }
5196 
getFormatShortString(const VkFormat format)5197 std::string getFormatShortString(const VkFormat format)
5198 {
5199     std::string s(de::toLower(getFormatName(format)));
5200     return s.substr(10);
5201 }
5202 
getFormatCaseName(const VkFormat color1Format,const VkFormat color2Format,const VkFormat color3Format,const VkFormat depthStencilFormat)5203 std::string getFormatCaseName(const VkFormat color1Format, const VkFormat color2Format, const VkFormat color3Format,
5204                               const VkFormat depthStencilFormat)
5205 {
5206     std::ostringstream str;
5207     str << getFormatShortString(color1Format) << "_" << getFormatShortString(color2Format) << "_"
5208         << getFormatShortString(color3Format) << "_" << getFormatShortString(depthStencilFormat);
5209     return str.str();
5210 }
5211 
getSampleCountCaseName(const VkSampleCountFlagBits sampleCount)5212 std::string getSampleCountCaseName(const VkSampleCountFlagBits sampleCount)
5213 {
5214     std::ostringstream str;
5215     str << sampleCount << "x";
5216     return str.str();
5217 }
5218 
getResolveModeCaseName(const VkResolveModeFlagBits resolveMode)5219 std::string getResolveModeCaseName(const VkResolveModeFlagBits resolveMode)
5220 {
5221     std::ostringstream str;
5222     if (resolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
5223         str << "ds_resolve_sample_zero";
5224     else if (resolveMode == VK_RESOLVE_MODE_MAX_BIT)
5225         str << "ds_resolve_max";
5226     else
5227         DE_ASSERT(false);
5228     return str.str();
5229 }
5230 
createMultisampledTestsInGroup(tcu::TestCaseGroup * rootGroup,const bool isMultisampledRenderToSingleSampled,PipelineConstructionType pipelineConstructionType,const bool dynamicRendering)5231 void createMultisampledTestsInGroup(tcu::TestCaseGroup *rootGroup, const bool isMultisampledRenderToSingleSampled,
5232                                     PipelineConstructionType pipelineConstructionType, const bool dynamicRendering)
5233 {
5234     // Color 1 is a float format
5235     const VkFormat color1FormatRange[] = {
5236         VK_FORMAT_R8G8B8A8_UNORM,
5237     };
5238     constexpr uint32_t color1FormatCount = DE_LENGTH_OF_ARRAY(color1FormatRange);
5239 
5240     // Color 2 is a float format
5241     const VkFormat color2FormatRange[] = {
5242         VK_FORMAT_R16G16B16A16_SFLOAT,
5243     };
5244     constexpr uint32_t color2FormatCount = DE_LENGTH_OF_ARRAY(color2FormatRange);
5245 
5246     // Color 3 is an integer format
5247     const VkFormat color3FormatRange[] = {
5248         VK_FORMAT_R32G32B32A32_UINT,
5249         VK_FORMAT_R16G16B16A16_SINT,
5250     };
5251     constexpr uint32_t color3FormatCount = DE_LENGTH_OF_ARRAY(color3FormatRange);
5252 
5253     // Test formats with only depth, only stencil or both
5254     const VkFormat depthStencilFormatRange[] = {
5255         VK_FORMAT_D16_UNORM,         //!< Must be supported
5256         VK_FORMAT_S8_UINT,           //!< May not be supported
5257         VK_FORMAT_D24_UNORM_S8_UINT, //!< Either this, or the next one must be supported
5258         VK_FORMAT_D32_SFLOAT_S8_UINT,
5259     };
5260     constexpr uint32_t depthStencilFormatCount = DE_LENGTH_OF_ARRAY(depthStencilFormatRange);
5261 
5262     const VkSampleCountFlagBits sampleRange[] = {
5263         VK_SAMPLE_COUNT_2_BIT,
5264         VK_SAMPLE_COUNT_4_BIT,
5265         VK_SAMPLE_COUNT_8_BIT,
5266         VK_SAMPLE_COUNT_16_BIT,
5267     };
5268 
5269     const VkResolveModeFlagBits depthStencilResolveModeRange[] = {
5270         VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
5271         VK_RESOLVE_MODE_MAX_BIT,
5272     };
5273 
5274     const bool boolRange[] = {false, true};
5275 
5276     // Test 1: Simple tests that verify Nx multisampling actually uses N samples.
5277     {
5278         MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(rootGroup->getTestContext(), "basic"));
5279 
5280         de::Random rng(0xDEADBEEF);
5281 
5282         for (const VkFormat color1Format : color1FormatRange)
5283             for (const VkFormat color2Format : color2FormatRange)
5284                 for (const VkFormat color3Format : color3FormatRange)
5285                     for (const VkFormat depthStencilFormat : depthStencilFormatRange)
5286                     {
5287                         MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(
5288                             rootGroup->getTestContext(),
5289                             getFormatCaseName(color1Format, color2Format, color3Format, depthStencilFormat).c_str()));
5290 
5291                         for (const VkSampleCountFlagBits sampleCount : sampleRange)
5292                         {
5293                             MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(
5294                                 rootGroup->getTestContext(), getSampleCountCaseName(sampleCount).c_str()));
5295 
5296                             for (const VkResolveModeFlagBits resolveMode : depthStencilResolveModeRange)
5297                             {
5298                                 MovePtr<tcu::TestCaseGroup> resolveGroup(new tcu::TestCaseGroup(
5299                                     rootGroup->getTestContext(), getResolveModeCaseName(resolveMode).c_str()));
5300 
5301                                 for (const bool renderToWholeFramebuffer : boolRange)
5302                                 {
5303                                     TestParams testParams;
5304                                     deMemset(&testParams, 0, sizeof(testParams));
5305 
5306                                     testParams.pipelineConstructionType = pipelineConstructionType;
5307                                     testParams.isMultisampledRenderToSingleSampled =
5308                                         isMultisampledRenderToSingleSampled;
5309                                     testParams.floatColor1Format    = color1Format;
5310                                     testParams.floatColor2Format    = color2Format;
5311                                     testParams.intColorFormat       = color3Format;
5312                                     testParams.depthStencilFormat   = depthStencilFormat;
5313                                     testParams.dynamicRendering     = dynamicRendering;
5314                                     testParams.useGarbageAttachment = false;
5315                                     testParams.renderToAttachment   = true;
5316 
5317                                     generateBasicTest(rng, testParams, sampleCount, resolveMode,
5318                                                       renderToWholeFramebuffer);
5319 
5320                                     addFunctionCaseWithPrograms(
5321                                         resolveGroup.get(),
5322                                         renderToWholeFramebuffer ? "whole_framebuffer" : "sub_framebuffer",
5323                                         checkRequirements, initBasicPrograms, testBasic, testParams);
5324                                 }
5325 
5326                                 sampleGroup->addChild(resolveGroup.release());
5327                             }
5328                             formatGroup->addChild(sampleGroup.release());
5329                         }
5330                         group->addChild(formatGroup.release());
5331                     }
5332 
5333         rootGroup->addChild(group.release());
5334     }
5335 
5336     // Test 2: Test that vkCmdClearAttachments works.
5337     {
5338         MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(rootGroup->getTestContext(), "clear_attachments"));
5339 
5340         de::Random rng(0x0FEDCBA9);
5341 
5342         for (const VkFormat color1Format : color1FormatRange)
5343             for (const VkFormat color2Format : color2FormatRange)
5344                 for (const VkFormat color3Format : color3FormatRange)
5345                     for (const VkFormat depthStencilFormat : depthStencilFormatRange)
5346                     {
5347                         MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(
5348                             rootGroup->getTestContext(),
5349                             getFormatCaseName(color1Format, color2Format, color3Format, depthStencilFormat).c_str()));
5350 
5351                         for (const VkSampleCountFlagBits sampleCount : sampleRange)
5352                         {
5353                             MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(
5354                                 rootGroup->getTestContext(), getSampleCountCaseName(sampleCount).c_str()));
5355 
5356                             for (const VkResolveModeFlagBits resolveMode : depthStencilResolveModeRange)
5357                             {
5358                                 MovePtr<tcu::TestCaseGroup> resolveGroup(new tcu::TestCaseGroup(
5359                                     rootGroup->getTestContext(), getResolveModeCaseName(resolveMode).c_str()));
5360 
5361                                 for (const bool renderToWholeFramebuffer : boolRange)
5362                                 {
5363                                     TestParams testParams;
5364                                     deMemset(&testParams, 0, sizeof(testParams));
5365 
5366                                     testParams.pipelineConstructionType = pipelineConstructionType;
5367                                     testParams.isMultisampledRenderToSingleSampled =
5368                                         isMultisampledRenderToSingleSampled;
5369                                     testParams.floatColor1Format    = color1Format;
5370                                     testParams.floatColor2Format    = color2Format;
5371                                     testParams.intColorFormat       = color3Format;
5372                                     testParams.depthStencilFormat   = depthStencilFormat;
5373                                     testParams.dynamicRendering     = dynamicRendering;
5374                                     testParams.useGarbageAttachment = false;
5375                                     testParams.renderToAttachment   = true;
5376 
5377                                     generateBasicTest(rng, testParams, sampleCount, resolveMode,
5378                                                       renderToWholeFramebuffer);
5379 
5380                                     addFunctionCaseWithPrograms(
5381                                         resolveGroup.get(),
5382                                         renderToWholeFramebuffer ? "whole_framebuffer" : "sub_framebuffer",
5383                                         checkRequirements, initBasicPrograms, testClearAttachments, testParams);
5384                                 }
5385                                 sampleGroup->addChild(resolveGroup.release());
5386                             }
5387                             formatGroup->addChild(sampleGroup.release());
5388                         }
5389                         group->addChild(formatGroup.release());
5390                     }
5391 
5392         rootGroup->addChild(group.release());
5393     }
5394 
5395     // Test 3: Tests with a single render pass, potentially with multiple subpasses.
5396     // Multiple subpasses can't be tested with dynamic rendering.
5397     if (!dynamicRendering)
5398     {
5399         // Single render pass with multiple subpasses
5400         MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(rootGroup->getTestContext(), "multi_subpass"));
5401         MovePtr<tcu::TestCaseGroup> formatGroup[color1FormatCount][color2FormatCount][color3FormatCount]
5402                                                [depthStencilFormatCount];
5403 
5404         for (uint32_t color1FormatNdx = 0; color1FormatNdx < color1FormatCount; ++color1FormatNdx)
5405             for (uint32_t color2FormatNdx = 0; color2FormatNdx < color2FormatCount; ++color2FormatNdx)
5406                 for (uint32_t color3FormatNdx = 0; color3FormatNdx < color3FormatCount; ++color3FormatNdx)
5407                     for (uint32_t depthStencilFormatNdx = 0; depthStencilFormatNdx < depthStencilFormatCount;
5408                          ++depthStencilFormatNdx)
5409                     {
5410                         formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx] =
5411                             MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(
5412                                 rootGroup->getTestContext(),
5413                                 getFormatCaseName(
5414                                     color1FormatRange[color1FormatNdx], color2FormatRange[color2FormatNdx],
5415                                     color3FormatRange[color3FormatNdx], depthStencilFormatRange[depthStencilFormatNdx])
5416                                     .c_str()));
5417                     }
5418 
5419         de::Random rng(0x12345678);
5420 
5421         for (uint32_t iteration = 0; iteration < (isMultisampledRenderToSingleSampled ? 1000u : 250u); ++iteration)
5422         {
5423             TestParams testParams;
5424             deMemset(&testParams, 0, sizeof(testParams));
5425 
5426             const uint32_t color1FormatNdx       = iteration % color1FormatCount;
5427             const uint32_t color2FormatNdx       = iteration % color2FormatCount;
5428             const uint32_t color3FormatNdx       = iteration % color3FormatCount;
5429             const uint32_t depthStencilFormatNdx = iteration % depthStencilFormatCount;
5430 
5431             testParams.pipelineConstructionType            = pipelineConstructionType;
5432             testParams.isMultisampledRenderToSingleSampled = isMultisampledRenderToSingleSampled;
5433             testParams.floatColor1Format                   = color1FormatRange[color1FormatNdx];
5434             testParams.floatColor2Format                   = color2FormatRange[color2FormatNdx];
5435             testParams.intColorFormat                      = color3FormatRange[color3FormatNdx];
5436             testParams.depthStencilFormat                  = depthStencilFormatRange[depthStencilFormatNdx];
5437             testParams.dynamicRendering                    = false;
5438             testParams.useGarbageAttachment                = false;
5439             testParams.renderToAttachment                  = true;
5440 
5441             generateMultiPassTest(rng, testParams);
5442 
5443             std::ostringstream name;
5444             name << "random_" << iteration;
5445 
5446             addFunctionCaseWithPrograms(
5447                 formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx].get(),
5448                 name.str().c_str(), checkRequirements, initMultipassPrograms, testSingleRenderPass, testParams);
5449         }
5450 
5451         for (uint32_t color1FormatNdx = 0; color1FormatNdx < color1FormatCount; ++color1FormatNdx)
5452             for (uint32_t color2FormatNdx = 0; color2FormatNdx < color2FormatCount; ++color2FormatNdx)
5453                 for (uint32_t color3FormatNdx = 0; color3FormatNdx < color3FormatCount; ++color3FormatNdx)
5454                     for (uint32_t depthStencilFormatNdx = 0; depthStencilFormatNdx < depthStencilFormatCount;
5455                          ++depthStencilFormatNdx)
5456                     {
5457                         group->addChild(
5458                             formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx]
5459                                 .release());
5460                     }
5461 
5462         rootGroup->addChild(group.release());
5463     }
5464 
5465     // Test 4: Tests with a multiple render passes, a single subpass each.
5466     {
5467         MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(rootGroup->getTestContext(), "multi_renderpass"));
5468         MovePtr<tcu::TestCaseGroup> formatGroup[color1FormatCount][color2FormatCount][color3FormatCount]
5469                                                [depthStencilFormatCount];
5470 
5471         for (uint32_t color1FormatNdx = 0; color1FormatNdx < color1FormatCount; ++color1FormatNdx)
5472             for (uint32_t color2FormatNdx = 0; color2FormatNdx < color2FormatCount; ++color2FormatNdx)
5473                 for (uint32_t color3FormatNdx = 0; color3FormatNdx < color3FormatCount; ++color3FormatNdx)
5474                     for (uint32_t depthStencilFormatNdx = 0; depthStencilFormatNdx < depthStencilFormatCount;
5475                          ++depthStencilFormatNdx)
5476                     {
5477                         formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx] =
5478                             MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(
5479                                 rootGroup->getTestContext(),
5480                                 getFormatCaseName(
5481                                     color1FormatRange[color1FormatNdx], color2FormatRange[color2FormatNdx],
5482                                     color3FormatRange[color3FormatNdx], depthStencilFormatRange[depthStencilFormatNdx])
5483                                     .c_str()));
5484                     }
5485 
5486         de::Random rng(0x87654321);
5487 
5488         for (uint32_t iteration = 0; iteration < (isMultisampledRenderToSingleSampled ? 1000u : 250u); ++iteration)
5489         {
5490             TestParams testParams;
5491             deMemset(&testParams, 0, sizeof(testParams));
5492 
5493             const uint32_t color1FormatNdx       = iteration % color1FormatCount;
5494             const uint32_t color2FormatNdx       = iteration % color2FormatCount;
5495             const uint32_t color3FormatNdx       = iteration % color3FormatCount;
5496             const uint32_t depthStencilFormatNdx = iteration % depthStencilFormatCount;
5497 
5498             testParams.pipelineConstructionType            = pipelineConstructionType;
5499             testParams.isMultisampledRenderToSingleSampled = isMultisampledRenderToSingleSampled;
5500             testParams.floatColor1Format                   = color1FormatRange[color1FormatNdx];
5501             testParams.floatColor2Format                   = color2FormatRange[color2FormatNdx];
5502             testParams.intColorFormat                      = color3FormatRange[color3FormatNdx];
5503             testParams.depthStencilFormat                  = depthStencilFormatRange[depthStencilFormatNdx];
5504             testParams.dynamicRendering                    = dynamicRendering;
5505             testParams.useGarbageAttachment                = false;
5506             testParams.renderToAttachment                  = true;
5507 
5508             generateMultiPassTest(rng, testParams);
5509 
5510             std::ostringstream name;
5511             name << "random_" << iteration;
5512 
5513             addFunctionCaseWithPrograms(
5514                 formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx].get(),
5515                 name.str().c_str(), checkRequirements, initMultipassPrograms, testMultiRenderPass, testParams);
5516         }
5517 
5518         for (uint32_t color1FormatNdx = 0; color1FormatNdx < color1FormatCount; ++color1FormatNdx)
5519             for (uint32_t color2FormatNdx = 0; color2FormatNdx < color2FormatCount; ++color2FormatNdx)
5520                 for (uint32_t color3FormatNdx = 0; color3FormatNdx < color3FormatCount; ++color3FormatNdx)
5521                     for (uint32_t depthStencilFormatNdx = 0; depthStencilFormatNdx < depthStencilFormatCount;
5522                          ++depthStencilFormatNdx)
5523                     {
5524                         group->addChild(
5525                             formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx]
5526                                 .release());
5527                     }
5528 
5529         rootGroup->addChild(group.release());
5530     }
5531 
5532     // Test 5: Tests multisampled rendering followed by use as input attachment.
5533     // These tests have two subpasses, so these can't be tested with dynamic rendering.
5534     if (!dynamicRendering && !vk::isConstructionTypeShaderObject(pipelineConstructionType))
5535     {
5536         // Tests that input attachment interaction with multisampled rendering works
5537         MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(rootGroup->getTestContext(), "input_attachments"));
5538 
5539         for (uint32_t i = 0; i < 2; ++i)
5540         {
5541             bool renderToAttachment = i == 0;
5542             if (!isMultisampledRenderToSingleSampled && !renderToAttachment)
5543                 continue;
5544             std::string input_name = renderToAttachment ? "render_to" : "initialize";
5545             MovePtr<tcu::TestCaseGroup> inputGroup(
5546                 new tcu::TestCaseGroup(rootGroup->getTestContext(), input_name.c_str()));
5547 
5548             de::Random rng(0x18273645);
5549 
5550             for (const VkFormat color1Format : color1FormatRange)
5551                 for (const VkFormat color2Format : color2FormatRange)
5552                     for (const VkFormat color3Format : color3FormatRange)
5553                         for (const VkFormat depthStencilFormat : depthStencilFormatRange)
5554                         {
5555                             // Combination of framebuffer attachment formats
5556                             MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(
5557                                 rootGroup->getTestContext(),
5558                                 getFormatCaseName(color1Format, color2Format, color3Format, depthStencilFormat)
5559                                     .c_str()));
5560 
5561                             for (const VkSampleCountFlagBits sampleCount : sampleRange)
5562                             {
5563                                 MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(
5564                                     rootGroup->getTestContext(), getSampleCountCaseName(sampleCount).c_str()));
5565 
5566                                 for (const VkResolveModeFlagBits resolveMode : depthStencilResolveModeRange)
5567                                 {
5568                                     MovePtr<tcu::TestCaseGroup> resolveGroup(new tcu::TestCaseGroup(
5569                                         rootGroup->getTestContext(), getResolveModeCaseName(resolveMode).c_str()));
5570 
5571                                     for (const bool renderToWholeFramebuffer : boolRange)
5572                                     {
5573                                         TestParams testParams;
5574                                         deMemset(&testParams, 0, sizeof(testParams));
5575 
5576                                         testParams.pipelineConstructionType = pipelineConstructionType;
5577                                         testParams.isMultisampledRenderToSingleSampled =
5578                                             isMultisampledRenderToSingleSampled;
5579                                         testParams.floatColor1Format    = color1Format;
5580                                         testParams.floatColor2Format    = color2Format;
5581                                         testParams.intColorFormat       = color3Format;
5582                                         testParams.depthStencilFormat   = depthStencilFormat;
5583                                         testParams.dynamicRendering     = false;
5584                                         testParams.useGarbageAttachment = false;
5585                                         testParams.renderToAttachment   = renderToAttachment;
5586 
5587                                         generateInputAttachmentsTest(rng, testParams, sampleCount, resolveMode,
5588                                                                      renderToWholeFramebuffer, renderToAttachment);
5589 
5590                                         addFunctionCaseWithPrograms(resolveGroup.get(),
5591                                                                     renderToWholeFramebuffer ? "whole_framebuffer" :
5592                                                                                                "sub_framebuffer",
5593                                                                     checkRequirements, initInputAttachmentsPrograms,
5594                                                                     testInputAttachments, testParams);
5595                                     }
5596                                     sampleGroup->addChild(resolveGroup.release());
5597                                 }
5598                                 formatGroup->addChild(sampleGroup.release());
5599                             }
5600                             inputGroup->addChild(formatGroup.release());
5601                         }
5602             group->addChild(inputGroup.release());
5603         }
5604 
5605         rootGroup->addChild(group.release());
5606     }
5607 
5608     // Test 6: Tests subpass resolve efficiency query.
5609     // Efficiency query tests don't need to be tested with different pipeline construction types and with dynamic rendering.
5610     if (isMultisampledRenderToSingleSampled && pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC &&
5611         !dynamicRendering)
5612     {
5613         MovePtr<tcu::TestCaseGroup> group(
5614             new tcu::TestCaseGroup(rootGroup->getTestContext(), "subpass_resolve_efficiency_query"));
5615 
5616         for (const VkFormat format : color1FormatRange)
5617         {
5618             addFunctionCase(group.get(), getFormatShortString(format), checkHasMsrtss, testPerfQuery, format);
5619         }
5620 
5621         for (const VkFormat format : color2FormatRange)
5622         {
5623             addFunctionCase(group.get(), getFormatShortString(format), checkHasMsrtss, testPerfQuery, format);
5624         }
5625 
5626         for (const VkFormat format : color3FormatRange)
5627         {
5628             addFunctionCase(group.get(), getFormatShortString(format), checkHasMsrtss, testPerfQuery, format);
5629         }
5630 
5631         for (const VkFormat format : depthStencilFormatRange)
5632         {
5633             addFunctionCase(group.get(), getFormatShortString(format), checkHasMsrtss, testPerfQuery, format);
5634         }
5635 
5636         rootGroup->addChild(group.release());
5637     }
5638 
5639     // Test 7: Test that work with garbage color attachments
5640     if (dynamicRendering && pipelineConstructionType != vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
5641     {
5642         MovePtr<tcu::TestCaseGroup> group(
5643             new tcu::TestCaseGroup(rootGroup->getTestContext(), "garbage_color_attachment"));
5644 
5645         de::Random rng(0x12348765);
5646 
5647         for (const VkFormat color1Format : color1FormatRange)
5648             for (const VkFormat color2Format : color2FormatRange)
5649                 for (const VkFormat color3Format : color3FormatRange)
5650                     for (const VkFormat depthStencilFormat : depthStencilFormatRange)
5651                     {
5652                         TestParams testParams;
5653                         deMemset(&testParams, 0, sizeof(testParams));
5654 
5655                         testParams.pipelineConstructionType            = pipelineConstructionType;
5656                         testParams.isMultisampledRenderToSingleSampled = isMultisampledRenderToSingleSampled;
5657                         testParams.floatColor1Format                   = color1Format;
5658                         testParams.floatColor2Format                   = color2Format;
5659                         testParams.intColorFormat                      = color3Format;
5660                         testParams.depthStencilFormat                  = depthStencilFormat;
5661                         testParams.dynamicRendering                    = dynamicRendering;
5662                         testParams.useGarbageAttachment                = true;
5663                         testParams.renderToAttachment                  = true;
5664 
5665                         generateBasicTest(rng, testParams, VK_SAMPLE_COUNT_2_BIT, VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
5666                                           true);
5667 
5668                         // Combination of framebuffer attachment formats
5669                         addFunctionCaseWithPrograms(
5670                             group.get(),
5671                             getFormatCaseName(color1Format, color2Format, color3Format, depthStencilFormat).c_str(),
5672                             checkRequirements, initBasicPrograms, testBasic, testParams);
5673                     }
5674 
5675         rootGroup->addChild(group.release());
5676     }
5677 }
5678 
createMultisampledRenderToSingleSampledTestsInGroup(tcu::TestCaseGroup * rootGroup,PipelineConstructionType pipelineConstructionType)5679 void createMultisampledRenderToSingleSampledTestsInGroup(tcu::TestCaseGroup *rootGroup,
5680                                                          PipelineConstructionType pipelineConstructionType)
5681 {
5682     createMultisampledTestsInGroup(rootGroup, true, pipelineConstructionType, false);
5683 
5684     MovePtr<tcu::TestCaseGroup> dynamicRenderingGroup(
5685         new tcu::TestCaseGroup(rootGroup->getTestContext(), "dynamic_rendering"));
5686     createMultisampledTestsInGroup(dynamicRenderingGroup.get(), true, pipelineConstructionType, true);
5687     rootGroup->addChild(dynamicRenderingGroup.release());
5688 }
5689 
createMultisampledMiscTestsInGroup(tcu::TestCaseGroup * rootGroup,PipelineConstructionType pipelineConstructionType)5690 void createMultisampledMiscTestsInGroup(tcu::TestCaseGroup *rootGroup,
5691                                         PipelineConstructionType pipelineConstructionType)
5692 {
5693     createMultisampledTestsInGroup(rootGroup, false, pipelineConstructionType, false);
5694 
5695     MovePtr<tcu::TestCaseGroup> dynamicRenderingGroup(
5696         new tcu::TestCaseGroup(rootGroup->getTestContext(), "dynamic_rendering"));
5697     createMultisampledTestsInGroup(dynamicRenderingGroup.get(), false, pipelineConstructionType, true);
5698     rootGroup->addChild(dynamicRenderingGroup.release());
5699 }
5700 
5701 } // namespace
5702 
createMultisampledRenderToSingleSampledTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)5703 tcu::TestCaseGroup *createMultisampledRenderToSingleSampledTests(tcu::TestContext &testCtx,
5704                                                                  vk::PipelineConstructionType pipelineConstructionType)
5705 {
5706     // Test multisampled rendering to single-sampled framebuffer attachments
5707     return createTestGroup(testCtx, "multisampled_render_to_single_sampled",
5708                            createMultisampledRenderToSingleSampledTestsInGroup, pipelineConstructionType);
5709 }
5710 
createMultisampledMiscTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)5711 tcu::TestCaseGroup *createMultisampledMiscTests(tcu::TestContext &testCtx,
5712                                                 vk::PipelineConstructionType pipelineConstructionType)
5713 {
5714     return createTestGroup(testCtx, "misc", createMultisampledMiscTestsInGroup, pipelineConstructionType);
5715 }
5716 
5717 } // namespace pipeline
5718 } // namespace vkt
5719