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_shader_fragment_mask
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineMultisampleShaderFragmentMaskTests.hpp"
26 #include "vktPipelineMakeUtil.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
30
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkImageUtil.hpp"
41
42 #include "deUniquePtr.hpp"
43 #include "deSharedPtr.hpp"
44 #include "deRandom.hpp"
45
46 #include "tcuVector.hpp"
47 #include "tcuTestLog.hpp"
48 #include "tcuImageCompare.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuTextureUtil.hpp"
51
52 #include <string>
53 #include <vector>
54
55 namespace vkt
56 {
57 namespace pipeline
58 {
59 namespace
60 {
61 using namespace vk;
62 using de::UniquePtr;
63 using de::MovePtr;
64 using de::SharedPtr;
65 using tcu::UVec2;
66 using tcu::UVec4;
67 using tcu::Vec2;
68 using tcu::Vec4;
69
70 typedef SharedPtr<Unique<VkImageView> > ImageViewSp;
71 typedef SharedPtr<Unique<VkPipeline> > PipelineSp;
72
73 struct PositionColor
74 {
75 tcu::Vec4 position;
76 VkClearColorValue color;
77
PositionColorvkt::pipeline::__anon71da35050111::PositionColor78 PositionColor (const tcu::Vec4& pos, const tcu::UVec4& col) : position(pos)
79 {
80 deMemcpy(color.uint32, col.getPtr(), sizeof(color.uint32));
81 }
82
PositionColorvkt::pipeline::__anon71da35050111::PositionColor83 PositionColor (const tcu::Vec4& pos, const tcu::Vec4& col) : position(pos)
84 {
85 deMemcpy(color.float32, col.getPtr(), sizeof(color.float32));
86 }
87
PositionColorvkt::pipeline::__anon71da35050111::PositionColor88 PositionColor (const PositionColor& rhs)
89 : position (rhs.position)
90 , color (rhs.color)
91 {
92 }
93 };
94
95 //! Make a dummy sampler.
makeSampler(const DeviceInterface & vk,const VkDevice device)96 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
97 {
98 const VkSamplerCreateInfo samplerParams =
99 {
100 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
101 DE_NULL, // const void* pNext;
102 (VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags;
103 VK_FILTER_NEAREST, // VkFilter magFilter;
104 VK_FILTER_NEAREST, // VkFilter minFilter;
105 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
106 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
107 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
108 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
109 0.0f, // float mipLodBias;
110 VK_FALSE, // VkBool32 anisotropyEnable;
111 1.0f, // float maxAnisotropy;
112 VK_FALSE, // VkBool32 compareEnable;
113 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
114 0.0f, // float minLod;
115 0.0f, // float maxLod;
116 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
117 VK_FALSE, // VkBool32 unnormalizedCoordinates;
118 };
119 return createSampler(vk, device, &samplerParams);
120 }
121
makeImage(const DeviceInterface & vk,const VkDevice device,const VkFormat format,const UVec2 & size,const deUint32 layers,const VkSampleCountFlagBits samples,const VkImageUsageFlags usage)122 Move<VkImage> makeImage (const DeviceInterface& vk,
123 const VkDevice device,
124 const VkFormat format,
125 const UVec2& size,
126 const deUint32 layers,
127 const VkSampleCountFlagBits samples,
128 const VkImageUsageFlags usage)
129 {
130 const VkImageCreateInfo imageParams =
131 {
132 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
133 DE_NULL, // const void* pNext;
134 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
135 VK_IMAGE_TYPE_2D, // VkImageType imageType;
136 format, // VkFormat format;
137 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
138 1u, // deUint32 mipLevels;
139 layers, // deUint32 arrayLayers;
140 samples, // VkSampleCountFlagBits samples;
141 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
142 usage, // VkImageUsageFlags usage;
143 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
144 0u, // deUint32 queueFamilyIndexCount;
145 DE_NULL, // const deUint32* pQueueFamilyIndices;
146 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
147 };
148 return createImage(vk, device, &imageParams);
149 }
150
151 //! 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 VkFormat vertexAttribColorFormat,const bool useColorAttachment,const deUint32 subpassNdx,const UVec2 & renderSize,const VkSampleCountFlagBits numSamples)152 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
153 const VkDevice device,
154 const VkPipelineLayout pipelineLayout,
155 const VkRenderPass renderPass,
156 const VkShaderModule vertexModule,
157 const VkShaderModule fragmentModule,
158 const bool useVertexInput,
159 const VkFormat vertexAttribColorFormat,
160 const bool useColorAttachment,
161 const deUint32 subpassNdx,
162 const UVec2& renderSize,
163 const VkSampleCountFlagBits numSamples)
164 {
165 std::vector<VkVertexInputBindingDescription> vertexInputBindingDescriptions;
166 std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions;
167
168 // Vertex attributes: position and color
169 if (useVertexInput)
170 {
171 vertexInputBindingDescriptions.push_back (makeVertexInputBindingDescription (0u, sizeof(PositionColor), VK_VERTEX_INPUT_RATE_VERTEX));
172 vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u));
173 vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(1u, 0u, vertexAttribColorFormat, sizeof(Vec4)));
174 }
175
176 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
177 {
178 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
179 DE_NULL, // const void* pNext;
180 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
181 static_cast<deUint32>(vertexInputBindingDescriptions.size()), // uint32_t vertexBindingDescriptionCount;
182 dataOrNullPtr(vertexInputBindingDescriptions), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
183 static_cast<deUint32>(vertexInputAttributeDescriptions.size()), // uint32_t vertexAttributeDescriptionCount;
184 dataOrNullPtr(vertexInputAttributeDescriptions), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
185 };
186
187 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
188 {
189 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
190 DE_NULL, // const void* pNext;
191 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
192 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
193 VK_FALSE, // VkBool32 primitiveRestartEnable;
194 };
195
196 const VkViewport viewport =
197 {
198 0.0f, 0.0f, // x, y
199 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), // widht, height
200 0.0f, 1.0f // minDepth, maxDepth
201 };
202
203 const VkRect2D scissor =
204 {
205 makeOffset2D(0, 0),
206 makeExtent2D(renderSize.x(), renderSize.y()),
207 };
208
209 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
210 {
211 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
212 DE_NULL, // const void* pNext;
213 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
214 1u, // uint32_t viewportCount;
215 &viewport, // const VkViewport* pViewports;
216 1u, // uint32_t scissorCount;
217 &scissor, // const VkRect2D* pScissors;
218 };
219
220 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
221 {
222 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
223 DE_NULL, // const void* pNext;
224 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
225 VK_FALSE, // VkBool32 depthClampEnable;
226 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
227 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
228 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
229 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
230 VK_FALSE, // VkBool32 depthBiasEnable;
231 0.0f, // float depthBiasConstantFactor;
232 0.0f, // float depthBiasClamp;
233 0.0f, // float depthBiasSlopeFactor;
234 1.0f, // float lineWidth;
235 };
236
237 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
238 {
239 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
240 DE_NULL, // const void* pNext;
241 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
242 numSamples, // VkSampleCountFlagBits rasterizationSamples;
243 VK_FALSE, // VkBool32 sampleShadingEnable;
244 1.0f, // float minSampleShading;
245 DE_NULL, // const VkSampleMask* pSampleMask;
246 VK_FALSE, // VkBool32 alphaToCoverageEnable;
247 VK_FALSE // VkBool32 alphaToOneEnable;
248 };
249
250 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
251 {
252 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
253 DE_NULL, // const void* pNext;
254 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
255 VK_FALSE, // VkBool32 depthTestEnable;
256 VK_TRUE, // VkBool32 depthWriteEnable;
257 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
258 VK_FALSE, // VkBool32 depthBoundsTestEnable;
259 VK_FALSE, // VkBool32 stencilTestEnable;
260 VkStencilOpState(), // VkStencilOpState front;
261 VkStencilOpState(), // VkStencilOpState back;
262 0.0f, // float minDepthBounds;
263 1.0f, // float maxDepthBounds;
264 };
265
266 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
267 const VkPipelineColorBlendAttachmentState defaultBlendAttachmentState =
268 {
269 VK_FALSE, // VkBool32 blendEnable;
270 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
271 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
272 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
273 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
274 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
275 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
276 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
277 };
278
279 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
280 {
281 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
282 DE_NULL, // const void* pNext;
283 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
284 VK_FALSE, // VkBool32 logicOpEnable;
285 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
286 (useColorAttachment ? 1u : 0u), // deUint32 attachmentCount;
287 &defaultBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
288 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
289 };
290
291 const VkPipelineShaderStageCreateInfo pShaderStages[] =
292 {
293 {
294 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
295 DE_NULL, // const void* pNext;
296 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
297 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
298 vertexModule, // VkShaderModule module;
299 "main", // const char* pName;
300 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
301 },
302 {
303 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
304 DE_NULL, // const void* pNext;
305 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
306 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
307 fragmentModule, // VkShaderModule module;
308 "main", // const char* pName;
309 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
310 }
311 };
312
313 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
314 {
315 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
316 DE_NULL, // const void* pNext;
317 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
318 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
319 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
320 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
321 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
322 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
323 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
324 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
325 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
326 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
327 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
328 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
329 pipelineLayout, // VkPipelineLayout layout;
330 renderPass, // VkRenderPass renderPass;
331 subpassNdx, // deUint32 subpass;
332 DE_NULL, // VkPipeline basePipelineHandle;
333 -1, // deInt32 basePipelineIndex;
334 };
335
336 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
337 }
338
genShapes(const VkFormat colorFormat)339 std::vector<PositionColor> genShapes (const VkFormat colorFormat)
340 {
341 std::vector<PositionColor> vertices;
342
343 if (colorFormat == VK_FORMAT_R8G8B8A8_UNORM)
344 {
345 vertices.push_back(PositionColor(Vec4( 0.0f, -0.75f, 0.0f, 1.0f), Vec4(0.5f, 0.5f, 0.5f, 1.0f)));
346 vertices.push_back(PositionColor(Vec4(-0.75f, 0.75f, 0.0f, 1.0f), Vec4(1.0f, 0.5f, 0.5f, 1.0f)));
347 vertices.push_back(PositionColor(Vec4( 0.75f, 0.65f, 0.0f, 1.0f), Vec4(0.0f, 0.5f, 1.0f, 1.0f)));
348 }
349 else
350 {
351 vertices.push_back(PositionColor(Vec4( 0.0f, -0.75f, 0.0f, 1.0f), UVec4(0xabcdu, 0u, 0u, 0u)));
352 vertices.push_back(PositionColor(Vec4(-0.75f, 0.75f, 0.0f, 1.0f), UVec4(0xbcdeu, 0u, 0u, 0u)));
353 vertices.push_back(PositionColor(Vec4( 0.75f, 0.65f, 0.0f, 1.0f), UVec4(0xcdefu, 0u, 0u, 0u)));
354 }
355
356 return vertices;
357 }
358
359 //! Map color image format to a convenient format used in vertex attributes
getVertexInputColorFormat(const VkFormat colorImageFormat)360 VkFormat getVertexInputColorFormat (const VkFormat colorImageFormat)
361 {
362 switch (tcu::getTextureChannelClass(mapVkFormat(colorImageFormat).type))
363 {
364 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
365 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
366 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
367 return VK_FORMAT_R32G32B32A32_SFLOAT;
368
369 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
370 return VK_FORMAT_R32G32B32A32_SINT;
371
372 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
373 return VK_FORMAT_R32G32B32A32_UINT;
374
375 default:
376 DE_ASSERT(0);
377 return VK_FORMAT_UNDEFINED;
378 }
379 }
380
381 enum SampleSource
382 {
383 SAMPLE_SOURCE_IMAGE, //!< texel fetch from an image
384 SAMPLE_SOURCE_SUBPASS_INPUT, //!< texel fetch from an input attachment
385 };
386
387 //! The parameters that define a test case
388 struct TestParams
389 {
390 UVec2 renderSize;
391 deUint32 numLayers; //!< 1 or N for layered image
392 SampleSource sampleSource; //!< source of texel fetch
393 VkSampleCountFlagBits numColorSamples;
394 VkFormat colorFormat; //!< Color attachment format
395
TestParamsvkt::pipeline::__anon71da35050111::TestParams396 TestParams (void)
397 : numLayers ()
398 , sampleSource (SAMPLE_SOURCE_IMAGE)
399 , numColorSamples ()
400 , colorFormat ()
401 {
402 }
403 };
404
checkRequirements(Context & context,TestParams params)405 void checkRequirements (Context& context, TestParams params)
406 {
407 context.requireDeviceFunctionality("VK_AMD_shader_fragment_mask");
408
409 // In the subpass input case we have to store fetch results into a buffer for subsequent verification in a compute shader.
410 const bool requireFragmentStores = (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT);
411
412 const VkPhysicalDeviceLimits& limits = context.getDeviceProperties().limits;
413
414 if ((limits.framebufferColorSampleCounts & params.numColorSamples) == 0u)
415 TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
416
417 if ((isIntFormat(params.colorFormat) || isUintFormat(params.colorFormat)))
418 {
419 if ((limits.sampledImageIntegerSampleCounts & params.numColorSamples) == 0u)
420 TCU_THROW(NotSupportedError, "sampledImageIntegerSampleCounts: sample count not supported");
421 }
422 else
423 {
424 if ((limits.sampledImageColorSampleCounts & params.numColorSamples) == 0u)
425 TCU_THROW(NotSupportedError, "sampledImageColorSampleCounts: sample count not supported");
426 }
427
428 if (requireFragmentStores)
429 {
430 if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
431 TCU_THROW(NotSupportedError, "fragmentStoresAndAtomics: feature not supported");
432 }
433 }
434
435 //! Common data used by the test
436 struct WorkingData
437 {
438 deUint32 numVertices; //!< Number of vertices defined in the vertex buffer
439 Move<VkBuffer> vertexBuffer;
440 MovePtr<Allocation> vertexBufferAlloc;
441 Move<VkImage> colorImage; //!< Color image
442 MovePtr<Allocation> colorImageAlloc;
443 Move<VkImageView> colorImageView; //!< Color image view spanning all layers
444 Move<VkBuffer> colorBuffer; //!< Buffer used to copy image data
445 MovePtr<Allocation> colorBufferAlloc;
446 VkDeviceSize colorBufferSize;
447 Move<VkSampler> defaultSampler; //!< Dummy sampler, we are using texel fetches
448
WorkingDatavkt::pipeline::__anon71da35050111::WorkingData449 WorkingData (void)
450 : numVertices ()
451 , colorBufferSize ()
452 {
453 }
454 };
455
initPrograms(SourceCollections & programCollection,const TestParams params)456 void initPrograms (SourceCollections& programCollection, const TestParams params)
457 {
458 std::string colorType; //!< color pixel type used by image functions
459 std::string colorBufferType; //!< packed pixel type as stored in a ssbo
460 std::string colorBufferPack; //!< a cast or a function call when writing back color format to the ssbo
461 std::string colorFragInQualifier; //!< fragment shader color input qualifier
462 std::string samplerPrefix; //!< u, i, or empty
463
464 switch (params.colorFormat)
465 {
466 case VK_FORMAT_R8G8B8A8_UNORM:
467 colorType = "vec4";
468 colorBufferType = "uint";
469 colorBufferPack = "packUnorm4x8";
470 break;
471
472 case VK_FORMAT_R32_UINT:
473 colorType = "uint";
474 colorBufferType = "uint";
475 colorBufferPack = colorBufferType;
476 colorFragInQualifier = "flat";
477 samplerPrefix = "u";
478 break;
479
480 case VK_FORMAT_R32_SINT:
481 colorType = "int";
482 colorBufferType = "int";
483 colorBufferPack = colorBufferType;
484 colorFragInQualifier = "flat";
485 samplerPrefix = "i";
486 break;
487
488 default:
489 DE_FATAL("initPrograms not handled for this color format");
490 break;
491 }
492
493 // Vertex shader - position and color
494 {
495 std::ostringstream src;
496 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
497 << "\n"
498 << "layout(location = 0) in vec4 in_position;\n"
499 << "layout(location = 1) in " << colorType << " in_color;\n"
500 << "layout(location = 0) out " << colorType << " o_color;\n"
501 << "\n"
502 << "out gl_PerVertex {\n"
503 << " vec4 gl_Position;\n"
504 << "};\n"
505 << "\n"
506 << "void main(void)\n"
507 << "{\n"
508 // Introduce a variance in geometry per instance index which maps to the image layer
509 << " float a = 0.25 * float(gl_InstanceIndex);\n"
510 << " mat3 rm = mat3( cos(a), sin(a), 0.0,\n"
511 << " -sin(a), cos(a), 0.0,\n"
512 << " 0.0, 0.0, 1.0);\n"
513 << " vec2 rpos = (rm * vec3(in_position.xy, 1.0)).xy;\n"
514 << "\n"
515 << " gl_Position = vec4(rpos, in_position.zw);\n"
516 << " o_color = in_color;\n"
517 << "}\n";
518
519 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
520 }
521
522 // Vertex shader - no vertex data, fill viewport with one primitive
523 {
524 std::ostringstream src;
525 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
526 << "\n"
527 << "out gl_PerVertex {\n"
528 << " vec4 gl_Position;\n"
529 << "};\n"
530 << "\n"
531 << "void main(void)\n"
532 << "{\n"
533 // Specify an oversized triangle covering the whole viewport.
534 << " switch (gl_VertexIndex)\n"
535 << " {\n"
536 << " case 0:\n"
537 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
538 << " break;\n"
539 << " case 1:\n"
540 << " gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n"
541 << " break;\n"
542 << " case 2:\n"
543 << " gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
544 << " break;\n"
545 << " }\n"
546 << "}\n";
547
548 programCollection.glslSources.add("vert_full") << glu::VertexSource(src.str());
549 }
550
551 // Fragment shader - output color from VS
552 {
553 std::ostringstream src;
554 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
555 << "\n"
556 << "layout(location = 0) in " << colorFragInQualifier << " " << colorType << " in_color;\n"
557 << "layout(location = 0) out " << colorType << " o_color;\n"
558 << "\n"
559 << "void main(void)\n"
560 << "{\n"
561 << " o_color = in_color;\n"
562 << "}\n";
563
564 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
565 }
566
567 // Fragment shader - FMASK fetch from an input attachment
568 if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
569 {
570 std::ostringstream src;
571 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
572 << "#extension GL_AMD_shader_fragment_mask : enable\n"
573 << "\n"
574 << "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n"
575 << "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n"
576 << " " << colorBufferType << " color[];\n"
577 << "} sb_out;\n"
578 << "layout(input_attachment_index = " << params.numLayers << ", set = 0, binding = 2) uniform " << samplerPrefix << "subpassInputMS" << " input_attach;\n"
579 << "\n"
580 << "void main(void)\n"
581 << "{\n"
582 << " ivec2 p = ivec2(gl_FragCoord.xy);\n"
583 << " int width = " << params.renderSize.x() << ";\n"
584 << " int numSamples = " << static_cast<deUint32>(params.numColorSamples) << ";\n"
585 << " int colorOutNdx = numSamples * (p.x + width * p.y);\n"
586 << "\n"
587 << " uint mask = fragmentMaskFetchAMD(input_attach);\n"
588 << " for (int sampleNdx = 0; sampleNdx < numSamples; ++sampleNdx)\n"
589 << " {\n"
590 << " int fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n"
591 << " " << samplerPrefix << "vec4 color = fragmentFetchAMD(input_attach, fragNdx);\n"
592 << " sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n"
593 << " }\n"
594 << "}\n";
595
596 programCollection.glslSources.add("frag_fmask_fetch") << glu::FragmentSource(src.str());
597 }
598
599 // Generate compute shaders
600 const struct ComputeShaderParams
601 {
602 const char* name;
603 bool isFmaskFetch;
604 bool enabled;
605 } computeShaders[] =
606 {
607 // name // FMASK? // enabled?
608 { "comp_fetch", false, true, },
609 { "comp_fmask_fetch", true, (params.sampleSource != SAMPLE_SOURCE_SUBPASS_INPUT) },
610 };
611
612 for (const ComputeShaderParams* pShaderParams = computeShaders; pShaderParams != DE_ARRAY_END(computeShaders); ++pShaderParams)
613 if (pShaderParams->enabled)
614 {
615 const std::string samplingPos = (params.numLayers == 1 ? "ivec2(gl_WorkGroupID.xy)"
616 : "ivec3(gl_WorkGroupID)");
617 std::ostringstream src;
618 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
619 << (pShaderParams->isFmaskFetch ? "#extension GL_AMD_shader_fragment_mask : enable\n" : "")
620 << "#define NUM_SAMPLES " << static_cast<deUint32>(params.numColorSamples) << "\n"
621 << "\n"
622 << "layout(local_size_x = NUM_SAMPLES) in;\n" // one work group per pixel, each sample gets a local invocation
623 << "\n"
624 << "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n"
625 << "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n"
626 << " " << colorBufferType << " color[];\n"
627 << "} sb_out;\n"
628 << "\n"
629 << "void main(void)\n"
630 << "{\n"
631 << " int sampleNdx = int(gl_LocalInvocationID.x);\n"
632 << " int colorOutNdx = NUM_SAMPLES * int(gl_WorkGroupID.x +\n"
633 << " gl_WorkGroupID.y * gl_NumWorkGroups.x +\n"
634 << " gl_WorkGroupID.z * gl_NumWorkGroups.x * gl_NumWorkGroups.y);\n"
635 << "\n";
636 if (pShaderParams->isFmaskFetch)
637 {
638 src << " uint mask = fragmentMaskFetchAMD(u_image, " << samplingPos << ");\n"
639 << " int fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n"
640 << " " << samplerPrefix << "vec4 color = fragmentFetchAMD(u_image, " << samplingPos << ", fragNdx);\n"
641 << " sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n";
642 }
643 else
644 {
645 src << " " << samplerPrefix << "vec4 color = texelFetch(u_image, " << samplingPos << ", sampleNdx);\n"
646 << " sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n";
647 }
648 src << "}\n";
649
650 programCollection.glslSources.add(pShaderParams->name) << glu::ComputeSource(src.str());
651 }
652 }
653
genClearValues(const VkFormat format,const deUint32 count)654 std::vector<VkClearValue> genClearValues (const VkFormat format, const deUint32 count)
655 {
656 std::vector<VkClearValue> clearValues;
657 de::Random rng (332);
658
659 switch (format)
660 {
661 case VK_FORMAT_R8G8B8A8_UNORM:
662 for (deUint32 i = 0u; i < count; ++i)
663 clearValues.push_back(makeClearValueColorF32(rng.getFloat(), rng.getFloat(), rng.getFloat(), 1.0f));
664 break;
665
666 case VK_FORMAT_R32_UINT:
667 case VK_FORMAT_R32_SINT:
668 for (deUint32 i = 0u; i < count; ++i)
669 clearValues.push_back(makeClearValueColorU32(rng.getUint32(), 0u, 0u, 0u));
670 break;
671
672 default:
673 DE_FATAL("Clear color not defined for this format");
674 break;
675 }
676
677 return clearValues;
678 }
679
680 //! For subpass load case draw and fetch must happen within the same render pass.
drawAndSampleInputAttachment(Context & context,const TestParams & params,WorkingData & wd)681 void drawAndSampleInputAttachment (Context& context, const TestParams& params, WorkingData& wd)
682 {
683 DE_ASSERT(params.numLayers == 1u); // subpass load with single-layer image
684
685 const DeviceInterface& vk = context.getDeviceInterface();
686 const VkDevice device = context.getDevice();
687
688 Move<VkRenderPass> renderPass;
689 Move<VkFramebuffer> framebuffer;
690
691 // Create descriptor set
692 const Unique<VkDescriptorSetLayout> descriptorSetLayout (DescriptorSetLayoutBuilder()
693 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &wd.defaultSampler.get())
694 .addSingleBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
695 .addSingleBinding (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
696 .build(vk, device));
697
698 const Unique<VkDescriptorPool> descriptorPool (DescriptorPoolBuilder()
699 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
700 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
701 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
702 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
703
704 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
705
706 {
707 const VkDescriptorImageInfo colorImageInfo = makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
708 const VkDescriptorBufferInfo bufferInfo = makeDescriptorBufferInfo(*wd.colorBuffer, 0u, wd.colorBufferSize);
709
710 DescriptorSetUpdateBuilder builder;
711
712 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
713 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
714
715 if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
716 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &colorImageInfo);
717
718 builder.update(vk, device);
719 }
720
721 // Create a render pass and a framebuffer
722 {
723 std::vector<VkSubpassDescription> subpasses;
724 std::vector<VkSubpassDependency> subpassDependencies;
725 std::vector<VkImageView> attachments;
726 std::vector<VkAttachmentDescription> attachmentDescriptions;
727 std::vector<VkAttachmentReference> attachmentReferences;
728
729 // Reserve capacity to avoid invalidating pointers to elements
730 attachmentReferences.reserve(2); // color image + input attachment
731
732 // Create a MS draw subpass
733 {
734 attachments.push_back(*wd.colorImageView);
735
736 attachmentDescriptions.push_back(makeAttachmentDescription(
737 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
738 params.colorFormat, // VkFormat format;
739 params.numColorSamples, // VkSampleCountFlagBits samples;
740 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
741 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
742 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
743 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
744 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
745 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout;
746 ));
747
748 attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
749 const VkAttachmentReference* colorRef = &attachmentReferences.back();
750
751 const VkSubpassDescription subpassDescription =
752 {
753 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
754 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
755 0u, // uint32_t inputAttachmentCount;
756 DE_NULL, // const VkAttachmentReference* pInputAttachments;
757 1u, // uint32_t colorAttachmentCount;
758 colorRef, // const VkAttachmentReference* pColorAttachments;
759 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
760 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
761 0u, // uint32_t preserveAttachmentCount;
762 DE_NULL, // const uint32_t* pPreserveAttachments;
763 };
764
765 subpasses.push_back(subpassDescription);
766 }
767
768 // Create a sampling subpass
769 {
770 attachmentReferences.push_back(makeAttachmentReference(0u, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
771 const VkAttachmentReference* inputRef = &attachmentReferences.back();
772
773 // No color attachment, side effects only
774 VkSubpassDescription subpassDescription =
775 {
776 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
777 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
778 1u, // uint32_t inputAttachmentCount;
779 inputRef, // const VkAttachmentReference* pInputAttachments;
780 0u, // uint32_t colorAttachmentCount;
781 DE_NULL, // const VkAttachmentReference* pColorAttachments;
782 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
783 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
784 0u, // uint32_t preserveAttachmentCount;
785 DE_NULL, // const uint32_t* pPreserveAttachments;
786 };
787
788 subpasses.push_back(subpassDescription);
789 }
790
791 // Serialize the subpasses
792 {
793 const VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
794 | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
795 | VK_ACCESS_SHADER_WRITE_BIT;
796 const VkSubpassDependency dependency =
797 {
798 0u, // uint32_t srcSubpass;
799 1u, // uint32_t dstSubpass;
800 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask;
801 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask;
802 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
803 dstAccessMask, // VkAccessFlags dstAccessMask;
804 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags;
805 };
806 subpassDependencies.push_back(dependency);
807 }
808
809 VkRenderPassCreateInfo renderPassInfo =
810 {
811 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
812 DE_NULL, // const void* pNext;
813 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
814 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
815 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments;
816 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
817 dataOrNullPtr(subpasses), // const VkSubpassDescription* pSubpasses;
818 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount;
819 dataOrNullPtr(subpassDependencies), // const VkSubpassDependency* pDependencies;
820 };
821
822 renderPass = createRenderPass(vk, device, &renderPassInfo);
823 framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y());
824 }
825
826 const Unique<VkShaderModule> vertexModuleDraw (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
827 const Unique<VkShaderModule> fragmentModuleDraw (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
828
829 // Create pipelines for MS draw
830 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
831 const Unique<VkPipeline> pipelineDraw (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleDraw, *fragmentModuleDraw,
832 true/*use vertex attribs*/, getVertexInputColorFormat(params.colorFormat), true/*use color attach*/, 0u/*subpass*/,
833 params.renderSize, params.numColorSamples));
834
835 // Sampling pass is single-sampled, output to storage buffer
836 const Unique<VkShaderModule> vertexModuleSample (createShaderModule(vk, device, context.getBinaryCollection().get("vert_full"), 0u));
837 const Unique<VkShaderModule> fragmentModuleSample (createShaderModule(vk, device, context.getBinaryCollection().get("frag_fmask_fetch"), 0u));
838
839 // Sampling pipeline
840 const Unique<VkPipeline> pipelineSample (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleSample, *fragmentModuleSample,
841 false/*use vertex attribs*/, VK_FORMAT_UNDEFINED, false/*no color output*/, 1u/*subpass*/,
842 params.renderSize, VK_SAMPLE_COUNT_1_BIT));
843
844 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
845 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
846
847 beginCommandBuffer(vk, *cmdBuffer);
848
849 {
850 // Generate clear values
851 std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers);
852
853 const VkRect2D renderArea =
854 {
855 { 0u, 0u },
856 { params.renderSize.x(), params.renderSize.y() }
857 };
858
859 const VkRenderPassBeginInfo renderPassBeginInfo =
860 {
861 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
862 DE_NULL, // const void* pNext;
863 *renderPass, // VkRenderPass renderPass;
864 *framebuffer, // VkFramebuffer framebuffer;
865 renderArea, // VkRect2D renderArea;
866 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
867 dataOrNullPtr(clearValues), // const VkClearValue* pClearValues;
868 };
869 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
870 }
871
872 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
873
874 {
875 const VkDeviceSize vertexBufferOffset = 0ull;
876 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
877 }
878
879 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineDraw);
880 vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, 0u);
881
882 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
883
884 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineSample);
885 vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u); // fill the framebuffer, geometry defined in the VS
886
887 vk.cmdEndRenderPass(*cmdBuffer);
888
889 // Buffer write barrier
890 {
891 const VkBufferMemoryBarrier barrier =
892 {
893 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
894 DE_NULL, // const void* pNext;
895 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask;
896 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
897 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
898 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
899 *wd.colorBuffer, // VkBuffer buffer;
900 0ull, // VkDeviceSize offset;
901 VK_WHOLE_SIZE, // VkDeviceSize size;
902 };
903
904 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
905 }
906
907 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
908 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
909
910 invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
911 }
912
913 //! Only draw a multisampled image
draw(Context & context,const TestParams & params,WorkingData & wd)914 void draw (Context& context, const TestParams& params, WorkingData& wd)
915 {
916 const DeviceInterface& vk = context.getDeviceInterface();
917 const VkDevice device = context.getDevice();
918
919 std::vector<ImageViewSp> imageViews;
920 Move<VkRenderPass> renderPass;
921 Move<VkFramebuffer> framebuffer;
922
923 // Create color attachments
924 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
925 {
926 imageViews.push_back(ImageViewSp(new Unique<VkImageView>(
927 makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)))));
928 }
929
930 // Create a render pass and a framebuffer
931 {
932 std::vector<VkSubpassDescription> subpasses;
933 std::vector<VkImageView> attachments;
934 std::vector<VkAttachmentDescription> attachmentDescriptions;
935 std::vector<VkAttachmentReference> attachmentReferences;
936
937 // Reserve capacity to avoid invalidating pointers to elements
938 attachmentReferences.reserve(params.numLayers);
939
940 // Create MS draw subpasses
941 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
942 {
943 attachments.push_back(**imageViews[layerNdx]);
944
945 attachmentDescriptions.push_back(makeAttachmentDescription(
946 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
947 params.colorFormat, // VkFormat format;
948 params.numColorSamples, // VkSampleCountFlagBits samples;
949 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
950 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
951 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
952 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
953 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
954 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout;
955 ));
956
957 attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
958 const VkAttachmentReference* colorRef = &attachmentReferences.back();
959
960 const VkSubpassDescription subpassDescription =
961 {
962 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
963 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
964 0u, // uint32_t inputAttachmentCount;
965 DE_NULL, // const VkAttachmentReference* pInputAttachments;
966 1u, // uint32_t colorAttachmentCount;
967 colorRef, // const VkAttachmentReference* pColorAttachments;
968 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
969 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
970 0u, // uint32_t preserveAttachmentCount;
971 DE_NULL, // const uint32_t* pPreserveAttachments;
972 };
973
974 subpasses.push_back(subpassDescription);
975 }
976
977 // All MS image drawing subpasses are independent
978 VkRenderPassCreateInfo renderPassInfo =
979 {
980 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
981 DE_NULL, // const void* pNext;
982 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
983 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
984 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments;
985 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
986 dataOrNullPtr(subpasses), // const VkSubpassDescription* pSubpasses;
987 0u, // deUint32 dependencyCount;
988 DE_NULL, // const VkSubpassDependency* pDependencies;
989 };
990
991 renderPass = createRenderPass(vk, device, &renderPassInfo);
992 framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y());
993 }
994
995 std::vector<PipelineSp> pipelines;
996 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device));
997 const Unique<VkShaderModule> vertexModuleDraw (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
998 const Unique<VkShaderModule> fragmentModuleDraw (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
999
1000 // Create pipelines for MS draw
1001 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1002 {
1003 pipelines.push_back(PipelineSp(new Unique<VkPipeline>(
1004 makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleDraw, *fragmentModuleDraw,
1005 true /*use vertex attribs*/, getVertexInputColorFormat(params.colorFormat), true/*use color attachment*/, layerNdx /*subpass*/,
1006 params.renderSize, params.numColorSamples))));
1007 }
1008
1009 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1010 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1011
1012 beginCommandBuffer(vk, *cmdBuffer);
1013
1014 {
1015 // Generate clear values
1016 std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers);
1017
1018 const VkRect2D renderArea =
1019 {
1020 { 0u, 0u },
1021 { params.renderSize.x(), params.renderSize.y() }
1022 };
1023
1024 const VkRenderPassBeginInfo renderPassBeginInfo =
1025 {
1026 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1027 DE_NULL, // const void* pNext;
1028 *renderPass, // VkRenderPass renderPass;
1029 *framebuffer, // VkFramebuffer framebuffer;
1030 renderArea, // VkRect2D renderArea;
1031 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
1032 dataOrNullPtr(clearValues), // const VkClearValue* pClearValues;
1033 };
1034 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1035 }
1036
1037 {
1038 const VkDeviceSize vertexBufferOffset = 0ull;
1039 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
1040 }
1041
1042 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1043 {
1044 if (layerNdx != 0u)
1045 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1046
1047 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]);
1048 vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, layerNdx); // pass instance index to slightly change geometry per layer
1049 }
1050
1051 vk.cmdEndRenderPass(*cmdBuffer);
1052
1053 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1054 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1055 }
1056
1057 //! Sample from an image in a compute shader, storing the result in a color buffer
dispatchSampleImage(Context & context,const TestParams & params,WorkingData & wd,const std::string & shaderName)1058 void dispatchSampleImage (Context& context, const TestParams& params, WorkingData& wd, const std::string& shaderName)
1059 {
1060 const DeviceInterface& vk = context.getDeviceInterface();
1061 const VkDevice device = context.getDevice();
1062
1063 // Create descriptor set
1064
1065 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1066 DescriptorSetLayoutBuilder()
1067 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &wd.defaultSampler.get())
1068 .addSingleBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1069 .build(vk, device));
1070
1071 const Unique<VkDescriptorPool> descriptorPool(
1072 DescriptorPoolBuilder()
1073 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1074 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1075 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1076
1077 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1078
1079 {
1080 const VkDescriptorImageInfo colorImageInfo = makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1081 const VkDescriptorBufferInfo resultBufferInfo = makeDescriptorBufferInfo(*wd.colorBuffer, 0ull, wd.colorBufferSize);
1082
1083 DescriptorSetUpdateBuilder builder;
1084
1085 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
1086 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo);
1087
1088 builder.update(vk, device);
1089 }
1090
1091 // Pipeline
1092
1093 const Unique<VkShaderModule> shaderModule (createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u));
1094 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
1095 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL));
1096
1097 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1098 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1099
1100 beginCommandBuffer(vk, *cmdBuffer);
1101
1102 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1103 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1104
1105 vk.cmdDispatch(*cmdBuffer, params.renderSize.x(), params.renderSize.y(), params.numLayers);
1106
1107 {
1108 const VkBufferMemoryBarrier barrier =
1109 {
1110 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1111 DE_NULL, // const void* pNext;
1112 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1113 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1114 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1115 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1116 *wd.colorBuffer, // VkBuffer buffer;
1117 0ull, // VkDeviceSize offset;
1118 VK_WHOLE_SIZE, // VkDeviceSize size;
1119 };
1120
1121 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0,
1122 (const VkMemoryBarrier*)DE_NULL, 1u, &barrier, 0u, (const VkImageMemoryBarrier*)DE_NULL);
1123 }
1124
1125 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1126 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1127
1128 invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1129 }
1130
1131 //! Get a single-sampled image access from a multisampled color buffer with samples packed per pixel
getSingleSampledAccess(const void * const imageData,const TestParams & params,const deUint32 sampleNdx,const deUint32 layerNdx)1132 tcu::ConstPixelBufferAccess getSingleSampledAccess (const void* const imageData, const TestParams& params, const deUint32 sampleNdx, const deUint32 layerNdx)
1133 {
1134 const deUint32 numSamples = static_cast<deUint32>(params.numColorSamples);
1135 const deUint32 pixelSize = tcu::getPixelSize(mapVkFormat(params.colorFormat));
1136 const deUint32 rowSize = pixelSize * params.renderSize.x();
1137 const deUint32 layerSize = rowSize * params.renderSize.y();
1138 const deUint8* src = static_cast<const deUint8*>(imageData)
1139 + (layerNdx * numSamples * layerSize)
1140 + (sampleNdx * pixelSize);
1141 const tcu::IVec3 size (params.renderSize.x(), params.renderSize.y(), 1);
1142 const tcu::IVec3 pitch (numSamples * pixelSize,
1143 numSamples * rowSize,
1144 numSamples * layerSize);
1145 return tcu::ConstPixelBufferAccess(mapVkFormat(params.colorFormat), size, pitch, src);
1146 }
1147
test(Context & context,const TestParams params)1148 tcu::TestStatus test (Context& context, const TestParams params)
1149 {
1150 WorkingData wd;
1151 const DeviceInterface& vk = context.getDeviceInterface();
1152 const VkDevice device = context.getDevice();
1153 MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1154
1155 // Initialize resources
1156 {
1157 const VkImageUsageFlags msImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
1158 | VK_IMAGE_USAGE_SAMPLED_BIT
1159 | (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0);
1160 wd.colorImage = makeImage(vk, device, params.colorFormat, params.renderSize, params.numLayers, params.numColorSamples, msImageUsage);
1161 wd.colorImageAlloc = bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any);
1162 wd.colorImageView = makeImageView(vk, device, *wd.colorImage, (params.numLayers == 1u ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY), params.colorFormat,
1163 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.numLayers));
1164
1165 wd.defaultSampler = makeSampler(vk, device);
1166
1167 // Color buffer is meant to hold data for all layers and all samples of the image.
1168 // Data is tightly packed layer by layer, for each pixel all samples are laid out together starting with sample 0.
1169 // E.g.: pixel(0,0)sample(0)sample(1), pixel(1,0)sample(0)sample(1), ...
1170 wd.colorBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat))
1171 * params.renderSize.x() * params.renderSize.y() * params.numLayers * static_cast<deUint32>(params.numColorSamples));
1172 wd.colorBuffer = makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1173 wd.colorBufferAlloc = bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible);
1174
1175 deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1176 flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1177
1178 const std::vector<PositionColor> vertices = genShapes(params.colorFormat);
1179 const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1180
1181 wd.numVertices = static_cast<deUint32>(vertices.size());
1182 wd.vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1183 wd.vertexBufferAlloc = bindBuffer(vk, device, *allocator, *wd.vertexBuffer, MemoryRequirement::HostVisible);
1184
1185 deMemcpy(wd.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize));
1186 flushMappedMemoryRange(vk, device, wd.vertexBufferAlloc->getMemory(), wd.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1187 }
1188
1189 if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
1190 {
1191 // Create a multisample image and sample from it
1192 drawAndSampleInputAttachment (context, params, wd);
1193 }
1194 else
1195 {
1196 // Draw the image, then sample from it in a CS
1197 draw (context, params, wd);
1198 dispatchSampleImage (context, params, wd, "comp_fmask_fetch");
1199 }
1200
1201 // Copy the result
1202 std::vector<deUint8> fmaskFetchColorBuffer (static_cast<deUint32>(wd.colorBufferSize));
1203 deMemcpy(&fmaskFetchColorBuffer[0], wd.colorBufferAlloc->getHostPtr(), static_cast<std::size_t>(wd.colorBufferSize));
1204
1205 // Clear the color buffer, just to be sure we're getting the new data
1206 deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1207 flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1208
1209 // Sample image using the standard texel fetch
1210 dispatchSampleImage (context, params, wd, "comp_fetch");
1211
1212 // Verify the images
1213 {
1214 const void* const fmaskResult = dataOrNullPtr(fmaskFetchColorBuffer);
1215 const void* const expectedResult = wd.colorBufferAlloc->getHostPtr();
1216
1217 DE_ASSERT(!isFloatFormat(params.colorFormat)); // we're using int compare
1218
1219 // Mismatch, do image compare to pinpoint the failure
1220 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1221 for (deUint32 sampleNdx = 0u; sampleNdx < static_cast<deUint32>(params.numColorSamples); ++sampleNdx)
1222 {
1223 const std::string imageName = "layer_" + de::toString(layerNdx) + "_sample_" + de::toString(sampleNdx);
1224 const std::string imageDesc = "Layer " + de::toString(layerNdx) + " Sample " + de::toString(sampleNdx);
1225 const tcu::ConstPixelBufferAccess expected = getSingleSampledAccess(expectedResult, params, sampleNdx, layerNdx);
1226 const tcu::ConstPixelBufferAccess actual = getSingleSampledAccess(fmaskResult, params, sampleNdx, layerNdx);
1227 const UVec4 threshold (0); // should match exactly
1228
1229 const bool ok = tcu::intThresholdCompare(context.getTestContext().getLog(), imageName.c_str(), imageDesc.c_str(),
1230 expected, actual, threshold, tcu::COMPARE_LOG_RESULT);
1231
1232 if (!ok)
1233 return tcu::TestStatus::fail("Some texels were incorrect");
1234 }
1235 }
1236
1237 return tcu::TestStatus::pass("Pass");
1238 }
1239
getFormatShortString(const VkFormat format)1240 std::string getFormatShortString (const VkFormat format)
1241 {
1242 std::string s(de::toLower(getFormatName(format)));
1243 return s.substr(10);
1244 }
1245
createShaderFragmentMaskTestsInGroup(tcu::TestCaseGroup * rootGroup)1246 void createShaderFragmentMaskTestsInGroup (tcu::TestCaseGroup* rootGroup)
1247 {
1248 // Per spec, the following formats must support color attachment and sampled image
1249 const VkFormat colorFormats[] =
1250 {
1251 VK_FORMAT_R8G8B8A8_UNORM,
1252 VK_FORMAT_R32_UINT,
1253 VK_FORMAT_R32_SINT,
1254 };
1255
1256 const VkSampleCountFlagBits sampleCounts[] =
1257 {
1258 VK_SAMPLE_COUNT_2_BIT,
1259 VK_SAMPLE_COUNT_4_BIT,
1260 VK_SAMPLE_COUNT_8_BIT,
1261 VK_SAMPLE_COUNT_16_BIT,
1262 };
1263
1264 const struct SourceCase
1265 {
1266 const char* name;
1267 deUint32 numLayers;
1268 SampleSource sampleSource;
1269 } sourceCases[] =
1270 {
1271 { "image_2d", 1u, SAMPLE_SOURCE_IMAGE },
1272 { "image_2d_array", 3u, SAMPLE_SOURCE_IMAGE },
1273 { "subpass_input", 1u, SAMPLE_SOURCE_SUBPASS_INPUT },
1274 };
1275
1276 // Test 1: Compare fragments fetched via FMASK and an ordinary texel fetch
1277 {
1278 for (const VkSampleCountFlagBits* pSampleCount = sampleCounts; pSampleCount != DE_ARRAY_END(sampleCounts); ++pSampleCount)
1279 {
1280 MovePtr<tcu::TestCaseGroup> sampleCountGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), ("samples_" + de::toString(*pSampleCount)).c_str(), ""));
1281 for (const SourceCase* pSourceCase = sourceCases; pSourceCase != DE_ARRAY_END(sourceCases); ++pSourceCase)
1282 {
1283 MovePtr<tcu::TestCaseGroup> sourceGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), pSourceCase->name, ""));
1284 for (const VkFormat* pColorFormat = colorFormats; pColorFormat != DE_ARRAY_END(colorFormats); ++pColorFormat)
1285 {
1286 TestParams params;
1287 params.renderSize = UVec2(32, 32);
1288 params.colorFormat = *pColorFormat;
1289 params.numColorSamples = *pSampleCount;
1290 params.numLayers = pSourceCase->numLayers;
1291 params.sampleSource = pSourceCase->sampleSource;
1292
1293 addFunctionCaseWithPrograms(sourceGroup.get(), getFormatShortString(*pColorFormat), "", checkRequirements, initPrograms, test, params);
1294 }
1295 sampleCountGroup->addChild(sourceGroup.release());
1296 }
1297 rootGroup->addChild(sampleCountGroup.release());
1298 }
1299 }
1300 }
1301
1302 } // anonymous ns
1303
createMultisampleShaderFragmentMaskTests(tcu::TestContext & testCtx)1304 tcu::TestCaseGroup* createMultisampleShaderFragmentMaskTests (tcu::TestContext& testCtx)
1305 {
1306 return createTestGroup(testCtx, "shader_fragment_mask", "Access raw texel values in a compressed MSAA surface", createShaderFragmentMaskTestsInGroup);
1307 }
1308
1309 } // pipeline
1310 } // vkt
1311