1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 Advanced Micro Devices, Inc.
6 * Copyright (c) 2019 The Khronos Group Inc.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Tests for VK_AMD_mixed_attachment_samples
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktPipelineMultisampleMixedAttachmentSamplesTests.hpp"
28 #include "vktPipelineSampleLocationsUtil.hpp"
29 #include "vktPipelineMakeUtil.hpp"
30 #include "vktTestCase.hpp"
31 #include "vktTestCaseUtil.hpp"
32 #include "vktTestGroupUtil.hpp"
33
34 #include "vkCmdUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkPlatform.hpp"
37 #include "vkMemUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkRefUtil.hpp"
41 #include "vkBuilderUtil.hpp"
42 #include "vkPrograms.hpp"
43 #include "vkImageUtil.hpp"
44
45 #include "deUniquePtr.hpp"
46 #include "deSharedPtr.hpp"
47 #include "deRandom.hpp"
48 #include "deMath.h"
49
50 #include "tcuVector.hpp"
51 #include "tcuTestLog.hpp"
52 #include "tcuImageCompare.hpp"
53 #include "tcuTextureUtil.hpp"
54 #include "tcuRGBA.hpp"
55
56 #include <string>
57 #include <vector>
58
59 namespace vkt
60 {
61 namespace pipeline
62 {
63 namespace
64 {
65 using namespace vk;
66 using de::MovePtr;
67 using de::SharedPtr;
68 using de::UniquePtr;
69 using tcu::UVec2;
70 using tcu::Vec2;
71 using tcu::Vec4;
72
compareGreenImage(tcu::TestLog & log,const char * name,const char * description,const tcu::ConstPixelBufferAccess & image)73 bool compareGreenImage(tcu::TestLog &log, const char *name, const char *description,
74 const tcu::ConstPixelBufferAccess &image)
75 {
76 tcu::TextureLevel greenImage(image.getFormat(), image.getWidth(), image.getHeight());
77 tcu::clear(greenImage.getAccess(), tcu::RGBA::green().toIVec());
78 return tcu::intThresholdCompare(log, name, description, greenImage.getAccess(), image, tcu::UVec4(2u),
79 tcu::COMPARE_LOG_RESULT);
80 }
81
getImageAspectFlags(const VkFormat format)82 VkImageAspectFlags getImageAspectFlags(const VkFormat format)
83 {
84 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
85
86 if (tcuFormat.order == tcu::TextureFormat::DS)
87 return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
88 else if (tcuFormat.order == tcu::TextureFormat::D)
89 return VK_IMAGE_ASPECT_DEPTH_BIT;
90 else if (tcuFormat.order == tcu::TextureFormat::S)
91 return VK_IMAGE_ASPECT_STENCIL_BIT;
92
93 DE_ASSERT(false);
94 return 0u;
95 }
96
97 struct CompareData
98 {
99 Vec4 color;
100 float depth;
101 uint32_t stencil;
102
103 // Pad to 2*16 bytes, in the shader the base alignment of this structure is 16 due to vec4
104 uint32_t padding[2];
105
CompareDatavkt::pipeline::__anon7e964aba0111::CompareData106 CompareData() : color(Vec4(0.0f)), depth(0.0f), stencil(0u)
107 {
108 padding[0] = 0u;
109 padding[1] = 0u;
110
111 static_assert(sizeof(CompareData) == (2 * 16), "Wrong structure size, expected 16 bytes");
112 }
113 };
114
115 //! Make a (unused) sampler.
makeSampler(const DeviceInterface & vk,const VkDevice device)116 Move<VkSampler> makeSampler(const DeviceInterface &vk, const VkDevice device)
117 {
118 const VkSamplerCreateInfo samplerParams = {
119 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
120 DE_NULL, // const void* pNext;
121 (VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags;
122 VK_FILTER_NEAREST, // VkFilter magFilter;
123 VK_FILTER_NEAREST, // VkFilter minFilter;
124 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
125 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
126 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
127 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
128 0.0f, // float mipLodBias;
129 VK_FALSE, // VkBool32 anisotropyEnable;
130 1.0f, // float maxAnisotropy;
131 VK_FALSE, // VkBool32 compareEnable;
132 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
133 0.0f, // float minLod;
134 0.0f, // float maxLod;
135 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
136 VK_FALSE, // VkBool32 unnormalizedCoordinates;
137 };
138 return createSampler(vk, device, &samplerParams);
139 }
140
makeImage(const DeviceInterface & vk,const VkDevice device,const VkFormat format,const UVec2 & size,const VkSampleCountFlagBits samples,const VkImageUsageFlags usage)141 Move<VkImage> makeImage(const DeviceInterface &vk, const VkDevice device, const VkFormat format, const UVec2 &size,
142 const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)
143 {
144 const VkImageCreateInfo imageParams = {
145 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
146 DE_NULL, // const void* pNext;
147 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
148 VK_IMAGE_TYPE_2D, // VkImageType imageType;
149 format, // VkFormat format;
150 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
151 1u, // uint32_t mipLevels;
152 1u, // uint32_t arrayLayers;
153 samples, // VkSampleCountFlagBits samples;
154 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
155 usage, // VkImageUsageFlags usage;
156 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
157 0u, // uint32_t queueFamilyIndexCount;
158 DE_NULL, // const uint32_t* pQueueFamilyIndices;
159 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
160 };
161 return createImage(vk, device, &imageParams);
162 }
163
isDepthFormat(const VkFormat format)164 inline bool isDepthFormat(const VkFormat format)
165 {
166 return (getImageAspectFlags(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
167 }
168
isStencilFormat(const VkFormat format)169 inline bool isStencilFormat(const VkFormat format)
170 {
171 return (getImageAspectFlags(format) & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
172 }
173
174 //! Create a test-specific MSAA pipeline
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper vertexModule,const ShaderWrapper fragmentModule,const bool useVertexInput,const uint32_t subpassNdx,const UVec2 & renderSize,const VkImageAspectFlags depthStencilAspect,const VkSampleCountFlagBits numSamples,const bool sampleShadingEnable,const bool useFragmentShadingRate,const VkSampleLocationsInfoEXT * pSampleLocationsInfo=DE_NULL)175 void preparePipelineWrapper(
176 GraphicsPipelineWrapper &gpw, const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass,
177 const ShaderWrapper vertexModule, const ShaderWrapper fragmentModule, const bool useVertexInput,
178 const uint32_t subpassNdx, const UVec2 &renderSize,
179 const VkImageAspectFlags depthStencilAspect, //!< Used to determine which D/S tests to turn on
180 const VkSampleCountFlagBits numSamples, const bool sampleShadingEnable, const bool useFragmentShadingRate,
181 const VkSampleLocationsInfoEXT *pSampleLocationsInfo = DE_NULL)
182 {
183 std::vector<VkVertexInputBindingDescription> vertexInputBindingDescriptions;
184 std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions;
185
186 // Vertex attributes: position and color
187 if (useVertexInput)
188 {
189 vertexInputBindingDescriptions.push_back(
190 makeVertexInputBindingDescription(0u, 2 * sizeof(Vec4), VK_VERTEX_INPUT_RATE_VERTEX));
191 vertexInputAttributeDescriptions.push_back(
192 makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u));
193 vertexInputAttributeDescriptions.push_back(
194 makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(Vec4)));
195 }
196
197 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {
198 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
199 DE_NULL, // const void* pNext;
200 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
201 static_cast<uint32_t>(vertexInputBindingDescriptions.size()), // uint32_t vertexBindingDescriptionCount;
202 dataOrNullPtr(
203 vertexInputBindingDescriptions), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
204 static_cast<uint32_t>(vertexInputAttributeDescriptions.size()), // uint32_t vertexAttributeDescriptionCount;
205 dataOrNullPtr(
206 vertexInputAttributeDescriptions), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
207 };
208
209 const std::vector<VkViewport> viewport{makeViewport(renderSize.x(), renderSize.y())};
210 const std::vector<VkRect2D> scissor{makeRect2D(renderSize.x(), renderSize.y())};
211
212 VkPipelineSampleLocationsStateCreateInfoEXT pipelineSampleLocationsCreateInfo = {
213 VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT, // VkStructureType sType;
214 DE_NULL, // const void* pNext;
215 VK_TRUE, // VkBool32 sampleLocationsEnable;
216 VkSampleLocationsInfoEXT(), // VkSampleLocationsInfoEXT sampleLocationsInfo;
217 };
218
219 VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = {
220 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
221 DE_NULL, // const void* pNext;
222 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
223 numSamples, // VkSampleCountFlagBits rasterizationSamples;
224 sampleShadingEnable, // VkBool32 sampleShadingEnable;
225 1.0f, // float minSampleShading;
226 DE_NULL, // const VkSampleMask* pSampleMask;
227 VK_FALSE, // VkBool32 alphaToCoverageEnable;
228 VK_FALSE // VkBool32 alphaToOneEnable;
229 };
230
231 if (pSampleLocationsInfo)
232 {
233 pipelineSampleLocationsCreateInfo.sampleLocationsInfo = *pSampleLocationsInfo;
234 pipelineMultisampleStateInfo.pNext = &pipelineSampleLocationsCreateInfo;
235 }
236
237 // Simply increment the buffer
238 const VkStencilOpState stencilOpState =
239 makeStencilOpState(VK_STENCIL_OP_KEEP, // stencil fail
240 VK_STENCIL_OP_INCREMENT_AND_CLAMP, // depth & stencil pass
241 VK_STENCIL_OP_KEEP, // depth only fail
242 VK_COMPARE_OP_ALWAYS, // compare op
243 ~0u, // compare mask
244 ~0u, // write mask
245 0u); // reference
246
247 // Always pass the depth test
248 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = {
249 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
250 DE_NULL, // const void* pNext;
251 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
252 (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0u, // VkBool32 depthTestEnable;
253 VK_TRUE, // VkBool32 depthWriteEnable;
254 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
255 VK_FALSE, // VkBool32 depthBoundsTestEnable;
256 (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0u, // VkBool32 stencilTestEnable;
257 stencilOpState, // VkStencilOpState front;
258 stencilOpState, // VkStencilOpState back;
259 0.0f, // float minDepthBounds;
260 1.0f, // float maxDepthBounds;
261 };
262
263 const VkColorComponentFlags colorComponentsAll =
264 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
265 const VkPipelineColorBlendAttachmentState defaultBlendAttachmentState = {
266 VK_FALSE, // VkBool32 blendEnable;
267 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
268 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
269 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
270 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
271 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
272 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
273 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
274 };
275
276 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = {
277 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
278 DE_NULL, // const void* pNext;
279 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
280 VK_FALSE, // VkBool32 logicOpEnable;
281 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
282 1u, // uint32_t attachmentCount;
283 &defaultBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
284 {0.0f, 0.0f, 0.0f, 0.0f}, // float blendConstants[4];
285 };
286
287 VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo{
288 VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType;
289 DE_NULL, // const void* pNext;
290 {2, 2}, // VkExtent2D fragmentSize;
291 {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
292 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR}, // VkFragmentShadingRateCombinerOpKHR combinerOps[2];
293 };
294
295 gpw.setDefaultRasterizationState()
296 .setupVertexInputState(&vertexInputStateInfo)
297 .setupPreRasterizationShaderState(viewport, scissor, pipelineLayout, renderPass, subpassNdx, vertexModule,
298 nullptr, ShaderWrapper(), ShaderWrapper(), ShaderWrapper(), DE_NULL,
299 (useFragmentShadingRate ? &shadingRateStateCreateInfo : nullptr))
300 .setupFragmentShaderState(pipelineLayout, renderPass, subpassNdx, fragmentModule,
301 &pipelineDepthStencilStateInfo, &pipelineMultisampleStateInfo)
302 .setupFragmentOutputState(renderPass, subpassNdx, &pipelineColorBlendStateInfo, &pipelineMultisampleStateInfo)
303 .setMonolithicPipelineLayout(pipelineLayout)
304 .buildPipeline();
305 }
306
307 //! Wrap float after an increment
wrapIncFloat(float a,float min,float max)308 inline float wrapIncFloat(float a, float min, float max)
309 {
310 return deFloatMax(min, deFloatMod(a, max));
311 }
312
313 //! Generate expected data for color, depth, and stencil samples of a given image.
314 //! Samples are ordered starting at pixel (0, 0) - see compute shader source for reference.
generateCompareData(const uint32_t seed,const UVec2 & imageSize,const uint32_t numCoverageSamples,const uint32_t numColorSamples,const uint32_t numDepthStencilSamples)315 std::vector<CompareData> generateCompareData(const uint32_t seed, const UVec2 &imageSize,
316 const uint32_t numCoverageSamples, const uint32_t numColorSamples,
317 const uint32_t numDepthStencilSamples)
318 {
319 std::vector<CompareData> allData;
320 de::Random rng(seed);
321
322 for (uint32_t y = 0u; y < imageSize.y(); ++y)
323 for (uint32_t x = 0u; x < imageSize.x(); ++x)
324 for (uint32_t sample = 0u; sample < numCoverageSamples; ++sample)
325 {
326 CompareData cd;
327
328 if (sample < numColorSamples)
329 {
330 for (int i = 0; i < 3; ++i)
331 cd.color[i] = 0.1f * static_cast<float>(rng.getInt(1, 10));
332
333 cd.color.w() = 1.0f;
334 }
335
336 if (sample < numDepthStencilSamples)
337 {
338 const uint32_t globalSample = sample + numColorSamples * (x + imageSize.x() * y);
339 cd.depth = wrapIncFloat(0.05f * static_cast<float>(1 + globalSample), 0.05f, 1.0f);
340 cd.stencil = 1 + globalSample % numCoverageSamples;
341 }
342
343 allData.push_back(cd);
344 }
345
346 return allData;
347 }
348
349 //! NDC transformation algorithm for sample locations
350 template <typename SampleAccessor>
ndcTransformEachSampleInPixel(const UVec2 & framebufferSize,const uint32_t numSamplesPerPixel,const SampleAccessor & access)351 std::vector<Vec2> ndcTransformEachSampleInPixel(const UVec2 &framebufferSize, const uint32_t numSamplesPerPixel,
352 const SampleAccessor &access)
353 {
354 std::vector<Vec2> locations;
355
356 for (uint32_t y = 0; y < framebufferSize.y(); ++y)
357 for (uint32_t x = 0; x < framebufferSize.x(); ++x)
358 for (uint32_t sampleNdx = 0; sampleNdx < numSamplesPerPixel; ++sampleNdx)
359 {
360 const Vec2 &sp = access(x, y, sampleNdx);
361 const float globalX = sp.x() + static_cast<float>(x);
362 const float globalY = sp.y() + static_cast<float>(y);
363
364 // Transform to [-1, 1] space
365 locations.push_back(Vec2(-1.0f + 2.0f * (globalX / static_cast<float>(framebufferSize.x())),
366 -1.0f + 2.0f * (globalY / static_cast<float>(framebufferSize.y()))));
367 }
368
369 return locations;
370 }
371
372 class AccessStandardSampleLocationsArray
373 {
374 public:
AccessStandardSampleLocationsArray(const Vec2 * ptr)375 AccessStandardSampleLocationsArray(const Vec2 *ptr) : m_pData(ptr)
376 {
377 }
378
operator ()(const uint32_t x,const uint32_t y,const uint32_t sampleNdx) const379 const Vec2 &operator()(const uint32_t x, const uint32_t y, const uint32_t sampleNdx) const
380 {
381 DE_UNREF(x);
382 DE_UNREF(y);
383 return m_pData[sampleNdx];
384 }
385
386 private:
387 const Vec2 *m_pData;
388 };
389
390 class AccessMultisamplePixelGrid
391 {
392 public:
AccessMultisamplePixelGrid(const MultisamplePixelGrid * ptr)393 AccessMultisamplePixelGrid(const MultisamplePixelGrid *ptr) : m_pGrid(ptr)
394 {
395 }
396
operator ()(const uint32_t x,const uint32_t y,const uint32_t sampleNdx) const397 Vec2 operator()(const uint32_t x, const uint32_t y, const uint32_t sampleNdx) const
398 {
399 const VkSampleLocationEXT &sp = m_pGrid->getSample(x, y, sampleNdx);
400 return Vec2(sp.x, sp.y);
401 }
402
403 private:
404 const MultisamplePixelGrid *m_pGrid;
405 };
406
407 //! Generate NDC space standard sample locations at each framebuffer pixel
408 //! Data is filled starting at pixel (0,0) and for each pixel there are numSamples samples
genFramebufferStandardSampleLocations(const VkSampleCountFlagBits numSamples,const UVec2 & framebufferSize)409 std::vector<Vec2> genFramebufferStandardSampleLocations(const VkSampleCountFlagBits numSamples,
410 const UVec2 &framebufferSize)
411 {
412 static const Vec2 s_location_samples_1[] = {
413 Vec2(0.5f, 0.5f),
414 };
415 static const Vec2 s_location_samples_2[] = {
416 Vec2(0.75f, 0.75f),
417 Vec2(0.25f, 0.25f),
418 };
419 static const Vec2 s_location_samples_4[] = {
420 Vec2(0.375f, 0.125f),
421 Vec2(0.875f, 0.375f),
422 Vec2(0.125f, 0.625f),
423 Vec2(0.625f, 0.875f),
424 };
425 static const Vec2 s_location_samples_8[] = {
426 Vec2(0.5625f, 0.3125f), Vec2(0.4375f, 0.6875f), Vec2(0.8125f, 0.5625f), Vec2(0.3125f, 0.1875f),
427 Vec2(0.1875f, 0.8125f), Vec2(0.0625f, 0.4375f), Vec2(0.6875f, 0.9375f), Vec2(0.9375f, 0.0625f),
428 };
429 static const Vec2 s_location_samples_16[] = {
430 Vec2(0.5625f, 0.5625f), Vec2(0.4375f, 0.3125f), Vec2(0.3125f, 0.6250f), Vec2(0.7500f, 0.4375f),
431 Vec2(0.1875f, 0.3750f), Vec2(0.6250f, 0.8125f), Vec2(0.8125f, 0.6875f), Vec2(0.6875f, 0.1875f),
432 Vec2(0.3750f, 0.8750f), Vec2(0.5000f, 0.0625f), Vec2(0.2500f, 0.1250f), Vec2(0.1250f, 0.7500f),
433 Vec2(0.0000f, 0.5000f), Vec2(0.9375f, 0.2500f), Vec2(0.8750f, 0.9375f), Vec2(0.0625f, 0.0000f),
434 };
435
436 const Vec2 *pSampleLocation = DE_NULL;
437
438 switch (numSamples)
439 {
440 case VK_SAMPLE_COUNT_1_BIT:
441 pSampleLocation = s_location_samples_1;
442 break;
443 case VK_SAMPLE_COUNT_2_BIT:
444 pSampleLocation = s_location_samples_2;
445 break;
446 case VK_SAMPLE_COUNT_4_BIT:
447 pSampleLocation = s_location_samples_4;
448 break;
449 case VK_SAMPLE_COUNT_8_BIT:
450 pSampleLocation = s_location_samples_8;
451 break;
452 case VK_SAMPLE_COUNT_16_BIT:
453 pSampleLocation = s_location_samples_16;
454 break;
455
456 default:
457 DE_ASSERT(0);
458 return std::vector<Vec2>();
459 }
460
461 return ndcTransformEachSampleInPixel(framebufferSize, static_cast<uint32_t>(numSamples),
462 AccessStandardSampleLocationsArray(pSampleLocation));
463 }
464
465 //! Generate NDC space custom sample locations at each framebuffer pixel, based on the given pixel grid
getSampleLocations(const MultisamplePixelGrid & pixelGrid,const UVec2 & framebufferSize)466 std::vector<Vec2> getSampleLocations(const MultisamplePixelGrid &pixelGrid, const UVec2 &framebufferSize)
467 {
468 return ndcTransformEachSampleInPixel(framebufferSize, pixelGrid.samplesPerPixel(),
469 AccessMultisamplePixelGrid(&pixelGrid));
470 }
471
472 struct PositionColor
473 {
474 tcu::Vec4 position;
475 tcu::Vec4 color;
476
PositionColorvkt::pipeline::__anon7e964aba0111::PositionColor477 PositionColor(const tcu::Vec4 &pos, const tcu::Vec4 &col) : position(pos), color(col)
478 {
479 }
480 };
481
482 //! Generate subpixel triangles containing the sample position, based on compare data.
483 //! Stencil values are created by overlapping triangles, so the stencil pipeline state must be set up accordingly.
generateSubpixelTriangles(const UVec2 & renderSize,const std::vector<CompareData> & compareData,const std::vector<Vec2> & sampleLocations)484 std::vector<PositionColor> generateSubpixelTriangles(const UVec2 &renderSize,
485 const std::vector<CompareData> &compareData,
486 const std::vector<Vec2> &sampleLocations)
487 {
488 std::vector<PositionColor> vertices;
489
490 // For each sample location (in the whole framebuffer), create a sub-pixel triangle that contains it.
491 // NDC viewport size is 2.0 in X and Y and NDC pixel width/height depends on the framebuffer resolution.
492 const Vec2 pixelSize = Vec2(2.0f) / renderSize.cast<float>();
493 const Vec2 offset = pixelSize / 16.0f; // 4 bits precision
494
495 // Surround with a roughly centered triangle
496 const float y1 = 0.5f * offset.y();
497 const float y2 = 0.35f * offset.y();
498 const float x1 = 0.5f * offset.x();
499
500 DE_ASSERT(compareData.size() == sampleLocations.size());
501
502 for (std::size_t globalSampleNdx = 0; globalSampleNdx < sampleLocations.size(); ++globalSampleNdx)
503 {
504 const Vec2 &loc = sampleLocations[globalSampleNdx];
505 const CompareData &cd = compareData[globalSampleNdx];
506
507 // Overdraw at the same position to get the desired stencil
508 // Draw at least once, if stencil is 0
509 for (uint32_t i = 0; i < deMaxu32(1u, cd.stencil); ++i)
510 {
511 vertices.push_back(PositionColor(Vec4(loc.x(), loc.y() - y1, cd.depth, 1.0f), cd.color));
512 vertices.push_back(PositionColor(Vec4(loc.x() - x1, loc.y() + y2, cd.depth, 1.0f), cd.color));
513 vertices.push_back(PositionColor(Vec4(loc.x() + x1, loc.y() + y2, cd.depth, 1.0f), cd.color));
514 }
515 }
516
517 return vertices;
518 }
519
reportSampleError(tcu::TestLog & log,const std::string & sampleDesc,UVec2 & renderSize,const uint32_t numCoverageSamples,const uint32_t globalSampleNdx)520 void reportSampleError(tcu::TestLog &log, const std::string &sampleDesc, UVec2 &renderSize,
521 const uint32_t numCoverageSamples, const uint32_t globalSampleNdx)
522 {
523 const uint32_t pixelNdx = globalSampleNdx / numCoverageSamples;
524 const uint32_t x = pixelNdx % renderSize.x();
525 const uint32_t y = pixelNdx / renderSize.x();
526 const uint32_t sample = globalSampleNdx % numCoverageSamples;
527
528 log << tcu::TestLog::Message << "Incorrect " << sampleDesc << " sample (" << sample << ") at pixel (" << x << ", "
529 << y << ")" << tcu::TestLog::EndMessage;
530 }
531
checkSampleRequirements(Context & context,const VkSampleCountFlagBits numColorSamples,const VkSampleCountFlagBits numDepthStencilSamples,const bool requireStandardSampleLocations)532 void checkSampleRequirements(Context &context, const VkSampleCountFlagBits numColorSamples,
533 const VkSampleCountFlagBits numDepthStencilSamples,
534 const bool requireStandardSampleLocations)
535 {
536 const VkPhysicalDeviceLimits &limits = context.getDeviceProperties().limits;
537
538 if ((limits.framebufferColorSampleCounts & numColorSamples) == 0u)
539 TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
540
541 if ((limits.framebufferDepthSampleCounts & numDepthStencilSamples) == 0u)
542 TCU_THROW(NotSupportedError, "framebufferDepthSampleCounts: sample count not supported");
543
544 if ((limits.framebufferStencilSampleCounts & numDepthStencilSamples) == 0u)
545 TCU_THROW(NotSupportedError, "framebufferStencilSampleCounts: sample count not supported");
546
547 if ((limits.sampledImageColorSampleCounts & numColorSamples) == 0u)
548 TCU_THROW(NotSupportedError, "sampledImageColorSampleCounts: sample count not supported");
549
550 if ((limits.sampledImageDepthSampleCounts & numDepthStencilSamples) == 0u)
551 TCU_THROW(NotSupportedError, "sampledImageDepthSampleCounts: sample count not supported");
552
553 if ((limits.sampledImageStencilSampleCounts & numDepthStencilSamples) == 0u)
554 TCU_THROW(NotSupportedError, "sampledImageStencilSampleCounts: sample count not supported");
555
556 // This is required to output geometry that is covering a specific sample
557 if (requireStandardSampleLocations && !limits.standardSampleLocations)
558 TCU_THROW(NotSupportedError, "standardSampleLocations: not supported");
559 }
560
checkImageRequirements(Context & context,const VkFormat format,const VkFormatFeatureFlags requiredFeatureFlags,const VkImageUsageFlags requiredUsageFlags,const VkSampleCountFlagBits requiredSampleCount=VK_SAMPLE_COUNT_1_BIT)561 void checkImageRequirements(Context &context, const VkFormat format, const VkFormatFeatureFlags requiredFeatureFlags,
562 const VkImageUsageFlags requiredUsageFlags,
563 const VkSampleCountFlagBits requiredSampleCount = VK_SAMPLE_COUNT_1_BIT)
564 {
565 const InstanceInterface &vki = context.getInstanceInterface();
566 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
567 VkImageFormatProperties imageProperties;
568
569 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
570
571 if ((formatProperties.optimalTilingFeatures & requiredFeatureFlags) != requiredFeatureFlags)
572 TCU_THROW(NotSupportedError, (de::toString(format) + ": format features not supported").c_str());
573
574 const VkResult result =
575 vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
576 requiredUsageFlags, (VkImageCreateFlags)0, &imageProperties);
577
578 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
579 TCU_THROW(NotSupportedError, (de::toString(format) + ": format not supported").c_str());
580
581 if ((imageProperties.sampleCounts & requiredSampleCount) != requiredSampleCount)
582 TCU_THROW(NotSupportedError, (de::toString(format) + ": sample count not supported").c_str());
583 }
584
585 //! Used after a render pass color output (draw or resolve)
recordCopyOutputImageToBuffer(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const UVec2 & imageSize,const VkImage srcImage,const VkBuffer dstBuffer)586 void recordCopyOutputImageToBuffer(const DeviceInterface &vk, const VkCommandBuffer cmdBuffer, const UVec2 &imageSize,
587 const VkImage srcImage, const VkBuffer dstBuffer)
588 {
589 // Image read barrier after color output
590 {
591 const VkImageMemoryBarrier barrier = {
592 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
593 DE_NULL, // const void* pNext;
594 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
595 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
596 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout oldLayout;
597 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
598 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
599 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
600 srcImage, // VkImage image;
601 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,
602 1u), // VkImageSubresourceRange subresourceRange;
603 };
604
605 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
606 (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
607 }
608 // Resolve image -> host buffer
609 {
610 const VkBufferImageCopy region = {
611 0ull, // VkDeviceSize bufferOffset;
612 0u, // uint32_t bufferRowLength;
613 0u, // uint32_t bufferImageHeight;
614 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
615 1u), // VkImageSubresourceLayers imageSubresource;
616 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
617 makeExtent3D(imageSize.x(), imageSize.y(), 1u), // VkExtent3D imageExtent;
618 };
619
620 vk.cmdCopyImageToBuffer(cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstBuffer, 1u, ®ion);
621 }
622 // Buffer write barrier
623 {
624 const VkBufferMemoryBarrier barrier = {
625 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
626 DE_NULL, // const void* pNext;
627 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
628 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
629 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
630 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
631 dstBuffer, // VkBuffer buffer;
632 0ull, // VkDeviceSize offset;
633 VK_WHOLE_SIZE, // VkDeviceSize size;
634 };
635
636 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
637 (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
638 }
639 }
640
641 namespace VerifySamples
642 {
643
644 //! The parameters that define a test case
645 struct TestParams
646 {
647 struct SampleCount
648 {
649 VkSampleCountFlagBits numCoverageSamples; //!< VkPipelineMultisampleStateCreateInfo::rasterizationSamples
650 VkSampleCountFlagBits numColorSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
651 VkSampleCountFlagBits
652 numDepthStencilSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
653 };
654
655 PipelineConstructionType pipelineConstructionType; //!< The wya pipeline is constructed
656 VkFormat colorFormat; //!< Color attachment format
657 VkFormat depthStencilFormat; //!< D/S attachment format. Will test both aspects if it's a mixed format
658 bool useProgrammableSampleLocations; //!< Try to use VK_EXT_sample_locations if available
659 bool useFragmentShadingRate; //!< Try to use VK_KHR_fragment_shading_rate if available
660 std::vector<SampleCount> perSubpassSamples; //!< Will use multiple subpasses if more than one element
661
TestParamsvkt::pipeline::__anon7e964aba0111::VerifySamples::TestParams662 TestParams(void) : colorFormat(), depthStencilFormat(), useProgrammableSampleLocations(), useFragmentShadingRate()
663 {
664 }
665 };
666
667 //! Common data used by the test
668 struct WorkingData
669 {
670 struct PerSubpass
671 {
672 uint32_t numVertices; //!< Number of vertices defined in the vertex buffer
673 Move<VkBuffer> vertexBuffer;
674 MovePtr<Allocation> vertexBufferAlloc;
675 Move<VkImage> colorImage; //!< Color image
676 Move<VkImageView> colorImageView; //!< Color attachment
677 MovePtr<Allocation> colorImageAlloc;
678 Move<VkImage> depthStencilImage; //!< Depth stencil image
679 Move<VkImageView> depthStencilImageView; //!< Depth stencil attachment
680 Move<VkImageView> depthOnlyImageView; //!< Depth aspect for shader read
681 Move<VkImageView> stencilOnlyImageView; //!< Stencil aspect for shader read
682 MovePtr<Allocation> depthStencilImageAlloc;
683 Move<VkBuffer> compareBuffer; //!< Buffer used to verify the images - comparison data
684 MovePtr<Allocation> compareBufferAlloc;
685 VkDeviceSize compareBufferSize;
686 Move<VkBuffer> resultBuffer; //!< Buffer used to verify the images - results
687 MovePtr<Allocation> resultBufferAlloc;
688 VkDeviceSize resultBufferSize;
689 uint32_t numResultElements; //!< Number of checksums in the result buffer
690 MovePtr<MultisamplePixelGrid> pixelGrid; //!< Programmable locations
691
PerSubpassvkt::pipeline::__anon7e964aba0111::VerifySamples::WorkingData::PerSubpass692 PerSubpass(void) : numVertices(), compareBufferSize(), resultBufferSize(), numResultElements()
693 {
694 }
695 };
696
697 UVec2 renderSize; //!< Size of the framebuffer
698 VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationsProperties; //!< Used with VK_EXT_sample_locations
699
700 std::vector<de::SharedPtr<PerSubpass>> perSubpass; //!< Test may use more than one set of data
701
WorkingDatavkt::pipeline::__anon7e964aba0111::VerifySamples::WorkingData702 WorkingData(void) : sampleLocationsProperties()
703 {
704 }
705 };
706
addVerificationComputeShader(SourceCollections & programCollection,const VkSampleCountFlagBits numCoverageSamples,const VkSampleCountFlagBits numColorSamples,const VkSampleCountFlagBits numDepthStencilSamples,const VkFormat depthStencilFormat,const std::string & nameSuffix)707 void addVerificationComputeShader(SourceCollections &programCollection, const VkSampleCountFlagBits numCoverageSamples,
708 const VkSampleCountFlagBits numColorSamples,
709 const VkSampleCountFlagBits numDepthStencilSamples, const VkFormat depthStencilFormat,
710 const std::string &nameSuffix)
711 {
712 const bool isColorMS = (numColorSamples != VK_SAMPLE_COUNT_1_BIT);
713 const bool isDepthStencilMS = (numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT);
714 const std::string colorBit = de::toString(static_cast<uint32_t>(VK_IMAGE_ASPECT_COLOR_BIT)) + "u";
715 const std::string depthBit = de::toString(static_cast<uint32_t>(VK_IMAGE_ASPECT_DEPTH_BIT)) + "u";
716 const std::string stencilBit = de::toString(static_cast<uint32_t>(VK_IMAGE_ASPECT_STENCIL_BIT)) + "u";
717
718 std::ostringstream src;
719 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
720 << "\n"
721 << "struct CompareData {\n"
722 << " vec4 color;\n"
723 << " float depth;\n"
724 << " uint stencil;\n"
725 << "};\n"
726 << "\n"
727 << "layout(local_size_x = " << static_cast<uint32_t>(numCoverageSamples)
728 << ") in;\n"
729 // Always use this descriptor layout and ignore unused bindings
730 << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
731 << " uint values[];\n"
732 << "} sb_out;\n"
733 << "layout(set = 0, binding = 1, std430) readonly buffer InputCompare {\n"
734 << " CompareData data[];\n"
735 << "} sb_cmp;\n"
736 << "layout(set = 0, binding = 2) uniform sampler2D" << (isColorMS ? "MS" : "") << " colorImage;\n"
737 << "layout(set = 0, binding = 3) uniform sampler2D" << (isDepthStencilMS ? "MS" : "") << " depthImage;\n"
738 << "layout(set = 0, binding = 4) uniform usampler2D" << (isDepthStencilMS ? "MS" : "") << " stencilImage;\n"
739 << "\n"
740 << "void main (void)\n"
741 << "{\n"
742
743 // Data for each sample in each pixel is laid out linearly (e.g 2 samples):
744 // [pixel(0, 0) sample(0)][pixel(0, 0) sample(1)][pixel(1, 0) sample(0)][pixel(1, 0) sample(1)]...
745
746 << " uint globalIndex = gl_LocalInvocationID.x + gl_WorkGroupSize.x * (gl_WorkGroupID.x + gl_WorkGroupID.y "
747 "* gl_NumWorkGroups.x);\n"
748 << " ivec2 position = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
749 << " int sampleNdx = int(gl_LocalInvocationID.x);\n"
750 << " uint result = 0u;\n"
751 << "\n"
752 << " // Verify color samples\n"
753 << " if (sampleNdx < " << static_cast<uint32_t>(numColorSamples) << ")\n"
754 << " {\n"
755 << " vec4 color = texelFetch(colorImage, position, sampleNdx);\n" // for non-MS (1 sample) case, sampleNdx = 0 and will instead be LOD = 0
756 << " vec4 diff = abs(color - sb_cmp.data[globalIndex].color);\n"
757 << " vec4 threshold = vec4(0.02);\n"
758 << "\n"
759 << " if (all(lessThan(diff, threshold)))\n"
760 << " result |= " << colorBit << ";\n"
761 << " }\n"
762 << " else\n"
763 << " result |= " << colorBit << ";\n" // Pass, if sample doesn't exist
764 << "\n";
765
766 if (isDepthFormat(depthStencilFormat))
767 {
768 src << " // Verify depth samples\n"
769 << " if (sampleNdx < " << static_cast<uint32_t>(numDepthStencilSamples) << ")\n"
770 << " {\n"
771 << " float depth = texelFetch(depthImage, position, sampleNdx).r;\n"
772 << " float diff = abs(depth - sb_cmp.data[globalIndex].depth);\n"
773 << " float threshold = 0.002;\n"
774 << "\n"
775 << " if (diff < threshold)\n"
776 << " result |= " << depthBit << ";\n"
777 << " }\n"
778 << " else\n"
779 << " result |= " << depthBit << ";\n"
780 << "\n";
781 }
782
783 if (isStencilFormat(depthStencilFormat))
784 {
785 src << " // Verify stencil samples\n"
786 << " if (sampleNdx < " << static_cast<uint32_t>(numDepthStencilSamples) << ")\n"
787 << " {\n"
788 << " uint stencil = texelFetch(stencilImage, position, sampleNdx).r;\n"
789 << " uint diff = stencil - sb_cmp.data[globalIndex].stencil;\n"
790 << "\n"
791 << " if (diff == 0u)\n"
792 << " result |= " << stencilBit << ";\n"
793 << " }\n"
794 << " else\n"
795 << " result |= " << stencilBit << ";\n"
796 << "\n";
797 }
798
799 src << " sb_out.values[globalIndex] = result;\n"
800 << "}\n";
801 programCollection.glslSources.add("comp" + nameSuffix) << glu::ComputeSource(src.str());
802 }
803
804 //! Get a compact sample count string in format X_Y_Z
getSampleCountString(const TestParams::SampleCount & samples)805 std::string getSampleCountString(const TestParams::SampleCount &samples)
806 {
807 std::ostringstream str;
808
809 str << static_cast<uint32_t>(samples.numCoverageSamples) << "_" << static_cast<uint32_t>(samples.numColorSamples)
810 << "_" << static_cast<uint32_t>(samples.numDepthStencilSamples);
811
812 return str.str();
813 }
814
initPrograms(SourceCollections & programCollection,const TestParams params)815 void initPrograms(SourceCollections &programCollection, const TestParams params)
816 {
817 // Vertex shader - position and color
818 {
819 std::ostringstream src;
820 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
821 << "\n"
822 << "layout(location = 0) in vec4 in_position;\n"
823 << "layout(location = 1) in vec4 in_color;\n"
824 << "layout(location = 0) out vec4 o_color;\n"
825 << "\n"
826 << "out gl_PerVertex {\n"
827 << " vec4 gl_Position;\n"
828 << "};\n"
829 << "\n"
830 << "void main(void)\n"
831 << "{\n"
832 << " gl_Position = in_position;\n"
833 << " o_color = in_color;\n"
834 << "}\n";
835
836 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
837 }
838
839 // Fragment shader - output color from VS
840 {
841 std::ostringstream src;
842 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
843 << "\n"
844 << "layout(location = 0) in vec4 in_color;\n"
845 << "layout(location = 0) out vec4 o_color;\n"
846 << "\n"
847 << "void main(void)\n"
848 << "{\n"
849 << " o_color = in_color;\n"
850 << "}\n";
851
852 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
853 }
854
855 // Compute shader - image verification
856 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
857 {
858 const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
859 addVerificationComputeShader(programCollection, samples.numCoverageSamples, samples.numColorSamples,
860 samples.numDepthStencilSamples, params.depthStencilFormat,
861 "_" + getSampleCountString(samples));
862 }
863 }
864
865 //! A simple color, depth/stencil draw. Subpasses (if more than one) are independent
draw(Context & context,const TestParams & params,WorkingData & wd)866 void draw(Context &context, const TestParams ¶ms, WorkingData &wd)
867 {
868 const InstanceInterface &vki = context.getInstanceInterface();
869 const DeviceInterface &vk = context.getDeviceInterface();
870 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
871 const VkDevice device = context.getDevice();
872 const uint32_t numSubpasses = static_cast<uint32_t>(wd.perSubpass.size());
873
874 RenderPassWrapper renderPass;
875 std::vector<VkSampleLocationsInfoEXT> perSubpassSampleLocationsInfo;
876 std::vector<VkAttachmentSampleLocationsEXT> attachmentSampleLocations;
877 std::vector<VkSubpassSampleLocationsEXT> subpassSampleLocations;
878
879 if (params.useProgrammableSampleLocations)
880 for (uint32_t subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
881 {
882 perSubpassSampleLocationsInfo.push_back(makeSampleLocationsInfo(*wd.perSubpass[subpassNdx]->pixelGrid));
883 }
884
885 // Create a render pass and a framebuffer
886 {
887 std::vector<VkSubpassDescription> subpasses;
888 std::vector<VkImage> images;
889 std::vector<VkImageView> attachments;
890 std::vector<VkAttachmentDescription> attachmentDescriptions;
891 std::vector<VkAttachmentReference> attachmentReferences;
892
893 // Reserve capacity to avoid invalidating pointers to elements
894 attachmentReferences.reserve(numSubpasses * 2);
895
896 for (uint32_t subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
897 {
898 images.push_back(wd.perSubpass[subpassNdx]->colorImage.get());
899 images.push_back(wd.perSubpass[subpassNdx]->depthStencilImage.get());
900 attachments.push_back(wd.perSubpass[subpassNdx]->colorImageView.get());
901 attachments.push_back(wd.perSubpass[subpassNdx]->depthStencilImageView.get());
902
903 attachmentDescriptions.push_back(makeAttachmentDescription(
904 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
905 params.colorFormat, // VkFormat format;
906 params.perSubpassSamples[subpassNdx].numColorSamples, // VkSampleCountFlagBits samples;
907 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
908 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
909 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
910 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
911 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
912 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout;
913 ));
914
915 attachmentDescriptions.push_back(makeAttachmentDescription(
916 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
917 params.depthStencilFormat, // VkFormat format;
918 params.perSubpassSamples[subpassNdx].numDepthStencilSamples, // VkSampleCountFlagBits samples;
919 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
920 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
921 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
922 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
923 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
924 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL // VkImageLayout finalLayout;
925 ));
926
927 attachmentReferences.push_back(makeAttachmentReference(static_cast<uint32_t>(attachmentReferences.size()),
928 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
929 const VkAttachmentReference *colorRef = &attachmentReferences.back();
930
931 attachmentReferences.push_back(makeAttachmentReference(static_cast<uint32_t>(attachmentReferences.size()),
932 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
933 const VkAttachmentReference *depthStencilRef = &attachmentReferences.back();
934
935 if (params.useProgrammableSampleLocations)
936 {
937 const VkAttachmentSampleLocationsEXT newAttachmentSampleLocations = {
938 attachmentReferences.back().attachment, // uint32_t attachmentIndex;
939 perSubpassSampleLocationsInfo[subpassNdx], // VkSampleLocationsInfoEXT sampleLocationsInfo;
940 };
941 attachmentSampleLocations.push_back(newAttachmentSampleLocations);
942
943 const VkSubpassSampleLocationsEXT newSubpassSampleLocations = {
944 subpassNdx, // uint32_t subpassIndex;
945 perSubpassSampleLocationsInfo[subpassNdx], // VkSampleLocationsInfoEXT sampleLocationsInfo;
946 };
947 subpassSampleLocations.push_back(newSubpassSampleLocations);
948 }
949
950 const VkSubpassDescription subpassDescription = {
951 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
952 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
953 0u, // uint32_t inputAttachmentCount;
954 DE_NULL, // const VkAttachmentReference* pInputAttachments;
955 1u, // uint32_t colorAttachmentCount;
956 colorRef, // const VkAttachmentReference* pColorAttachments;
957 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
958 depthStencilRef, // const VkAttachmentReference* pDepthStencilAttachment;
959 0u, // uint32_t preserveAttachmentCount;
960 DE_NULL, // const uint32_t* pPreserveAttachments;
961 };
962
963 subpasses.push_back(subpassDescription);
964 }
965
966 // Assume there are no dependencies between subpasses
967 const VkRenderPassCreateInfo renderPassInfo = {
968 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
969 DE_NULL, // const void* pNext;
970 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
971 static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t attachmentCount;
972 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments;
973 static_cast<uint32_t>(subpasses.size()), // uint32_t subpassCount;
974 dataOrNullPtr(subpasses), // const VkSubpassDescription* pSubpasses;
975 0u, // uint32_t dependencyCount;
976 DE_NULL, // const VkSubpassDependency* pDependencies;
977 };
978
979 renderPass = RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo);
980 renderPass.createFramebuffer(vk, device, static_cast<uint32_t>(attachments.size()), dataOrNullPtr(images),
981 dataOrNullPtr(attachments), wd.renderSize.x(), wd.renderSize.y());
982 }
983
984 const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
985 const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
986 const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device);
987
988 std::vector<GraphicsPipelineWrapper> pipelines;
989
990 for (uint32_t subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
991 {
992 const VkSampleLocationsInfoEXT *pSampleLocationsInfo =
993 (params.useProgrammableSampleLocations ? &perSubpassSampleLocationsInfo[subpassNdx] : DE_NULL);
994
995 pipelines.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
996 params.pipelineConstructionType);
997 preparePipelineWrapper(pipelines.back(), pipelineLayout, *renderPass, vertexModule, fragmentModule,
998 /*use vertex input*/ true, subpassNdx, wd.renderSize,
999 getImageAspectFlags(params.depthStencilFormat),
1000 params.perSubpassSamples[subpassNdx].numCoverageSamples,
1001 /*use sample shading*/ true, params.useFragmentShadingRate, pSampleLocationsInfo);
1002 }
1003
1004 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1005 context.getUniversalQueueFamilyIndex()));
1006 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1007
1008 beginCommandBuffer(vk, *cmdBuffer);
1009
1010 {
1011 std::vector<VkClearValue> clearValues;
1012
1013 for (uint32_t subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
1014 {
1015 clearValues.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f));
1016 clearValues.push_back(makeClearValueDepthStencil(1.0f, 0u));
1017 }
1018
1019 const VkRect2D renderArea = {{0u, 0u}, {wd.renderSize.x(), wd.renderSize.y()}};
1020
1021 if (params.useProgrammableSampleLocations)
1022 {
1023 const VkRenderPassSampleLocationsBeginInfoEXT renderPassSampleLocationsBeginInfo = {
1024 VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT, // VkStructureType sType;
1025 DE_NULL, // const void* pNext;
1026 static_cast<uint32_t>(
1027 attachmentSampleLocations
1028 .size()), // uint32_t attachmentInitialSampleLocationsCount;
1029 dataOrNullPtr(
1030 attachmentSampleLocations), // const VkAttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations;
1031 static_cast<uint32_t>(
1032 subpassSampleLocations
1033 .size()), // uint32_t postSubpassSampleLocationsCount;
1034 dataOrNullPtr(
1035 subpassSampleLocations), // const VkSubpassSampleLocationsEXT* pPostSubpassSampleLocations;
1036 };
1037
1038 renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<uint32_t>(clearValues.size()),
1039 dataOrNullPtr(clearValues), VK_SUBPASS_CONTENTS_INLINE,
1040 &renderPassSampleLocationsBeginInfo);
1041 }
1042 else
1043 renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<uint32_t>(clearValues.size()),
1044 dataOrNullPtr(clearValues));
1045 }
1046
1047 for (uint32_t subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx)
1048 {
1049 if (subpassNdx != 0)
1050 renderPass.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1051
1052 const VkDeviceSize vertexBufferOffset = 0ull;
1053 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.perSubpass[subpassNdx]->vertexBuffer.get(),
1054 &vertexBufferOffset);
1055
1056 pipelines[subpassNdx].bind(*cmdBuffer);
1057
1058 vk.cmdDraw(*cmdBuffer, wd.perSubpass[subpassNdx]->numVertices, 1u, 0u, 0u);
1059 }
1060
1061 renderPass.end(vk, *cmdBuffer);
1062
1063 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1064 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1065 }
1066
dispatchImageCheck(Context & context,const TestParams & params,WorkingData & wd,const uint32_t subpassNdx)1067 void dispatchImageCheck(Context &context, const TestParams ¶ms, WorkingData &wd, const uint32_t subpassNdx)
1068 {
1069 const DeviceInterface &vk = context.getDeviceInterface();
1070 const VkDevice device = context.getDevice();
1071 WorkingData::PerSubpass &subpassData = *wd.perSubpass[subpassNdx];
1072
1073 const Unique<VkSampler> defaultSampler(makeSampler(vk, device));
1074
1075 // Create descriptor set
1076
1077 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1078 DescriptorSetLayoutBuilder()
1079 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1080 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1081 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT,
1082 &defaultSampler.get())
1083 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT,
1084 &defaultSampler.get())
1085 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT,
1086 &defaultSampler.get())
1087 .build(vk, device));
1088
1089 const Unique<VkDescriptorPool> descriptorPool(
1090 DescriptorPoolBuilder()
1091 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u)
1092 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3u)
1093 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1094
1095 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1096
1097 {
1098 const VkDescriptorBufferInfo compareBufferInfo =
1099 makeDescriptorBufferInfo(*subpassData.compareBuffer, 0ull, subpassData.compareBufferSize);
1100 const VkDescriptorBufferInfo resultBufferInfo =
1101 makeDescriptorBufferInfo(*subpassData.resultBuffer, 0ull, subpassData.resultBufferSize);
1102 const VkDescriptorImageInfo colorImageInfo =
1103 makeDescriptorImageInfo(DE_NULL, *subpassData.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1104 const VkDescriptorImageInfo depthImageInfo =
1105 makeDescriptorImageInfo(DE_NULL, *subpassData.depthOnlyImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1106 const VkDescriptorImageInfo stencilImageInfo = makeDescriptorImageInfo(
1107 DE_NULL, *subpassData.stencilOnlyImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1108
1109 DescriptorSetUpdateBuilder builder;
1110
1111 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1112 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo);
1113 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
1114 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &compareBufferInfo);
1115 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u),
1116 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
1117
1118 if (subpassData.depthOnlyImageView)
1119 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u),
1120 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &depthImageInfo);
1121
1122 if (subpassData.stencilOnlyImageView)
1123 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(4u),
1124 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &stencilImageInfo);
1125
1126 builder.update(vk, device);
1127 }
1128
1129 // Pipeline
1130
1131 const std::string shaderName("comp_" + getSampleCountString(params.perSubpassSamples[subpassNdx]));
1132 const Unique<VkShaderModule> shaderModule(
1133 createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u));
1134 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
1135 const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
1136
1137 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1138 context.getUniversalQueueFamilyIndex()));
1139 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1140
1141 beginCommandBuffer(vk, *cmdBuffer);
1142
1143 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1144 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(),
1145 0u, DE_NULL);
1146
1147 vk.cmdDispatch(*cmdBuffer, wd.renderSize.x(), wd.renderSize.y(), 1u);
1148
1149 {
1150 const VkBufferMemoryBarrier barrier = {
1151 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1152 DE_NULL, // const void* pNext;
1153 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1154 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1155 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1156 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1157 *subpassData.resultBuffer, // VkBuffer buffer;
1158 0ull, // VkDeviceSize offset;
1159 VK_WHOLE_SIZE, // VkDeviceSize size;
1160 };
1161
1162 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1163 (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 1u, &barrier, 0u,
1164 (const VkImageMemoryBarrier *)DE_NULL);
1165 }
1166
1167 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1168 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1169
1170 invalidateMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(),
1171 subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1172 }
1173
createPerSubpassData(Context & context,const TestParams & params,WorkingData & wd,const uint32_t subpassNdx)1174 void createPerSubpassData(Context &context, const TestParams ¶ms, WorkingData &wd, const uint32_t subpassNdx)
1175 {
1176 const DeviceInterface &vk = context.getDeviceInterface();
1177 const VkDevice device = context.getDevice();
1178 MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(
1179 vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1180 const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1181 WorkingData::PerSubpass &subpassData = *wd.perSubpass[subpassNdx];
1182
1183 // Create images
1184 {
1185
1186 const VkImageUsageFlags colorImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1187 const VkImageUsageFlags depthStencilImageUsageFlags =
1188 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1189
1190 checkImageRequirements(context, params.colorFormat,
1191 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1192 colorImageUsageFlags, samples.numColorSamples);
1193
1194 subpassData.colorImage =
1195 makeImage(vk, device, params.colorFormat, wd.renderSize, samples.numColorSamples, colorImageUsageFlags);
1196 subpassData.colorImageAlloc =
1197 bindImage(vk, device, *allocator, *subpassData.colorImage, MemoryRequirement::Any);
1198 subpassData.colorImageView =
1199 makeImageView(vk, device, *subpassData.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1200 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1201
1202 checkImageRequirements(context, params.depthStencilFormat,
1203 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1204 depthStencilImageUsageFlags, samples.numDepthStencilSamples);
1205
1206 subpassData.depthStencilImage = makeImage(vk, device, params.depthStencilFormat, wd.renderSize,
1207 samples.numDepthStencilSamples, depthStencilImageUsageFlags);
1208 subpassData.depthStencilImageAlloc =
1209 bindImage(vk, device, *allocator, *subpassData.depthStencilImage, MemoryRequirement::Any);
1210 subpassData.depthStencilImageView =
1211 makeImageView(vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1212 makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u));
1213
1214 if (isDepthFormat(params.depthStencilFormat))
1215 subpassData.depthOnlyImageView = makeImageView(
1216 vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1217 makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u));
1218
1219 if (isStencilFormat(params.depthStencilFormat))
1220 subpassData.stencilOnlyImageView = makeImageView(
1221 vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1222 makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u));
1223 }
1224
1225 // Create vertex and comparison buffers
1226 {
1227 const uint32_t seed = 123 + 19 * subpassNdx;
1228 const std::vector<CompareData> compareData = generateCompareData(
1229 seed, wd.renderSize, samples.numCoverageSamples, samples.numColorSamples, samples.numDepthStencilSamples);
1230
1231 subpassData.compareBufferSize = static_cast<VkDeviceSize>(sizeof(CompareData) * compareData.size());
1232 subpassData.compareBuffer =
1233 makeBuffer(vk, device, subpassData.compareBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1234 subpassData.compareBufferAlloc =
1235 bindBuffer(vk, device, *allocator, *subpassData.compareBuffer, MemoryRequirement::HostVisible);
1236
1237 deMemcpy(subpassData.compareBufferAlloc->getHostPtr(), dataOrNullPtr(compareData),
1238 static_cast<std::size_t>(subpassData.compareBufferSize));
1239 flushMappedMemoryRange(vk, device, subpassData.compareBufferAlloc->getMemory(),
1240 subpassData.compareBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1241
1242 subpassData.numResultElements = static_cast<uint32_t>(compareData.size());
1243 subpassData.resultBufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t) * compareData.size());
1244 subpassData.resultBuffer =
1245 makeBuffer(vk, device, subpassData.resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1246 subpassData.resultBufferAlloc =
1247 bindBuffer(vk, device, *allocator, *subpassData.resultBuffer, MemoryRequirement::HostVisible);
1248
1249 deMemset(subpassData.resultBufferAlloc->getHostPtr(), 0,
1250 static_cast<std::size_t>(subpassData.resultBufferSize));
1251 flushMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(),
1252 subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1253
1254 std::vector<PositionColor> vertices;
1255
1256 if (params.useProgrammableSampleLocations)
1257 {
1258 subpassData.pixelGrid = MovePtr<MultisamplePixelGrid>(
1259 new MultisamplePixelGrid(UVec2(wd.sampleLocationsProperties.maxSampleLocationGridSize.width,
1260 wd.sampleLocationsProperties.maxSampleLocationGridSize.height),
1261 samples.numCoverageSamples));
1262
1263 const uint32_t locationsSeed = 211 + 4 * subpassNdx;
1264 fillSampleLocationsRandom(*subpassData.pixelGrid, wd.sampleLocationsProperties.sampleLocationSubPixelBits,
1265 locationsSeed);
1266 vertices = generateSubpixelTriangles(wd.renderSize, compareData,
1267 getSampleLocations(*subpassData.pixelGrid, wd.renderSize));
1268 }
1269 else
1270 {
1271 const std::vector<Vec2> locations =
1272 genFramebufferStandardSampleLocations(samples.numCoverageSamples, wd.renderSize);
1273 vertices = generateSubpixelTriangles(wd.renderSize, compareData, locations);
1274 }
1275
1276 const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1277 subpassData.numVertices = static_cast<uint32_t>(vertices.size());
1278 subpassData.vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1279 subpassData.vertexBufferAlloc =
1280 bindBuffer(vk, device, *allocator, *subpassData.vertexBuffer, MemoryRequirement::HostVisible);
1281
1282 deMemcpy(subpassData.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices),
1283 static_cast<std::size_t>(vertexBufferSize));
1284 flushMappedMemoryRange(vk, device, subpassData.vertexBufferAlloc->getMemory(),
1285 subpassData.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1286 }
1287 }
1288
checkRequirements(Context & context,TestParams params)1289 void checkRequirements(Context &context, TestParams params)
1290 {
1291 context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples");
1292
1293 if (params.useProgrammableSampleLocations)
1294 context.requireDeviceFunctionality("VK_EXT_sample_locations");
1295
1296 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1297 {
1298 const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1299 checkSampleRequirements(context, samples.numColorSamples, samples.numDepthStencilSamples,
1300 !params.useProgrammableSampleLocations);
1301 }
1302
1303 const auto &vki = context.getInstanceInterface();
1304 const auto physicalDevice = context.getPhysicalDevice();
1305
1306 if (params.useFragmentShadingRate)
1307 {
1308 context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
1309
1310 if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
1311 TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
1312
1313 // Fetch information about supported fragment shading rates
1314 uint32_t supportedFragmentShadingRateCount = 0;
1315 vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, DE_NULL);
1316
1317 std::vector<vk::VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates(
1318 supportedFragmentShadingRateCount, {vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR,
1319 DE_NULL,
1320 vk::VK_SAMPLE_COUNT_1_BIT,
1321 {1, 1}});
1322 vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount,
1323 supportedFragmentShadingRates.data());
1324
1325 uint32_t cumulativeNeededSamples = 0;
1326 for (const TestParams::SampleCount &samples : params.perSubpassSamples)
1327 cumulativeNeededSamples |= samples.numColorSamples;
1328
1329 bool requiredRateFound = false;
1330 for (const auto &rate : supportedFragmentShadingRates)
1331 {
1332 if ((rate.fragmentSize.width == 2u) && (rate.fragmentSize.height == 2u) &&
1333 (rate.sampleCounts & cumulativeNeededSamples))
1334 {
1335 requiredRateFound = true;
1336 break;
1337 }
1338 }
1339
1340 if (!requiredRateFound)
1341 TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
1342 }
1343
1344 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1345 params.pipelineConstructionType);
1346 }
1347
1348 //! Verify the values of all samples in all attachments.
test(Context & context,const TestParams params)1349 tcu::TestStatus test(Context &context, const TestParams params)
1350 {
1351 WorkingData wd;
1352 wd.renderSize = UVec2(2, 2); // Use a very small image, as we will verify all samples for all pixels
1353
1354 // Query state related to programmable sample locations
1355 if (params.useProgrammableSampleLocations)
1356 {
1357 const InstanceInterface &vki = context.getInstanceInterface();
1358 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1359
1360 wd.sampleLocationsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT;
1361 wd.sampleLocationsProperties.pNext = DE_NULL;
1362
1363 VkPhysicalDeviceProperties2 properties = {
1364 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // VkStructureType sType;
1365 &wd.sampleLocationsProperties, // void* pNext;
1366 VkPhysicalDeviceProperties(), // VkPhysicalDeviceProperties properties;
1367 };
1368
1369 vki.getPhysicalDeviceProperties2(physicalDevice, &properties);
1370
1371 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1372 {
1373 if ((wd.sampleLocationsProperties.sampleLocationSampleCounts &
1374 params.perSubpassSamples[subpassNdx].numCoverageSamples) == 0u)
1375 TCU_THROW(NotSupportedError, "VkSampleLocationsPropertiesAMD: sample count not supported");
1376 }
1377 }
1378
1379 // Create subpass data
1380 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1381 {
1382 wd.perSubpass.push_back(SharedPtr<WorkingData::PerSubpass>(new WorkingData::PerSubpass()));
1383 createPerSubpassData(context, params, wd, subpassNdx);
1384 }
1385
1386 // Draw test geometry
1387 draw(context, params, wd);
1388
1389 // Verify images with a compute shader
1390 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1391 dispatchImageCheck(context, params, wd, subpassNdx);
1392
1393 // Test checksums
1394 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1395 {
1396 const uint32_t *const pSampleChecksumBase =
1397 static_cast<uint32_t *>(wd.perSubpass[subpassNdx]->resultBufferAlloc->getHostPtr());
1398 const bool hasDepth = isDepthFormat(params.depthStencilFormat);
1399 const bool hasStencil = isStencilFormat(params.depthStencilFormat);
1400 bool allOk = true;
1401
1402 context.getTestContext().getLog()
1403 << tcu::TestLog::Message << "Verify images in subpass " << subpassNdx << tcu::TestLog::EndMessage;
1404
1405 for (uint32_t globalSampleNdx = 0; globalSampleNdx < wd.perSubpass[subpassNdx]->numResultElements;
1406 ++globalSampleNdx)
1407 {
1408 const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1409 const uint32_t checksum = pSampleChecksumBase[globalSampleNdx];
1410
1411 if ((checksum & VK_IMAGE_ASPECT_COLOR_BIT) == 0u)
1412 {
1413 reportSampleError(context.getTestContext().getLog(), "color", wd.renderSize, samples.numCoverageSamples,
1414 globalSampleNdx);
1415 allOk = false;
1416 }
1417
1418 if (hasDepth && ((checksum & VK_IMAGE_ASPECT_DEPTH_BIT) == 0u))
1419 {
1420 reportSampleError(context.getTestContext().getLog(), "depth", wd.renderSize, samples.numCoverageSamples,
1421 globalSampleNdx);
1422 allOk = false;
1423 }
1424
1425 if (hasStencil && ((checksum & VK_IMAGE_ASPECT_STENCIL_BIT) == 0u))
1426 {
1427 reportSampleError(context.getTestContext().getLog(), "stencil", wd.renderSize,
1428 samples.numCoverageSamples, globalSampleNdx);
1429 allOk = false;
1430 }
1431 }
1432
1433 if (!allOk)
1434 return tcu::TestStatus::fail("Multisampled image has incorrect samples");
1435 }
1436
1437 return tcu::TestStatus::pass("Pass");
1438 }
1439
1440 } // namespace VerifySamples
1441
1442 namespace ShaderBuiltins
1443 {
1444
1445 struct TestParams
1446 {
1447 PipelineConstructionType pipelineConstructionType; //!< The way pipeline is constructed
1448 VkSampleCountFlagBits numCoverageSamples; //!< VkPipelineMultisampleStateCreateInfo::rasterizationSamples
1449 VkSampleCountFlagBits numColorSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
1450 VkSampleCountFlagBits numDepthStencilSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
1451 VkFormat colorFormat; //!< Color attachment format
1452 VkFormat depthStencilFormat; //!< D/S attachment format. Will test both aspects if it's a mixed format
1453 };
1454
1455 struct WorkingData
1456 {
1457 UVec2 renderSize; //!< Size of the framebuffer
1458 uint32_t numVertices; //!< Number of vertices defined in the vertex buffer
1459 Move<VkBuffer> vertexBuffer;
1460 MovePtr<Allocation> vertexBufferAlloc;
1461 Move<VkImage> colorImage; //!< Color image
1462 Move<VkImageView> colorImageView; //!< Color attachment
1463 MovePtr<Allocation> colorImageAlloc;
1464 Move<VkImage> depthStencilImage; //!< Depth stencil image
1465 Move<VkImageView> depthStencilImageView; //!< Depth stencil attachment
1466 Move<VkImageView> depthOnlyImageView; //!< Depth aspect for shader read
1467 Move<VkImageView> stencilOnlyImageView; //!< Stencil aspect for shader read
1468 MovePtr<Allocation> depthStencilImageAlloc;
1469 Move<VkImage> resolveImage; //!< Resolve image
1470 Move<VkImageView> resolveImageView; //!< Resolve attachment
1471 MovePtr<Allocation> resolveImageAlloc;
1472 Move<VkBuffer> colorBuffer; //!< Buffer used to copy resolve output
1473 MovePtr<Allocation> colorBufferAlloc;
1474 VkDeviceSize colorBufferSize;
1475
WorkingDatavkt::pipeline::__anon7e964aba0111::ShaderBuiltins::WorkingData1476 WorkingData(void) : numVertices(), colorBufferSize(0)
1477 {
1478 }
1479 };
1480
initPrograms(SourceCollections & programCollection,const TestParams params)1481 void initPrograms(SourceCollections &programCollection, const TestParams params)
1482 {
1483 // Vertex shader - no vertex data
1484 {
1485 std::ostringstream src;
1486 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1487 << "\n"
1488 << "out gl_PerVertex {\n"
1489 << " vec4 gl_Position;\n"
1490 << "};\n"
1491 << "\n"
1492 << "void main(void)\n"
1493 << "{\n"
1494 // Specify an oversized triangle covering the whole viewport.
1495 << " switch (gl_VertexIndex)\n"
1496 << " {\n"
1497 << " case 0:\n"
1498 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1499 << " break;\n"
1500 << " case 1:\n"
1501 << " gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n"
1502 << " break;\n"
1503 << " case 2:\n"
1504 << " gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
1505 << " break;\n"
1506 << " }\n"
1507 << "}\n";
1508
1509 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1510 }
1511
1512 // Fragment shader
1513 {
1514 std::ostringstream src;
1515 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1516 << "\n"
1517 << "layout(location = 0) out vec4 o_color;\n"
1518 << "\n"
1519 << "void main(void)\n"
1520 << "{\n"
1521 << " vec4 col = vec4(0.0, 0.0, 0.0, 1.0);\n"
1522 << "\n";
1523
1524 if (params.numColorSamples == VK_SAMPLE_COUNT_1_BIT)
1525 {
1526 const uint32_t expectedMask = ((1u << static_cast<uint32_t>(params.numCoverageSamples)) - 1u);
1527
1528 // Expect all covered samples to be lit, the rest is zero
1529 src << " if (gl_SampleMaskIn[0] == " << expectedMask << ")\n"
1530 << " col.g = 1.0;\n"
1531 << " else\n"
1532 << " col.r = 1.0;\n";
1533 }
1534 else
1535 {
1536 // Expect only a matching sample to be lit
1537 src << " if (gl_SampleMaskIn[0] == (1 << gl_SampleID))\n"
1538 << " col.g = 1.0;\n"
1539 << " else\n"
1540 << " col.r = 1.0;\n"
1541 << "\n"
1542 << " if (gl_SampleID >= " << static_cast<uint32_t>(params.numColorSamples)
1543 << ") // number of color samples, should not happen\n"
1544 << " col.b = 1.0;\n";
1545 }
1546
1547 src << "\n"
1548 << " o_color = col;\n"
1549 << "}\n";
1550
1551 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1552 }
1553 }
1554
1555 //! A simple color, depth/stencil draw. Single subpass, no vertex input
drawResolve(Context & context,const TestParams & params,WorkingData & wd)1556 void drawResolve(Context &context, const TestParams ¶ms, WorkingData &wd)
1557 {
1558 const InstanceInterface &vki = context.getInstanceInterface();
1559 const DeviceInterface &vk = context.getDeviceInterface();
1560 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1561 const VkDevice device = context.getDevice();
1562 const bool needResolve = (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT);
1563
1564 RenderPassWrapper renderPass;
1565
1566 // Create a render pass and a framebuffer
1567 {
1568 std::vector<VkImage> images;
1569 std::vector<VkImageView> attachments;
1570 std::vector<VkAttachmentDescription> attachmentDescriptions;
1571
1572 images.push_back(*wd.colorImage);
1573 images.push_back(*wd.depthStencilImage);
1574 attachments.push_back(*wd.colorImageView);
1575 attachments.push_back(*wd.depthStencilImageView);
1576
1577 attachmentDescriptions.push_back(
1578 makeAttachmentDescription((VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
1579 params.colorFormat, // VkFormat format;
1580 params.numColorSamples, // VkSampleCountFlagBits samples;
1581 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1582 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1583 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1584 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1585 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1586 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout;
1587 ));
1588
1589 attachmentDescriptions.push_back(
1590 makeAttachmentDescription((VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
1591 params.depthStencilFormat, // VkFormat format;
1592 params.numDepthStencilSamples, // VkSampleCountFlagBits samples;
1593 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1594 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1595 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
1596 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
1597 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1598 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
1599 ));
1600
1601 if (needResolve)
1602 {
1603 images.push_back(*wd.resolveImage);
1604 attachments.push_back(*wd.resolveImageView);
1605
1606 attachmentDescriptions.push_back(
1607 makeAttachmentDescription((VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
1608 params.colorFormat, // VkFormat format;
1609 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1610 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
1611 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1612 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1613 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1614 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1615 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout;
1616 ));
1617 }
1618
1619 const VkAttachmentReference colorRef = makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1620 const VkAttachmentReference depthStencilRef =
1621 makeAttachmentReference(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
1622 const VkAttachmentReference resolveRef = makeAttachmentReference(2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1623
1624 const VkSubpassDescription subpassDescription = {
1625 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
1626 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1627 0u, // uint32_t inputAttachmentCount;
1628 DE_NULL, // const VkAttachmentReference* pInputAttachments;
1629 1u, // uint32_t colorAttachmentCount;
1630 &colorRef, // const VkAttachmentReference* pColorAttachments;
1631 (needResolve ? &resolveRef : DE_NULL), // const VkAttachmentReference* pResolveAttachments;
1632 &depthStencilRef, // const VkAttachmentReference* pDepthStencilAttachment;
1633 0u, // uint32_t preserveAttachmentCount;
1634 DE_NULL, // const uint32_t* pPreserveAttachments;
1635 };
1636
1637 // Assume there are no dependencies between subpasses
1638 VkRenderPassCreateInfo renderPassInfo = {
1639 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1640 DE_NULL, // const void* pNext;
1641 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
1642 static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t attachmentCount;
1643 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments;
1644 1u, // uint32_t subpassCount;
1645 &subpassDescription, // const VkSubpassDescription* pSubpasses;
1646 0u, // uint32_t dependencyCount;
1647 DE_NULL, // const VkSubpassDependency* pDependencies;
1648 };
1649
1650 renderPass = RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo);
1651 renderPass.createFramebuffer(vk, device, static_cast<uint32_t>(attachments.size()), dataOrNullPtr(images),
1652 dataOrNullPtr(attachments), wd.renderSize.x(), wd.renderSize.y());
1653 }
1654
1655 const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
1656 const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
1657 const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device);
1658 const bool useVertexInput = false;
1659 const bool sampleShading = (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT);
1660 const uint32_t subpassNdx = 0u;
1661 GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
1662 params.pipelineConstructionType);
1663 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1664 context.getUniversalQueueFamilyIndex()));
1665 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1666
1667 preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, useVertexInput,
1668 subpassNdx, wd.renderSize, getImageAspectFlags(params.depthStencilFormat),
1669 params.numCoverageSamples, sampleShading, false);
1670
1671 beginCommandBuffer(vk, *cmdBuffer);
1672
1673 {
1674 std::vector<VkClearValue> clearValues;
1675 clearValues.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f));
1676 clearValues.push_back(makeClearValueDepthStencil(1.0f, 0u));
1677
1678 const VkRect2D renderArea = {{0u, 0u}, {wd.renderSize.x(), wd.renderSize.y()}};
1679
1680 renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<uint32_t>(clearValues.size()),
1681 dataOrNullPtr(clearValues));
1682 }
1683
1684 pipeline.bind(*cmdBuffer);
1685 vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
1686
1687 renderPass.end(vk, *cmdBuffer);
1688
1689 if (needResolve)
1690 recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.resolveImage, *wd.colorBuffer);
1691 else
1692 recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.colorImage, *wd.colorBuffer);
1693
1694 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1695 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1696 }
1697
checkRequirements(Context & context,TestParams params)1698 void checkRequirements(Context &context, TestParams params)
1699 {
1700 context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples");
1701
1702 checkSampleRequirements(context, params.numColorSamples, params.numDepthStencilSamples,
1703 false /* require standard sample locations */);
1704 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1705 params.pipelineConstructionType);
1706
1707 if (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT)
1708 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1709 }
1710
1711 //! Verify the values of shader builtins
test(Context & context,const TestParams params)1712 tcu::TestStatus test(Context &context, const TestParams params)
1713 {
1714 WorkingData wd;
1715 const DeviceInterface &vk = context.getDeviceInterface();
1716 const VkDevice device = context.getDevice();
1717 MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(
1718 vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1719
1720 wd.renderSize = UVec2(16, 16);
1721
1722 // Create images and a color buffer
1723 {
1724
1725 const VkImageUsageFlags colorImageUsageFlags =
1726 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1727 const VkImageUsageFlags depthStencilImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1728
1729 checkImageRequirements(context, params.colorFormat, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT,
1730 colorImageUsageFlags, params.numColorSamples);
1731
1732 wd.colorImage =
1733 makeImage(vk, device, params.colorFormat, wd.renderSize, params.numColorSamples, colorImageUsageFlags);
1734 wd.colorImageAlloc = bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any);
1735 wd.colorImageView = makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1736 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1737
1738 if (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT)
1739 {
1740 wd.resolveImage =
1741 makeImage(vk, device, params.colorFormat, wd.renderSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags);
1742 wd.resolveImageAlloc = bindImage(vk, device, *allocator, *wd.resolveImage, MemoryRequirement::Any);
1743 wd.resolveImageView = makeImageView(vk, device, *wd.resolveImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1744 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1745 }
1746
1747 // Resolve result
1748 wd.colorBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat)) *
1749 wd.renderSize.x() * wd.renderSize.y());
1750 wd.colorBuffer = makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1751 wd.colorBufferAlloc = bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible);
1752
1753 deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1754 flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(),
1755 VK_WHOLE_SIZE);
1756
1757 checkImageRequirements(context, params.depthStencilFormat, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT,
1758 depthStencilImageUsageFlags, params.numDepthStencilSamples);
1759
1760 wd.depthStencilImage = makeImage(vk, device, params.depthStencilFormat, wd.renderSize,
1761 params.numDepthStencilSamples, depthStencilImageUsageFlags);
1762 wd.depthStencilImageAlloc = bindImage(vk, device, *allocator, *wd.depthStencilImage, MemoryRequirement::Any);
1763 wd.depthStencilImageView =
1764 makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1765 makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u));
1766
1767 if (isDepthFormat(params.depthStencilFormat))
1768 wd.depthOnlyImageView =
1769 makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1770 makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u));
1771
1772 if (isStencilFormat(params.depthStencilFormat))
1773 wd.stencilOnlyImageView =
1774 makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1775 makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u));
1776 }
1777
1778 // Draw, resolve, and copy to color buffer (see the fragment shader for details)
1779 drawResolve(context, params, wd);
1780
1781 // Verify resolved image
1782 {
1783 const tcu::ConstPixelBufferAccess image(tcu::ConstPixelBufferAccess(
1784 mapVkFormat(params.colorFormat), tcu::IVec3(wd.renderSize.x(), wd.renderSize.y(), 1),
1785 wd.colorBufferAlloc->getHostPtr()));
1786
1787 if (compareGreenImage(context.getTestContext().getLog(), "resolve0", "Resolved test image", image))
1788 return tcu::TestStatus::pass("Pass");
1789 else
1790 return tcu::TestStatus::fail("Some samples were incorrect");
1791 }
1792 }
1793
1794 } // namespace ShaderBuiltins
1795
getSampleCountGroupName(const VkSampleCountFlagBits coverageCount,const VkSampleCountFlagBits colorCount,const VkSampleCountFlagBits depthStencilCount)1796 std::string getSampleCountGroupName(const VkSampleCountFlagBits coverageCount, const VkSampleCountFlagBits colorCount,
1797 const VkSampleCountFlagBits depthStencilCount)
1798 {
1799 std::ostringstream str;
1800 str << "coverage_" << static_cast<uint32_t>(coverageCount) << "_color_" << static_cast<uint32_t>(colorCount)
1801 << "_depth_stencil_" << static_cast<uint32_t>(depthStencilCount);
1802 return str.str();
1803 }
1804
getFormatShortString(const VkFormat format)1805 std::string getFormatShortString(const VkFormat format)
1806 {
1807 std::string s(de::toLower(getFormatName(format)));
1808 return s.substr(10);
1809 }
1810
getFormatCaseName(const VkFormat colorFormat,const VkFormat depthStencilFormat)1811 std::string getFormatCaseName(const VkFormat colorFormat, const VkFormat depthStencilFormat)
1812 {
1813 std::ostringstream str;
1814 str << getFormatShortString(colorFormat) << "_" << getFormatShortString(depthStencilFormat);
1815 return str.str();
1816 }
1817
createMixedAttachmentSamplesTestsInGroup(tcu::TestCaseGroup * rootGroup,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)1818 void createMixedAttachmentSamplesTestsInGroup(tcu::TestCaseGroup *rootGroup,
1819 PipelineConstructionType pipelineConstructionType,
1820 bool useFragmentShadingRate)
1821 {
1822 const VkFormat colorFormatRange[] = {
1823 VK_FORMAT_R8G8B8A8_UNORM,
1824 // If you add more, make sure it is handled in the test/shader
1825 };
1826
1827 const VkFormat depthStencilFormatRange[] = {
1828 VK_FORMAT_D16_UNORM, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT, VK_FORMAT_S8_UINT,
1829 VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT,
1830 };
1831
1832 // Minimal set of formats to cover depth and stencil
1833 const VkFormat depthStencilReducedFormatRange[] = {
1834 VK_FORMAT_D16_UNORM, //!< Must be supported
1835 VK_FORMAT_D24_UNORM_S8_UINT, //!< Either this, or the next one must be supported
1836 VK_FORMAT_D32_SFLOAT_S8_UINT,
1837 };
1838
1839 struct SampleCase
1840 {
1841 VkSampleCountFlagBits colorSamples;
1842 VkSampleCountFlagBits depthStencilSamples;
1843 };
1844
1845 // Currently supported EQAA cases
1846 static const SampleCase singlePassCases[] = {
1847 // Less color than depth/stencil
1848 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT}, {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1849 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT}, {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_16_BIT},
1850 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT}, {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1851 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_16_BIT}, {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1852 {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_16_BIT}, {VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT},
1853 };
1854
1855 // Multi-subpass cases
1856
1857 static const SampleCase caseSubpassIncreaseColor_1[] = {
1858 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1859 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1860 };
1861 static const SampleCase caseSubpassIncreaseColor_2[] = {
1862 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT},
1863 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1864 {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1865 };
1866 static const SampleCase caseSubpassDecreaseColor_1[] = {
1867 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1868 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1869 };
1870 static const SampleCase caseSubpassDecreaseColor_2[] = {
1871 {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1872 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1873 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT},
1874 };
1875 static const SampleCase caseSubpassIncreaseCoverage_1[] = {
1876 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1877 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1878 };
1879 static const SampleCase caseSubpassIncreaseCoverage_2[] = {
1880 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1881 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1882 {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1883 };
1884 static const SampleCase caseSubpassDecreaseCoverage_1[] = {
1885 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1886 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1887 };
1888 static const SampleCase caseSubpassDecreaseCoverage_2[] = {
1889 {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1890 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1891 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1892 };
1893
1894 static const struct
1895 {
1896 const char *const caseName;
1897 const uint32_t numSampleCases;
1898 const SampleCase *pSampleCase;
1899 } subpassCases[] = {
1900 {"multi_subpass_decrease_color_4", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_1), caseSubpassDecreaseColor_1},
1901 {"multi_subpass_decrease_color_8", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_2), caseSubpassDecreaseColor_2},
1902 {"multi_subpass_decrease_coverage_4", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_1),
1903 caseSubpassDecreaseCoverage_1},
1904 {"multi_subpass_decrease_coverage_8", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_2),
1905 caseSubpassDecreaseCoverage_2},
1906 {"multi_subpass_increase_color_4", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_1), caseSubpassIncreaseColor_1},
1907 {"multi_subpass_increase_color_8", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_2), caseSubpassIncreaseColor_2},
1908 {"multi_subpass_increase_coverage_4", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_1),
1909 caseSubpassIncreaseCoverage_1},
1910 {"multi_subpass_increase_coverage_8", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_2),
1911 caseSubpassIncreaseCoverage_2},
1912 };
1913
1914 // Test 1: Per-sample expected value check
1915 {
1916 MovePtr<tcu::TestCaseGroup> standardLocationsGroup(
1917 new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_standard_locations"));
1918 MovePtr<tcu::TestCaseGroup> programmableLocationsGroup(
1919 new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_programmable_locations"));
1920
1921 tcu::TestCaseGroup *locationsGroups[2] = {standardLocationsGroup.get(), programmableLocationsGroup.get()};
1922
1923 for (uint32_t groupNdx = 0u; groupNdx < DE_LENGTH_OF_ARRAY(locationsGroups); ++groupNdx)
1924 {
1925 // Single subpass cases
1926 for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx)
1927 {
1928 VerifySamples::TestParams::SampleCount samples;
1929 samples.numColorSamples = singlePassCases[caseNdx].colorSamples;
1930 samples.numDepthStencilSamples = singlePassCases[caseNdx].depthStencilSamples;
1931 samples.numCoverageSamples = de::max(samples.numColorSamples, samples.numDepthStencilSamples);
1932
1933 VerifySamples::TestParams params;
1934 params.pipelineConstructionType = pipelineConstructionType;
1935 params.perSubpassSamples.push_back(samples);
1936 params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get());
1937 params.useFragmentShadingRate = useFragmentShadingRate;
1938
1939 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(
1940 new tcu::TestCaseGroup(rootGroup->getTestContext(),
1941 getSampleCountGroupName(samples.numCoverageSamples, samples.numColorSamples,
1942 samples.numDepthStencilSamples)
1943 .c_str()));
1944
1945 for (const VkFormat *pDepthStencilFormat = depthStencilFormatRange;
1946 pDepthStencilFormat != DE_ARRAY_END(depthStencilFormatRange); ++pDepthStencilFormat)
1947 for (const VkFormat *pColorFormat = colorFormatRange;
1948 pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat)
1949 {
1950 params.colorFormat = *pColorFormat;
1951 params.depthStencilFormat = *pDepthStencilFormat;
1952
1953 addFunctionCaseWithPrograms(
1954 sampleCaseGroup.get(),
1955 getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
1956 VerifySamples::checkRequirements, VerifySamples::initPrograms, VerifySamples::test, params);
1957 }
1958
1959 locationsGroups[groupNdx]->addChild(sampleCaseGroup.release());
1960 }
1961
1962 // Multi subpass cases
1963 for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(subpassCases); ++caseNdx)
1964 {
1965 VerifySamples::TestParams params;
1966 params.pipelineConstructionType = pipelineConstructionType;
1967 params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get());
1968 params.useFragmentShadingRate = useFragmentShadingRate;
1969
1970 for (uint32_t subpassNdx = 0; subpassNdx < subpassCases[caseNdx].numSampleCases; ++subpassNdx)
1971 {
1972 VerifySamples::TestParams::SampleCount samples;
1973 samples.numColorSamples = subpassCases[caseNdx].pSampleCase[subpassNdx].colorSamples;
1974 samples.numDepthStencilSamples = subpassCases[caseNdx].pSampleCase[subpassNdx].depthStencilSamples;
1975 samples.numCoverageSamples = de::max(samples.numColorSamples, samples.numDepthStencilSamples);
1976 params.perSubpassSamples.push_back(samples);
1977 }
1978
1979 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(
1980 new tcu::TestCaseGroup(rootGroup->getTestContext(), subpassCases[caseNdx].caseName));
1981
1982 for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange;
1983 pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat)
1984 for (const VkFormat *pColorFormat = colorFormatRange;
1985 pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat)
1986 {
1987 params.colorFormat = *pColorFormat;
1988 params.depthStencilFormat = *pDepthStencilFormat;
1989
1990 addFunctionCaseWithPrograms(
1991 sampleCaseGroup.get(),
1992 getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
1993 VerifySamples::checkRequirements, VerifySamples::initPrograms, VerifySamples::test, params);
1994 }
1995
1996 locationsGroups[groupNdx]->addChild(sampleCaseGroup.release());
1997 }
1998 }
1999
2000 rootGroup->addChild(standardLocationsGroup.release());
2001 rootGroup->addChild(programmableLocationsGroup.release());
2002 }
2003
2004 // Test 2: Shader built-ins check
2005 if (!useFragmentShadingRate)
2006 {
2007 MovePtr<tcu::TestCaseGroup> builtinsGroup(
2008 new tcu::TestCaseGroup(rootGroup->getTestContext(), "shader_builtins"));
2009
2010 for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx)
2011 {
2012 ShaderBuiltins::TestParams params;
2013 params.pipelineConstructionType = pipelineConstructionType;
2014 params.numColorSamples = singlePassCases[caseNdx].colorSamples;
2015 params.numDepthStencilSamples = singlePassCases[caseNdx].depthStencilSamples;
2016 params.numCoverageSamples = de::max(params.numColorSamples, params.numDepthStencilSamples);
2017
2018 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(new tcu::TestCaseGroup(
2019 rootGroup->getTestContext(), getSampleCountGroupName(params.numCoverageSamples, params.numColorSamples,
2020 params.numDepthStencilSamples)
2021 .c_str()));
2022
2023 for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange;
2024 pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat)
2025 for (const VkFormat *pColorFormat = colorFormatRange; pColorFormat != DE_ARRAY_END(colorFormatRange);
2026 ++pColorFormat)
2027 {
2028 params.colorFormat = *pColorFormat;
2029 params.depthStencilFormat = *pDepthStencilFormat;
2030
2031 addFunctionCaseWithPrograms(
2032 sampleCaseGroup.get(), getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
2033 ShaderBuiltins::checkRequirements, ShaderBuiltins::initPrograms, ShaderBuiltins::test, params);
2034 }
2035
2036 builtinsGroup->addChild(sampleCaseGroup.release());
2037 }
2038
2039 rootGroup->addChild(builtinsGroup.release());
2040 }
2041 }
2042
2043 } // namespace
2044
createMultisampleMixedAttachmentSamplesTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)2045 tcu::TestCaseGroup *createMultisampleMixedAttachmentSamplesTests(tcu::TestContext &testCtx,
2046 PipelineConstructionType pipelineConstructionType,
2047 bool useFragmentShadingRate)
2048 {
2049 // Test a graphics pipeline with varying sample count per color and depth/stencil attachments
2050 return createTestGroup(testCtx, "mixed_attachment_samples", createMixedAttachmentSamplesTestsInGroup,
2051 pipelineConstructionType, useFragmentShadingRate);
2052 }
2053
2054 } // namespace pipeline
2055 } // namespace vkt
2056