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::__anonea1bc53a0111::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 nullptr, // 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 nullptr, // 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 nullptr, // 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=nullptr)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 = nullptr)
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 nullptr, // 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 nullptr, // 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 nullptr, // const void* pNext;
222 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
223 numSamples, // VkSampleCountFlagBits rasterizationSamples;
224 sampleShadingEnable, // VkBool32 sampleShadingEnable;
225 1.0f, // float minSampleShading;
226 nullptr, // 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 nullptr, // 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 nullptr, // 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 nullptr, // 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(), nullptr,
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 = nullptr;
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::__anonea1bc53a0111::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 nullptr, // 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, nullptr, 0u, nullptr, 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 nullptr, // 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, nullptr, 1u, &barrier, 0u, nullptr);
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::__anonea1bc53a0111::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::__anonea1bc53a0111::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::__anonea1bc53a0111::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 nullptr, // const VkAttachmentReference* pInputAttachments;
955 1u, // uint32_t colorAttachmentCount;
956 colorRef, // const VkAttachmentReference* pColorAttachments;
957 nullptr, // const VkAttachmentReference* pResolveAttachments;
958 depthStencilRef, // const VkAttachmentReference* pDepthStencilAttachment;
959 0u, // uint32_t preserveAttachmentCount;
960 nullptr, // 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 nullptr, // 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 nullptr, // 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] : nullptr);
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 nullptr, // 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 = makeDescriptorImageInfo(
1103 VK_NULL_HANDLE, *subpassData.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1104 const VkDescriptorImageInfo depthImageInfo = makeDescriptorImageInfo(
1105 VK_NULL_HANDLE, *subpassData.depthOnlyImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1106 const VkDescriptorImageInfo stencilImageInfo = makeDescriptorImageInfo(
1107 VK_NULL_HANDLE, *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, nullptr);
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 nullptr, // 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, nullptr, 1u, &barrier, 0u, nullptr);
1164 }
1165
1166 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1167 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1168
1169 invalidateMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(),
1170 subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1171 }
1172
createPerSubpassData(Context & context,const TestParams & params,WorkingData & wd,const uint32_t subpassNdx)1173 void createPerSubpassData(Context &context, const TestParams ¶ms, WorkingData &wd, const uint32_t subpassNdx)
1174 {
1175 const DeviceInterface &vk = context.getDeviceInterface();
1176 const VkDevice device = context.getDevice();
1177 MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(
1178 vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1179 const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1180 WorkingData::PerSubpass &subpassData = *wd.perSubpass[subpassNdx];
1181
1182 // Create images
1183 {
1184
1185 const VkImageUsageFlags colorImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1186 const VkImageUsageFlags depthStencilImageUsageFlags =
1187 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1188
1189 checkImageRequirements(context, params.colorFormat,
1190 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1191 colorImageUsageFlags, samples.numColorSamples);
1192
1193 subpassData.colorImage =
1194 makeImage(vk, device, params.colorFormat, wd.renderSize, samples.numColorSamples, colorImageUsageFlags);
1195 subpassData.colorImageAlloc =
1196 bindImage(vk, device, *allocator, *subpassData.colorImage, MemoryRequirement::Any);
1197 subpassData.colorImageView =
1198 makeImageView(vk, device, *subpassData.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1199 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1200
1201 checkImageRequirements(context, params.depthStencilFormat,
1202 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1203 depthStencilImageUsageFlags, samples.numDepthStencilSamples);
1204
1205 subpassData.depthStencilImage = makeImage(vk, device, params.depthStencilFormat, wd.renderSize,
1206 samples.numDepthStencilSamples, depthStencilImageUsageFlags);
1207 subpassData.depthStencilImageAlloc =
1208 bindImage(vk, device, *allocator, *subpassData.depthStencilImage, MemoryRequirement::Any);
1209 subpassData.depthStencilImageView =
1210 makeImageView(vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1211 makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u));
1212
1213 if (isDepthFormat(params.depthStencilFormat))
1214 subpassData.depthOnlyImageView = makeImageView(
1215 vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1216 makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u));
1217
1218 if (isStencilFormat(params.depthStencilFormat))
1219 subpassData.stencilOnlyImageView = makeImageView(
1220 vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1221 makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u));
1222 }
1223
1224 // Create vertex and comparison buffers
1225 {
1226 const uint32_t seed = 123 + 19 * subpassNdx;
1227 const std::vector<CompareData> compareData = generateCompareData(
1228 seed, wd.renderSize, samples.numCoverageSamples, samples.numColorSamples, samples.numDepthStencilSamples);
1229
1230 subpassData.compareBufferSize = static_cast<VkDeviceSize>(sizeof(CompareData) * compareData.size());
1231 subpassData.compareBuffer =
1232 makeBuffer(vk, device, subpassData.compareBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1233 subpassData.compareBufferAlloc =
1234 bindBuffer(vk, device, *allocator, *subpassData.compareBuffer, MemoryRequirement::HostVisible);
1235
1236 deMemcpy(subpassData.compareBufferAlloc->getHostPtr(), dataOrNullPtr(compareData),
1237 static_cast<std::size_t>(subpassData.compareBufferSize));
1238 flushMappedMemoryRange(vk, device, subpassData.compareBufferAlloc->getMemory(),
1239 subpassData.compareBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1240
1241 subpassData.numResultElements = static_cast<uint32_t>(compareData.size());
1242 subpassData.resultBufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t) * compareData.size());
1243 subpassData.resultBuffer =
1244 makeBuffer(vk, device, subpassData.resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1245 subpassData.resultBufferAlloc =
1246 bindBuffer(vk, device, *allocator, *subpassData.resultBuffer, MemoryRequirement::HostVisible);
1247
1248 deMemset(subpassData.resultBufferAlloc->getHostPtr(), 0,
1249 static_cast<std::size_t>(subpassData.resultBufferSize));
1250 flushMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(),
1251 subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1252
1253 std::vector<PositionColor> vertices;
1254
1255 if (params.useProgrammableSampleLocations)
1256 {
1257 subpassData.pixelGrid = MovePtr<MultisamplePixelGrid>(
1258 new MultisamplePixelGrid(UVec2(wd.sampleLocationsProperties.maxSampleLocationGridSize.width,
1259 wd.sampleLocationsProperties.maxSampleLocationGridSize.height),
1260 samples.numCoverageSamples));
1261
1262 const uint32_t locationsSeed = 211 + 4 * subpassNdx;
1263 fillSampleLocationsRandom(*subpassData.pixelGrid, wd.sampleLocationsProperties.sampleLocationSubPixelBits,
1264 locationsSeed);
1265 vertices = generateSubpixelTriangles(wd.renderSize, compareData,
1266 getSampleLocations(*subpassData.pixelGrid, wd.renderSize));
1267 }
1268 else
1269 {
1270 const std::vector<Vec2> locations =
1271 genFramebufferStandardSampleLocations(samples.numCoverageSamples, wd.renderSize);
1272 vertices = generateSubpixelTriangles(wd.renderSize, compareData, locations);
1273 }
1274
1275 const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1276 subpassData.numVertices = static_cast<uint32_t>(vertices.size());
1277 subpassData.vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1278 subpassData.vertexBufferAlloc =
1279 bindBuffer(vk, device, *allocator, *subpassData.vertexBuffer, MemoryRequirement::HostVisible);
1280
1281 deMemcpy(subpassData.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices),
1282 static_cast<std::size_t>(vertexBufferSize));
1283 flushMappedMemoryRange(vk, device, subpassData.vertexBufferAlloc->getMemory(),
1284 subpassData.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1285 }
1286 }
1287
checkRequirements(Context & context,TestParams params)1288 void checkRequirements(Context &context, TestParams params)
1289 {
1290 context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples");
1291
1292 if (params.useProgrammableSampleLocations)
1293 context.requireDeviceFunctionality("VK_EXT_sample_locations");
1294
1295 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1296 {
1297 const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1298 checkSampleRequirements(context, samples.numColorSamples, samples.numDepthStencilSamples,
1299 !params.useProgrammableSampleLocations);
1300 }
1301
1302 const auto &vki = context.getInstanceInterface();
1303 const auto physicalDevice = context.getPhysicalDevice();
1304
1305 if (params.useFragmentShadingRate)
1306 {
1307 context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
1308
1309 if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
1310 TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
1311
1312 // Fetch information about supported fragment shading rates
1313 uint32_t supportedFragmentShadingRateCount = 0;
1314 vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, nullptr);
1315
1316 std::vector<vk::VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates(
1317 supportedFragmentShadingRateCount, {vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR,
1318 nullptr,
1319 vk::VK_SAMPLE_COUNT_1_BIT,
1320 {1, 1}});
1321 vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount,
1322 supportedFragmentShadingRates.data());
1323
1324 uint32_t cumulativeNeededSamples = 0;
1325 for (const TestParams::SampleCount &samples : params.perSubpassSamples)
1326 cumulativeNeededSamples |= samples.numColorSamples;
1327
1328 bool requiredRateFound = false;
1329 for (const auto &rate : supportedFragmentShadingRates)
1330 {
1331 if ((rate.fragmentSize.width == 2u) && (rate.fragmentSize.height == 2u) &&
1332 (rate.sampleCounts & cumulativeNeededSamples))
1333 {
1334 requiredRateFound = true;
1335 break;
1336 }
1337 }
1338
1339 if (!requiredRateFound)
1340 TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
1341 }
1342
1343 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1344 params.pipelineConstructionType);
1345 }
1346
1347 //! Verify the values of all samples in all attachments.
test(Context & context,const TestParams params)1348 tcu::TestStatus test(Context &context, const TestParams params)
1349 {
1350 WorkingData wd;
1351 wd.renderSize = UVec2(2, 2); // Use a very small image, as we will verify all samples for all pixels
1352
1353 // Query state related to programmable sample locations
1354 if (params.useProgrammableSampleLocations)
1355 {
1356 const InstanceInterface &vki = context.getInstanceInterface();
1357 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1358
1359 wd.sampleLocationsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT;
1360 wd.sampleLocationsProperties.pNext = nullptr;
1361
1362 VkPhysicalDeviceProperties2 properties = {
1363 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // VkStructureType sType;
1364 &wd.sampleLocationsProperties, // void* pNext;
1365 VkPhysicalDeviceProperties(), // VkPhysicalDeviceProperties properties;
1366 };
1367
1368 vki.getPhysicalDeviceProperties2(physicalDevice, &properties);
1369
1370 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1371 {
1372 if ((wd.sampleLocationsProperties.sampleLocationSampleCounts &
1373 params.perSubpassSamples[subpassNdx].numCoverageSamples) == 0u)
1374 TCU_THROW(NotSupportedError, "VkSampleLocationsPropertiesAMD: sample count not supported");
1375 }
1376 }
1377
1378 // Create subpass data
1379 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1380 {
1381 wd.perSubpass.push_back(SharedPtr<WorkingData::PerSubpass>(new WorkingData::PerSubpass()));
1382 createPerSubpassData(context, params, wd, subpassNdx);
1383 }
1384
1385 // Draw test geometry
1386 draw(context, params, wd);
1387
1388 // Verify images with a compute shader
1389 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1390 dispatchImageCheck(context, params, wd, subpassNdx);
1391
1392 // Test checksums
1393 for (uint32_t subpassNdx = 0; subpassNdx < static_cast<uint32_t>(params.perSubpassSamples.size()); ++subpassNdx)
1394 {
1395 const uint32_t *const pSampleChecksumBase =
1396 static_cast<uint32_t *>(wd.perSubpass[subpassNdx]->resultBufferAlloc->getHostPtr());
1397 const bool hasDepth = isDepthFormat(params.depthStencilFormat);
1398 const bool hasStencil = isStencilFormat(params.depthStencilFormat);
1399 bool allOk = true;
1400
1401 context.getTestContext().getLog()
1402 << tcu::TestLog::Message << "Verify images in subpass " << subpassNdx << tcu::TestLog::EndMessage;
1403
1404 for (uint32_t globalSampleNdx = 0; globalSampleNdx < wd.perSubpass[subpassNdx]->numResultElements;
1405 ++globalSampleNdx)
1406 {
1407 const TestParams::SampleCount &samples = params.perSubpassSamples[subpassNdx];
1408 const uint32_t checksum = pSampleChecksumBase[globalSampleNdx];
1409
1410 if ((checksum & VK_IMAGE_ASPECT_COLOR_BIT) == 0u)
1411 {
1412 reportSampleError(context.getTestContext().getLog(), "color", wd.renderSize, samples.numCoverageSamples,
1413 globalSampleNdx);
1414 allOk = false;
1415 }
1416
1417 if (hasDepth && ((checksum & VK_IMAGE_ASPECT_DEPTH_BIT) == 0u))
1418 {
1419 reportSampleError(context.getTestContext().getLog(), "depth", wd.renderSize, samples.numCoverageSamples,
1420 globalSampleNdx);
1421 allOk = false;
1422 }
1423
1424 if (hasStencil && ((checksum & VK_IMAGE_ASPECT_STENCIL_BIT) == 0u))
1425 {
1426 reportSampleError(context.getTestContext().getLog(), "stencil", wd.renderSize,
1427 samples.numCoverageSamples, globalSampleNdx);
1428 allOk = false;
1429 }
1430 }
1431
1432 if (!allOk)
1433 return tcu::TestStatus::fail("Multisampled image has incorrect samples");
1434 }
1435
1436 return tcu::TestStatus::pass("Pass");
1437 }
1438
1439 } // namespace VerifySamples
1440
1441 namespace ShaderBuiltins
1442 {
1443
1444 struct TestParams
1445 {
1446 PipelineConstructionType pipelineConstructionType; //!< The way pipeline is constructed
1447 VkSampleCountFlagBits numCoverageSamples; //!< VkPipelineMultisampleStateCreateInfo::rasterizationSamples
1448 VkSampleCountFlagBits numColorSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
1449 VkSampleCountFlagBits numDepthStencilSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
1450 VkFormat colorFormat; //!< Color attachment format
1451 VkFormat depthStencilFormat; //!< D/S attachment format. Will test both aspects if it's a mixed format
1452 };
1453
1454 struct WorkingData
1455 {
1456 UVec2 renderSize; //!< Size of the framebuffer
1457 uint32_t numVertices; //!< Number of vertices defined in the vertex buffer
1458 Move<VkBuffer> vertexBuffer;
1459 MovePtr<Allocation> vertexBufferAlloc;
1460 Move<VkImage> colorImage; //!< Color image
1461 Move<VkImageView> colorImageView; //!< Color attachment
1462 MovePtr<Allocation> colorImageAlloc;
1463 Move<VkImage> depthStencilImage; //!< Depth stencil image
1464 Move<VkImageView> depthStencilImageView; //!< Depth stencil attachment
1465 Move<VkImageView> depthOnlyImageView; //!< Depth aspect for shader read
1466 Move<VkImageView> stencilOnlyImageView; //!< Stencil aspect for shader read
1467 MovePtr<Allocation> depthStencilImageAlloc;
1468 Move<VkImage> resolveImage; //!< Resolve image
1469 Move<VkImageView> resolveImageView; //!< Resolve attachment
1470 MovePtr<Allocation> resolveImageAlloc;
1471 Move<VkBuffer> colorBuffer; //!< Buffer used to copy resolve output
1472 MovePtr<Allocation> colorBufferAlloc;
1473 VkDeviceSize colorBufferSize;
1474
WorkingDatavkt::pipeline::__anonea1bc53a0111::ShaderBuiltins::WorkingData1475 WorkingData(void) : numVertices(), colorBufferSize(0)
1476 {
1477 }
1478 };
1479
initPrograms(SourceCollections & programCollection,const TestParams params)1480 void initPrograms(SourceCollections &programCollection, const TestParams params)
1481 {
1482 // Vertex shader - no vertex data
1483 {
1484 std::ostringstream src;
1485 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1486 << "\n"
1487 << "out gl_PerVertex {\n"
1488 << " vec4 gl_Position;\n"
1489 << "};\n"
1490 << "\n"
1491 << "void main(void)\n"
1492 << "{\n"
1493 // Specify an oversized triangle covering the whole viewport.
1494 << " switch (gl_VertexIndex)\n"
1495 << " {\n"
1496 << " case 0:\n"
1497 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1498 << " break;\n"
1499 << " case 1:\n"
1500 << " gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n"
1501 << " break;\n"
1502 << " case 2:\n"
1503 << " gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
1504 << " break;\n"
1505 << " }\n"
1506 << "}\n";
1507
1508 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1509 }
1510
1511 // Fragment shader
1512 {
1513 std::ostringstream src;
1514 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1515 << "\n"
1516 << "layout(location = 0) out vec4 o_color;\n"
1517 << "\n"
1518 << "void main(void)\n"
1519 << "{\n"
1520 << " vec4 col = vec4(0.0, 0.0, 0.0, 1.0);\n"
1521 << "\n";
1522
1523 if (params.numColorSamples == VK_SAMPLE_COUNT_1_BIT)
1524 {
1525 const uint32_t expectedMask = ((1u << static_cast<uint32_t>(params.numCoverageSamples)) - 1u);
1526
1527 // Expect all covered samples to be lit, the rest is zero
1528 src << " if (gl_SampleMaskIn[0] == " << expectedMask << ")\n"
1529 << " col.g = 1.0;\n"
1530 << " else\n"
1531 << " col.r = 1.0;\n";
1532 }
1533 else
1534 {
1535 // Expect only a matching sample to be lit
1536 src << " if (gl_SampleMaskIn[0] == (1 << gl_SampleID))\n"
1537 << " col.g = 1.0;\n"
1538 << " else\n"
1539 << " col.r = 1.0;\n"
1540 << "\n"
1541 << " if (gl_SampleID >= " << static_cast<uint32_t>(params.numColorSamples)
1542 << ") // number of color samples, should not happen\n"
1543 << " col.b = 1.0;\n";
1544 }
1545
1546 src << "\n"
1547 << " o_color = col;\n"
1548 << "}\n";
1549
1550 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1551 }
1552 }
1553
1554 //! A simple color, depth/stencil draw. Single subpass, no vertex input
drawResolve(Context & context,const TestParams & params,WorkingData & wd)1555 void drawResolve(Context &context, const TestParams ¶ms, WorkingData &wd)
1556 {
1557 const InstanceInterface &vki = context.getInstanceInterface();
1558 const DeviceInterface &vk = context.getDeviceInterface();
1559 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1560 const VkDevice device = context.getDevice();
1561 const bool needResolve = (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT);
1562
1563 RenderPassWrapper renderPass;
1564
1565 // Create a render pass and a framebuffer
1566 {
1567 std::vector<VkImage> images;
1568 std::vector<VkImageView> attachments;
1569 std::vector<VkAttachmentDescription> attachmentDescriptions;
1570
1571 images.push_back(*wd.colorImage);
1572 images.push_back(*wd.depthStencilImage);
1573 attachments.push_back(*wd.colorImageView);
1574 attachments.push_back(*wd.depthStencilImageView);
1575
1576 attachmentDescriptions.push_back(
1577 makeAttachmentDescription((VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
1578 params.colorFormat, // VkFormat format;
1579 params.numColorSamples, // VkSampleCountFlagBits samples;
1580 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1581 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1582 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1583 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1584 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1585 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout;
1586 ));
1587
1588 attachmentDescriptions.push_back(
1589 makeAttachmentDescription((VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
1590 params.depthStencilFormat, // VkFormat format;
1591 params.numDepthStencilSamples, // VkSampleCountFlagBits samples;
1592 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1593 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1594 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
1595 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
1596 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1597 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
1598 ));
1599
1600 if (needResolve)
1601 {
1602 images.push_back(*wd.resolveImage);
1603 attachments.push_back(*wd.resolveImageView);
1604
1605 attachmentDescriptions.push_back(
1606 makeAttachmentDescription((VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
1607 params.colorFormat, // VkFormat format;
1608 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1609 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
1610 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1611 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1612 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1613 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1614 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout;
1615 ));
1616 }
1617
1618 const VkAttachmentReference colorRef = makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1619 const VkAttachmentReference depthStencilRef =
1620 makeAttachmentReference(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
1621 const VkAttachmentReference resolveRef = makeAttachmentReference(2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
1622
1623 const VkSubpassDescription subpassDescription = {
1624 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
1625 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1626 0u, // uint32_t inputAttachmentCount;
1627 nullptr, // const VkAttachmentReference* pInputAttachments;
1628 1u, // uint32_t colorAttachmentCount;
1629 &colorRef, // const VkAttachmentReference* pColorAttachments;
1630 (needResolve ? &resolveRef : nullptr), // const VkAttachmentReference* pResolveAttachments;
1631 &depthStencilRef, // const VkAttachmentReference* pDepthStencilAttachment;
1632 0u, // uint32_t preserveAttachmentCount;
1633 nullptr, // const uint32_t* pPreserveAttachments;
1634 };
1635
1636 // Assume there are no dependencies between subpasses
1637 VkRenderPassCreateInfo renderPassInfo = {
1638 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1639 nullptr, // const void* pNext;
1640 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
1641 static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t attachmentCount;
1642 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments;
1643 1u, // uint32_t subpassCount;
1644 &subpassDescription, // const VkSubpassDescription* pSubpasses;
1645 0u, // uint32_t dependencyCount;
1646 nullptr, // const VkSubpassDependency* pDependencies;
1647 };
1648
1649 renderPass = RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo);
1650 renderPass.createFramebuffer(vk, device, static_cast<uint32_t>(attachments.size()), dataOrNullPtr(images),
1651 dataOrNullPtr(attachments), wd.renderSize.x(), wd.renderSize.y());
1652 }
1653
1654 const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
1655 const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
1656 const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, device);
1657 const bool useVertexInput = false;
1658 const bool sampleShading = (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT);
1659 const uint32_t subpassNdx = 0u;
1660 GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
1661 params.pipelineConstructionType);
1662 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1663 context.getUniversalQueueFamilyIndex()));
1664 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1665
1666 preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, useVertexInput,
1667 subpassNdx, wd.renderSize, getImageAspectFlags(params.depthStencilFormat),
1668 params.numCoverageSamples, sampleShading, false);
1669
1670 beginCommandBuffer(vk, *cmdBuffer);
1671
1672 {
1673 std::vector<VkClearValue> clearValues;
1674 clearValues.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f));
1675 clearValues.push_back(makeClearValueDepthStencil(1.0f, 0u));
1676
1677 const VkRect2D renderArea = {{0u, 0u}, {wd.renderSize.x(), wd.renderSize.y()}};
1678
1679 renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<uint32_t>(clearValues.size()),
1680 dataOrNullPtr(clearValues));
1681 }
1682
1683 pipeline.bind(*cmdBuffer);
1684 vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
1685
1686 renderPass.end(vk, *cmdBuffer);
1687
1688 if (needResolve)
1689 recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.resolveImage, *wd.colorBuffer);
1690 else
1691 recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.colorImage, *wd.colorBuffer);
1692
1693 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1694 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1695 }
1696
checkRequirements(Context & context,TestParams params)1697 void checkRequirements(Context &context, TestParams params)
1698 {
1699 context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples");
1700
1701 checkSampleRequirements(context, params.numColorSamples, params.numDepthStencilSamples,
1702 false /* require standard sample locations */);
1703 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1704 params.pipelineConstructionType);
1705
1706 if (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT)
1707 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1708 }
1709
1710 //! Verify the values of shader builtins
test(Context & context,const TestParams params)1711 tcu::TestStatus test(Context &context, const TestParams params)
1712 {
1713 WorkingData wd;
1714 const DeviceInterface &vk = context.getDeviceInterface();
1715 const VkDevice device = context.getDevice();
1716 MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(
1717 vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1718
1719 wd.renderSize = UVec2(16, 16);
1720
1721 // Create images and a color buffer
1722 {
1723
1724 const VkImageUsageFlags colorImageUsageFlags =
1725 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1726 const VkImageUsageFlags depthStencilImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1727
1728 checkImageRequirements(context, params.colorFormat, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT,
1729 colorImageUsageFlags, params.numColorSamples);
1730
1731 wd.colorImage =
1732 makeImage(vk, device, params.colorFormat, wd.renderSize, params.numColorSamples, colorImageUsageFlags);
1733 wd.colorImageAlloc = bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any);
1734 wd.colorImageView = makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1735 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1736
1737 if (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT)
1738 {
1739 wd.resolveImage =
1740 makeImage(vk, device, params.colorFormat, wd.renderSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags);
1741 wd.resolveImageAlloc = bindImage(vk, device, *allocator, *wd.resolveImage, MemoryRequirement::Any);
1742 wd.resolveImageView = makeImageView(vk, device, *wd.resolveImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat,
1743 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1744 }
1745
1746 // Resolve result
1747 wd.colorBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat)) *
1748 wd.renderSize.x() * wd.renderSize.y());
1749 wd.colorBuffer = makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1750 wd.colorBufferAlloc = bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible);
1751
1752 deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1753 flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(),
1754 VK_WHOLE_SIZE);
1755
1756 checkImageRequirements(context, params.depthStencilFormat, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT,
1757 depthStencilImageUsageFlags, params.numDepthStencilSamples);
1758
1759 wd.depthStencilImage = makeImage(vk, device, params.depthStencilFormat, wd.renderSize,
1760 params.numDepthStencilSamples, depthStencilImageUsageFlags);
1761 wd.depthStencilImageAlloc = bindImage(vk, device, *allocator, *wd.depthStencilImage, MemoryRequirement::Any);
1762 wd.depthStencilImageView =
1763 makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1764 makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u));
1765
1766 if (isDepthFormat(params.depthStencilFormat))
1767 wd.depthOnlyImageView =
1768 makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1769 makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u));
1770
1771 if (isStencilFormat(params.depthStencilFormat))
1772 wd.stencilOnlyImageView =
1773 makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat,
1774 makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u));
1775 }
1776
1777 // Draw, resolve, and copy to color buffer (see the fragment shader for details)
1778 drawResolve(context, params, wd);
1779
1780 // Verify resolved image
1781 {
1782 const tcu::ConstPixelBufferAccess image(tcu::ConstPixelBufferAccess(
1783 mapVkFormat(params.colorFormat), tcu::IVec3(wd.renderSize.x(), wd.renderSize.y(), 1),
1784 wd.colorBufferAlloc->getHostPtr()));
1785
1786 if (compareGreenImage(context.getTestContext().getLog(), "resolve0", "Resolved test image", image))
1787 return tcu::TestStatus::pass("Pass");
1788 else
1789 return tcu::TestStatus::fail("Some samples were incorrect");
1790 }
1791 }
1792
1793 } // namespace ShaderBuiltins
1794
getSampleCountGroupName(const VkSampleCountFlagBits coverageCount,const VkSampleCountFlagBits colorCount,const VkSampleCountFlagBits depthStencilCount)1795 std::string getSampleCountGroupName(const VkSampleCountFlagBits coverageCount, const VkSampleCountFlagBits colorCount,
1796 const VkSampleCountFlagBits depthStencilCount)
1797 {
1798 std::ostringstream str;
1799 str << "coverage_" << static_cast<uint32_t>(coverageCount) << "_color_" << static_cast<uint32_t>(colorCount)
1800 << "_depth_stencil_" << static_cast<uint32_t>(depthStencilCount);
1801 return str.str();
1802 }
1803
getFormatShortString(const VkFormat format)1804 std::string getFormatShortString(const VkFormat format)
1805 {
1806 std::string s(de::toLower(getFormatName(format)));
1807 return s.substr(10);
1808 }
1809
getFormatCaseName(const VkFormat colorFormat,const VkFormat depthStencilFormat)1810 std::string getFormatCaseName(const VkFormat colorFormat, const VkFormat depthStencilFormat)
1811 {
1812 std::ostringstream str;
1813 str << getFormatShortString(colorFormat) << "_" << getFormatShortString(depthStencilFormat);
1814 return str.str();
1815 }
1816
createMixedAttachmentSamplesTestsInGroup(tcu::TestCaseGroup * rootGroup,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)1817 void createMixedAttachmentSamplesTestsInGroup(tcu::TestCaseGroup *rootGroup,
1818 PipelineConstructionType pipelineConstructionType,
1819 bool useFragmentShadingRate)
1820 {
1821 const VkFormat colorFormatRange[] = {
1822 VK_FORMAT_R8G8B8A8_UNORM,
1823 // If you add more, make sure it is handled in the test/shader
1824 };
1825
1826 const VkFormat depthStencilFormatRange[] = {
1827 VK_FORMAT_D16_UNORM, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT, VK_FORMAT_S8_UINT,
1828 VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT,
1829 };
1830
1831 // Minimal set of formats to cover depth and stencil
1832 const VkFormat depthStencilReducedFormatRange[] = {
1833 VK_FORMAT_D16_UNORM, //!< Must be supported
1834 VK_FORMAT_D24_UNORM_S8_UINT, //!< Either this, or the next one must be supported
1835 VK_FORMAT_D32_SFLOAT_S8_UINT,
1836 };
1837
1838 struct SampleCase
1839 {
1840 VkSampleCountFlagBits colorSamples;
1841 VkSampleCountFlagBits depthStencilSamples;
1842 };
1843
1844 // Currently supported EQAA cases
1845 static const SampleCase singlePassCases[] = {
1846 // Less color than depth/stencil
1847 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT}, {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1848 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT}, {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_16_BIT},
1849 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT}, {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1850 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_16_BIT}, {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1851 {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_16_BIT}, {VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT},
1852 };
1853
1854 // Multi-subpass cases
1855
1856 static const SampleCase caseSubpassIncreaseColor_1[] = {
1857 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1858 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1859 };
1860 static const SampleCase caseSubpassIncreaseColor_2[] = {
1861 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT},
1862 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1863 {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1864 };
1865 static const SampleCase caseSubpassDecreaseColor_1[] = {
1866 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1867 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT},
1868 };
1869 static const SampleCase caseSubpassDecreaseColor_2[] = {
1870 {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1871 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT},
1872 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT},
1873 };
1874 static const SampleCase caseSubpassIncreaseCoverage_1[] = {
1875 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1876 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1877 };
1878 static const SampleCase caseSubpassIncreaseCoverage_2[] = {
1879 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1880 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1881 {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1882 };
1883 static const SampleCase caseSubpassDecreaseCoverage_1[] = {
1884 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1885 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1886 };
1887 static const SampleCase caseSubpassDecreaseCoverage_2[] = {
1888 {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT},
1889 {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT},
1890 {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT},
1891 };
1892
1893 static const struct
1894 {
1895 const char *const caseName;
1896 const uint32_t numSampleCases;
1897 const SampleCase *pSampleCase;
1898 } subpassCases[] = {
1899 {"multi_subpass_decrease_color_4", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_1), caseSubpassDecreaseColor_1},
1900 {"multi_subpass_decrease_color_8", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_2), caseSubpassDecreaseColor_2},
1901 {"multi_subpass_decrease_coverage_4", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_1),
1902 caseSubpassDecreaseCoverage_1},
1903 {"multi_subpass_decrease_coverage_8", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_2),
1904 caseSubpassDecreaseCoverage_2},
1905 {"multi_subpass_increase_color_4", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_1), caseSubpassIncreaseColor_1},
1906 {"multi_subpass_increase_color_8", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_2), caseSubpassIncreaseColor_2},
1907 {"multi_subpass_increase_coverage_4", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_1),
1908 caseSubpassIncreaseCoverage_1},
1909 {"multi_subpass_increase_coverage_8", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_2),
1910 caseSubpassIncreaseCoverage_2},
1911 };
1912
1913 // Test 1: Per-sample expected value check
1914 {
1915 MovePtr<tcu::TestCaseGroup> standardLocationsGroup(
1916 new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_standard_locations"));
1917 MovePtr<tcu::TestCaseGroup> programmableLocationsGroup(
1918 new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_programmable_locations"));
1919
1920 tcu::TestCaseGroup *locationsGroups[2] = {standardLocationsGroup.get(), programmableLocationsGroup.get()};
1921
1922 for (uint32_t groupNdx = 0u; groupNdx < DE_LENGTH_OF_ARRAY(locationsGroups); ++groupNdx)
1923 {
1924 // Single subpass cases
1925 for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx)
1926 {
1927 VerifySamples::TestParams::SampleCount samples;
1928 samples.numColorSamples = singlePassCases[caseNdx].colorSamples;
1929 samples.numDepthStencilSamples = singlePassCases[caseNdx].depthStencilSamples;
1930 samples.numCoverageSamples = de::max(samples.numColorSamples, samples.numDepthStencilSamples);
1931
1932 VerifySamples::TestParams params;
1933 params.pipelineConstructionType = pipelineConstructionType;
1934 params.perSubpassSamples.push_back(samples);
1935 params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get());
1936 params.useFragmentShadingRate = useFragmentShadingRate;
1937
1938 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(
1939 new tcu::TestCaseGroup(rootGroup->getTestContext(),
1940 getSampleCountGroupName(samples.numCoverageSamples, samples.numColorSamples,
1941 samples.numDepthStencilSamples)
1942 .c_str()));
1943
1944 for (const VkFormat *pDepthStencilFormat = depthStencilFormatRange;
1945 pDepthStencilFormat != DE_ARRAY_END(depthStencilFormatRange); ++pDepthStencilFormat)
1946 for (const VkFormat *pColorFormat = colorFormatRange;
1947 pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat)
1948 {
1949 params.colorFormat = *pColorFormat;
1950 params.depthStencilFormat = *pDepthStencilFormat;
1951
1952 addFunctionCaseWithPrograms(
1953 sampleCaseGroup.get(),
1954 getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
1955 VerifySamples::checkRequirements, VerifySamples::initPrograms, VerifySamples::test, params);
1956 }
1957
1958 locationsGroups[groupNdx]->addChild(sampleCaseGroup.release());
1959 }
1960
1961 // Multi subpass cases
1962 for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(subpassCases); ++caseNdx)
1963 {
1964 VerifySamples::TestParams params;
1965 params.pipelineConstructionType = pipelineConstructionType;
1966 params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get());
1967 params.useFragmentShadingRate = useFragmentShadingRate;
1968
1969 for (uint32_t subpassNdx = 0; subpassNdx < subpassCases[caseNdx].numSampleCases; ++subpassNdx)
1970 {
1971 VerifySamples::TestParams::SampleCount samples;
1972 samples.numColorSamples = subpassCases[caseNdx].pSampleCase[subpassNdx].colorSamples;
1973 samples.numDepthStencilSamples = subpassCases[caseNdx].pSampleCase[subpassNdx].depthStencilSamples;
1974 samples.numCoverageSamples = de::max(samples.numColorSamples, samples.numDepthStencilSamples);
1975 params.perSubpassSamples.push_back(samples);
1976 }
1977
1978 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(
1979 new tcu::TestCaseGroup(rootGroup->getTestContext(), subpassCases[caseNdx].caseName));
1980
1981 for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange;
1982 pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat)
1983 for (const VkFormat *pColorFormat = colorFormatRange;
1984 pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat)
1985 {
1986 params.colorFormat = *pColorFormat;
1987 params.depthStencilFormat = *pDepthStencilFormat;
1988
1989 addFunctionCaseWithPrograms(
1990 sampleCaseGroup.get(),
1991 getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
1992 VerifySamples::checkRequirements, VerifySamples::initPrograms, VerifySamples::test, params);
1993 }
1994
1995 locationsGroups[groupNdx]->addChild(sampleCaseGroup.release());
1996 }
1997 }
1998
1999 rootGroup->addChild(standardLocationsGroup.release());
2000 rootGroup->addChild(programmableLocationsGroup.release());
2001 }
2002
2003 // Test 2: Shader built-ins check
2004 if (!useFragmentShadingRate)
2005 {
2006 MovePtr<tcu::TestCaseGroup> builtinsGroup(
2007 new tcu::TestCaseGroup(rootGroup->getTestContext(), "shader_builtins"));
2008
2009 for (uint32_t caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx)
2010 {
2011 ShaderBuiltins::TestParams params;
2012 params.pipelineConstructionType = pipelineConstructionType;
2013 params.numColorSamples = singlePassCases[caseNdx].colorSamples;
2014 params.numDepthStencilSamples = singlePassCases[caseNdx].depthStencilSamples;
2015 params.numCoverageSamples = de::max(params.numColorSamples, params.numDepthStencilSamples);
2016
2017 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(new tcu::TestCaseGroup(
2018 rootGroup->getTestContext(), getSampleCountGroupName(params.numCoverageSamples, params.numColorSamples,
2019 params.numDepthStencilSamples)
2020 .c_str()));
2021
2022 for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange;
2023 pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat)
2024 for (const VkFormat *pColorFormat = colorFormatRange; pColorFormat != DE_ARRAY_END(colorFormatRange);
2025 ++pColorFormat)
2026 {
2027 params.colorFormat = *pColorFormat;
2028 params.depthStencilFormat = *pDepthStencilFormat;
2029
2030 addFunctionCaseWithPrograms(
2031 sampleCaseGroup.get(), getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(),
2032 ShaderBuiltins::checkRequirements, ShaderBuiltins::initPrograms, ShaderBuiltins::test, params);
2033 }
2034
2035 builtinsGroup->addChild(sampleCaseGroup.release());
2036 }
2037
2038 rootGroup->addChild(builtinsGroup.release());
2039 }
2040 }
2041
2042 } // namespace
2043
createMultisampleMixedAttachmentSamplesTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,bool useFragmentShadingRate)2044 tcu::TestCaseGroup *createMultisampleMixedAttachmentSamplesTests(tcu::TestContext &testCtx,
2045 PipelineConstructionType pipelineConstructionType,
2046 bool useFragmentShadingRate)
2047 {
2048 // Test a graphics pipeline with varying sample count per color and depth/stencil attachments
2049 return createTestGroup(testCtx, "mixed_attachment_samples", createMixedAttachmentSamplesTestsInGroup,
2050 pipelineConstructionType, useFragmentShadingRate);
2051 }
2052
2053 } // namespace pipeline
2054 } // namespace vkt
2055