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