1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 Mobica Ltd.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and/or associated documentation files (the
9 * "Materials"), to deal in the Materials without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Materials, and to
12 * permit persons to whom the Materials are furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice(s) and this permission notice shall be included
16 * in all copies or substantial portions of the Materials.
18 * The Materials are Confidential Information as defined by the
19 * Khronos Membership Agreement until designated non-confidential by Khronos,
20 * at which point this condition clause shall be removed.
22 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
32 * \brief Memory qualifiers tests
33 *//*--------------------------------------------------------------------*/
35 #include "vktImageQualifiersTests.hpp"
36 #include "vktImageLoadStoreTests.hpp"
37 #include "vktImageTestsUtil.hpp"
40 #include "vkImageUtil.hpp"
42 #include "vkRefUtil.hpp"
43 #include "vktTestCase.hpp"
44 #include "vktTestCaseUtil.hpp"
45 #include "vkPlatform.hpp"
46 #include "vkPrograms.hpp"
47 #include "vkMemUtil.hpp"
48 #include "vkBuilderUtil.hpp"
49 #include "vkQueryUtil.hpp"
50 #include "vkTypeUtil.hpp"
53 #include "deStringUtil.hpp"
54 #include "deUniquePtr.hpp"
56 #include "tcuImageCompare.hpp"
57 #include "tcuTexture.hpp"
58 #include "tcuTextureUtil.hpp"
59 #include "tcuVectorType.hpp"
70 static const tcu::UVec3 g_localWorkGroupSizeBase = tcu::UVec3(8, 8, 2);
71 static const deInt32 g_ShaderReadOffsetsX[4] = { 1, 4, 7, 10 };
72 static const deInt32 g_ShaderReadOffsetsY[4] = { 2, 5, 8, 11 };
73 static const deInt32 g_ShaderReadOffsetsZ[4] = { 3, 6, 9, 12 };
74 static const char* const g_ShaderReadOffsetsXStr = "int[]( 1, 4, 7, 10 )";
75 static const char* const g_ShaderReadOffsetsYStr = "int[]( 2, 5, 8, 11 )";
76 static const char* const g_ShaderReadOffsetsZStr = "int[]( 3, 6, 9, 12 )";
78 const tcu::UVec3 getComputeGridSize (const ImageType imageType, const tcu::UVec4& imageSize)
84 case IMAGE_TYPE_2D_ARRAY:
87 case IMAGE_TYPE_CUBE_ARRAY:
88 case IMAGE_TYPE_BUFFER:
89 return tcu::UVec3(imageSize.x(), imageSize.y(), imageSize.z() * imageSize.w());
91 case IMAGE_TYPE_1D_ARRAY:
92 return tcu::UVec3(imageSize.x(), imageSize.w(), 1);
95 DE_FATAL("Unknown image type");
96 return tcu::UVec3(1, 1, 1);
100 const tcu::UVec3 getLocalWorkGroupSize (const ImageType imageType, const tcu::UVec4& imageSize)
102 const tcu::UVec3 computeGridSize = getComputeGridSize(imageType, imageSize);
104 const tcu::UVec3 localWorkGroupSize = tcu::UVec3(de::min(g_localWorkGroupSizeBase.x(), computeGridSize.x()),
105 de::min(g_localWorkGroupSizeBase.y(), computeGridSize.y()),
106 de::min(g_localWorkGroupSizeBase.z(), computeGridSize.z()));
107 return localWorkGroupSize;
110 const tcu::UVec3 getNumWorkGroups (const ImageType imageType, const tcu::UVec4& imageSize)
112 const tcu::UVec3 computeGridSize = getComputeGridSize(imageType, imageSize);
113 const tcu::UVec3 localWorkGroupSize = getLocalWorkGroupSize(imageType, imageSize);
115 return computeGridSize / localWorkGroupSize;
118 tcu::ConstPixelBufferAccess getLayerOrSlice (const ImageType imageType,
119 const tcu::ConstPixelBufferAccess& access,
120 const deUint32 layer)
126 case IMAGE_TYPE_BUFFER:
127 DE_ASSERT(layer == 0);
130 case IMAGE_TYPE_1D_ARRAY:
131 return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
133 case IMAGE_TYPE_2D_ARRAY:
135 case IMAGE_TYPE_CUBE:
136 case IMAGE_TYPE_CUBE_ARRAY:
137 return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
140 DE_FATAL("Unknown image type");
141 return tcu::ConstPixelBufferAccess();
145 bool comparePixelBuffers (tcu::TestContext& testCtx,
146 const ImageType imageType,
147 const tcu::UVec4& imageSize,
148 const tcu::TextureFormat& format,
149 const tcu::ConstPixelBufferAccess& reference,
150 const tcu::ConstPixelBufferAccess& result)
152 DE_ASSERT(reference.getFormat() == result.getFormat());
153 DE_ASSERT(reference.getSize() == result.getSize());
155 const bool intFormat = isIntFormat(mapTextureFormat(format)) || isUintFormat(mapTextureFormat(format));
156 deUint32 passedLayers = 0;
158 for (deUint32 layerNdx = 0; layerNdx < imageSize.z() * imageSize.w(); ++layerNdx)
160 const std::string comparisonName = "Comparison" + de::toString(layerNdx);
162 std::string comparisonDesc = "Image Comparison, ";
166 comparisonDesc = comparisonDesc + "slice " + de::toString(layerNdx);
169 case IMAGE_TYPE_CUBE:
170 case IMAGE_TYPE_CUBE_ARRAY:
171 comparisonDesc = comparisonDesc + "face " + de::toString(layerNdx % 6) + ", cube " + de::toString(layerNdx / 6);
175 comparisonDesc = comparisonDesc + "layer " + de::toString(layerNdx);
179 const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(imageType, reference, layerNdx);
180 const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(imageType, result, layerNdx);
184 ok = tcu::intThresholdCompare(testCtx.getLog(), comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
186 ok = tcu::floatThresholdCompare(testCtx.getLog(), comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
192 return passedLayers == (imageSize.z() * imageSize.w());
195 const std::string getCoordStr (const ImageType imageType,
196 const std::string& x,
197 const std::string& y,
198 const std::string& z)
203 case IMAGE_TYPE_BUFFER:
206 case IMAGE_TYPE_1D_ARRAY:
208 return "ivec2(" + x + "," + y + ")";
210 case IMAGE_TYPE_2D_ARRAY:
212 case IMAGE_TYPE_CUBE:
213 case IMAGE_TYPE_CUBE_ARRAY:
214 return "ivec3(" + x + "," + y + "," + z + ")";
222 class MemoryQualifierTestCase : public vkt::TestCase
228 QUALIFIER_COHERENT = 0,
234 MemoryQualifierTestCase (tcu::TestContext& testCtx,
235 const std::string& name,
236 const std::string& description,
237 const Qualifier qualifier,
238 const ImageType imageType,
239 const tcu::UVec4& imageSize,
240 const tcu::TextureFormat& format,
241 const glu::GLSLVersion glslVersion);
243 virtual ~MemoryQualifierTestCase (void) {}
245 virtual void initPrograms (SourceCollections& programCollection) const;
246 virtual TestInstance* createInstance (Context& context) const;
250 const Qualifier m_qualifier;
251 const ImageType m_imageType;
252 const tcu::UVec4 m_imageSize;
253 const tcu::TextureFormat m_format;
254 const glu::GLSLVersion m_glslVersion;
257 MemoryQualifierTestCase::MemoryQualifierTestCase (tcu::TestContext& testCtx,
258 const std::string& name,
259 const std::string& description,
260 const Qualifier qualifier,
261 const ImageType imageType,
262 const tcu::UVec4& imageSize,
263 const tcu::TextureFormat& format,
264 const glu::GLSLVersion glslVersion)
265 : vkt::TestCase(testCtx, name, description)
266 , m_qualifier(qualifier)
267 , m_imageType(imageType)
268 , m_imageSize(imageSize)
270 , m_glslVersion(glslVersion)
274 void MemoryQualifierTestCase::initPrograms (SourceCollections& programCollection) const
276 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
278 const char* const qualifierName = m_qualifier == QUALIFIER_COHERENT ? "coherent"
279 : m_qualifier == QUALIFIER_VOLATILE ? "volatile"
282 const bool uintFormat = isUintFormat(mapTextureFormat(m_format));
283 const bool intFormat = isIntFormat(mapTextureFormat(m_format));
284 const std::string colorVecTypeName = std::string(uintFormat ? "u" : intFormat ? "i" : "") + "vec4";
285 const std::string colorScalarTypeName = std::string(uintFormat ? "uint" : intFormat ? "int" : "float");
286 const std::string invocationCoord = getCoordStr(m_imageType, "gx", "gy", "gz");
287 const std::string shaderImageFormat = getShaderImageFormatQualifier(m_format);
288 const std::string shaderImageType = getShaderImageType(m_format, m_imageType);
290 const tcu::UVec3 localWorkGroupSize = getLocalWorkGroupSize(m_imageType, m_imageSize);
291 const std::string localSizeX = de::toString(localWorkGroupSize.x());
292 const std::string localSizeY = de::toString(localWorkGroupSize.y());
293 const std::string localSizeZ = de::toString(localWorkGroupSize.z());
295 std::ostringstream programBuffer;
298 << versionDecl << "\n"
300 << "precision highp " << shaderImageType << ";\n"
302 << "layout (local_size_x = " << localSizeX << ", local_size_y = " << localSizeY << ", local_size_z = " + localSizeZ << ") in;\n"
303 << "layout (" << shaderImageFormat << ", binding=0) " << qualifierName << " uniform " << shaderImageType << " u_image;\n"
304 << "void main (void)\n"
306 << " int gx = int(gl_GlobalInvocationID.x);\n"
307 << " int gy = int(gl_GlobalInvocationID.y);\n"
308 << " int gz = int(gl_GlobalInvocationID.z);\n"
309 << " imageStore(u_image, " << invocationCoord << ", " << colorVecTypeName << "(gx^gy^gz));\n"
311 << " memoryBarrier();\n"
314 << " " << colorScalarTypeName << " sum = " << colorScalarTypeName << "(0);\n"
315 << " int groupBaseX = gx/" << localSizeX << "*" << localSizeX << ";\n"
316 << " int groupBaseY = gy/" << localSizeY << "*" << localSizeY << ";\n"
317 << " int groupBaseZ = gz/" << localSizeZ << "*" << localSizeZ << ";\n"
318 << " int xOffsets[] = " << g_ShaderReadOffsetsXStr << ";\n"
319 << " int yOffsets[] = " << g_ShaderReadOffsetsYStr << ";\n"
320 << " int zOffsets[] = " << g_ShaderReadOffsetsZStr << ";\n"
321 << " for (int i = 0; i < " << de::toString(DE_LENGTH_OF_ARRAY(g_ShaderReadOffsetsX)) << "; i++)\n"
323 << " int readX = groupBaseX + (gx + xOffsets[i]) % " + localSizeX + ";\n"
324 << " int readY = groupBaseY + (gy + yOffsets[i]) % " + localSizeY + ";\n"
325 << " int readZ = groupBaseZ + (gz + zOffsets[i]) % " + localSizeZ + ";\n"
326 << " sum += imageLoad(u_image, " << getCoordStr(m_imageType, "readX", "readY", "readZ") << ").x;\n"
329 << " memoryBarrier();\n"
332 << " imageStore(u_image, " + invocationCoord + ", " + colorVecTypeName + "(sum));\n"
335 programCollection.glslSources.add(m_name) << glu::ComputeSource(programBuffer.str());
338 class MemoryQualifierInstanceBase : public vkt::TestInstance
341 MemoryQualifierInstanceBase (Context& context,
342 const std::string& name,
343 const ImageType imageType,
344 const tcu::UVec4& imageSize,
345 const tcu::TextureFormat& format);
347 virtual ~MemoryQualifierInstanceBase (void) {};
349 virtual tcu::TestStatus iterate (void);
351 virtual void prepareResources (const VkDeviceSize bufferSizeInBytes) = 0;
353 virtual void prepareDescriptors (void) = 0;
355 virtual void commandsBeforeCompute (const VkCommandBuffer cmdBuffer,
356 const VkDeviceSize bufferSizeInBytes) const = 0;
358 virtual void commandsAfterCompute (const VkCommandBuffer cmdBuffer,
359 const VkDeviceSize bufferSizeInBytes) const = 0;
362 tcu::TextureLevel generateReferenceImage (void) const;
364 const std::string m_name;
365 const ImageType m_imageType;
366 const tcu::UVec4 m_imageSize;
367 const tcu::TextureFormat m_format;
369 de::MovePtr<Buffer> m_buffer;
370 Move<VkDescriptorPool> m_descriptorPool;
371 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
372 Move<VkDescriptorSet> m_descriptorSet;
375 MemoryQualifierInstanceBase::MemoryQualifierInstanceBase (Context& context,
376 const std::string& name,
377 const ImageType imageType,
378 const tcu::UVec4& imageSize,
379 const tcu::TextureFormat& format)
380 : vkt::TestInstance(context)
382 , m_imageType(imageType)
383 , m_imageSize(imageSize)
388 tcu::TestStatus MemoryQualifierInstanceBase::iterate (void)
390 const VkDevice device = m_context.getDevice();
391 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
392 const VkQueue queue = m_context.getUniversalQueue();
393 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
395 const VkDeviceSize bufferSizeInBytes = m_imageSize.x() * m_imageSize.y() * m_imageSize.z() * m_imageSize.w() * tcu::getPixelSize(m_format);
397 // Prepare resources for the test
398 prepareResources(bufferSizeInBytes);
400 // Prepare descriptor sets
401 prepareDescriptors();
403 // Create compute shader
404 const vk::Unique<VkShaderModule> shaderModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get(m_name), 0u));
406 // Create compute pipeline
407 const vk::Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(deviceInterface, device, *m_descriptorSetLayout));
408 const vk::Unique<VkPipeline> pipeline(makeComputePipeline(deviceInterface, device, *pipelineLayout, *shaderModule));
410 // Create command buffer
411 const Unique<VkCommandPool> cmdPool(makeCommandPool(deviceInterface, device, queueFamilyIndex));
412 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(deviceInterface, device, *cmdPool));
414 // Start recording commands
415 beginCommandBuffer(deviceInterface, *cmdBuffer);
417 deviceInterface.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
418 deviceInterface.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
420 commandsBeforeCompute(*cmdBuffer, bufferSizeInBytes);
422 const tcu::UVec3 numGroups = getNumWorkGroups(m_imageType, m_imageSize);
423 deviceInterface.cmdDispatch(*cmdBuffer, numGroups.x(), numGroups.y(), numGroups.z());
425 commandsAfterCompute(*cmdBuffer, bufferSizeInBytes);
427 endCommandBuffer(deviceInterface, *cmdBuffer);
429 // Submit and wait for completion
430 submitCommandsAndWait(deviceInterface, device, queue, *cmdBuffer);
432 // Retrieve data from buffer to host memory
433 const Allocation& allocation = m_buffer->getAllocation();
434 invalidateMappedMemoryRange(deviceInterface, device, allocation.getMemory(), allocation.getOffset(), bufferSizeInBytes);
436 const tcu::UVec3 computeGridSize = getComputeGridSize(m_imageType, m_imageSize);
437 tcu::ConstPixelBufferAccess resultPixelBuffer(m_format, computeGridSize.x(), computeGridSize.y(), computeGridSize.z(), allocation.getHostPtr());
439 // Create a reference image
440 tcu::TextureLevel referenceImage = generateReferenceImage();
441 tcu::ConstPixelBufferAccess referencePixelBuffer = referenceImage.getAccess();
443 // Validate the result
444 if (comparePixelBuffers(m_context.getTestContext(), m_imageType, m_imageSize, m_format, referencePixelBuffer, resultPixelBuffer))
445 return tcu::TestStatus::pass("Passed");
447 return tcu::TestStatus::fail("Image comparison failed");
450 tcu::TextureLevel MemoryQualifierInstanceBase::generateReferenceImage (void) const
452 // Generate a reference image data using the storage format
453 const tcu::UVec3 computeGridSize = getComputeGridSize(m_imageType, m_imageSize);
455 tcu::TextureLevel base(m_format, computeGridSize.x(), computeGridSize.y(), computeGridSize.z());
456 tcu::PixelBufferAccess baseAccess = base.getAccess();
458 tcu::TextureLevel reference(m_format, computeGridSize.x(), computeGridSize.y(), computeGridSize.z());
459 tcu::PixelBufferAccess referenceAccess = reference.getAccess();
461 for (deInt32 z = 0; z < baseAccess.getDepth(); ++z)
462 for (deInt32 y = 0; y < baseAccess.getHeight(); ++y)
463 for (deInt32 x = 0; x < baseAccess.getWidth(); ++x)
465 baseAccess.setPixel(tcu::IVec4(x^y^z), x, y, z);
468 const tcu::UVec3 localWorkGroupSize = getLocalWorkGroupSize(m_imageType, m_imageSize);
470 for (deInt32 z = 0; z < referenceAccess.getDepth(); ++z)
471 for (deInt32 y = 0; y < referenceAccess.getHeight(); ++y)
472 for (deInt32 x = 0; x < referenceAccess.getWidth(); ++x)
474 const deInt32 groupBaseX = x / localWorkGroupSize.x() * localWorkGroupSize.x();
475 const deInt32 groupBaseY = y / localWorkGroupSize.y() * localWorkGroupSize.y();
476 const deInt32 groupBaseZ = z / localWorkGroupSize.z() * localWorkGroupSize.z();
479 for (deInt32 i = 0; i < DE_LENGTH_OF_ARRAY(g_ShaderReadOffsetsX); i++)
481 sum += baseAccess.getPixelInt(
482 groupBaseX + (x + g_ShaderReadOffsetsX[i]) % localWorkGroupSize.x(),
483 groupBaseY + (y + g_ShaderReadOffsetsY[i]) % localWorkGroupSize.y(),
484 groupBaseZ + (z + g_ShaderReadOffsetsZ[i]) % localWorkGroupSize.z()).x();
487 referenceAccess.setPixel(tcu::IVec4(sum), x, y, z);
493 class MemoryQualifierInstanceImage : public MemoryQualifierInstanceBase
496 MemoryQualifierInstanceImage (Context& context,
497 const std::string& name,
498 const ImageType imageType,
499 const tcu::UVec4& imageSize,
500 const tcu::TextureFormat& format)
501 : MemoryQualifierInstanceBase(context, name, imageType, imageSize, format) {}
503 virtual ~MemoryQualifierInstanceImage (void) {};
505 virtual void prepareResources (const VkDeviceSize bufferSizeInBytes);
507 virtual void prepareDescriptors (void);
509 virtual void commandsBeforeCompute (const VkCommandBuffer cmdBuffer,
510 const VkDeviceSize bufferSizeInBytes) const;
512 virtual void commandsAfterCompute (const VkCommandBuffer cmdBuffer,
513 const VkDeviceSize bufferSizeInBytes) const;
516 de::MovePtr<Image> m_image;
517 Move<VkImageView> m_imageView;
520 void MemoryQualifierInstanceImage::prepareResources (const VkDeviceSize bufferSizeInBytes)
522 const VkDevice device = m_context.getDevice();
523 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
524 Allocator& allocator = m_context.getDefaultAllocator();
527 const VkImageCreateInfo imageCreateInfo =
529 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
530 DE_NULL, // const void* pNext;
531 m_imageType == IMAGE_TYPE_CUBE ||
532 m_imageType == IMAGE_TYPE_CUBE_ARRAY
533 ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u, // VkImageCreateFlags flags;
534 mapImageType(m_imageType), // VkImageType imageType;
535 mapTextureFormat(m_format), // VkFormat format;
536 vk::makeExtent3D(m_imageSize.x(), m_imageSize.y(), m_imageSize.z()), // VkExtent3D extent;
537 1u, // deUint32 mipLevels;
538 m_imageSize.w(), // deUint32 arrayLayers;
539 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
540 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
541 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT, // VkImageUsageFlags usage;
542 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
543 0u, // deUint32 queueFamilyIndexCount;
544 DE_NULL, // const deUint32* pQueueFamilyIndices;
545 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
548 m_image = de::MovePtr<Image>(new Image(deviceInterface, device, allocator, imageCreateInfo, MemoryRequirement::Any));
551 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_imageSize.w());
552 m_imageView = makeImageView(deviceInterface, device, m_image->get(), mapImageViewType(m_imageType), mapTextureFormat(m_format), subresourceRange);
554 // Create a buffer to store shader output (copied from image data)
555 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
556 m_buffer = de::MovePtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
558 void MemoryQualifierInstanceImage::prepareDescriptors (void)
560 const VkDevice device = m_context.getDevice();
561 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
563 // Create descriptor pool
565 DescriptorPoolBuilder()
566 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
567 .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
569 // Create descriptor set layout
570 m_descriptorSetLayout =
571 DescriptorSetLayoutBuilder()
572 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
573 .build(deviceInterface, device);
575 // Allocate descriptor set
576 m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *m_descriptorSetLayout);
579 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
581 DescriptorSetUpdateBuilder()
582 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
583 .update(deviceInterface, device);
586 void MemoryQualifierInstanceImage::commandsBeforeCompute (const VkCommandBuffer cmdBuffer, const VkDeviceSize bufferSizeInBytes) const
588 DE_UNREF(bufferSizeInBytes);
590 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
591 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_imageSize.w());
593 const VkImageMemoryBarrier imageLayoutBarrier
594 = makeImageMemoryBarrier(0u,
595 VK_ACCESS_SHADER_READ_BIT,
596 VK_IMAGE_LAYOUT_UNDEFINED,
597 VK_IMAGE_LAYOUT_GENERAL,
601 const void* preComputeBarriers[] = { &imageLayoutBarrier };
602 deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, DE_FALSE, DE_LENGTH_OF_ARRAY(preComputeBarriers), preComputeBarriers);
605 void MemoryQualifierInstanceImage::commandsAfterCompute (const VkCommandBuffer cmdBuffer, const VkDeviceSize bufferSizeInBytes) const
607 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
608 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_imageSize.w());
610 const VkImageMemoryBarrier imagePreCopyBarrier
611 = makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT,
612 VK_ACCESS_TRANSFER_READ_BIT,
613 VK_IMAGE_LAYOUT_GENERAL,
614 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
618 const void* preCopyBarriers[] = { &imagePreCopyBarrier };
619 deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, DE_LENGTH_OF_ARRAY(preCopyBarriers), preCopyBarriers);
621 const VkBufferImageCopy copyParams = makeBufferImageCopy(vk::makeExtent3D(m_imageSize.x(), m_imageSize.y(), m_imageSize.z()), m_imageSize.w());
622 deviceInterface.cmdCopyImageToBuffer(cmdBuffer, m_image->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_buffer->get(), 1u, ©Params);
624 const VkBufferMemoryBarrier bufferPostCopyBarrier
625 = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
626 VK_ACCESS_HOST_READ_BIT,
631 const void* postCopyBarriers[] = { &bufferPostCopyBarrier };
632 deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, DE_LENGTH_OF_ARRAY(postCopyBarriers), postCopyBarriers);
635 class MemoryQualifierInstanceBuffer : public MemoryQualifierInstanceBase
638 MemoryQualifierInstanceBuffer (Context& context,
639 const std::string& name,
640 const ImageType imageType,
641 const tcu::UVec4& imageSize,
642 const tcu::TextureFormat& format)
643 : MemoryQualifierInstanceBase(context, name, imageType, imageSize, format) {}
645 virtual ~MemoryQualifierInstanceBuffer (void) {};
647 virtual void prepareResources (const VkDeviceSize bufferSizeInBytes);
649 virtual void prepareDescriptors (void);
651 virtual void commandsBeforeCompute (const VkCommandBuffer,
652 const VkDeviceSize) const {}
654 virtual void commandsAfterCompute (const VkCommandBuffer cmdBuffer,
655 const VkDeviceSize bufferSizeInBytes) const;
658 Move<VkBufferView> m_bufferView;
661 void MemoryQualifierInstanceBuffer::prepareResources (const VkDeviceSize bufferSizeInBytes)
663 const VkDevice device = m_context.getDevice();
664 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
665 Allocator& allocator = m_context.getDefaultAllocator();
667 // Create a buffer to store shader output
668 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSizeInBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
669 m_buffer = de::MovePtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
671 m_bufferView = makeBufferView(deviceInterface, device, m_buffer->get(), mapTextureFormat(m_format), 0ull, bufferSizeInBytes);
674 void MemoryQualifierInstanceBuffer::prepareDescriptors (void)
676 const VkDevice device = m_context.getDevice();
677 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
679 // Create descriptor pool
681 DescriptorPoolBuilder()
682 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
683 .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
685 // Create descriptor set layout
686 m_descriptorSetLayout =
687 DescriptorSetLayoutBuilder()
688 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
689 .build(deviceInterface, device);
691 // Allocate descriptor set
692 m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *m_descriptorSetLayout);
695 DescriptorSetUpdateBuilder()
696 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
697 .update(deviceInterface, device);
700 void MemoryQualifierInstanceBuffer::commandsAfterCompute (const VkCommandBuffer cmdBuffer, const VkDeviceSize bufferSizeInBytes) const
702 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
704 const VkBufferMemoryBarrier shaderWriteBarrier
705 = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT,
706 VK_ACCESS_HOST_READ_BIT,
711 const void* barriers[] = { &shaderWriteBarrier };
712 deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, DE_LENGTH_OF_ARRAY(barriers), barriers);
715 TestInstance* MemoryQualifierTestCase::createInstance (Context& context) const
717 if ( m_imageType == IMAGE_TYPE_BUFFER )
718 return new MemoryQualifierInstanceBuffer(context, m_name, m_imageType, m_imageSize, m_format);
720 return new MemoryQualifierInstanceImage(context, m_name, m_imageType, m_imageSize, m_format);
725 tcu::TestCaseGroup* createImageQualifiersTests (tcu::TestContext& testCtx)
727 de::MovePtr<tcu::TestCaseGroup> imageQualifiersTests(new tcu::TestCaseGroup(testCtx, "qualifiers", "Coherent, volatile and restrict"));
729 struct ImageParameters
732 tcu::UVec4 imageSize;
735 static const ImageParameters imageParametersArray[] =
737 { IMAGE_TYPE_1D, tcu::UVec4(64, 1, 1, 1) },
738 { IMAGE_TYPE_1D_ARRAY, tcu::UVec4(64, 1, 1, 8) },
739 { IMAGE_TYPE_2D, tcu::UVec4(64, 64, 1, 1) },
740 { IMAGE_TYPE_2D_ARRAY, tcu::UVec4(64, 64, 1, 8) },
741 { IMAGE_TYPE_3D, tcu::UVec4(64, 64, 8, 1) },
742 { IMAGE_TYPE_CUBE, tcu::UVec4(64, 64, 1, 6) },
743 { IMAGE_TYPE_CUBE_ARRAY, tcu::UVec4(64, 64, 1, 6*8) },
744 { IMAGE_TYPE_BUFFER, tcu::UVec4(64, 1, 1, 1) }
747 static const tcu::TextureFormat formats[] =
749 tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT),
750 tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32),
751 tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32),
754 for (deUint32 qualifierI = 0; qualifierI < MemoryQualifierTestCase::QUALIFIER_LAST; ++qualifierI)
756 const MemoryQualifierTestCase::Qualifier memoryQualifier = (MemoryQualifierTestCase::Qualifier)qualifierI;
757 const char* const memoryQualifierName =
758 memoryQualifier == MemoryQualifierTestCase::QUALIFIER_COHERENT ? "coherent" :
759 memoryQualifier == MemoryQualifierTestCase::QUALIFIER_VOLATILE ? "volatile" :
760 memoryQualifier == MemoryQualifierTestCase::QUALIFIER_RESTRICT ? "restrict" :
763 de::MovePtr<tcu::TestCaseGroup> qualifierGroup(new tcu::TestCaseGroup(testCtx, memoryQualifierName, ""));
765 for (deInt32 imageTypeNdx = 0; imageTypeNdx < DE_LENGTH_OF_ARRAY(imageParametersArray); imageTypeNdx++)
767 const ImageType imageType = imageParametersArray[imageTypeNdx].imageType;
768 const tcu::UVec4 imageSize = imageParametersArray[imageTypeNdx].imageSize;
770 if (memoryQualifier == MemoryQualifierTestCase::QUALIFIER_RESTRICT)
772 de::MovePtr<TestCase> restrictCase = createImageQualifierRestrictCase(testCtx, imageType, getImageTypeName(imageType));
773 qualifierGroup->addChild(restrictCase.release());
777 for (deInt32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
779 const tcu::TextureFormat& format = formats[formatNdx];
780 const std::string formatName = getShaderImageFormatQualifier(formats[formatNdx]);
782 qualifierGroup->addChild(
783 new MemoryQualifierTestCase(testCtx, getImageTypeName(imageType) + std::string("_") + formatName,
784 "", memoryQualifier, imageType, imageSize, format, glu::GLSL_VERSION_440));
789 imageQualifiersTests->addChild(qualifierGroup.release());
792 return imageQualifiersTests.release();