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