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