1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 The Android Open Source Project
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Image load/store Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktImageLoadStoreTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktImageTestsUtil.hpp"
28 #include "vktImageLoadStoreUtil.hpp"
29 #include "vktImageTexture.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkImageUtil.hpp"
41 #include "deUniquePtr.hpp"
42 #include "deSharedPtr.hpp"
43 #include "deStringUtil.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuTexture.hpp"
47 #include "tcuTextureUtil.hpp"
48 #include "tcuFloat.hpp"
62 inline VkBufferImageCopy makeBufferImageCopy (const Texture& texture)
64 return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers());
67 tcu::ConstPixelBufferAccess getLayerOrSlice (const Texture& texture, const tcu::ConstPixelBufferAccess access, const int layer)
69 switch (texture.type())
73 case IMAGE_TYPE_BUFFER:
75 DE_ASSERT(layer == 0);
78 case IMAGE_TYPE_1D_ARRAY:
79 return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
81 case IMAGE_TYPE_2D_ARRAY:
83 case IMAGE_TYPE_CUBE_ARRAY:
84 case IMAGE_TYPE_3D: // 3d texture is treated as if depth was the layers
85 return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
88 DE_FATAL("Internal test error");
89 return tcu::ConstPixelBufferAccess();
93 //! \return true if all layers match in both pixel buffers
94 bool comparePixelBuffers (tcu::TestLog& log,
95 const Texture& texture,
96 const VkFormat format,
97 const tcu::ConstPixelBufferAccess reference,
98 const tcu::ConstPixelBufferAccess result)
100 DE_ASSERT(reference.getFormat() == result.getFormat());
101 DE_ASSERT(reference.getSize() == result.getSize());
103 const bool intFormat = isIntegerFormat(format);
104 const bool is3d = (texture.type() == IMAGE_TYPE_3D);
105 const int numLayersOrSlices = (is3d ? texture.size().z() : texture.numLayers());
106 const int numCubeFaces = 6;
108 int passedLayers = 0;
109 for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx)
111 const std::string comparisonName = "Comparison" + de::toString(layerNdx);
112 const std::string comparisonDesc = "Image Comparison, " +
113 (isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " + de::toString(layerNdx / numCubeFaces) :
114 is3d ? "slice " + de::toString(layerNdx) : "layer " + de::toString(layerNdx));
116 const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx);
117 const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx);
121 ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
123 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
128 return passedLayers == numLayersOrSlices;
131 //!< Zero out invalid pixels in the image (denormalized, infinite, NaN values)
132 void replaceBadFloatReinterpretValues (const tcu::PixelBufferAccess access)
134 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
136 for (int z = 0; z < access.getDepth(); ++z)
137 for (int y = 0; y < access.getHeight(); ++y)
138 for (int x = 0; x < access.getWidth(); ++x)
140 const tcu::Vec4 color(access.getPixel(x, y, z));
141 tcu::Vec4 newColor = color;
143 for (int i = 0; i < 4; ++i)
145 if (access.getFormat().type == tcu::TextureFormat::HALF_FLOAT)
147 const tcu::Float16 f(color[i]);
148 if (f.isDenorm() || f.isInf() || f.isNaN())
153 const tcu::Float32 f(color[i]);
154 if (f.isDenorm() || f.isInf() || f.isNaN())
159 if (newColor != color)
160 access.setPixel(newColor, x, y, z);
164 //!< replace invalid pixels in the image (-128)
165 void replaceSnormReinterpretValues (const tcu::PixelBufferAccess access)
167 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
169 for (int z = 0; z < access.getDepth(); ++z)
170 for (int y = 0; y < access.getHeight(); ++y)
171 for (int x = 0; x < access.getWidth(); ++x)
173 const tcu::IVec4 color(access.getPixelInt(x, y, z));
174 tcu::IVec4 newColor = color;
176 for (int i = 0; i < 4; ++i)
178 const deInt32 oldColor(color[i]);
179 if (oldColor == -128) newColor[i] = -127;
182 if (newColor != color)
183 access.setPixel(newColor, x, y, z);
187 tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, const VkFormat readFormat)
189 // Generate a reference image data using the storage format
191 tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z());
192 const tcu::PixelBufferAccess access = reference.getAccess();
194 const float storeColorScale = computeStoreColorScale(imageFormat, imageSize);
195 const float storeColorBias = computeStoreColorBias(imageFormat);
197 const bool intFormat = isIntegerFormat(imageFormat);
198 const int xMax = imageSize.x() - 1;
199 const int yMax = imageSize.y() - 1;
201 for (int z = 0; z < imageSize.z(); ++z)
202 for (int y = 0; y < imageSize.y(); ++y)
203 for (int x = 0; x < imageSize.x(); ++x)
205 const tcu::IVec4 color(x^y^z, (xMax - x)^y^z, x^(yMax - y)^z, (xMax - x)^(yMax - y)^z);
208 access.setPixel(color, x, y, z);
210 access.setPixel(color.asFloat()*storeColorScale + storeColorBias, x, y, z);
213 // If the image is to be accessed as a float texture, get rid of invalid values
215 if (isFloatFormat(readFormat) && imageFormat != readFormat)
216 replaceBadFloatReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
217 if (isSnormFormat(readFormat) && imageFormat != readFormat)
218 replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
223 inline tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat)
225 return generateReferenceImage(imageSize, imageFormat, imageFormat);
228 void flipHorizontally (const tcu::PixelBufferAccess access)
230 const int xMax = access.getWidth() - 1;
231 const int halfWidth = access.getWidth() / 2;
233 if (isIntegerFormat(mapTextureFormat(access.getFormat())))
234 for (int z = 0; z < access.getDepth(); z++)
235 for (int y = 0; y < access.getHeight(); y++)
236 for (int x = 0; x < halfWidth; x++)
238 const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z);
239 access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z);
240 access.setPixel(temp, x, y, z);
243 for (int z = 0; z < access.getDepth(); z++)
244 for (int y = 0; y < access.getHeight(); y++)
245 for (int x = 0; x < halfWidth; x++)
247 const tcu::Vec4 temp = access.getPixel(xMax - x, y, z);
248 access.setPixel(access.getPixel(x, y, z), xMax - x, y, z);
249 access.setPixel(temp, x, y, z);
253 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
255 return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
258 void commandImageWriteBarrierBetweenShaderInvocations (Context& context, const VkCommandBuffer cmdBuffer, const VkImage image, const Texture& texture)
260 const DeviceInterface& vk = context.getDeviceInterface();
262 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
263 const VkImageMemoryBarrier shaderWriteBarrier = makeImageMemoryBarrier(
264 VK_ACCESS_SHADER_WRITE_BIT, 0u,
265 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
266 image, fullImageSubresourceRange);
268 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier);
271 void commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes)
273 const DeviceInterface& vk = context.getDeviceInterface();
275 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
276 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
277 buffer, 0ull, bufferSizeBytes);
279 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
282 //! Copy all layers of an image to a buffer.
283 void commandCopyImageToBuffer (Context& context,
284 const VkCommandBuffer cmdBuffer,
286 const VkBuffer buffer,
287 const VkDeviceSize bufferSizeBytes,
288 const Texture& texture)
290 const DeviceInterface& vk = context.getDeviceInterface();
292 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
293 const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
294 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
295 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
296 image, fullImageSubresourceRange);
298 const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture);
300 const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
301 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
302 buffer, 0ull, bufferSizeBytes);
304 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier);
305 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, ©Region);
306 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©Barrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
309 class StoreTest : public TestCase
314 FLAG_SINGLE_LAYER_BIND = 0x1, //!< Run the shader multiple times, each time binding a different layer.
315 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 0x2, //!< Declare the format of the images in the shader code
318 StoreTest (tcu::TestContext& testCtx,
319 const std::string& name,
320 const std::string& description,
321 const Texture& texture,
322 const VkFormat format,
323 const deUint32 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
325 void initPrograms (SourceCollections& programCollection) const;
327 TestInstance* createInstance (Context& context) const;
330 const Texture m_texture;
331 const VkFormat m_format;
332 const bool m_declareImageFormatInShader;
333 const bool m_singleLayerBind;
336 StoreTest::StoreTest (tcu::TestContext& testCtx,
337 const std::string& name,
338 const std::string& description,
339 const Texture& texture,
340 const VkFormat format,
341 const deUint32 flags)
342 : TestCase (testCtx, name, description)
343 , m_texture (texture)
345 , m_declareImageFormatInShader ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
346 , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
348 if (m_singleLayerBind)
349 DE_ASSERT(m_texture.numLayers() > 1);
352 void StoreTest::initPrograms (SourceCollections& programCollection) const
354 const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
355 const float storeColorBias = computeStoreColorBias(m_format);
356 DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
358 const std::string xMax = de::toString(m_texture.size().x() - 1);
359 const std::string yMax = de::toString(m_texture.size().y() - 1);
360 const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
361 const std::string colorBaseExpr = signednessPrefix + "vec4("
363 + "(" + xMax + "-gx)^gy^gz, "
364 + "gx^(" + yMax + "-gy)^gz, "
365 + "(" + xMax + "-gx)^(" + yMax + "-gy)^gz)";
367 const std::string colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
368 + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
370 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
371 const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
373 const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
374 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
375 const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
377 for (deUint32 variant = 0; variant <= 1; variant++)
379 std::ostringstream src;
380 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
382 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
384 src << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " u_image;\n";
386 src << "layout (binding = 0) writeonly uniform " << imageTypeStr << " u_image;\n";
388 if (m_singleLayerBind)
389 src << "layout (binding = 1) readonly uniform Constants {\n"
390 << " int u_layerNdx;\n"
394 << "void main (void)\n"
396 << " int gx = int(gl_GlobalInvocationID.x);\n"
397 << " int gy = int(gl_GlobalInvocationID.y);\n"
398 << " int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
399 << " imageStore(u_image, " << texelCoordStr << ", " << colorExpr << ");\n"
402 programCollection.glslSources.add(variant == 0 ? "comp" : "comp_fmt_unknown") << glu::ComputeSource(src.str());
406 //! Generic test iteration algorithm for image tests
407 class BaseTestInstance : public TestInstance
410 BaseTestInstance (Context& context,
411 const Texture& texture,
412 const VkFormat format,
413 const bool declareImageFormatInShader,
414 const bool singleLayerBind);
416 tcu::TestStatus iterate (void);
418 virtual ~BaseTestInstance (void) {}
421 virtual VkDescriptorSetLayout prepareDescriptors (void) = 0;
422 virtual tcu::TestStatus verifyResult (void) = 0;
424 virtual void commandBeforeCompute (const VkCommandBuffer cmdBuffer) = 0;
425 virtual void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer) = 0;
426 virtual void commandAfterCompute (const VkCommandBuffer cmdBuffer) = 0;
428 virtual void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
429 const VkPipelineLayout pipelineLayout,
430 const int layerNdx) = 0;
431 virtual void checkRequirements (void) {};
433 const Texture m_texture;
434 const VkFormat m_format;
435 const bool m_declareImageFormatInShader;
436 const bool m_singleLayerBind;
439 BaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind)
440 : TestInstance (context)
441 , m_texture (texture)
443 , m_declareImageFormatInShader (declareImageFormatInShader)
444 , m_singleLayerBind (singleLayerBind)
448 tcu::TestStatus BaseTestInstance::iterate (void)
452 const DeviceInterface& vk = m_context.getDeviceInterface();
453 const VkDevice device = m_context.getDevice();
454 const VkQueue queue = m_context.getUniversalQueue();
455 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
457 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get(m_declareImageFormatInShader ? "comp" : "comp_fmt_unknown"), 0));
459 const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
460 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
461 const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
463 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT, queueFamilyIndex));
464 const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
466 beginCommandBuffer(vk, *cmdBuffer);
468 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
469 commandBeforeCompute(*cmdBuffer);
471 const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
472 const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
473 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
475 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
478 commandBetweenShaderInvocations(*cmdBuffer);
480 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
483 commandAfterCompute(*cmdBuffer);
485 endCommandBuffer(vk, *cmdBuffer);
487 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
489 return verifyResult();
492 //! Base store test implementation
493 class StoreTestInstance : public BaseTestInstance
496 StoreTestInstance (Context& context,
497 const Texture& texture,
498 const VkFormat format,
499 const bool declareImageFormatInShader,
500 const bool singleLayerBind);
503 tcu::TestStatus verifyResult (void);
505 // Add empty implementations for functions that might be not needed
506 void commandBeforeCompute (const VkCommandBuffer) {}
507 void commandBetweenShaderInvocations (const VkCommandBuffer) {}
508 void commandAfterCompute (const VkCommandBuffer) {}
509 void checkRequirements (void);
511 de::MovePtr<Buffer> m_imageBuffer;
512 const VkDeviceSize m_imageSizeBytes;
515 StoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind)
516 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind)
517 , m_imageSizeBytes (getImageSizeBytes(texture.size(), format))
519 const DeviceInterface& vk = m_context.getDeviceInterface();
520 const VkDevice device = m_context.getDevice();
521 Allocator& allocator = m_context.getDefaultAllocator();
523 // A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
525 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
526 vk, device, allocator,
527 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
528 MemoryRequirement::HostVisible));
531 tcu::TestStatus StoreTestInstance::verifyResult (void)
533 const DeviceInterface& vk = m_context.getDeviceInterface();
534 const VkDevice device = m_context.getDevice();
536 const tcu::IVec3 imageSize = m_texture.size();
537 const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format);
539 const Allocation& alloc = m_imageBuffer->getAllocation();
540 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
541 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, alloc.getHostPtr());
543 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
544 return tcu::TestStatus::pass("Passed");
546 return tcu::TestStatus::fail("Image comparison failed");
549 void StoreTestInstance::checkRequirements (void)
551 const VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
553 if (!m_declareImageFormatInShader && !features.shaderStorageImageWriteWithoutFormat)
554 throw tcu::NotSupportedError("shaderStorageImageWriteWithoutFormat feature not supported");
557 //! Store test for images
558 class ImageStoreTestInstance : public StoreTestInstance
561 ImageStoreTestInstance (Context& context,
562 const Texture& texture,
563 const VkFormat format,
564 const bool declareImageFormatInShader,
565 const bool singleLayerBind);
568 VkDescriptorSetLayout prepareDescriptors (void);
569 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
570 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
571 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
573 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
574 const VkPipelineLayout pipelineLayout,
577 de::MovePtr<Image> m_image;
578 de::MovePtr<Buffer> m_constantsBuffer;
579 const VkDeviceSize m_constantsBufferChunkSizeBytes;
580 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
581 Move<VkDescriptorPool> m_descriptorPool;
582 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
583 std::vector<SharedVkImageView> m_allImageViews;
586 ImageStoreTestInstance::ImageStoreTestInstance (Context& context,
587 const Texture& texture,
588 const VkFormat format,
589 const bool declareImageFormatInShader,
590 const bool singleLayerBind)
591 : StoreTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind)
592 , m_constantsBufferChunkSizeBytes (getOptimalUniformBufferChunkSize(context.getInstanceInterface(), context.getPhysicalDevice(), sizeof(deUint32)))
593 , m_allDescriptorSets (texture.numLayers())
594 , m_allImageViews (texture.numLayers())
596 const DeviceInterface& vk = m_context.getDeviceInterface();
597 const VkDevice device = m_context.getDevice();
598 Allocator& allocator = m_context.getDefaultAllocator();
600 m_image = de::MovePtr<Image>(new Image(
601 vk, device, allocator,
602 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
603 MemoryRequirement::Any));
605 // This buffer will be used to pass constants to the shader
607 const int numLayers = m_texture.numLayers();
608 const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
609 m_constantsBuffer = de::MovePtr<Buffer>(new Buffer(
610 vk, device, allocator,
611 makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
612 MemoryRequirement::HostVisible));
615 const Allocation& alloc = m_constantsBuffer->getAllocation();
616 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
618 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
620 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
622 deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
623 *valuePtr = static_cast<deUint32>(layerNdx);
626 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), constantsBufferSizeBytes);
630 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void)
632 const DeviceInterface& vk = m_context.getDeviceInterface();
633 const VkDevice device = m_context.getDevice();
635 const int numLayers = m_texture.numLayers();
636 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
637 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
638 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
641 m_descriptorPool = DescriptorPoolBuilder()
642 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
643 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
644 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
646 if (m_singleLayerBind)
648 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
650 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
651 m_allImageViews[layerNdx] = makeVkSharedPtr(makeImageView(
652 vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
653 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
656 else // bind all layers at once
658 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
659 m_allImageViews[0] = makeVkSharedPtr(makeImageView(
660 vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
661 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
664 return *m_descriptorSetLayout; // not passing the ownership
667 void ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
669 const DeviceInterface& vk = m_context.getDeviceInterface();
670 const VkDevice device = m_context.getDevice();
672 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
673 const VkImageView imageView = **m_allImageViews[layerNdx];
675 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
677 // Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
678 const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
679 m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
681 DescriptorSetUpdateBuilder()
682 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
683 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
685 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
688 void ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
690 const DeviceInterface& vk = m_context.getDeviceInterface();
692 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
693 const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
695 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
696 m_image->get(), fullImageSubresourceRange);
698 const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
699 const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
700 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
701 m_constantsBuffer->get(), 0ull, constantsBufferSize);
703 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &writeConstantsBarrier, 1, &setImageLayoutBarrier);
706 void ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
708 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture);
711 void ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
713 commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
716 //! Store test for buffers
717 class BufferStoreTestInstance : public StoreTestInstance
720 BufferStoreTestInstance (Context& context,
721 const Texture& texture,
722 const VkFormat format,
723 const bool declareImageFormatInShader);
726 VkDescriptorSetLayout prepareDescriptors (void);
727 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
729 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
730 const VkPipelineLayout pipelineLayout,
733 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
734 Move<VkDescriptorPool> m_descriptorPool;
735 Move<VkDescriptorSet> m_descriptorSet;
736 Move<VkBufferView> m_bufferView;
739 BufferStoreTestInstance::BufferStoreTestInstance (Context& context,
740 const Texture& texture,
741 const VkFormat format,
742 const bool declareImageFormatInShader)
743 : StoreTestInstance(context, texture, format, declareImageFormatInShader, false)
747 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void)
749 const DeviceInterface& vk = m_context.getDeviceInterface();
750 const VkDevice device = m_context.getDevice();
752 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
753 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
756 m_descriptorPool = DescriptorPoolBuilder()
757 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
758 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
760 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
761 m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes);
763 return *m_descriptorSetLayout; // not passing the ownership
766 void BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
768 DE_ASSERT(layerNdx == 0);
771 const VkDevice device = m_context.getDevice();
772 const DeviceInterface& vk = m_context.getDeviceInterface();
774 DescriptorSetUpdateBuilder()
775 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
777 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
780 void BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
782 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes);
785 class LoadStoreTest : public TestCase
790 FLAG_SINGLE_LAYER_BIND = 1 << 0, //!< Run the shader multiple times, each time binding a different layer.
791 FLAG_RESTRICT_IMAGES = 1 << 1, //!< If given, images in the shader will be qualified with "restrict".
792 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 1 << 2, //!< Declare the format of the images in the shader code
795 LoadStoreTest (tcu::TestContext& testCtx,
796 const std::string& name,
797 const std::string& description,
798 const Texture& texture,
799 const VkFormat format,
800 const VkFormat imageFormat,
801 const deUint32 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
803 void initPrograms (SourceCollections& programCollection) const;
804 TestInstance* createInstance (Context& context) const;
807 const Texture m_texture;
808 const VkFormat m_format; //!< Format as accessed in the shader
809 const VkFormat m_imageFormat; //!< Storage format
810 const bool m_declareImageFormatInShader; //!< Whether the shader will specify the format layout qualifier of the images
811 const bool m_singleLayerBind;
812 const bool m_restrictImages;
815 LoadStoreTest::LoadStoreTest (tcu::TestContext& testCtx,
816 const std::string& name,
817 const std::string& description,
818 const Texture& texture,
819 const VkFormat format,
820 const VkFormat imageFormat,
821 const deUint32 flags)
822 : TestCase (testCtx, name, description)
823 , m_texture (texture)
825 , m_imageFormat (imageFormat)
826 , m_declareImageFormatInShader ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
827 , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
828 , m_restrictImages ((flags & FLAG_RESTRICT_IMAGES) != 0)
830 if (m_singleLayerBind)
831 DE_ASSERT(m_texture.numLayers() > 1);
833 DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
836 void LoadStoreTest::initPrograms (SourceCollections& programCollection) const
838 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
839 const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
840 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
841 const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
842 const std::string maybeRestrictStr = (m_restrictImages ? "restrict " : "");
843 const std::string xMax = de::toString(m_texture.size().x() - 1);
845 for (deUint32 variant = 0; variant <= 1; variant++)
847 std::ostringstream src;
848 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
852 src << "#extension GL_EXT_shader_image_load_formatted : require\n";
854 src << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
856 src << "layout (binding = 0, " << formatQualifierStr << ") " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
858 src << "layout (binding = 0) " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
859 src << "layout (binding = 1, " << formatQualifierStr << ") " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n"
861 << "void main (void)\n"
864 " int pos = int(gl_GlobalInvocationID.x);\n"
865 " imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n"
867 " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
868 " imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n"
870 " ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
871 " imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n"
875 programCollection.glslSources.add(variant == 0 ? "comp" : "comp_fmt_unknown") << glu::ComputeSource(src.str());
879 //! Load/store test base implementation
880 class LoadStoreTestInstance : public BaseTestInstance
883 LoadStoreTestInstance (Context& context,
884 const Texture& texture,
885 const VkFormat format,
886 const VkFormat imageFormat,
887 const bool declareImageFormatInShader,
888 const bool singleLayerBind);
891 virtual Buffer* getResultBuffer (void) const = 0; //!< Get the buffer that contains the result image
893 tcu::TestStatus verifyResult (void);
895 // Add empty implementations for functions that might be not needed
896 void commandBeforeCompute (const VkCommandBuffer) {}
897 void commandBetweenShaderInvocations (const VkCommandBuffer) {}
898 void commandAfterCompute (const VkCommandBuffer) {}
899 void checkRequirements (void);
901 de::MovePtr<Buffer> m_imageBuffer; //!< Source data and helper buffer
902 const VkDeviceSize m_imageSizeBytes;
903 const VkFormat m_imageFormat; //!< Image format (for storage, may be different than texture format)
904 tcu::TextureLevel m_referenceImage; //!< Used as input data and later to verify result image
907 LoadStoreTestInstance::LoadStoreTestInstance (Context& context,
908 const Texture& texture,
909 const VkFormat format,
910 const VkFormat imageFormat,
911 const bool declareImageFormatInShader,
912 const bool singleLayerBind)
913 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind)
914 , m_imageSizeBytes (getImageSizeBytes(texture.size(), format))
915 , m_imageFormat (imageFormat)
916 , m_referenceImage (generateReferenceImage(texture.size(), imageFormat, format))
918 const DeviceInterface& vk = m_context.getDeviceInterface();
919 const VkDevice device = m_context.getDevice();
920 Allocator& allocator = m_context.getDefaultAllocator();
922 // A helper buffer with enough space to hold the whole image.
924 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
925 vk, device, allocator,
926 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
927 MemoryRequirement::HostVisible));
929 // Copy reference data to buffer for subsequent upload to image.
931 const Allocation& alloc = m_imageBuffer->getAllocation();
932 deMemcpy(alloc.getHostPtr(), m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes));
933 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
936 tcu::TestStatus LoadStoreTestInstance::verifyResult (void)
938 const DeviceInterface& vk = m_context.getDeviceInterface();
939 const VkDevice device = m_context.getDevice();
941 // Apply the same transformation as done in the shader
942 const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
943 flipHorizontally(reference);
945 const Allocation& alloc = getResultBuffer()->getAllocation();
946 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
947 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), alloc.getHostPtr());
949 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
950 return tcu::TestStatus::pass("Passed");
952 return tcu::TestStatus::fail("Image comparison failed");
955 void LoadStoreTestInstance::checkRequirements (void)
957 const VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
959 if (!m_declareImageFormatInShader && !features.shaderStorageImageReadWithoutFormat)
960 throw tcu::NotSupportedError("shaderStorageImageReadWithoutFormat feature not supported");
964 //! Load/store test for images
965 class ImageLoadStoreTestInstance : public LoadStoreTestInstance
968 ImageLoadStoreTestInstance (Context& context,
969 const Texture& texture,
970 const VkFormat format,
971 const VkFormat imageFormat,
972 const bool declareImageFormatInShader,
973 const bool singleLayerBind);
976 VkDescriptorSetLayout prepareDescriptors (void);
977 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
978 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer);
979 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
981 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
982 const VkPipelineLayout pipelineLayout,
985 Buffer* getResultBuffer (void) const { return m_imageBuffer.get(); }
987 de::MovePtr<Image> m_imageSrc;
988 de::MovePtr<Image> m_imageDst;
989 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
990 Move<VkDescriptorPool> m_descriptorPool;
991 std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
992 std::vector<SharedVkImageView> m_allSrcImageViews;
993 std::vector<SharedVkImageView> m_allDstImageViews;
996 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context& context,
997 const Texture& texture,
998 const VkFormat format,
999 const VkFormat imageFormat,
1000 const bool declareImageFormatInShader,
1001 const bool singleLayerBind)
1002 : LoadStoreTestInstance (context, texture, format, imageFormat, declareImageFormatInShader, singleLayerBind)
1003 , m_allDescriptorSets (texture.numLayers())
1004 , m_allSrcImageViews (texture.numLayers())
1005 , m_allDstImageViews (texture.numLayers())
1007 const DeviceInterface& vk = m_context.getDeviceInterface();
1008 const VkDevice device = m_context.getDevice();
1009 Allocator& allocator = m_context.getDefaultAllocator();
1010 const VkImageCreateFlags imageFlags = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1012 m_imageSrc = de::MovePtr<Image>(new Image(
1013 vk, device, allocator,
1014 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, imageFlags),
1015 MemoryRequirement::Any));
1017 m_imageDst = de::MovePtr<Image>(new Image(
1018 vk, device, allocator,
1019 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, imageFlags),
1020 MemoryRequirement::Any));
1023 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void)
1025 const VkDevice device = m_context.getDevice();
1026 const DeviceInterface& vk = m_context.getDeviceInterface();
1028 const int numLayers = m_texture.numLayers();
1029 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1030 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1031 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1034 m_descriptorPool = DescriptorPoolBuilder()
1035 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1036 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1037 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1039 if (m_singleLayerBind)
1041 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1043 const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1044 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u);
1046 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1047 m_allSrcImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1048 m_allDstImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1051 else // bind all layers at once
1053 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1054 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
1056 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1057 m_allSrcImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1058 m_allDstImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1061 return *m_descriptorSetLayout; // not passing the ownership
1064 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1066 const VkDevice device = m_context.getDevice();
1067 const DeviceInterface& vk = m_context.getDeviceInterface();
1069 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1070 const VkImageView srcImageView = **m_allSrcImageViews[layerNdx];
1071 const VkImageView dstImageView = **m_allDstImageViews[layerNdx];
1073 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1074 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1076 DescriptorSetUpdateBuilder()
1077 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1078 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1079 .update(vk, device);
1080 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1083 void ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1085 const DeviceInterface& vk = m_context.getDeviceInterface();
1087 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1089 const VkImageMemoryBarrier preCopyImageBarriers[] =
1091 makeImageMemoryBarrier(
1092 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1093 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1094 m_imageSrc->get(), fullImageSubresourceRange),
1095 makeImageMemoryBarrier(
1096 0u, VK_ACCESS_SHADER_WRITE_BIT,
1097 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1098 m_imageDst->get(), fullImageSubresourceRange)
1101 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1102 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1103 m_imageBuffer->get(), 0ull, m_imageSizeBytes);
1105 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1106 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1109 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1110 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1111 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1112 m_imageSrc->get(), fullImageSubresourceRange);
1114 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
1116 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
1117 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierAfterCopy);
1121 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1123 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1126 void ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1128 commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1131 //! Load/store test for buffers
1132 class BufferLoadStoreTestInstance : public LoadStoreTestInstance
1135 BufferLoadStoreTestInstance (Context& context,
1136 const Texture& texture,
1137 const VkFormat format,
1138 const VkFormat imageFormat,
1139 const bool declareImageFormatInShader);
1142 VkDescriptorSetLayout prepareDescriptors (void);
1143 void commandAfterCompute (const VkCommandBuffer cmdBuffer);
1145 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer,
1146 const VkPipelineLayout pipelineLayout,
1147 const int layerNdx);
1149 Buffer* getResultBuffer (void) const { return m_imageBufferDst.get(); }
1151 de::MovePtr<Buffer> m_imageBufferDst;
1152 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1153 Move<VkDescriptorPool> m_descriptorPool;
1154 Move<VkDescriptorSet> m_descriptorSet;
1155 Move<VkBufferView> m_bufferViewSrc;
1156 Move<VkBufferView> m_bufferViewDst;
1159 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context& context,
1160 const Texture& texture,
1161 const VkFormat format,
1162 const VkFormat imageFormat,
1163 const bool declareImageFormatInShader)
1164 : LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, false)
1166 const DeviceInterface& vk = m_context.getDeviceInterface();
1167 const VkDevice device = m_context.getDevice();
1168 Allocator& allocator = m_context.getDefaultAllocator();
1170 // Create a destination buffer.
1172 m_imageBufferDst = de::MovePtr<Buffer>(new Buffer(
1173 vk, device, allocator,
1174 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
1175 MemoryRequirement::HostVisible));
1178 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void)
1180 const DeviceInterface& vk = m_context.getDeviceInterface();
1181 const VkDevice device = m_context.getDevice();
1183 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1184 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1185 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1188 m_descriptorPool = DescriptorPoolBuilder()
1189 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1190 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1191 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1193 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1194 m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes);
1195 m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), m_format, 0ull, m_imageSizeBytes);
1197 return *m_descriptorSetLayout; // not passing the ownership
1200 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1202 DE_ASSERT(layerNdx == 0);
1205 const VkDevice device = m_context.getDevice();
1206 const DeviceInterface& vk = m_context.getDeviceInterface();
1208 DescriptorSetUpdateBuilder()
1209 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewSrc.get())
1210 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
1211 .update(vk, device);
1212 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1215 void BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1217 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes);
1220 TestInstance* StoreTest::createInstance (Context& context) const
1222 if (m_texture.type() == IMAGE_TYPE_BUFFER)
1223 return new BufferStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader);
1225 return new ImageStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_singleLayerBind);
1228 TestInstance* LoadStoreTest::createInstance (Context& context) const
1230 if (m_texture.type() == IMAGE_TYPE_BUFFER)
1231 return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader);
1233 return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind);
1236 static const Texture s_textures[] =
1238 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1),
1239 Texture(IMAGE_TYPE_1D_ARRAY, tcu::IVec3(64, 1, 1), 8),
1240 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1),
1241 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(64, 64, 1), 8),
1242 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1),
1243 Texture(IMAGE_TYPE_CUBE, tcu::IVec3(64, 64, 1), 6),
1244 Texture(IMAGE_TYPE_CUBE_ARRAY, tcu::IVec3(64, 64, 1), 2*6),
1245 Texture(IMAGE_TYPE_BUFFER, tcu::IVec3(64, 1, 1), 1),
1248 const Texture& getTestTexture (const ImageType imageType)
1250 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1251 if (s_textures[textureNdx].type() == imageType)
1252 return s_textures[textureNdx];
1254 DE_FATAL("Internal error");
1255 return s_textures[0];
1258 static const VkFormat s_formats[] =
1260 VK_FORMAT_R32G32B32A32_SFLOAT,
1261 VK_FORMAT_R16G16B16A16_SFLOAT,
1262 VK_FORMAT_R32_SFLOAT,
1264 VK_FORMAT_R32G32B32A32_UINT,
1265 VK_FORMAT_R16G16B16A16_UINT,
1266 VK_FORMAT_R8G8B8A8_UINT,
1269 VK_FORMAT_R32G32B32A32_SINT,
1270 VK_FORMAT_R16G16B16A16_SINT,
1271 VK_FORMAT_R8G8B8A8_SINT,
1274 VK_FORMAT_R8G8B8A8_UNORM,
1276 VK_FORMAT_R8G8B8A8_SNORM,
1281 tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
1283 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store", "Plain imageStore() cases"));
1284 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for write images"));
1285 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for write images"));
1287 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1289 const Texture& texture = s_textures[textureNdx];
1290 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1291 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1292 const bool isLayered = (texture.numLayers() > 1);
1294 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1296 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
1297 groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], 0));
1300 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
1301 texture, s_formats[formatNdx],
1302 StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
1305 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
1306 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
1309 testGroup->addChild(testGroupWithFormat.release());
1310 testGroup->addChild(testGroupWithoutFormat.release());
1312 return testGroup.release();
1315 tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
1317 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()"));
1318 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
1319 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
1321 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1323 const Texture& texture = s_textures[textureNdx];
1324 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1325 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1326 const bool isLayered = (texture.numLayers() > 1);
1328 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1330 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx]));
1331 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0));
1334 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
1335 texture, s_formats[formatNdx], s_formats[formatNdx],
1336 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
1339 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
1340 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
1343 testGroup->addChild(testGroupWithFormat.release());
1344 testGroup->addChild(testGroupWithoutFormat.release());
1346 return testGroup.release();
1349 tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx)
1351 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret", "Cases with differing texture and image formats"));
1353 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1355 const Texture& texture = s_textures[textureNdx];
1356 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1358 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
1359 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1361 const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]);
1362 if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
1363 groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx]));
1365 testGroup->addChild(groupByImageViewType.release());
1368 return testGroup.release();
1371 de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name)
1373 const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
1374 const Texture& texture = getTestTexture(imageType);
1375 return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES));