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