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::__anonb8f720ed0111::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::__anonb8f720ed0111::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::__anonb8f720ed0111::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::__anonb8f720ed0111::TestParams396 TestParams (void)
397 : numLayers ()
398 , numColorSamples ()
399 , colorFormat ()
400 {
401 }
402 };
403
checkRequirements(Context & context,TestParams params)404 void checkRequirements (Context& context, TestParams params)
405 {
406 context.requireDeviceFunctionality("VK_AMD_shader_fragment_mask");
407
408 // In the subpass input case we have to store fetch results into a buffer for subsequent verification in a compute shader.
409 const bool requireFragmentStores = (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT);
410
411 const VkPhysicalDeviceLimits& limits = context.getDeviceProperties().limits;
412
413 if ((limits.framebufferColorSampleCounts & params.numColorSamples) == 0u)
414 TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
415
416 if ((isIntFormat(params.colorFormat) || isUintFormat(params.colorFormat)))
417 {
418 if ((limits.sampledImageIntegerSampleCounts & params.numColorSamples) == 0u)
419 TCU_THROW(NotSupportedError, "sampledImageIntegerSampleCounts: sample count not supported");
420 }
421 else
422 {
423 if ((limits.sampledImageColorSampleCounts & params.numColorSamples) == 0u)
424 TCU_THROW(NotSupportedError, "sampledImageColorSampleCounts: sample count not supported");
425 }
426
427 if (requireFragmentStores)
428 {
429 if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
430 TCU_THROW(NotSupportedError, "fragmentStoresAndAtomics: feature not supported");
431 }
432 }
433
434 //! Common data used by the test
435 struct WorkingData
436 {
437 deUint32 numVertices; //!< Number of vertices defined in the vertex buffer
438 Move<VkBuffer> vertexBuffer;
439 MovePtr<Allocation> vertexBufferAlloc;
440 Move<VkImage> colorImage; //!< Color image
441 MovePtr<Allocation> colorImageAlloc;
442 Move<VkImageView> colorImageView; //!< Color image view spanning all layers
443 Move<VkBuffer> colorBuffer; //!< Buffer used to copy image data
444 MovePtr<Allocation> colorBufferAlloc;
445 VkDeviceSize colorBufferSize;
446 Move<VkSampler> defaultSampler; //!< Dummy sampler, we are using texel fetches
447
WorkingDatavkt::pipeline::__anonb8f720ed0111::WorkingData448 WorkingData (void)
449 : numVertices ()
450 , colorBufferSize ()
451 {
452 }
453 };
454
initPrograms(SourceCollections & programCollection,const TestParams params)455 void initPrograms (SourceCollections& programCollection, const TestParams params)
456 {
457 std::string colorType; //!< color pixel type used by image functions
458 std::string colorBufferType; //!< packed pixel type as stored in a ssbo
459 std::string colorBufferPack; //!< a cast or a function call when writing back color format to the ssbo
460 std::string colorFragInQualifier; //!< fragment shader color input qualifier
461 std::string samplerPrefix; //!< u, i, or empty
462
463 switch (params.colorFormat)
464 {
465 case VK_FORMAT_R8G8B8A8_UNORM:
466 colorType = "vec4";
467 colorBufferType = "uint";
468 colorBufferPack = "packUnorm4x8";
469 break;
470
471 case VK_FORMAT_R32_UINT:
472 colorType = "uint";
473 colorBufferType = "uint";
474 colorBufferPack = colorBufferType;
475 colorFragInQualifier = "flat";
476 samplerPrefix = "u";
477 break;
478
479 case VK_FORMAT_R32_SINT:
480 colorType = "int";
481 colorBufferType = "int";
482 colorBufferPack = colorBufferType;
483 colorFragInQualifier = "flat";
484 samplerPrefix = "i";
485 break;
486
487 default:
488 DE_FATAL("initPrograms not handled for this color format");
489 break;
490 }
491
492 // Vertex shader - position and color
493 {
494 std::ostringstream src;
495 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
496 << "\n"
497 << "layout(location = 0) in vec4 in_position;\n"
498 << "layout(location = 1) in " << colorType << " in_color;\n"
499 << "layout(location = 0) out " << colorType << " o_color;\n"
500 << "\n"
501 << "out gl_PerVertex {\n"
502 << " vec4 gl_Position;\n"
503 << "};\n"
504 << "\n"
505 << "void main(void)\n"
506 << "{\n"
507 // Introduce a variance in geometry per instance index which maps to the image layer
508 << " float a = 0.25 * float(gl_InstanceIndex);\n"
509 << " mat3 rm = mat3( cos(a), sin(a), 0.0,\n"
510 << " -sin(a), cos(a), 0.0,\n"
511 << " 0.0, 0.0, 1.0);\n"
512 << " vec2 rpos = (rm * vec3(in_position.xy, 1.0)).xy;\n"
513 << "\n"
514 << " gl_Position = vec4(rpos, in_position.zw);\n"
515 << " o_color = in_color;\n"
516 << "}\n";
517
518 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
519 }
520
521 // Vertex shader - no vertex data, fill viewport with one primitive
522 {
523 std::ostringstream src;
524 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
525 << "\n"
526 << "out gl_PerVertex {\n"
527 << " vec4 gl_Position;\n"
528 << "};\n"
529 << "\n"
530 << "void main(void)\n"
531 << "{\n"
532 // Specify an oversized triangle covering the whole viewport.
533 << " switch (gl_VertexIndex)\n"
534 << " {\n"
535 << " case 0:\n"
536 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
537 << " break;\n"
538 << " case 1:\n"
539 << " gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n"
540 << " break;\n"
541 << " case 2:\n"
542 << " gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
543 << " break;\n"
544 << " }\n"
545 << "}\n";
546
547 programCollection.glslSources.add("vert_full") << glu::VertexSource(src.str());
548 }
549
550 // Fragment shader - output color from VS
551 {
552 std::ostringstream src;
553 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
554 << "\n"
555 << "layout(location = 0) in " << colorFragInQualifier << " " << colorType << " in_color;\n"
556 << "layout(location = 0) out " << colorType << " o_color;\n"
557 << "\n"
558 << "void main(void)\n"
559 << "{\n"
560 << " o_color = in_color;\n"
561 << "}\n";
562
563 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
564 }
565
566 // Fragment shader - FMASK fetch from an input attachment
567 if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
568 {
569 std::ostringstream src;
570 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
571 << "#extension GL_AMD_shader_fragment_mask : enable\n"
572 << "\n"
573 << "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n"
574 << "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n"
575 << " " << colorBufferType << " color[];\n"
576 << "} sb_out;\n"
577 << "layout(input_attachment_index = " << params.numLayers << ", set = 0, binding = 2) uniform " << samplerPrefix << "subpassInputMS" << " input_attach;\n"
578 << "\n"
579 << "void main(void)\n"
580 << "{\n"
581 << " ivec2 p = ivec2(gl_FragCoord.xy);\n"
582 << " int width = " << params.renderSize.x() << ";\n"
583 << " int numSamples = " << static_cast<deUint32>(params.numColorSamples) << ";\n"
584 << " int colorOutNdx = numSamples * (p.x + width * p.y);\n"
585 << "\n"
586 << " uint mask = fragmentMaskFetchAMD(input_attach);\n"
587 << " for (int sampleNdx = 0; sampleNdx < numSamples; ++sampleNdx)\n"
588 << " {\n"
589 << " int fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n"
590 << " " << samplerPrefix << "vec4 color = fragmentFetchAMD(input_attach, fragNdx);\n"
591 << " sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n"
592 << " }\n"
593 << "}\n";
594
595 programCollection.glslSources.add("frag_fmask_fetch") << glu::FragmentSource(src.str());
596 }
597
598 // Generate compute shaders
599 const struct ComputeShaderParams
600 {
601 const char* name;
602 bool isFmaskFetch;
603 bool enabled;
604 } computeShaders[] =
605 {
606 // name // FMASK? // enabled?
607 { "comp_fetch", false, true, },
608 { "comp_fmask_fetch", true, (params.sampleSource != SAMPLE_SOURCE_SUBPASS_INPUT) },
609 };
610
611 for (const ComputeShaderParams* pShaderParams = computeShaders; pShaderParams != DE_ARRAY_END(computeShaders); ++pShaderParams)
612 if (pShaderParams->enabled)
613 {
614 const std::string samplingPos = (params.numLayers == 1 ? "ivec2(gl_WorkGroupID.xy)"
615 : "ivec3(gl_WorkGroupID)");
616 std::ostringstream src;
617 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
618 << (pShaderParams->isFmaskFetch ? "#extension GL_AMD_shader_fragment_mask : enable\n" : "")
619 << "#define NUM_SAMPLES " << static_cast<deUint32>(params.numColorSamples) << "\n"
620 << "\n"
621 << "layout(local_size_x = NUM_SAMPLES) in;\n" // one work group per pixel, each sample gets a local invocation
622 << "\n"
623 << "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n"
624 << "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n"
625 << " " << colorBufferType << " color[];\n"
626 << "} sb_out;\n"
627 << "\n"
628 << "void main(void)\n"
629 << "{\n"
630 << " int sampleNdx = int(gl_LocalInvocationID.x);\n"
631 << " int colorOutNdx = NUM_SAMPLES * int(gl_WorkGroupID.x +\n"
632 << " gl_WorkGroupID.y * gl_NumWorkGroups.x +\n"
633 << " gl_WorkGroupID.z * gl_NumWorkGroups.x * gl_NumWorkGroups.y);\n"
634 << "\n";
635 if (pShaderParams->isFmaskFetch)
636 {
637 src << " uint mask = fragmentMaskFetchAMD(u_image, " << samplingPos << ");\n"
638 << " int fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n"
639 << " " << samplerPrefix << "vec4 color = fragmentFetchAMD(u_image, " << samplingPos << ", fragNdx);\n"
640 << " sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n";
641 }
642 else
643 {
644 src << " " << samplerPrefix << "vec4 color = texelFetch(u_image, " << samplingPos << ", sampleNdx);\n"
645 << " sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n";
646 }
647 src << "}\n";
648
649 programCollection.glslSources.add(pShaderParams->name) << glu::ComputeSource(src.str());
650 }
651 }
652
genClearValues(const VkFormat format,const deUint32 count)653 std::vector<VkClearValue> genClearValues (const VkFormat format, const deUint32 count)
654 {
655 std::vector<VkClearValue> clearValues;
656 de::Random rng (332);
657
658 switch (format)
659 {
660 case VK_FORMAT_R8G8B8A8_UNORM:
661 for (deUint32 i = 0u; i < count; ++i)
662 clearValues.push_back(makeClearValueColorF32(rng.getFloat(), rng.getFloat(), rng.getFloat(), 1.0f));
663 break;
664
665 case VK_FORMAT_R32_UINT:
666 case VK_FORMAT_R32_SINT:
667 for (deUint32 i = 0u; i < count; ++i)
668 clearValues.push_back(makeClearValueColorU32(rng.getUint32(), 0u, 0u, 0u));
669 break;
670
671 default:
672 DE_FATAL("Clear color not defined for this format");
673 break;
674 }
675
676 return clearValues;
677 }
678
679 //! For subpass load case draw and fetch must happen within the same render pass.
drawAndSampleInputAttachment(Context & context,const TestParams & params,WorkingData & wd)680 void drawAndSampleInputAttachment (Context& context, const TestParams& params, WorkingData& wd)
681 {
682 DE_ASSERT(params.numLayers == 1u); // subpass load with single-layer image
683
684 const DeviceInterface& vk = context.getDeviceInterface();
685 const VkDevice device = context.getDevice();
686
687 Move<VkRenderPass> renderPass;
688 Move<VkFramebuffer> framebuffer;
689
690 // Create descriptor set
691 const Unique<VkDescriptorSetLayout> descriptorSetLayout (DescriptorSetLayoutBuilder()
692 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &wd.defaultSampler.get())
693 .addSingleBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
694 .addSingleBinding (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
695 .build(vk, device));
696
697 const Unique<VkDescriptorPool> descriptorPool (DescriptorPoolBuilder()
698 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
699 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
700 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
701 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
702
703 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
704
705 {
706 const VkDescriptorImageInfo colorImageInfo = makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
707 const VkDescriptorBufferInfo bufferInfo = makeDescriptorBufferInfo(*wd.colorBuffer, 0u, wd.colorBufferSize);
708
709 DescriptorSetUpdateBuilder builder;
710
711 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
712 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
713
714 if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
715 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &colorImageInfo);
716
717 builder.update(vk, device);
718 }
719
720 // Create a render pass and a framebuffer
721 {
722 std::vector<VkSubpassDescription> subpasses;
723 std::vector<VkSubpassDependency> subpassDependencies;
724 std::vector<VkImageView> attachments;
725 std::vector<VkAttachmentDescription> attachmentDescriptions;
726 std::vector<VkAttachmentReference> attachmentReferences;
727
728 // Reserve capacity to avoid invalidating pointers to elements
729 attachmentReferences.reserve(2); // color image + input attachment
730
731 // Create a MS draw subpass
732 {
733 attachments.push_back(*wd.colorImageView);
734
735 attachmentDescriptions.push_back(makeAttachmentDescription(
736 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
737 params.colorFormat, // VkFormat format;
738 params.numColorSamples, // VkSampleCountFlagBits samples;
739 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
740 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
741 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
742 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
743 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
744 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout;
745 ));
746
747 attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
748 const VkAttachmentReference* colorRef = &attachmentReferences.back();
749
750 const VkSubpassDescription subpassDescription =
751 {
752 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
753 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
754 0u, // uint32_t inputAttachmentCount;
755 DE_NULL, // const VkAttachmentReference* pInputAttachments;
756 1u, // uint32_t colorAttachmentCount;
757 colorRef, // const VkAttachmentReference* pColorAttachments;
758 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
759 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
760 0u, // uint32_t preserveAttachmentCount;
761 DE_NULL, // const uint32_t* pPreserveAttachments;
762 };
763
764 subpasses.push_back(subpassDescription);
765 }
766
767 // Create a sampling subpass
768 {
769 attachmentReferences.push_back(makeAttachmentReference(0u, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
770 const VkAttachmentReference* inputRef = &attachmentReferences.back();
771
772 // No color attachment, side effects only
773 VkSubpassDescription subpassDescription =
774 {
775 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
776 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
777 1u, // uint32_t inputAttachmentCount;
778 inputRef, // const VkAttachmentReference* pInputAttachments;
779 0u, // uint32_t colorAttachmentCount;
780 DE_NULL, // const VkAttachmentReference* pColorAttachments;
781 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
782 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
783 0u, // uint32_t preserveAttachmentCount;
784 DE_NULL, // const uint32_t* pPreserveAttachments;
785 };
786
787 subpasses.push_back(subpassDescription);
788 }
789
790 // Serialize the subpasses
791 {
792 const VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
793 | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
794 | VK_ACCESS_SHADER_WRITE_BIT;
795 const VkSubpassDependency dependency =
796 {
797 0u, // uint32_t srcSubpass;
798 1u, // uint32_t dstSubpass;
799 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask;
800 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask;
801 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
802 dstAccessMask, // VkAccessFlags dstAccessMask;
803 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags;
804 };
805 subpassDependencies.push_back(dependency);
806 }
807
808 VkRenderPassCreateInfo renderPassInfo =
809 {
810 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
811 DE_NULL, // const void* pNext;
812 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
813 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
814 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments;
815 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
816 dataOrNullPtr(subpasses), // const VkSubpassDescription* pSubpasses;
817 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount;
818 dataOrNullPtr(subpassDependencies), // const VkSubpassDependency* pDependencies;
819 };
820
821 renderPass = createRenderPass(vk, device, &renderPassInfo);
822 framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y());
823 }
824
825 const Unique<VkShaderModule> vertexModuleDraw (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
826 const Unique<VkShaderModule> fragmentModuleDraw (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
827
828 // Create pipelines for MS draw
829 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
830 const Unique<VkPipeline> pipelineDraw (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleDraw, *fragmentModuleDraw,
831 true/*use vertex attribs*/, getVertexInputColorFormat(params.colorFormat), true/*use color attach*/, 0u/*subpass*/,
832 params.renderSize, params.numColorSamples));
833
834 // Sampling pass is single-sampled, output to storage buffer
835 const Unique<VkShaderModule> vertexModuleSample (createShaderModule(vk, device, context.getBinaryCollection().get("vert_full"), 0u));
836 const Unique<VkShaderModule> fragmentModuleSample (createShaderModule(vk, device, context.getBinaryCollection().get("frag_fmask_fetch"), 0u));
837
838 // Sampling pipeline
839 const Unique<VkPipeline> pipelineSample (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleSample, *fragmentModuleSample,
840 false/*use vertex attribs*/, VK_FORMAT_UNDEFINED, false/*no color output*/, 1u/*subpass*/,
841 params.renderSize, VK_SAMPLE_COUNT_1_BIT));
842
843 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
844 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
845
846 beginCommandBuffer(vk, *cmdBuffer);
847
848 {
849 // Generate clear values
850 std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers);
851
852 const VkRect2D renderArea =
853 {
854 { 0u, 0u },
855 { params.renderSize.x(), params.renderSize.y() }
856 };
857
858 const VkRenderPassBeginInfo renderPassBeginInfo =
859 {
860 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
861 DE_NULL, // const void* pNext;
862 *renderPass, // VkRenderPass renderPass;
863 *framebuffer, // VkFramebuffer framebuffer;
864 renderArea, // VkRect2D renderArea;
865 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
866 dataOrNullPtr(clearValues), // const VkClearValue* pClearValues;
867 };
868 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
869 }
870
871 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
872
873 {
874 const VkDeviceSize vertexBufferOffset = 0ull;
875 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
876 }
877
878 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineDraw);
879 vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, 0u);
880
881 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
882
883 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineSample);
884 vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u); // fill the framebuffer, geometry defined in the VS
885
886 vk.cmdEndRenderPass(*cmdBuffer);
887
888 // Buffer write barrier
889 {
890 const VkBufferMemoryBarrier barrier =
891 {
892 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
893 DE_NULL, // const void* pNext;
894 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask;
895 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
896 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
897 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
898 *wd.colorBuffer, // VkBuffer buffer;
899 0ull, // VkDeviceSize offset;
900 VK_WHOLE_SIZE, // VkDeviceSize size;
901 };
902
903 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
904 }
905
906 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
907 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
908
909 invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
910 }
911
912 //! Only draw a multisampled image
draw(Context & context,const TestParams & params,WorkingData & wd)913 void draw (Context& context, const TestParams& params, WorkingData& wd)
914 {
915 const DeviceInterface& vk = context.getDeviceInterface();
916 const VkDevice device = context.getDevice();
917
918 std::vector<ImageViewSp> imageViews;
919 Move<VkRenderPass> renderPass;
920 Move<VkFramebuffer> framebuffer;
921
922 // Create color attachments
923 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
924 {
925 imageViews.push_back(ImageViewSp(new Unique<VkImageView>(
926 makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)))));
927 }
928
929 // Create a render pass and a framebuffer
930 {
931 std::vector<VkSubpassDescription> subpasses;
932 std::vector<VkImageView> attachments;
933 std::vector<VkAttachmentDescription> attachmentDescriptions;
934 std::vector<VkAttachmentReference> attachmentReferences;
935
936 // Reserve capacity to avoid invalidating pointers to elements
937 attachmentReferences.reserve(params.numLayers);
938
939 // Create MS draw subpasses
940 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
941 {
942 attachments.push_back(**imageViews[layerNdx]);
943
944 attachmentDescriptions.push_back(makeAttachmentDescription(
945 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
946 params.colorFormat, // VkFormat format;
947 params.numColorSamples, // VkSampleCountFlagBits samples;
948 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
949 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
950 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
951 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
952 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
953 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout;
954 ));
955
956 attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
957 const VkAttachmentReference* colorRef = &attachmentReferences.back();
958
959 const VkSubpassDescription subpassDescription =
960 {
961 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
962 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
963 0u, // uint32_t inputAttachmentCount;
964 DE_NULL, // const VkAttachmentReference* pInputAttachments;
965 1u, // uint32_t colorAttachmentCount;
966 colorRef, // const VkAttachmentReference* pColorAttachments;
967 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
968 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
969 0u, // uint32_t preserveAttachmentCount;
970 DE_NULL, // const uint32_t* pPreserveAttachments;
971 };
972
973 subpasses.push_back(subpassDescription);
974 }
975
976 // All MS image drawing subpasses are independent
977 VkRenderPassCreateInfo renderPassInfo =
978 {
979 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
980 DE_NULL, // const void* pNext;
981 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
982 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
983 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments;
984 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
985 dataOrNullPtr(subpasses), // const VkSubpassDescription* pSubpasses;
986 0u, // deUint32 dependencyCount;
987 DE_NULL, // const VkSubpassDependency* pDependencies;
988 };
989
990 renderPass = createRenderPass(vk, device, &renderPassInfo);
991 framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y());
992 }
993
994 std::vector<PipelineSp> pipelines;
995 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device));
996 const Unique<VkShaderModule> vertexModuleDraw (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
997 const Unique<VkShaderModule> fragmentModuleDraw (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
998
999 // Create pipelines for MS draw
1000 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1001 {
1002 pipelines.push_back(PipelineSp(new Unique<VkPipeline>(
1003 makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleDraw, *fragmentModuleDraw,
1004 true /*use vertex attribs*/, getVertexInputColorFormat(params.colorFormat), true/*use color attachment*/, layerNdx /*subpass*/,
1005 params.renderSize, params.numColorSamples))));
1006 }
1007
1008 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1009 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1010
1011 beginCommandBuffer(vk, *cmdBuffer);
1012
1013 {
1014 // Generate clear values
1015 std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers);
1016
1017 const VkRect2D renderArea =
1018 {
1019 { 0u, 0u },
1020 { params.renderSize.x(), params.renderSize.y() }
1021 };
1022
1023 const VkRenderPassBeginInfo renderPassBeginInfo =
1024 {
1025 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1026 DE_NULL, // const void* pNext;
1027 *renderPass, // VkRenderPass renderPass;
1028 *framebuffer, // VkFramebuffer framebuffer;
1029 renderArea, // VkRect2D renderArea;
1030 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
1031 dataOrNullPtr(clearValues), // const VkClearValue* pClearValues;
1032 };
1033 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1034 }
1035
1036 {
1037 const VkDeviceSize vertexBufferOffset = 0ull;
1038 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
1039 }
1040
1041 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1042 {
1043 if (layerNdx != 0u)
1044 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1045
1046 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]);
1047 vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, layerNdx); // pass instance index to slightly change geometry per layer
1048 }
1049
1050 vk.cmdEndRenderPass(*cmdBuffer);
1051
1052 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1053 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1054 }
1055
1056 //! 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)1057 void dispatchSampleImage (Context& context, const TestParams& params, WorkingData& wd, const std::string& shaderName)
1058 {
1059 const DeviceInterface& vk = context.getDeviceInterface();
1060 const VkDevice device = context.getDevice();
1061
1062 // Create descriptor set
1063
1064 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1065 DescriptorSetLayoutBuilder()
1066 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &wd.defaultSampler.get())
1067 .addSingleBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1068 .build(vk, device));
1069
1070 const Unique<VkDescriptorPool> descriptorPool(
1071 DescriptorPoolBuilder()
1072 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1073 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1074 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1075
1076 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1077
1078 {
1079 const VkDescriptorImageInfo colorImageInfo = makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1080 const VkDescriptorBufferInfo resultBufferInfo = makeDescriptorBufferInfo(*wd.colorBuffer, 0ull, wd.colorBufferSize);
1081
1082 DescriptorSetUpdateBuilder builder;
1083
1084 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
1085 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo);
1086
1087 builder.update(vk, device);
1088 }
1089
1090 // Pipeline
1091
1092 const Unique<VkShaderModule> shaderModule (createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u));
1093 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
1094 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL));
1095
1096 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1097 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1098
1099 beginCommandBuffer(vk, *cmdBuffer);
1100
1101 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1102 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1103
1104 vk.cmdDispatch(*cmdBuffer, params.renderSize.x(), params.renderSize.y(), params.numLayers);
1105
1106 {
1107 const VkBufferMemoryBarrier barrier =
1108 {
1109 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1110 DE_NULL, // const void* pNext;
1111 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1112 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1113 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1114 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1115 *wd.colorBuffer, // VkBuffer buffer;
1116 0ull, // VkDeviceSize offset;
1117 VK_WHOLE_SIZE, // VkDeviceSize size;
1118 };
1119
1120 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0,
1121 (const VkMemoryBarrier*)DE_NULL, 1u, &barrier, 0u, (const VkImageMemoryBarrier*)DE_NULL);
1122 }
1123
1124 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1125 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1126
1127 invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1128 }
1129
1130 //! 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)1131 tcu::ConstPixelBufferAccess getSingleSampledAccess (const void* const imageData, const TestParams& params, const deUint32 sampleNdx, const deUint32 layerNdx)
1132 {
1133 const deUint32 numSamples = static_cast<deUint32>(params.numColorSamples);
1134 const deUint32 pixelSize = tcu::getPixelSize(mapVkFormat(params.colorFormat));
1135 const deUint32 rowSize = pixelSize * params.renderSize.x();
1136 const deUint32 layerSize = rowSize * params.renderSize.y();
1137 const deUint8* src = static_cast<const deUint8*>(imageData)
1138 + (layerNdx * numSamples * layerSize)
1139 + (sampleNdx * pixelSize);
1140 const tcu::IVec3 size (params.renderSize.x(), params.renderSize.y(), 1);
1141 const tcu::IVec3 pitch (numSamples * pixelSize,
1142 numSamples * rowSize,
1143 numSamples * layerSize);
1144 return tcu::ConstPixelBufferAccess(mapVkFormat(params.colorFormat), size, pitch, src);
1145 }
1146
test(Context & context,const TestParams params)1147 tcu::TestStatus test (Context& context, const TestParams params)
1148 {
1149 WorkingData wd;
1150 const DeviceInterface& vk = context.getDeviceInterface();
1151 const VkDevice device = context.getDevice();
1152 MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1153
1154 // Initialize resources
1155 {
1156 const VkImageUsageFlags msImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
1157 | VK_IMAGE_USAGE_SAMPLED_BIT
1158 | (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0);
1159 wd.colorImage = makeImage(vk, device, params.colorFormat, params.renderSize, params.numLayers, params.numColorSamples, msImageUsage);
1160 wd.colorImageAlloc = bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any);
1161 wd.colorImageView = makeImageView(vk, device, *wd.colorImage, (params.numLayers == 1u ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY), params.colorFormat,
1162 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.numLayers));
1163
1164 wd.defaultSampler = makeSampler(vk, device);
1165
1166 // Color buffer is meant to hold data for all layers and all samples of the image.
1167 // Data is tightly packed layer by layer, for each pixel all samples are laid out together starting with sample 0.
1168 // E.g.: pixel(0,0)sample(0)sample(1), pixel(1,0)sample(0)sample(1), ...
1169 wd.colorBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat))
1170 * params.renderSize.x() * params.renderSize.y() * params.numLayers * static_cast<deUint32>(params.numColorSamples));
1171 wd.colorBuffer = makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1172 wd.colorBufferAlloc = bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible);
1173
1174 deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1175 flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1176
1177 const std::vector<PositionColor> vertices = genShapes(params.colorFormat);
1178 const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1179
1180 wd.numVertices = static_cast<deUint32>(vertices.size());
1181 wd.vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1182 wd.vertexBufferAlloc = bindBuffer(vk, device, *allocator, *wd.vertexBuffer, MemoryRequirement::HostVisible);
1183
1184 deMemcpy(wd.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize));
1185 flushMappedMemoryRange(vk, device, wd.vertexBufferAlloc->getMemory(), wd.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1186 }
1187
1188 if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
1189 {
1190 // Create a multisample image and sample from it
1191 drawAndSampleInputAttachment (context, params, wd);
1192 }
1193 else
1194 {
1195 // Draw the image, then sample from it in a CS
1196 draw (context, params, wd);
1197 dispatchSampleImage (context, params, wd, "comp_fmask_fetch");
1198 }
1199
1200 // Copy the result
1201 std::vector<deUint8> fmaskFetchColorBuffer (static_cast<deUint32>(wd.colorBufferSize));
1202 deMemcpy(&fmaskFetchColorBuffer[0], wd.colorBufferAlloc->getHostPtr(), static_cast<std::size_t>(wd.colorBufferSize));
1203
1204 // Clear the color buffer, just to be sure we're getting the new data
1205 deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1206 flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1207
1208 // Sample image using the standard texel fetch
1209 dispatchSampleImage (context, params, wd, "comp_fetch");
1210
1211 // Verify the images
1212 {
1213 const void* const fmaskResult = dataOrNullPtr(fmaskFetchColorBuffer);
1214 const void* const expectedResult = wd.colorBufferAlloc->getHostPtr();
1215
1216 DE_ASSERT(!isFloatFormat(params.colorFormat)); // we're using int compare
1217
1218 // Mismatch, do image compare to pinpoint the failure
1219 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1220 for (deUint32 sampleNdx = 0u; sampleNdx < static_cast<deUint32>(params.numColorSamples); ++sampleNdx)
1221 {
1222 const std::string imageName = "layer_" + de::toString(layerNdx) + "_sample_" + de::toString(sampleNdx);
1223 const std::string imageDesc = "Layer " + de::toString(layerNdx) + " Sample " + de::toString(sampleNdx);
1224 const tcu::ConstPixelBufferAccess expected = getSingleSampledAccess(expectedResult, params, sampleNdx, layerNdx);
1225 const tcu::ConstPixelBufferAccess actual = getSingleSampledAccess(fmaskResult, params, sampleNdx, layerNdx);
1226 const UVec4 threshold (0); // should match exactly
1227
1228 const bool ok = tcu::intThresholdCompare(context.getTestContext().getLog(), imageName.c_str(), imageDesc.c_str(),
1229 expected, actual, threshold, tcu::COMPARE_LOG_RESULT);
1230
1231 if (!ok)
1232 return tcu::TestStatus::fail("Some texels were incorrect");
1233 }
1234 }
1235
1236 return tcu::TestStatus::pass("Pass");
1237 }
1238
getFormatShortString(const VkFormat format)1239 std::string getFormatShortString (const VkFormat format)
1240 {
1241 std::string s(de::toLower(getFormatName(format)));
1242 return s.substr(10);
1243 }
1244
createShaderFragmentMaskTestsInGroup(tcu::TestCaseGroup * rootGroup)1245 void createShaderFragmentMaskTestsInGroup (tcu::TestCaseGroup* rootGroup)
1246 {
1247 // Per spec, the following formats must support color attachment and sampled image
1248 const VkFormat colorFormats[] =
1249 {
1250 VK_FORMAT_R8G8B8A8_UNORM,
1251 VK_FORMAT_R32_UINT,
1252 VK_FORMAT_R32_SINT,
1253 };
1254
1255 const VkSampleCountFlagBits sampleCounts[] =
1256 {
1257 VK_SAMPLE_COUNT_2_BIT,
1258 VK_SAMPLE_COUNT_4_BIT,
1259 VK_SAMPLE_COUNT_8_BIT,
1260 VK_SAMPLE_COUNT_16_BIT,
1261 };
1262
1263 const struct SourceCase
1264 {
1265 const char* name;
1266 deUint32 numLayers;
1267 SampleSource sampleSource;
1268 } sourceCases[] =
1269 {
1270 { "image_2d", 1u, SAMPLE_SOURCE_IMAGE },
1271 { "image_2d_array", 3u, SAMPLE_SOURCE_IMAGE },
1272 { "subpass_input", 1u, SAMPLE_SOURCE_SUBPASS_INPUT },
1273 };
1274
1275 // Test 1: Compare fragments fetched via FMASK and an ordinary texel fetch
1276 {
1277 for (const VkSampleCountFlagBits* pSampleCount = sampleCounts; pSampleCount != DE_ARRAY_END(sampleCounts); ++pSampleCount)
1278 {
1279 MovePtr<tcu::TestCaseGroup> sampleCountGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), ("samples_" + de::toString(*pSampleCount)).c_str(), ""));
1280 for (const SourceCase* pSourceCase = sourceCases; pSourceCase != DE_ARRAY_END(sourceCases); ++pSourceCase)
1281 {
1282 MovePtr<tcu::TestCaseGroup> sourceGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), pSourceCase->name, ""));
1283 for (const VkFormat* pColorFormat = colorFormats; pColorFormat != DE_ARRAY_END(colorFormats); ++pColorFormat)
1284 {
1285 TestParams params;
1286 params.renderSize = UVec2(32, 32);
1287 params.colorFormat = *pColorFormat;
1288 params.numColorSamples = *pSampleCount;
1289 params.numLayers = pSourceCase->numLayers;
1290 params.sampleSource = pSourceCase->sampleSource;
1291
1292 addFunctionCaseWithPrograms(sourceGroup.get(), getFormatShortString(*pColorFormat), "", checkRequirements, initPrograms, test, params);
1293 }
1294 sampleCountGroup->addChild(sourceGroup.release());
1295 }
1296 rootGroup->addChild(sampleCountGroup.release());
1297 }
1298 }
1299 }
1300
1301 } // anonymous ns
1302
createMultisampleShaderFragmentMaskTests(tcu::TestContext & testCtx)1303 tcu::TestCaseGroup* createMultisampleShaderFragmentMaskTests (tcu::TestContext& testCtx)
1304 {
1305 return createTestGroup(testCtx, "shader_fragment_mask", "Access raw texel values in a compressed MSAA surface", createShaderFragmentMaskTestsInGroup);
1306 }
1307
1308 } // pipeline
1309 } // vkt
1310