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