1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 Imagination Technologies Ltd.
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 Robust buffer access tests for uniform/storage buffers and
23 * uniform/storage texel buffers.
24 *//*--------------------------------------------------------------------*/
26 #include "vktRobustnessBufferAccessTests.hpp"
27 #include "vktRobustnessUtil.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vkBuilderUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkPrograms.hpp"
32 #include "vkQueryUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "tcuTestLog.hpp"
50 SHADER_TYPE_MATRIX_COPY,
51 SHADER_TYPE_VECTOR_COPY,
52 SHADER_TYPE_SCALAR_COPY,
53 SHADER_TYPE_TEXEL_COPY,
60 BUFFER_ACCESS_TYPE_READ,
61 BUFFER_ACCESS_TYPE_READ_FROM_STORAGE,
62 BUFFER_ACCESS_TYPE_WRITE,
65 static VkDeviceSize min (VkDeviceSize a, VkDeviceSize b)
67 return (a < b) ? a : b;
70 class RobustBufferAccessTest : public vkt::TestCase
73 static const deUint32 s_testArraySize;
74 static const deUint32 s_numberOfBytesAccessed;
76 RobustBufferAccessTest (tcu::TestContext& testContext,
77 const std::string& name,
78 const std::string& description,
79 VkShaderStageFlags shaderStage,
80 ShaderType shaderType,
81 VkFormat bufferFormat);
83 virtual ~RobustBufferAccessTest (void) {}
86 static void genBufferShaderAccess (ShaderType shaderType,
87 VkFormat bufferFormat,
89 std::ostringstream& bufferDefinition,
90 std::ostringstream& bufferUse);
92 static void genTexelBufferShaderAccess (VkFormat bufferFormat,
93 std::ostringstream& bufferDefinition,
94 std::ostringstream& bufferUse,
95 bool readFromStorage);
98 static void initBufferAccessPrograms (SourceCollections& programCollection,
99 VkShaderStageFlags shaderStage,
100 ShaderType shaderType,
101 VkFormat bufferFormat,
102 bool readFromStorage);
104 const VkShaderStageFlags m_shaderStage;
105 const ShaderType m_shaderType;
106 const VkFormat m_bufferFormat;
109 class RobustBufferReadTest : public RobustBufferAccessTest
112 RobustBufferReadTest (tcu::TestContext& testContext,
113 const std::string& name,
114 const std::string& description,
115 VkShaderStageFlags shaderStage,
116 ShaderType shaderType,
117 VkFormat bufferFormat,
118 VkDeviceSize readAccessRange,
119 bool readFromStorage,
120 bool accessOutOfBackingMemory);
122 virtual ~RobustBufferReadTest (void) {}
124 virtual void initPrograms (SourceCollections& programCollection) const;
125 virtual TestInstance* createInstance (Context& context) const;
128 const bool m_readFromStorage;
129 const VkDeviceSize m_readAccessRange;
130 const bool m_accessOutOfBackingMemory;
133 class RobustBufferWriteTest : public RobustBufferAccessTest
136 RobustBufferWriteTest (tcu::TestContext& testContext,
137 const std::string& name,
138 const std::string& description,
139 VkShaderStageFlags shaderStage,
140 ShaderType shaderType,
141 VkFormat bufferFormat,
142 VkDeviceSize writeAccessRange,
143 bool accessOutOfBackingMemory);
145 virtual ~RobustBufferWriteTest (void) {}
147 virtual void initPrograms (SourceCollections& programCollection) const;
148 virtual TestInstance* createInstance (Context& context) const;
151 const VkDeviceSize m_writeAccessRange;
152 const bool m_accessOutOfBackingMemory;
155 class BufferAccessInstance : public vkt::TestInstance
158 BufferAccessInstance (Context& context,
159 Move<VkDevice> device,
160 ShaderType shaderType,
161 VkShaderStageFlags shaderStage,
162 VkFormat bufferFormat,
163 BufferAccessType bufferAccessType,
164 VkDeviceSize inBufferAccessRange,
165 VkDeviceSize outBufferAccessRange,
166 bool accessOutOfBackingMemory);
168 virtual ~BufferAccessInstance (void) {}
170 virtual tcu::TestStatus iterate (void);
172 virtual bool verifyResult (void);
175 bool isExpectedValueFromInBuffer (VkDeviceSize offsetInBytes, const void* valuePtr, VkDeviceSize valueSize);
176 bool isOutBufferValueUnchanged (VkDeviceSize offsetInBytes, VkDeviceSize valueSize);
179 Move<VkDevice> m_device;
180 de::MovePtr<TestEnvironment> m_testEnvironment;
182 const ShaderType m_shaderType;
183 const VkShaderStageFlags m_shaderStage;
185 const VkFormat m_bufferFormat;
186 const BufferAccessType m_bufferAccessType;
188 const VkDeviceSize m_inBufferAccessRange;
189 Move<VkBuffer> m_inBuffer;
190 de::MovePtr<Allocation> m_inBufferAlloc;
191 VkDeviceSize m_inBufferAllocSize;
192 VkDeviceSize m_inBufferMaxAccessRange;
194 const VkDeviceSize m_outBufferAccessRange;
195 Move<VkBuffer> m_outBuffer;
196 de::MovePtr<Allocation> m_outBufferAlloc;
197 VkDeviceSize m_outBufferAllocSize;
198 VkDeviceSize m_outBufferMaxAccessRange;
200 Move<VkBuffer> m_indicesBuffer;
201 de::MovePtr<Allocation> m_indicesBufferAlloc;
203 Move<VkDescriptorPool> m_descriptorPool;
204 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
205 Move<VkDescriptorSet> m_descriptorSet;
207 Move<VkFence> m_fence;
210 // Used when m_shaderStage == VK_SHADER_STAGE_VERTEX_BIT
211 Move<VkBuffer> m_vertexBuffer;
212 de::MovePtr<Allocation> m_vertexBufferAlloc;
214 // Used when m_shaderType == SHADER_TYPE_TEXEL_COPY
215 Move<VkBufferView> m_inTexelBufferView;
216 Move<VkBufferView> m_outTexelBufferView;
218 const bool m_accessOutOfBackingMemory;
221 class BufferReadInstance: public BufferAccessInstance
224 BufferReadInstance (Context& context,
225 Move<VkDevice> device,
226 ShaderType shaderType,
227 VkShaderStageFlags shaderStage,
228 VkFormat bufferFormat,
229 bool readFromStorage,
230 VkDeviceSize inBufferAccessRange,
231 bool accessOutOfBackingMemory);
233 virtual ~BufferReadInstance (void) {}
238 class BufferWriteInstance: public BufferAccessInstance
241 BufferWriteInstance (Context& context,
242 Move<VkDevice> device,
243 ShaderType shaderType,
244 VkShaderStageFlags shaderStage,
245 VkFormat bufferFormat,
246 VkDeviceSize writeBufferAccessRange,
247 bool accessOutOfBackingMemory);
249 virtual ~BufferWriteInstance (void) {}
252 // RobustBufferAccessTest
254 const deUint32 RobustBufferAccessTest::s_testArraySize = 1024;
255 const deUint32 RobustBufferAccessTest::s_numberOfBytesAccessed = (deUint32)(16 * sizeof(float)); // size of mat4
257 RobustBufferAccessTest::RobustBufferAccessTest (tcu::TestContext& testContext,
258 const std::string& name,
259 const std::string& description,
260 VkShaderStageFlags shaderStage,
261 ShaderType shaderType,
262 VkFormat bufferFormat)
263 : vkt::TestCase (testContext, name, description)
264 , m_shaderStage (shaderStage)
265 , m_shaderType (shaderType)
266 , m_bufferFormat (bufferFormat)
268 DE_ASSERT(m_shaderStage == VK_SHADER_STAGE_VERTEX_BIT || m_shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT || m_shaderStage == VK_SHADER_STAGE_COMPUTE_BIT);
271 void RobustBufferAccessTest::genBufferShaderAccess (ShaderType shaderType,
272 VkFormat bufferFormat,
273 bool readFromStorage,
274 std::ostringstream& bufferDefinition,
275 std::ostringstream& bufferUse)
277 if (isFloatFormat(bufferFormat))
280 "layout(binding = 0, " << (readFromStorage ? "std430" : "std140") << ") " << (readFromStorage ? "buffer" : "uniform") << " InBuffer\n"
282 " mat4 inMatrix[" << s_testArraySize << "];\n"
286 "layout(binding = 1, std430) buffer OutBuffer\n"
288 " mat4 outMatrix[" << s_testArraySize << "];\n"
292 "layout(binding = 2, std140) uniform Indices\n"
300 case SHADER_TYPE_MATRIX_COPY:
302 " mat4 tmp = inMatrix[inIndex];\n"
303 " outMatrix[outIndex] = tmp;\n";
306 case SHADER_TYPE_VECTOR_COPY:
308 " outMatrix[outIndex][0] = inMatrix[inIndex][0];\n"
309 " outMatrix[outIndex][1] = inMatrix[inIndex][1];\n"
310 " outMatrix[outIndex][2] = inMatrix[inIndex][2];\n"
311 " outMatrix[outIndex][3] = inMatrix[inIndex][3];\n";
314 case SHADER_TYPE_SCALAR_COPY:
316 " outMatrix[outIndex][0][0] = inMatrix[inIndex][0][0];\n"
317 " outMatrix[outIndex][0][1] = inMatrix[inIndex][0][1];\n"
318 " outMatrix[outIndex][0][2] = inMatrix[inIndex][0][2];\n"
319 " outMatrix[outIndex][0][3] = inMatrix[inIndex][0][3];\n"
321 " outMatrix[outIndex][1][0] = inMatrix[inIndex][1][0];\n"
322 " outMatrix[outIndex][1][1] = inMatrix[inIndex][1][1];\n"
323 " outMatrix[outIndex][1][2] = inMatrix[inIndex][1][2];\n"
324 " outMatrix[outIndex][1][3] = inMatrix[inIndex][1][3];\n"
326 " outMatrix[outIndex][2][0] = inMatrix[inIndex][2][0];\n"
327 " outMatrix[outIndex][2][1] = inMatrix[inIndex][2][1];\n"
328 " outMatrix[outIndex][2][2] = inMatrix[inIndex][2][2];\n"
329 " outMatrix[outIndex][2][3] = inMatrix[inIndex][2][3];\n"
331 " outMatrix[outIndex][3][0] = inMatrix[inIndex][3][0];\n"
332 " outMatrix[outIndex][3][1] = inMatrix[inIndex][3][1];\n"
333 " outMatrix[outIndex][3][2] = inMatrix[inIndex][3][2];\n"
334 " outMatrix[outIndex][3][3] = inMatrix[inIndex][3][3];\n";
343 std::string typePrefixStr;
345 if (isUintFormat(bufferFormat))
349 else if (isIntFormat(bufferFormat))
359 "layout(binding = 0, " << (readFromStorage ? "std430" : "std140") << ") " << (readFromStorage ? "buffer readonly" : "uniform") << " InBuffer\n"
361 " " << typePrefixStr << "vec4 inVecs[" << s_testArraySize << "][4];\n"
365 "layout(binding = 1, std430) buffer OutBuffer\n"
367 " " << typePrefixStr << "vec4 outVecs[" << s_testArraySize << "][4];\n"
371 "layout(binding = 2, std140) uniform Indices\n"
379 case SHADER_TYPE_MATRIX_COPY:
380 // Shader type not supported for integer types.
384 case SHADER_TYPE_VECTOR_COPY:
386 " outVecs[outIndex][0] = inVecs[inIndex][0];\n"
387 " outVecs[outIndex][1] = inVecs[inIndex][1];\n"
388 " outVecs[outIndex][2] = inVecs[inIndex][2];\n"
389 " outVecs[outIndex][3] = inVecs[inIndex][3];\n";
392 case SHADER_TYPE_SCALAR_COPY:
394 " outVecs[outIndex][0][0] = inVecs[inIndex][0][0];\n"
395 " outVecs[outIndex][0][1] = inVecs[inIndex][0][1];\n"
396 " outVecs[outIndex][0][2] = inVecs[inIndex][0][2];\n"
397 " outVecs[outIndex][0][3] = inVecs[inIndex][0][3];\n"
399 " outVecs[outIndex][1][0] = inVecs[inIndex][1][0];\n"
400 " outVecs[outIndex][1][1] = inVecs[inIndex][1][1];\n"
401 " outVecs[outIndex][1][2] = inVecs[inIndex][1][2];\n"
402 " outVecs[outIndex][1][3] = inVecs[inIndex][1][3];\n"
404 " outVecs[outIndex][2][0] = inVecs[inIndex][2][0];\n"
405 " outVecs[outIndex][2][1] = inVecs[inIndex][2][1];\n"
406 " outVecs[outIndex][2][2] = inVecs[inIndex][2][2];\n"
407 " outVecs[outIndex][2][3] = inVecs[inIndex][2][3];\n"
409 " outVecs[outIndex][3][0] = inVecs[inIndex][3][0];\n"
410 " outVecs[outIndex][3][1] = inVecs[inIndex][3][1];\n"
411 " outVecs[outIndex][3][2] = inVecs[inIndex][3][2];\n"
412 " outVecs[outIndex][3][3] = inVecs[inIndex][3][3];\n";
421 void RobustBufferAccessTest::genTexelBufferShaderAccess (VkFormat bufferFormat,
422 std::ostringstream& bufferDefinition,
423 std::ostringstream& bufferUse,
424 bool readFromStorage)
426 const char* layoutTypeStr;
427 const char* inTexelBufferTypeStr;
428 const char* outTexelBufferTypeStr;
429 const deUint32 texelSize = mapVkFormat(bufferFormat).getPixelSize();
431 if (isFloatFormat(bufferFormat))
433 layoutTypeStr = "rgba32f";
434 inTexelBufferTypeStr = readFromStorage ? "imageBuffer" : "samplerBuffer";
435 outTexelBufferTypeStr = "imageBuffer";
437 else if (isUintFormat(bufferFormat))
439 layoutTypeStr = "rgba32ui";
440 inTexelBufferTypeStr = readFromStorage ? "uimageBuffer" : "usamplerBuffer";
441 outTexelBufferTypeStr = "uimageBuffer";
443 else if (isIntFormat(bufferFormat))
445 layoutTypeStr = "rgba32i";
446 inTexelBufferTypeStr = readFromStorage ? "iimageBuffer" : "isamplerBuffer";
447 outTexelBufferTypeStr = "iimageBuffer";
449 else if (bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
451 layoutTypeStr = "rgb10_a2";
452 inTexelBufferTypeStr = readFromStorage ? "imageBuffer" : "samplerBuffer"; outTexelBufferTypeStr = "imageBuffer";
456 TCU_THROW(NotSupportedError, (std::string("Unsupported format: ") + getFormatName(bufferFormat)).c_str());
459 bufferDefinition << "layout(set = 0, binding = 0" << ((readFromStorage) ? (std::string(", ") + layoutTypeStr) : "") << ") uniform highp "
460 << ((readFromStorage) ? "readonly " : "") << inTexelBufferTypeStr << " inImage;\n";
462 bufferDefinition << "layout(set = 0, binding = 1, " << layoutTypeStr << ") uniform highp writeonly " << outTexelBufferTypeStr << " outImage;\n";
465 "layout(binding = 2, std140) uniform Offsets\n"
471 bufferUse << " for (int i = 0; i < " << (s_numberOfBytesAccessed / texelSize) << "; i++)\n"
473 << " imageStore(outImage, outOffset + i, " << (readFromStorage ? "imageLoad" : "texelFetch") << "(inImage, inOffset + i));\n"
477 void RobustBufferAccessTest::initBufferAccessPrograms (SourceCollections& programCollection,
478 VkShaderStageFlags shaderStage,
479 ShaderType shaderType,
480 VkFormat bufferFormat,
481 bool readFromStorage)
483 std::ostringstream bufferDefinition;
484 std::ostringstream bufferUse;
486 if (shaderType != SHADER_TYPE_TEXEL_COPY)
488 genBufferShaderAccess(shaderType, bufferFormat, readFromStorage, bufferDefinition, bufferUse);
491 if (shaderStage == VK_SHADER_STAGE_COMPUTE_BIT)
493 std::ostringstream computeShaderSource;
495 if (shaderType == SHADER_TYPE_TEXEL_COPY)
496 genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
498 computeShaderSource <<
500 "#extension GL_EXT_texture_buffer : require\n"
501 "precision highp float;\n"
502 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
503 << bufferDefinition.str() <<
506 << bufferUse.str() <<
509 programCollection.glslSources.add("compute") << glu::ComputeSource(computeShaderSource.str());
513 std::ostringstream vertexShaderSource;
514 std::ostringstream fragmentShaderSource;
516 if (shaderStage == VK_SHADER_STAGE_VERTEX_BIT)
518 if (shaderType == SHADER_TYPE_TEXEL_COPY)
519 genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
521 vertexShaderSource <<
523 "#extension GL_EXT_texture_buffer : require\n"
524 "precision highp float;\n"
525 "layout(location = 0) in vec4 position;\n\n"
526 << bufferDefinition.str() << "\n"
527 "out gl_PerVertex {\n"
528 " vec4 gl_Position;\n"
532 << bufferUse.str() <<
533 " gl_Position = position;\n"
538 vertexShaderSource <<
540 "precision highp float;\n"
541 "layout(location = 0) in vec4 position;\n\n"
542 "out gl_PerVertex {\n"
543 " vec4 gl_Position;\n"
547 " gl_Position = position;\n"
551 programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str());
553 if (shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT)
555 if (shaderType == SHADER_TYPE_TEXEL_COPY)
556 genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
558 fragmentShaderSource <<
560 "#extension GL_EXT_texture_buffer : require\n"
561 "precision highp float;\n"
562 "layout(location = 0) out vec4 fragColor;\n"
563 << bufferDefinition.str() <<
566 << bufferUse.str() <<
567 " fragColor = vec4(1.0);\n"
572 fragmentShaderSource <<
574 "precision highp float;\n"
575 "layout(location = 0) out vec4 fragColor;\n\n"
578 " fragColor = vec4(1.0);\n"
582 programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str());
586 // RobustBufferReadTest
588 RobustBufferReadTest::RobustBufferReadTest (tcu::TestContext& testContext,
589 const std::string& name,
590 const std::string& description,
591 VkShaderStageFlags shaderStage,
592 ShaderType shaderType,
593 VkFormat bufferFormat,
594 VkDeviceSize readAccessRange,
595 bool readFromStorage,
596 bool accessOutOfBackingMemory)
597 : RobustBufferAccessTest (testContext, name, description, shaderStage, shaderType, bufferFormat)
598 , m_readFromStorage (readFromStorage)
599 , m_readAccessRange (readAccessRange)
600 , m_accessOutOfBackingMemory (accessOutOfBackingMemory)
604 void RobustBufferReadTest::initPrograms (SourceCollections& programCollection) const
606 initBufferAccessPrograms(programCollection, m_shaderStage, m_shaderType, m_bufferFormat, m_readFromStorage);
609 TestInstance* RobustBufferReadTest::createInstance (Context& context) const
611 Move<VkDevice> device = createRobustBufferAccessDevice(context);
613 return new BufferReadInstance(context, device, m_shaderType, m_shaderStage, m_bufferFormat, m_readFromStorage, m_readAccessRange, m_accessOutOfBackingMemory);
616 // RobustBufferWriteTest
618 RobustBufferWriteTest::RobustBufferWriteTest (tcu::TestContext& testContext,
619 const std::string& name,
620 const std::string& description,
621 VkShaderStageFlags shaderStage,
622 ShaderType shaderType,
623 VkFormat bufferFormat,
624 VkDeviceSize writeAccessRange,
625 bool accessOutOfBackingMemory)
627 : RobustBufferAccessTest (testContext, name, description, shaderStage, shaderType, bufferFormat)
628 , m_writeAccessRange (writeAccessRange)
629 , m_accessOutOfBackingMemory (accessOutOfBackingMemory)
633 void RobustBufferWriteTest::initPrograms (SourceCollections& programCollection) const
635 initBufferAccessPrograms(programCollection, m_shaderStage, m_shaderType, m_bufferFormat, false /* readFromStorage */);
638 TestInstance* RobustBufferWriteTest::createInstance (Context& context) const
640 Move<VkDevice> device = createRobustBufferAccessDevice(context);
642 return new BufferWriteInstance(context, device, m_shaderType, m_shaderStage, m_bufferFormat, m_writeAccessRange, m_accessOutOfBackingMemory);
645 // BufferAccessInstance
647 BufferAccessInstance::BufferAccessInstance (Context& context,
648 Move<VkDevice> device,
649 ShaderType shaderType,
650 VkShaderStageFlags shaderStage,
651 VkFormat bufferFormat,
652 BufferAccessType bufferAccessType,
653 VkDeviceSize inBufferAccessRange,
654 VkDeviceSize outBufferAccessRange,
655 bool accessOutOfBackingMemory)
656 : vkt::TestInstance (context)
658 , m_shaderType (shaderType)
659 , m_shaderStage (shaderStage)
660 , m_bufferFormat (bufferFormat)
661 , m_bufferAccessType (bufferAccessType)
662 , m_inBufferAccessRange (inBufferAccessRange)
663 , m_outBufferAccessRange (outBufferAccessRange)
664 , m_accessOutOfBackingMemory (accessOutOfBackingMemory)
666 const DeviceInterface& vk = context.getDeviceInterface();
667 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
668 const bool isTexelAccess = !!(m_shaderType == SHADER_TYPE_TEXEL_COPY);
669 const bool readFromStorage = !!(m_bufferAccessType == BUFFER_ACCESS_TYPE_READ_FROM_STORAGE);
670 SimpleAllocator memAlloc (vk, *m_device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
671 tcu::TestLog& log = m_context.getTestContext().getLog();
673 DE_ASSERT(RobustBufferAccessTest::s_numberOfBytesAccessed % sizeof(deUint32) == 0);
674 DE_ASSERT(inBufferAccessRange <= RobustBufferAccessTest::s_numberOfBytesAccessed);
675 DE_ASSERT(outBufferAccessRange <= RobustBufferAccessTest::s_numberOfBytesAccessed);
677 // Check storage support
678 if (shaderStage == VK_SHADER_STAGE_VERTEX_BIT)
680 if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics)
682 TCU_THROW(NotSupportedError, "Stores not supported in vertex stage");
685 else if (shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT)
687 if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
689 TCU_THROW(NotSupportedError, "Stores not supported in fragment stage");
693 // Check format support
695 VkFormatFeatureFlags requiredFormatFeatures = 0;
696 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_bufferFormat);
700 requiredFormatFeatures = VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
703 if ((formatProperties.bufferFeatures & requiredFormatFeatures) != requiredFormatFeatures)
705 TCU_THROW(NotSupportedError, (std::string("Format cannot be used in uniform and storage") + (isTexelAccess ? " texel" : "") + " buffers: "
706 + getFormatName(m_bufferFormat)).c_str());
710 // Create buffer to read data from
712 VkBufferUsageFlags inBufferUsageFlags;
713 VkMemoryRequirements inBufferMemoryReqs;
717 inBufferUsageFlags = readFromStorage ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
721 inBufferUsageFlags = readFromStorage ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
724 const VkBufferCreateInfo inBufferParams =
726 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
727 DE_NULL, // const void* pNext;
728 0u, // VkBufferCreateFlags flags;
729 m_inBufferAccessRange, // VkDeviceSize size;
730 inBufferUsageFlags, // VkBufferUsageFlags usage;
731 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
732 VK_QUEUE_FAMILY_IGNORED, // deUint32 queueFamilyIndexCount;
733 DE_NULL // const deUint32* pQueueFamilyIndices;
736 m_inBuffer = createBuffer(vk, *m_device, &inBufferParams);
738 inBufferMemoryReqs = getBufferMemoryRequirements(vk, *m_device, *m_inBuffer);
739 m_inBufferAllocSize = inBufferMemoryReqs.size;
740 m_inBufferAlloc = memAlloc.allocate(inBufferMemoryReqs, MemoryRequirement::HostVisible);
742 // Size of the most restrictive bound
743 m_inBufferMaxAccessRange = min(m_inBufferAllocSize, min(inBufferParams.size, m_inBufferAccessRange));
745 VK_CHECK(vk.bindBufferMemory(*m_device, *m_inBuffer, m_inBufferAlloc->getMemory(), m_inBufferAlloc->getOffset()));
746 populateBufferWithTestValues(m_inBufferAlloc->getHostPtr(), m_inBufferAllocSize, m_bufferFormat);
747 flushMappedMemoryRange(vk, *m_device, m_inBufferAlloc->getMemory(), m_inBufferAlloc->getOffset(), VK_WHOLE_SIZE);
749 log << tcu::TestLog::Message << "inBufferAllocSize = " << m_inBufferAllocSize << tcu::TestLog::EndMessage;
750 log << tcu::TestLog::Message << "inBufferMaxAccessRange = " << m_inBufferMaxAccessRange << tcu::TestLog::EndMessage;
753 // Create buffer to write data into
755 VkMemoryRequirements outBufferMemoryReqs;
756 const VkBufferUsageFlags outBufferUsageFlags = (m_shaderType == SHADER_TYPE_TEXEL_COPY) ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
757 : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
759 const VkBufferCreateInfo outBufferParams =
761 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
762 DE_NULL, // const void* pNext;
763 0u, // VkBufferCreateFlags flags;
764 m_outBufferAccessRange, // VkDeviceSize size;
765 outBufferUsageFlags, // VkBufferUsageFlags usage;
766 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
767 VK_QUEUE_FAMILY_IGNORED, // deUint32 queueFamilyIndexCount;
768 DE_NULL // const deUint32* pQueueFamilyIndices;
771 m_outBuffer = createBuffer(vk, *m_device, &outBufferParams);
773 outBufferMemoryReqs = getBufferMemoryRequirements(vk, *m_device, *m_outBuffer);
774 m_outBufferAllocSize = outBufferMemoryReqs.size;
775 m_outBufferAlloc = memAlloc.allocate(outBufferMemoryReqs, MemoryRequirement::HostVisible);
777 // If we are requesting access out of the memory that backs the buffer, make sure the test is able to do so.
778 if (m_accessOutOfBackingMemory)
780 if (m_outBufferAllocSize >= ((RobustBufferAccessTest::s_testArraySize + 1) * RobustBufferAccessTest::s_numberOfBytesAccessed))
782 TCU_THROW(NotSupportedError, "Cannot access beyond the end of the memory that backs the buffer");
786 // Size of the most restrictive bound
787 m_outBufferMaxAccessRange = min(m_outBufferAllocSize, min(outBufferParams.size, m_outBufferAccessRange));
789 VK_CHECK(vk.bindBufferMemory(*m_device, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
790 deMemset(m_outBufferAlloc->getHostPtr(), 0xFF, (size_t)m_outBufferAllocSize);
791 flushMappedMemoryRange(vk, *m_device, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset(), VK_WHOLE_SIZE);
793 log << tcu::TestLog::Message << "outBufferAllocSize = " << m_outBufferAllocSize << tcu::TestLog::EndMessage;
794 log << tcu::TestLog::Message << "outBufferMaxAccessRange = " << m_outBufferMaxAccessRange << tcu::TestLog::EndMessage;
797 // Create buffer for indices/offsets
805 IndicesBuffer indices = { 0, 0 };
807 const VkBufferCreateInfo indicesBufferParams =
809 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
810 DE_NULL, // const void* pNext;
811 0u, // VkBufferCreateFlags flags;
812 sizeof(IndicesBuffer), // VkDeviceSize size;
813 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, // VkBufferUsageFlags usage;
814 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
815 VK_QUEUE_FAMILY_IGNORED, // deUint32 queueFamilyIndexCount;
816 DE_NULL, // const deUint32* pQueueFamilyIndices;
819 m_indicesBuffer = createBuffer(vk, *m_device, &indicesBufferParams);
820 m_indicesBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indicesBuffer), MemoryRequirement::HostVisible);
822 VK_CHECK(vk.bindBufferMemory(*m_device, *m_indicesBuffer, m_indicesBufferAlloc->getMemory(), m_indicesBufferAlloc->getOffset()));
824 if (m_accessOutOfBackingMemory)
826 if (m_bufferAccessType == BUFFER_ACCESS_TYPE_WRITE)
828 indices.outIndex = RobustBufferAccessTest::s_testArraySize - 1;
832 indices.inIndex = RobustBufferAccessTest::s_testArraySize - 1;
836 deMemcpy(m_indicesBufferAlloc->getHostPtr(), &indices, sizeof(IndicesBuffer));
838 flushMappedMemoryRange(vk, *m_device, m_indicesBufferAlloc->getMemory(), m_indicesBufferAlloc->getOffset(), VK_WHOLE_SIZE);
840 log << tcu::TestLog::Message << "inIndex = " << indices.inIndex << tcu::TestLog::EndMessage;
841 log << tcu::TestLog::Message << "outIndex = " << indices.outIndex << tcu::TestLog::EndMessage;
844 // Create descriptor data
846 VkDescriptorType inBufferDescriptorType;
847 VkDescriptorType outBufferDescriptorType;
851 inBufferDescriptorType = readFromStorage ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
852 outBufferDescriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
856 inBufferDescriptorType = readFromStorage ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
857 outBufferDescriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
860 DescriptorPoolBuilder descriptorPoolBuilder;
861 descriptorPoolBuilder.addType(inBufferDescriptorType, 1u);
862 descriptorPoolBuilder.addType(outBufferDescriptorType, 1u);
863 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u);
864 m_descriptorPool = descriptorPoolBuilder.build(vk, *m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
866 DescriptorSetLayoutBuilder setLayoutBuilder;
867 setLayoutBuilder.addSingleBinding(inBufferDescriptorType, VK_SHADER_STAGE_ALL);
868 setLayoutBuilder.addSingleBinding(outBufferDescriptorType, VK_SHADER_STAGE_ALL);
869 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
870 m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device);
872 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
874 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
875 DE_NULL, // const void* pNext;
876 *m_descriptorPool, // VkDescriptorPool descriptorPool;
877 1u, // deUint32 setLayoutCount;
878 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts;
881 m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo);
883 DescriptorSetUpdateBuilder setUpdateBuilder;
887 const VkBufferViewCreateInfo inBufferViewCreateInfo =
889 VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
890 DE_NULL, // const void* pNext;
891 0u, // VkBufferViewCreateFlags flags;
892 *m_inBuffer, // VkBuffer buffer;
893 m_bufferFormat, // VkFormat format;
894 0ull, // VkDeviceSize offset;
895 m_inBufferAccessRange // VkDeviceSize range;
897 m_inTexelBufferView = createBufferView(vk, *m_device, &inBufferViewCreateInfo, DE_NULL);
899 const VkBufferViewCreateInfo outBufferViewCreateInfo =
901 VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
902 DE_NULL, // const void* pNext;
903 0u, // VkBufferViewCreateFlags flags;
904 *m_outBuffer, // VkBuffer buffer;
905 m_bufferFormat, // VkFormat format;
906 0ull, // VkDeviceSize offset;
907 m_outBufferAccessRange, // VkDeviceSize range;
909 m_outTexelBufferView = createBufferView(vk, *m_device, &outBufferViewCreateInfo, DE_NULL);
911 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), inBufferDescriptorType, &m_inTexelBufferView.get());
912 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1), outBufferDescriptorType, &m_outTexelBufferView.get());
916 const VkDescriptorBufferInfo inBufferDescriptorInfo = makeDescriptorBufferInfo(*m_inBuffer, 0ull, m_inBufferAccessRange);
917 const VkDescriptorBufferInfo outBufferDescriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, 0ull, m_outBufferAccessRange);
919 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), inBufferDescriptorType, &inBufferDescriptorInfo);
920 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1), outBufferDescriptorType, &outBufferDescriptorInfo);
923 const VkDescriptorBufferInfo indicesBufferDescriptorInfo = makeDescriptorBufferInfo(*m_indicesBuffer, 0ull, 8ull);
924 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &indicesBufferDescriptorInfo);
926 setUpdateBuilder.update(vk, *m_device);
931 const VkFenceCreateInfo fenceParams =
933 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
934 DE_NULL, // const void* pNext;
935 0u // VkFenceCreateFlags flags;
938 m_fence = createFence(vk, *m_device, &fenceParams);
942 vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue);
944 if (m_shaderStage == VK_SHADER_STAGE_COMPUTE_BIT)
946 m_testEnvironment = de::MovePtr<TestEnvironment>(new ComputeEnvironment(m_context, *m_device, *m_descriptorSetLayout, *m_descriptorSet));
952 const VkVertexInputBindingDescription vertexInputBindingDescription =
954 0u, // deUint32 binding;
955 sizeof(tcu::Vec4), // deUint32 strideInBytes;
956 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
959 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
961 0u, // deUint32 location;
962 0u, // deUint32 binding;
963 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
964 0u // deUint32 offset;
967 const Vec4 vertices[] =
969 Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
970 Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
971 Vec4(1.0f, -1.0f, 0.0f, 1.0f),
974 // Create vertex buffer
976 const VkDeviceSize vertexBufferSize = (VkDeviceSize)(4u * sizeof(tcu::Vec4));
977 const VkBufferCreateInfo vertexBufferParams =
979 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
980 DE_NULL, // const void* pNext;
981 0u, // VkBufferCreateFlags flags;
982 vertexBufferSize, // VkDeviceSize size;
983 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
984 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
985 VK_QUEUE_FAMILY_IGNORED, // deUint32 queueFamilyIndexCount;
986 DE_NULL // const deUint32* pQueueFamilyIndices;
989 DE_ASSERT(vertexBufferSize > 0);
991 m_vertexBuffer = createBuffer(vk, *m_device, &vertexBufferParams);
992 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexBuffer), MemoryRequirement::HostVisible);
994 VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
996 // Load vertices into vertex buffer
997 deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices, sizeof(tcu::Vec4) * DE_LENGTH_OF_ARRAY(vertices));
998 flushMappedMemoryRange(vk, *m_device, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1001 const GraphicsEnvironment::DrawConfig drawWithOneVertexBuffer =
1003 std::vector<VkBuffer>(1, *m_vertexBuffer), // std::vector<VkBuffer> vertexBuffers;
1004 DE_LENGTH_OF_ARRAY(vertices), // deUint32 vertexCount;
1005 1, // deUint32 instanceCount;
1006 DE_NULL, // VkBuffer indexBuffer;
1007 0u, // deUint32 indexCount;
1010 m_testEnvironment = de::MovePtr<TestEnvironment>(new GraphicsEnvironment(m_context,
1012 *m_descriptorSetLayout,
1014 GraphicsEnvironment::VertexBindings(1, vertexInputBindingDescription),
1015 GraphicsEnvironment::VertexAttributes(1, vertexInputAttributeDescription),
1016 drawWithOneVertexBuffer));
1020 // Verifies if the buffer has the value initialized by BufferAccessInstance::populateReadBuffer at a given offset.
1021 bool BufferAccessInstance::isExpectedValueFromInBuffer (VkDeviceSize offsetInBytes, const void* valuePtr, VkDeviceSize valueSize)
1023 DE_ASSERT(offsetInBytes % 4 == 0);
1024 DE_ASSERT(offsetInBytes < m_inBufferAllocSize);
1026 const deUint32 valueIndex = deUint32(offsetInBytes / 4) + 2;
1028 if (isUintFormat(m_bufferFormat))
1030 return !deMemCmp(valuePtr, &valueIndex, (size_t)valueSize);
1032 else if (isIntFormat(m_bufferFormat))
1034 const deInt32 value = -deInt32(valueIndex);
1035 return !deMemCmp(valuePtr, &value, (size_t)valueSize);
1037 else if (isFloatFormat(m_bufferFormat))
1039 const float value = float(valueIndex);
1040 return !deMemCmp(valuePtr, &value, (size_t)valueSize);
1042 else if (m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1044 const deUint32 r = ((valueIndex + 0) & ((2u << 10) - 1u));
1045 const deUint32 g = ((valueIndex + 1) & ((2u << 10) - 1u));
1046 const deUint32 b = ((valueIndex + 2) & ((2u << 10) - 1u));
1047 const deUint32 a = ((valueIndex + 0) & ((2u << 2) - 1u));
1048 const deUint32 abgr = (a << 30) | (b << 20) | (g << 10) | r;
1050 return !deMemCmp(valuePtr, &abgr, (size_t)valueSize);
1059 bool BufferAccessInstance::isOutBufferValueUnchanged (VkDeviceSize offsetInBytes, VkDeviceSize valueSize)
1061 const deUint8 *const outValuePtr = (deUint8*)m_outBufferAlloc->getHostPtr() + offsetInBytes;
1062 const deUint32 defaultValue = 0xFFFFFFFFu;
1064 return !deMemCmp(outValuePtr, &defaultValue, (size_t)valueSize);
1067 tcu::TestStatus BufferAccessInstance::iterate (void)
1069 const DeviceInterface& vk = m_context.getDeviceInterface();
1070 const vk::VkCommandBuffer cmdBuffer = m_testEnvironment->getCommandBuffer();
1072 // Submit command buffer
1074 const VkSubmitInfo submitInfo =
1076 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
1077 DE_NULL, // const void* pNext;
1078 0u, // deUint32 waitSemaphoreCount;
1079 DE_NULL, // const VkSemaphore* pWaitSemaphores;
1080 DE_NULL, // const VkPIpelineStageFlags* pWaitDstStageMask;
1081 1u, // deUint32 commandBufferCount;
1082 &cmdBuffer, // const VkCommandBuffer* pCommandBuffers;
1083 0u, // deUint32 signalSemaphoreCount;
1084 DE_NULL // const VkSemaphore* pSignalSemaphores;
1087 VK_CHECK(vk.resetFences(*m_device, 1, &m_fence.get()));
1088 VK_CHECK(vk.queueSubmit(m_queue, 1, &submitInfo, *m_fence));
1089 VK_CHECK(vk.waitForFences(*m_device, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
1092 // Prepare result buffer for read
1094 const VkMappedMemoryRange outBufferRange =
1096 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
1097 DE_NULL, // const void* pNext;
1098 m_outBufferAlloc->getMemory(), // VkDeviceMemory mem;
1099 0ull, // VkDeviceSize offset;
1100 m_outBufferAllocSize, // VkDeviceSize size;
1103 VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
1107 return tcu::TestStatus::pass("All values OK");
1109 return tcu::TestStatus::fail("Invalid value(s) found");
1112 bool BufferAccessInstance::verifyResult (void)
1114 std::ostringstream logMsg;
1115 tcu::TestLog& log = m_context.getTestContext().getLog();
1116 const bool isReadAccess = !!(m_bufferAccessType == BUFFER_ACCESS_TYPE_READ || m_bufferAccessType == BUFFER_ACCESS_TYPE_READ_FROM_STORAGE);
1117 const void* inDataPtr = m_inBufferAlloc->getHostPtr();
1118 const void* outDataPtr = m_outBufferAlloc->getHostPtr();
1120 deUint32 valueNdx = 0;
1121 const VkDeviceSize maxAccessRange = isReadAccess ? m_inBufferMaxAccessRange : m_outBufferMaxAccessRange;
1123 for (VkDeviceSize offsetInBytes = 0; offsetInBytes < m_outBufferAllocSize; offsetInBytes += 4)
1125 deUint8* outValuePtr = (deUint8*)outDataPtr + offsetInBytes;
1126 const size_t outValueSize = (size_t)min(4, (m_outBufferAllocSize - offsetInBytes));
1128 if (offsetInBytes >= RobustBufferAccessTest::s_numberOfBytesAccessed)
1130 // The shader will only write 16 values into the result buffer. The rest of the values
1131 // should remain unchanged or may be modified if we are writing out of bounds.
1132 if (!isOutBufferValueUnchanged(offsetInBytes, outValueSize)
1133 && (isReadAccess || !isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, 4)))
1135 logMsg << "\nValue " << valueNdx++ << " has been modified with an unknown value: " << *((deUint32 *)outValuePtr);
1141 const deInt32 distanceToOutOfBounds = (deInt32)maxAccessRange - (deInt32)offsetInBytes;
1142 bool isOutOfBoundsAccess = false;
1144 logMsg << "\n" << valueNdx++ << ": ";
1146 logValue(logMsg, outValuePtr, m_bufferFormat, outValueSize);
1148 if (m_accessOutOfBackingMemory)
1149 isOutOfBoundsAccess = true;
1151 // Check if the shader operation accessed an operand located less than 16 bytes away
1152 // from the out of bounds address.
1153 if (!isOutOfBoundsAccess && distanceToOutOfBounds < 16)
1155 deUint32 operandSize = 0;
1157 switch (m_shaderType)
1159 case SHADER_TYPE_SCALAR_COPY:
1160 operandSize = 4; // Size of scalar
1163 case SHADER_TYPE_VECTOR_COPY:
1164 operandSize = 4 * 4; // Size of vec4
1167 case SHADER_TYPE_MATRIX_COPY:
1168 operandSize = 4 * 16; // Size of mat4
1171 case SHADER_TYPE_TEXEL_COPY:
1172 operandSize = mapVkFormat(m_bufferFormat).getPixelSize();
1179 isOutOfBoundsAccess = (((offsetInBytes / operandSize) + 1) * operandSize > maxAccessRange);
1182 if (isOutOfBoundsAccess)
1184 logMsg << " (out of bounds " << (isReadAccess ? "read": "write") << ")";
1186 const bool isValuePartiallyOutOfBounds = ((distanceToOutOfBounds > 0) && ((deUint32)distanceToOutOfBounds < 4));
1187 bool isValidValue = false;
1189 if (isValuePartiallyOutOfBounds && !m_accessOutOfBackingMemory)
1191 // The value is partially out of bounds
1193 bool isOutOfBoundsPartOk = true;
1194 bool isWithinBoundsPartOk = true;
1198 isWithinBoundsPartOk = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, distanceToOutOfBounds);
1199 isOutOfBoundsPartOk = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, (deUint8*)outValuePtr + distanceToOutOfBounds , outValueSize - distanceToOutOfBounds);
1203 isWithinBoundsPartOk = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, distanceToOutOfBounds)
1204 || isOutBufferValueUnchanged(offsetInBytes, distanceToOutOfBounds);
1206 isOutOfBoundsPartOk = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, (deUint8*)outValuePtr + distanceToOutOfBounds, outValueSize - distanceToOutOfBounds)
1207 || isOutBufferValueUnchanged(offsetInBytes + distanceToOutOfBounds, outValueSize - distanceToOutOfBounds);
1210 logMsg << ", first " << distanceToOutOfBounds << " byte(s) " << (isWithinBoundsPartOk ? "OK": "wrong");
1211 logMsg << ", last " << outValueSize - distanceToOutOfBounds << " byte(s) " << (isOutOfBoundsPartOk ? "OK": "wrong");
1213 isValidValue = isWithinBoundsPartOk && isOutOfBoundsPartOk;
1219 isValidValue = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, outValueSize);
1223 isValidValue = isOutBufferValueUnchanged(offsetInBytes, outValueSize);
1227 // Out of bounds writes may modify values withing the memory ranges bound to the buffer
1228 isValidValue = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, outValueSize);
1231 logMsg << ", OK, written within the memory range bound to the buffer";
1238 // Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
1239 // or the maximum representable positive integer value (if the format is integer-based).
1241 const bool canMatchVec4Pattern = (isReadAccess
1242 && !isValuePartiallyOutOfBounds
1243 && (m_shaderType == SHADER_TYPE_VECTOR_COPY || m_shaderType == SHADER_TYPE_TEXEL_COPY)
1244 && ((offsetInBytes / 4 + 1) % 4 == 0 || m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32));
1245 bool matchesVec4Pattern = false;
1247 if (canMatchVec4Pattern)
1249 if (m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1250 matchesVec4Pattern = verifyOutOfBoundsVec4(outValuePtr, m_bufferFormat);
1252 matchesVec4Pattern = verifyOutOfBoundsVec4(reinterpret_cast<deUint32*>(outValuePtr) - 3, m_bufferFormat);
1255 if (!canMatchVec4Pattern || !matchesVec4Pattern)
1257 logMsg << ". Failed: ";
1261 logMsg << "expected value within the buffer range or 0";
1263 if (canMatchVec4Pattern)
1264 logMsg << ", or the [0, 0, 0, x] pattern";
1268 logMsg << "written out of the range";
1275 else // We are within bounds
1279 if (!isExpectedValueFromInBuffer(offsetInBytes, outValuePtr, 4))
1281 logMsg << ", Failed: unexpected value";
1287 // Out of bounds writes may change values within the bounds.
1288 if (!isValueWithinBufferOrZero(inDataPtr, m_inBufferAccessRange, outValuePtr, 4))
1290 logMsg << ", Failed: unexpected value";
1298 log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
1303 // BufferReadInstance
1305 BufferReadInstance::BufferReadInstance (Context& context,
1306 Move<VkDevice> device,
1307 ShaderType shaderType,
1308 VkShaderStageFlags shaderStage,
1309 VkFormat bufferFormat,
1310 bool readFromStorage,
1311 VkDeviceSize inBufferAccessRange,
1312 bool accessOutOfBackingMemory)
1314 : BufferAccessInstance (context, device, shaderType, shaderStage, bufferFormat,
1315 readFromStorage ? BUFFER_ACCESS_TYPE_READ_FROM_STORAGE : BUFFER_ACCESS_TYPE_READ,
1316 inBufferAccessRange,
1317 RobustBufferAccessTest::s_numberOfBytesAccessed, // outBufferAccessRange
1318 accessOutOfBackingMemory)
1322 // BufferWriteInstance
1324 BufferWriteInstance::BufferWriteInstance (Context& context,
1325 Move<VkDevice> device,
1326 ShaderType shaderType,
1327 VkShaderStageFlags shaderStage,
1328 VkFormat bufferFormat,
1329 VkDeviceSize writeBufferAccessRange,
1330 bool accessOutOfBackingMemory)
1332 : BufferAccessInstance (context, device, shaderType, shaderStage, bufferFormat,
1333 BUFFER_ACCESS_TYPE_WRITE,
1334 RobustBufferAccessTest::s_numberOfBytesAccessed, // inBufferAccessRange
1335 writeBufferAccessRange,
1336 accessOutOfBackingMemory)
1340 // Test node creation functions
1342 static const char* getShaderStageName (VkShaderStageFlagBits shaderStage)
1344 switch (shaderStage)
1346 case VK_SHADER_STAGE_VERTEX_BIT: return "vertex";
1347 case VK_SHADER_STAGE_FRAGMENT_BIT: return "fragment";
1348 case VK_SHADER_STAGE_COMPUTE_BIT: return "compute";
1349 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return "tess_control";
1350 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return "tess_eval";
1351 case VK_SHADER_STAGE_GEOMETRY_BIT: return "geometry";
1360 static void addBufferAccessTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentNode)
1362 struct BufferRangeConfig
1368 const VkShaderStageFlagBits bufferAccessStages[] =
1370 VK_SHADER_STAGE_VERTEX_BIT,
1371 VK_SHADER_STAGE_FRAGMENT_BIT,
1372 VK_SHADER_STAGE_COMPUTE_BIT,
1375 const VkFormat bufferFormats[] =
1379 VK_FORMAT_R32_SFLOAT
1382 const VkFormat texelBufferFormats[] =
1384 VK_FORMAT_R32G32B32A32_SINT,
1385 VK_FORMAT_R32G32B32A32_UINT,
1386 VK_FORMAT_R32G32B32A32_SFLOAT,
1388 VK_FORMAT_A2B10G10R10_UNORM_PACK32
1391 const BufferRangeConfig bufferRangeConfigs[] =
1393 { "range_1_byte", 1ull },
1394 { "range_3_bytes", 3ull },
1395 { "range_4_bytes", 4ull }, // size of float
1396 { "range_32_bytes", 32ull }, // size of half mat4
1399 const BufferRangeConfig texelBufferRangeConfigs[] =
1401 { "range_1_texel", 1u },
1402 { "range_3_texels", 3u },
1405 const char* shaderTypeNames[SHADER_TYPE_COUNT] =
1413 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(bufferAccessStages); stageNdx++)
1415 const VkShaderStageFlagBits stage = bufferAccessStages[stageNdx];
1416 de::MovePtr<tcu::TestCaseGroup> stageTests (new tcu::TestCaseGroup(testCtx, getShaderStageName(stage), ""));
1418 for (int shaderTypeNdx = 0; shaderTypeNdx < SHADER_TYPE_COUNT; shaderTypeNdx++)
1420 const VkFormat* formats;
1421 size_t formatsLength;
1422 const BufferRangeConfig* ranges;
1423 size_t rangesLength;
1424 deUint32 rangeMultiplier;
1425 de::MovePtr<tcu::TestCaseGroup> shaderTypeTests (new tcu::TestCaseGroup(testCtx, shaderTypeNames[shaderTypeNdx], ""));
1427 if ((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY)
1429 formats = texelBufferFormats;
1430 formatsLength = DE_LENGTH_OF_ARRAY(texelBufferFormats);
1432 ranges = texelBufferRangeConfigs;
1433 rangesLength = DE_LENGTH_OF_ARRAY(texelBufferRangeConfigs);
1437 formats = bufferFormats;
1438 formatsLength = DE_LENGTH_OF_ARRAY(bufferFormats);
1440 ranges = bufferRangeConfigs;
1441 rangesLength = DE_LENGTH_OF_ARRAY(bufferRangeConfigs);
1444 for (size_t formatNdx = 0; formatNdx < formatsLength; formatNdx++)
1446 const VkFormat bufferFormat = formats[formatNdx];
1448 rangeMultiplier = ((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY) ? mapVkFormat(bufferFormat).getPixelSize() : 1;
1450 if (!isFloatFormat(bufferFormat) && ((ShaderType)shaderTypeNdx) == SHADER_TYPE_MATRIX_COPY)
1452 // Use SHADER_TYPE_MATRIX_COPY with floating-point formats only
1456 const std::string formatName = getFormatName(bufferFormat);
1457 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
1459 de::MovePtr<tcu::TestCaseGroup> uboReadTests (new tcu::TestCaseGroup(testCtx, "oob_uniform_read", ""));
1460 de::MovePtr<tcu::TestCaseGroup> ssboReadTests (new tcu::TestCaseGroup(testCtx, "oob_storage_read", ""));
1461 de::MovePtr<tcu::TestCaseGroup> ssboWriteTests (new tcu::TestCaseGroup(testCtx, "oob_storage_write", ""));
1463 for (size_t rangeNdx = 0; rangeNdx < rangesLength; rangeNdx++)
1465 const BufferRangeConfig& rangeConfig = ranges[rangeNdx];
1466 const VkDeviceSize rangeInBytes = rangeConfig.range * rangeMultiplier;
1468 uboReadTests->addChild(new RobustBufferReadTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, rangeInBytes, false, false));
1469 ssboReadTests->addChild(new RobustBufferReadTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, rangeInBytes, true, false));
1470 ssboWriteTests->addChild(new RobustBufferWriteTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, rangeInBytes, false));
1474 formatTests->addChild(uboReadTests.release());
1475 formatTests->addChild(ssboReadTests.release());
1476 formatTests->addChild(ssboWriteTests.release());
1478 shaderTypeTests->addChild(formatTests.release());
1481 // Read/write out of the memory that backs the buffer
1483 de::MovePtr<tcu::TestCaseGroup> outOfAllocTests (new tcu::TestCaseGroup(testCtx, "out_of_alloc", ""));
1485 const VkFormat format = (((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY ) ? VK_FORMAT_R32G32B32A32_SFLOAT : VK_FORMAT_R32_SFLOAT);
1487 outOfAllocTests->addChild(new RobustBufferReadTest(testCtx, "oob_uniform_read", "", stage, (ShaderType)shaderTypeNdx, format, 16, false, true));
1488 outOfAllocTests->addChild(new RobustBufferReadTest(testCtx, "oob_storage_read", "", stage, (ShaderType)shaderTypeNdx, format, 16, true, true));
1489 outOfAllocTests->addChild(new RobustBufferWriteTest(testCtx, "oob_storage_write", "", stage, (ShaderType)shaderTypeNdx, format, 16, true));
1491 shaderTypeTests->addChild(outOfAllocTests.release());
1494 stageTests->addChild(shaderTypeTests.release());
1496 parentNode->addChild(stageTests.release());
1500 tcu::TestCaseGroup* createBufferAccessTests (tcu::TestContext& testCtx)
1502 de::MovePtr<tcu::TestCaseGroup> bufferAccessTests (new tcu::TestCaseGroup(testCtx, "buffer_access", ""));
1504 addBufferAccessTests(testCtx, bufferAccessTests.get());
1506 return bufferAccessTests.release();