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