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