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"
33 #include "vkDeviceUtil.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "tcuTestLog.hpp"
51 SHADER_TYPE_MATRIX_COPY,
52 SHADER_TYPE_VECTOR_COPY,
53 SHADER_TYPE_SCALAR_COPY,
54 SHADER_TYPE_TEXEL_COPY,
61 BUFFER_ACCESS_TYPE_READ,
62 BUFFER_ACCESS_TYPE_READ_FROM_STORAGE,
63 BUFFER_ACCESS_TYPE_WRITE,
66 static VkDeviceSize min (VkDeviceSize a, VkDeviceSize b)
68 return (a < b) ? a : b;
71 class RobustBufferAccessTest : public vkt::TestCase
74 static const deUint32 s_testArraySize;
75 static const deUint32 s_numberOfBytesAccessed;
77 RobustBufferAccessTest (tcu::TestContext& testContext,
78 const std::string& name,
79 const std::string& description,
80 VkShaderStageFlags shaderStage,
81 ShaderType shaderType,
82 VkFormat bufferFormat,
83 bool testPipelineRobustness);
85 virtual ~RobustBufferAccessTest (void) {}
87 virtual void checkSupport (Context& context) const;
90 static void genBufferShaderAccess (ShaderType shaderType,
91 VkFormat bufferFormat,
93 std::ostringstream& bufferDefinition,
94 std::ostringstream& bufferUse);
96 static void genTexelBufferShaderAccess (VkFormat bufferFormat,
97 std::ostringstream& bufferDefinition,
98 std::ostringstream& bufferUse,
99 bool readFromStorage);
102 static void initBufferAccessPrograms (SourceCollections& programCollection,
103 VkShaderStageFlags shaderStage,
104 ShaderType shaderType,
105 VkFormat bufferFormat,
106 bool readFromStorage);
108 const VkShaderStageFlags m_shaderStage;
109 const ShaderType m_shaderType;
110 const VkFormat m_bufferFormat;
111 const bool m_testPipelineRobustness;
114 class RobustBufferReadTest : public RobustBufferAccessTest
117 RobustBufferReadTest (tcu::TestContext& testContext,
118 const std::string& name,
119 const std::string& description,
120 VkShaderStageFlags shaderStage,
121 ShaderType shaderType,
122 VkFormat bufferFormat,
123 bool testPipelineRobustness,
124 VkDeviceSize readAccessRange,
125 bool readFromStorage,
126 bool accessOutOfBackingMemory);
128 virtual ~RobustBufferReadTest (void) {}
130 virtual void initPrograms (SourceCollections& programCollection) const;
131 virtual TestInstance* createInstance (Context& context) const;
134 const bool m_readFromStorage;
135 const VkDeviceSize m_readAccessRange;
136 const bool m_accessOutOfBackingMemory;
139 class RobustBufferWriteTest : public RobustBufferAccessTest
142 RobustBufferWriteTest (tcu::TestContext& testContext,
143 const std::string& name,
144 const std::string& description,
145 VkShaderStageFlags shaderStage,
146 ShaderType shaderType,
147 VkFormat bufferFormat,
148 bool testPipelineRobustness,
149 VkDeviceSize writeAccessRange,
150 bool accessOutOfBackingMemory);
152 virtual ~RobustBufferWriteTest (void) {}
154 virtual void initPrograms (SourceCollections& programCollection) const;
155 virtual TestInstance* createInstance (Context& context) const;
158 const VkDeviceSize m_writeAccessRange;
159 const bool m_accessOutOfBackingMemory;
162 class BufferAccessInstance : public vkt::TestInstance
165 BufferAccessInstance (Context& context,
166 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
167 Move<VkDevice> device,
168 #ifndef CTS_USES_VULKANSC
169 de::MovePtr<vk::DeviceDriver> deviceDriver,
171 de::MovePtr<vk::DeviceDriverSC,vk::DeinitDeviceDeleter> deviceDriver,
172 #endif // CTS_USES_VULKANSC
173 ShaderType shaderType,
174 VkShaderStageFlags shaderStage,
175 VkFormat bufferFormat,
176 BufferAccessType bufferAccessType,
177 VkDeviceSize inBufferAccessRange,
178 VkDeviceSize outBufferAccessRange,
179 bool accessOutOfBackingMemory,
180 bool testPipelineRobustness);
182 virtual ~BufferAccessInstance (void);
184 virtual tcu::TestStatus iterate (void);
186 virtual bool verifyResult (void);
189 bool isExpectedValueFromInBuffer (VkDeviceSize offsetInBytes, const void* valuePtr, VkDeviceSize valueSize);
190 bool isOutBufferValueUnchanged (VkDeviceSize offsetInBytes, VkDeviceSize valueSize);
193 std::shared_ptr<CustomInstanceWrapper> m_instanceWrapper;
194 Move<VkDevice> m_device;
195 #ifndef CTS_USES_VULKANSC
196 de::MovePtr<vk::DeviceDriver> m_deviceDriver;
198 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> m_deviceDriver;
199 #endif // CTS_USES_VULKANSC
200 de::MovePtr<TestEnvironment> m_testEnvironment;
202 const ShaderType m_shaderType;
203 const VkShaderStageFlags m_shaderStage;
205 const VkFormat m_bufferFormat;
206 const BufferAccessType m_bufferAccessType;
208 const VkDeviceSize m_inBufferAccessRange;
209 Move<VkBuffer> m_inBuffer;
210 de::MovePtr<Allocation> m_inBufferAlloc;
211 VkDeviceSize m_inBufferAllocSize;
212 VkDeviceSize m_inBufferMaxAccessRange;
214 const VkDeviceSize m_outBufferAccessRange;
215 Move<VkBuffer> m_outBuffer;
216 de::MovePtr<Allocation> m_outBufferAlloc;
217 VkDeviceSize m_outBufferAllocSize;
218 VkDeviceSize m_outBufferMaxAccessRange;
220 Move<VkBuffer> m_indicesBuffer;
221 de::MovePtr<Allocation> m_indicesBufferAlloc;
223 Move<VkDescriptorPool> m_descriptorPool;
224 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
225 Move<VkDescriptorSet> m_descriptorSet;
227 Move<VkFence> m_fence;
230 // Used when m_shaderStage == VK_SHADER_STAGE_VERTEX_BIT
231 Move<VkBuffer> m_vertexBuffer;
232 de::MovePtr<Allocation> m_vertexBufferAlloc;
234 // Used when m_shaderType == SHADER_TYPE_TEXEL_COPY
235 Move<VkBufferView> m_inTexelBufferView;
236 Move<VkBufferView> m_outTexelBufferView;
238 const bool m_accessOutOfBackingMemory;
239 const bool m_testPipelineRobustness;
242 class BufferReadInstance: public BufferAccessInstance
245 BufferReadInstance (Context& context,
246 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
247 Move<VkDevice> device,
248 #ifndef CTS_USES_VULKANSC
249 de::MovePtr<vk::DeviceDriver> deviceDriver,
251 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
252 #endif // CTS_USES_VULKANSC
253 ShaderType shaderType,
254 VkShaderStageFlags shaderStage,
255 VkFormat bufferFormat,
256 bool readFromStorage,
257 VkDeviceSize inBufferAccessRange,
258 bool accessOutOfBackingMemory,
259 bool testPipelineRobustness);
261 virtual ~BufferReadInstance (void) {}
266 class BufferWriteInstance: public BufferAccessInstance
269 BufferWriteInstance (Context& context,
270 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
271 Move<VkDevice> device,
272 #ifndef CTS_USES_VULKANSC
273 de::MovePtr<vk::DeviceDriver> deviceDriver,
275 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
276 #endif // CTS_USES_VULKANSC
277 ShaderType shaderType,
278 VkShaderStageFlags shaderStage,
279 VkFormat bufferFormat,
280 VkDeviceSize writeBufferAccessRange,
281 bool accessOutOfBackingMemory,
282 bool testPipelineRobustness);
284 virtual ~BufferWriteInstance (void) {}
287 // RobustBufferAccessTest
289 const deUint32 RobustBufferAccessTest::s_testArraySize = 128; // Fit within minimum required maxUniformBufferRange
290 const deUint32 RobustBufferAccessTest::s_numberOfBytesAccessed = (deUint32)(16 * sizeof(float)); // size of mat4
292 RobustBufferAccessTest::RobustBufferAccessTest (tcu::TestContext& testContext,
293 const std::string& name,
294 const std::string& description,
295 VkShaderStageFlags shaderStage,
296 ShaderType shaderType,
297 VkFormat bufferFormat,
298 bool testPipelineRobustness)
299 : vkt::TestCase (testContext, name, description)
300 , m_shaderStage (shaderStage)
301 , m_shaderType (shaderType)
302 , m_bufferFormat (bufferFormat)
303 , m_testPipelineRobustness (testPipelineRobustness)
305 DE_ASSERT(m_shaderStage == VK_SHADER_STAGE_VERTEX_BIT || m_shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT || m_shaderStage == VK_SHADER_STAGE_COMPUTE_BIT);
308 void RobustBufferAccessTest::checkSupport(Context& context) const
310 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getDeviceFeatures().robustBufferAccess)
311 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: robustBufferAccess not supported by this implementation");
314 void RobustBufferAccessTest::genBufferShaderAccess (ShaderType shaderType,
315 VkFormat bufferFormat,
316 bool readFromStorage,
317 std::ostringstream& bufferDefinition,
318 std::ostringstream& bufferUse)
320 if (isFloatFormat(bufferFormat))
323 "layout(binding = 0, " << (readFromStorage ? "std430" : "std140") << ") " << (readFromStorage ? "buffer" : "uniform") << " InBuffer\n"
325 " mat4 inMatrix[" << s_testArraySize << "];\n"
329 "layout(binding = 1, std430) buffer OutBuffer\n"
331 " mat4 outMatrix[" << s_testArraySize << "];\n"
335 "layout(binding = 2, std140) uniform Indices\n"
343 case SHADER_TYPE_MATRIX_COPY:
345 " mat4 tmp = inMatrix[inIndex];\n"
346 " outMatrix[outIndex] = tmp;\n";
349 case SHADER_TYPE_VECTOR_COPY:
351 " outMatrix[outIndex][0] = inMatrix[inIndex][0];\n"
352 " outMatrix[outIndex][1] = inMatrix[inIndex][1];\n"
353 " outMatrix[outIndex][2] = inMatrix[inIndex][2];\n"
354 " outMatrix[outIndex][3] = inMatrix[inIndex][3];\n";
357 case SHADER_TYPE_SCALAR_COPY:
359 " outMatrix[outIndex][0][0] = inMatrix[inIndex][0][0];\n"
360 " outMatrix[outIndex][0][1] = inMatrix[inIndex][0][1];\n"
361 " outMatrix[outIndex][0][2] = inMatrix[inIndex][0][2];\n"
362 " outMatrix[outIndex][0][3] = inMatrix[inIndex][0][3];\n"
364 " outMatrix[outIndex][1][0] = inMatrix[inIndex][1][0];\n"
365 " outMatrix[outIndex][1][1] = inMatrix[inIndex][1][1];\n"
366 " outMatrix[outIndex][1][2] = inMatrix[inIndex][1][2];\n"
367 " outMatrix[outIndex][1][3] = inMatrix[inIndex][1][3];\n"
369 " outMatrix[outIndex][2][0] = inMatrix[inIndex][2][0];\n"
370 " outMatrix[outIndex][2][1] = inMatrix[inIndex][2][1];\n"
371 " outMatrix[outIndex][2][2] = inMatrix[inIndex][2][2];\n"
372 " outMatrix[outIndex][2][3] = inMatrix[inIndex][2][3];\n"
374 " outMatrix[outIndex][3][0] = inMatrix[inIndex][3][0];\n"
375 " outMatrix[outIndex][3][1] = inMatrix[inIndex][3][1];\n"
376 " outMatrix[outIndex][3][2] = inMatrix[inIndex][3][2];\n"
377 " outMatrix[outIndex][3][3] = inMatrix[inIndex][3][3];\n";
386 std::string typePrefixStr;
388 if (isUintFormat(bufferFormat))
392 else if (isIntFormat(bufferFormat))
401 typePrefixStr += (bufferFormat == vk::VK_FORMAT_R64_UINT || bufferFormat == vk::VK_FORMAT_R64_SINT) ?
405 "layout(binding = 0, " << (readFromStorage ? "std430" : "std140") << ") " << (readFromStorage ? "buffer readonly" : "uniform") << " InBuffer\n"
407 " " << typePrefixStr << "vec4 inVecs[" << s_testArraySize << "][4];\n"
411 "layout(binding = 1, std430) buffer OutBuffer\n"
413 " " << typePrefixStr << "vec4 outVecs[" << s_testArraySize << "][4];\n"
417 "layout(binding = 2, std140) uniform Indices\n"
425 case SHADER_TYPE_MATRIX_COPY:
426 // Shader type not supported for integer types.
430 case SHADER_TYPE_VECTOR_COPY:
432 " outVecs[outIndex][0] = inVecs[inIndex][0];\n"
433 " outVecs[outIndex][1] = inVecs[inIndex][1];\n"
434 " outVecs[outIndex][2] = inVecs[inIndex][2];\n"
435 " outVecs[outIndex][3] = inVecs[inIndex][3];\n";
438 case SHADER_TYPE_SCALAR_COPY:
440 " outVecs[outIndex][0][0] = inVecs[inIndex][0][0];\n"
441 " outVecs[outIndex][0][1] = inVecs[inIndex][0][1];\n"
442 " outVecs[outIndex][0][2] = inVecs[inIndex][0][2];\n"
443 " outVecs[outIndex][0][3] = inVecs[inIndex][0][3];\n"
445 " outVecs[outIndex][1][0] = inVecs[inIndex][1][0];\n"
446 " outVecs[outIndex][1][1] = inVecs[inIndex][1][1];\n"
447 " outVecs[outIndex][1][2] = inVecs[inIndex][1][2];\n"
448 " outVecs[outIndex][1][3] = inVecs[inIndex][1][3];\n"
450 " outVecs[outIndex][2][0] = inVecs[inIndex][2][0];\n"
451 " outVecs[outIndex][2][1] = inVecs[inIndex][2][1];\n"
452 " outVecs[outIndex][2][2] = inVecs[inIndex][2][2];\n"
453 " outVecs[outIndex][2][3] = inVecs[inIndex][2][3];\n"
455 " outVecs[outIndex][3][0] = inVecs[inIndex][3][0];\n"
456 " outVecs[outIndex][3][1] = inVecs[inIndex][3][1];\n"
457 " outVecs[outIndex][3][2] = inVecs[inIndex][3][2];\n"
458 " outVecs[outIndex][3][3] = inVecs[inIndex][3][3];\n";
467 void RobustBufferAccessTest::genTexelBufferShaderAccess (VkFormat bufferFormat,
468 std::ostringstream& bufferDefinition,
469 std::ostringstream& bufferUse,
470 bool readFromStorage)
472 const char* layoutTypeStr;
473 const char* inTexelBufferTypeStr;
474 const char* outTexelBufferTypeStr;
475 const deUint32 texelSize = mapVkFormat(bufferFormat).getPixelSize();
477 if (isFloatFormat(bufferFormat))
479 layoutTypeStr = "rgba32f";
480 inTexelBufferTypeStr = readFromStorage ? "imageBuffer" : "textureBuffer";
481 outTexelBufferTypeStr = "imageBuffer";
483 else if (isUintFormat(bufferFormat))
485 layoutTypeStr = "rgba32ui";
486 inTexelBufferTypeStr = readFromStorage ? "uimageBuffer" : "utextureBuffer";
487 outTexelBufferTypeStr = "uimageBuffer";
489 else if (isIntFormat(bufferFormat))
491 layoutTypeStr = "rgba32i";
492 inTexelBufferTypeStr = readFromStorage ? "iimageBuffer" : "itextureBuffer";
493 outTexelBufferTypeStr = "iimageBuffer";
495 else if (bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
497 layoutTypeStr = "rgb10_a2";
498 inTexelBufferTypeStr = readFromStorage ? "imageBuffer" : "textureBuffer"; outTexelBufferTypeStr = "imageBuffer";
502 TCU_THROW(NotSupportedError, (std::string("Unsupported format: ") + getFormatName(bufferFormat)).c_str());
505 bufferDefinition << "layout(set = 0, binding = 0" << ((readFromStorage) ? (std::string(", ") + layoutTypeStr) : "") << ") uniform highp "
506 << ((readFromStorage) ? "readonly " : "") << inTexelBufferTypeStr << " inImage;\n";
508 bufferDefinition << "layout(set = 0, binding = 1, " << layoutTypeStr << ") uniform highp writeonly " << outTexelBufferTypeStr << " outImage;\n";
511 "layout(binding = 2, std140) uniform Offsets\n"
517 bufferUse << " for (int i = 0; i < " << (s_numberOfBytesAccessed / texelSize) << "; i++)\n"
519 << " imageStore(outImage, outOffset + i, " << (readFromStorage ? "imageLoad" : "texelFetch") << "(inImage, inOffset + i));\n"
523 void RobustBufferAccessTest::initBufferAccessPrograms (SourceCollections& programCollection,
524 VkShaderStageFlags shaderStage,
525 ShaderType shaderType,
526 VkFormat bufferFormat,
527 bool readFromStorage)
529 std::ostringstream bufferDefinition;
530 std::ostringstream bufferUse;
531 std::string extensions;
533 if (bufferFormat == vk::VK_FORMAT_R64_UINT || bufferFormat == vk::VK_FORMAT_R64_SINT)
535 extensions = "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
538 if (shaderType != SHADER_TYPE_TEXEL_COPY)
540 genBufferShaderAccess(shaderType, bufferFormat, readFromStorage, bufferDefinition, bufferUse);
543 if (shaderStage == VK_SHADER_STAGE_COMPUTE_BIT)
545 std::ostringstream computeShaderSource;
547 if (shaderType == SHADER_TYPE_TEXEL_COPY)
548 genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
550 computeShaderSource <<
552 "#extension GL_EXT_texture_buffer : require\n"
554 "precision highp float;\n"
555 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
556 << bufferDefinition.str() <<
559 << bufferUse.str() <<
562 programCollection.glslSources.add("compute") << glu::ComputeSource(computeShaderSource.str());
566 std::ostringstream vertexShaderSource;
567 std::ostringstream fragmentShaderSource;
569 if (shaderStage == VK_SHADER_STAGE_VERTEX_BIT)
571 if (shaderType == SHADER_TYPE_TEXEL_COPY)
572 genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
574 vertexShaderSource <<
576 "#extension GL_EXT_texture_buffer : require\n"
578 "precision highp float;\n"
579 "layout(location = 0) in vec4 position;\n\n"
580 << bufferDefinition.str() << "\n"
581 "out gl_PerVertex {\n"
582 " vec4 gl_Position;\n"
586 << bufferUse.str() <<
587 " gl_Position = position;\n"
592 vertexShaderSource <<
594 "precision highp float;\n"
595 "layout(location = 0) in vec4 position;\n\n"
596 "out gl_PerVertex {\n"
597 " vec4 gl_Position;\n"
601 " gl_Position = position;\n"
605 programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str());
607 if (shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT)
609 if (shaderType == SHADER_TYPE_TEXEL_COPY)
610 genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
612 fragmentShaderSource <<
614 "#extension GL_EXT_texture_buffer : require\n"
616 "precision highp float;\n"
617 "layout(location = 0) out vec4 fragColor;\n"
618 << bufferDefinition.str() <<
621 << bufferUse.str() <<
622 " fragColor = vec4(1.0);\n"
627 fragmentShaderSource <<
629 "precision highp float;\n"
630 "layout(location = 0) out vec4 fragColor;\n\n"
633 " fragColor = vec4(1.0);\n"
637 programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str());
641 // RobustBufferReadTest
643 RobustBufferReadTest::RobustBufferReadTest (tcu::TestContext& testContext,
644 const std::string& name,
645 const std::string& description,
646 VkShaderStageFlags shaderStage,
647 ShaderType shaderType,
648 VkFormat bufferFormat,
649 bool testPipelineRobustness,
650 VkDeviceSize readAccessRange,
651 bool readFromStorage,
652 bool accessOutOfBackingMemory)
653 : RobustBufferAccessTest (testContext, name, description, shaderStage, shaderType, bufferFormat, testPipelineRobustness)
654 , m_readFromStorage (readFromStorage)
655 , m_readAccessRange (readAccessRange)
656 , m_accessOutOfBackingMemory (accessOutOfBackingMemory)
660 void RobustBufferReadTest::initPrograms (SourceCollections& programCollection) const
662 initBufferAccessPrograms(programCollection, m_shaderStage, m_shaderType, m_bufferFormat, m_readFromStorage);
665 TestInstance* RobustBufferReadTest::createInstance (Context& context) const
667 std::shared_ptr<CustomInstanceWrapper> instanceWrapper(new CustomInstanceWrapper(context));
668 VkPhysicalDeviceFeatures2 features2 = initVulkanStructure();
670 #ifndef CTS_USES_VULKANSC
671 VkPhysicalDevicePipelineRobustnessFeaturesEXT pipelineRobustnessFeatures = initVulkanStructure();
672 if (m_testPipelineRobustness)
674 context.requireDeviceFunctionality("VK_EXT_pipeline_robustness");
676 pipelineRobustnessFeatures.pipelineRobustness = VK_TRUE;
678 pipelineRobustnessFeatures.pNext = features2.pNext;
679 features2.pNext = &pipelineRobustnessFeatures;
683 Move<VkDevice> device = createRobustBufferAccessDevice(context, instanceWrapper->instance, instanceWrapper->instance.getDriver(), m_testPipelineRobustness ? &features2 : DE_NULL);
684 #ifndef CTS_USES_VULKANSC
685 de::MovePtr<vk::DeviceDriver> deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(context.getPlatformInterface(), instanceWrapper->instance, *device));
687 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(context.getPlatformInterface(), instanceWrapper->instance, *device, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties()), vk::DeinitDeviceDeleter( context.getResourceInterface().get(), *device ));
688 #endif // CTS_USES_VULKANSC
690 return new BufferReadInstance(context, instanceWrapper, device, deviceDriver, m_shaderType, m_shaderStage, m_bufferFormat, m_readFromStorage, m_readAccessRange, m_accessOutOfBackingMemory, m_testPipelineRobustness);
693 // RobustBufferWriteTest
695 RobustBufferWriteTest::RobustBufferWriteTest (tcu::TestContext& testContext,
696 const std::string& name,
697 const std::string& description,
698 VkShaderStageFlags shaderStage,
699 ShaderType shaderType,
700 VkFormat bufferFormat,
701 bool testPipelineRobustness,
702 VkDeviceSize writeAccessRange,
703 bool accessOutOfBackingMemory)
705 : RobustBufferAccessTest (testContext, name, description, shaderStage, shaderType, bufferFormat, testPipelineRobustness)
706 , m_writeAccessRange (writeAccessRange)
707 , m_accessOutOfBackingMemory (accessOutOfBackingMemory)
711 void RobustBufferWriteTest::initPrograms (SourceCollections& programCollection) const
713 initBufferAccessPrograms(programCollection, m_shaderStage, m_shaderType, m_bufferFormat, false /* readFromStorage */);
716 TestInstance* RobustBufferWriteTest::createInstance (Context& context) const
718 std::shared_ptr<CustomInstanceWrapper> instanceWrapper(new CustomInstanceWrapper(context));
719 VkPhysicalDeviceFeatures2 features2 = initVulkanStructure();
721 #ifndef CTS_USES_VULKANSC
722 VkPhysicalDevicePipelineRobustnessFeaturesEXT pipelineRobustnessFeatures = initVulkanStructure();
723 if (m_testPipelineRobustness)
725 context.requireDeviceFunctionality("VK_EXT_pipeline_robustness");
727 const auto& vki = context.getInstanceInterface();
728 const auto physicalDevice = context.getPhysicalDevice();
730 pipelineRobustnessFeatures.pNext = features2.pNext;
731 features2.pNext = &pipelineRobustnessFeatures;
733 vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
737 Move<VkDevice> device = createRobustBufferAccessDevice(context, instanceWrapper->instance, instanceWrapper->instance.getDriver(), m_testPipelineRobustness ? &features2 : DE_NULL);
738 #ifndef CTS_USES_VULKANSC
739 de::MovePtr<vk::DeviceDriver> deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(context.getPlatformInterface(), instanceWrapper->instance, *device));
741 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver = de::MovePtr<DeviceDriverSC,DeinitDeviceDeleter>(new DeviceDriverSC(context.getPlatformInterface(), instanceWrapper->instance, *device, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties()), DeinitDeviceDeleter(context.getResourceInterface().get(), *device));
742 #endif // CTS_USES_VULKANSC
744 return new BufferWriteInstance(context, instanceWrapper, device, deviceDriver, m_shaderType, m_shaderStage, m_bufferFormat, m_writeAccessRange, m_accessOutOfBackingMemory, m_testPipelineRobustness);
747 // BufferAccessInstance
749 BufferAccessInstance::BufferAccessInstance (Context& context,
750 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
751 Move<VkDevice> device,
752 #ifndef CTS_USES_VULKANSC
753 de::MovePtr<vk::DeviceDriver> deviceDriver,
755 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
756 #endif // CTS_USES_VULKANSC
757 ShaderType shaderType,
758 VkShaderStageFlags shaderStage,
759 VkFormat bufferFormat,
760 BufferAccessType bufferAccessType,
761 VkDeviceSize inBufferAccessRange,
762 VkDeviceSize outBufferAccessRange,
763 bool accessOutOfBackingMemory,
764 bool testPipelineRobustness)
765 : vkt::TestInstance (context)
766 , m_instanceWrapper (instanceWrapper)
768 , m_deviceDriver (deviceDriver)
769 , m_shaderType (shaderType)
770 , m_shaderStage (shaderStage)
771 , m_bufferFormat (bufferFormat)
772 , m_bufferAccessType (bufferAccessType)
773 , m_inBufferAccessRange (inBufferAccessRange)
774 , m_outBufferAccessRange (outBufferAccessRange)
775 , m_accessOutOfBackingMemory (accessOutOfBackingMemory)
776 , m_testPipelineRobustness (testPipelineRobustness)
778 const DeviceInterface& vk = *m_deviceDriver;
779 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
780 const bool isTexelAccess = !!(m_shaderType == SHADER_TYPE_TEXEL_COPY);
781 const bool readFromStorage = !!(m_bufferAccessType == BUFFER_ACCESS_TYPE_READ_FROM_STORAGE);
782 const VkPhysicalDevice physicalDevice = chooseDevice(instanceWrapper->instance.getDriver(), instanceWrapper->instance, context.getTestContext().getCommandLine());
783 SimpleAllocator memAlloc (vk, *m_device, getPhysicalDeviceMemoryProperties(instanceWrapper->instance.getDriver(), physicalDevice));
784 tcu::TestLog& log = m_context.getTestContext().getLog();
786 DE_ASSERT(RobustBufferAccessTest::s_numberOfBytesAccessed % sizeof(deUint32) == 0);
787 DE_ASSERT(inBufferAccessRange <= RobustBufferAccessTest::s_numberOfBytesAccessed);
788 DE_ASSERT(outBufferAccessRange <= RobustBufferAccessTest::s_numberOfBytesAccessed);
790 if (m_bufferFormat == VK_FORMAT_R64_UINT || m_bufferFormat == VK_FORMAT_R64_SINT)
792 context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
795 // Check storage support
796 if (shaderStage == VK_SHADER_STAGE_VERTEX_BIT)
798 if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics)
800 TCU_THROW(NotSupportedError, "Stores not supported in vertex stage");
803 else if (shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT)
805 if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
807 TCU_THROW(NotSupportedError, "Stores not supported in fragment stage");
811 // Check format support
813 VkFormatFeatureFlags requiredFormatFeatures = 0;
814 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instanceWrapper->instance.getDriver(), physicalDevice, m_bufferFormat);
818 requiredFormatFeatures = VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
821 if ((formatProperties.bufferFeatures & requiredFormatFeatures) != requiredFormatFeatures)
823 TCU_THROW(NotSupportedError, (std::string("Format cannot be used in uniform and storage") + (isTexelAccess ? " texel" : "") + " buffers: "
824 + getFormatName(m_bufferFormat)).c_str());
828 // Create buffer to read data from
830 VkBufferUsageFlags inBufferUsageFlags;
831 VkMemoryRequirements inBufferMemoryReqs;
835 inBufferUsageFlags = readFromStorage ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
839 inBufferUsageFlags = readFromStorage ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
842 const VkBufferCreateInfo inBufferParams =
844 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
845 DE_NULL, // const void* pNext;
846 0u, // VkBufferCreateFlags flags;
847 m_inBufferAccessRange, // VkDeviceSize size;
848 inBufferUsageFlags, // VkBufferUsageFlags usage;
849 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
850 VK_QUEUE_FAMILY_IGNORED, // deUint32 queueFamilyIndexCount;
851 DE_NULL // const deUint32* pQueueFamilyIndices;
854 m_inBuffer = createBuffer(vk, *m_device, &inBufferParams);
856 inBufferMemoryReqs = getBufferMemoryRequirements(vk, *m_device, *m_inBuffer);
857 m_inBufferAllocSize = inBufferMemoryReqs.size;
858 m_inBufferAlloc = memAlloc.allocate(inBufferMemoryReqs, MemoryRequirement::HostVisible);
860 // Size of the most restrictive bound
861 m_inBufferMaxAccessRange = min(m_inBufferAllocSize, min(inBufferParams.size, m_inBufferAccessRange));
863 VK_CHECK(vk.bindBufferMemory(*m_device, *m_inBuffer, m_inBufferAlloc->getMemory(), m_inBufferAlloc->getOffset()));
864 populateBufferWithTestValues(m_inBufferAlloc->getHostPtr(), m_inBufferAllocSize, m_bufferFormat);
865 flushMappedMemoryRange(vk, *m_device, m_inBufferAlloc->getMemory(), m_inBufferAlloc->getOffset(), VK_WHOLE_SIZE);
867 log << tcu::TestLog::Message << "inBufferAllocSize = " << m_inBufferAllocSize << tcu::TestLog::EndMessage;
868 log << tcu::TestLog::Message << "inBufferMaxAccessRange = " << m_inBufferMaxAccessRange << tcu::TestLog::EndMessage;
871 // Create buffer to write data into
873 VkMemoryRequirements outBufferMemoryReqs;
874 const VkBufferUsageFlags outBufferUsageFlags = (m_shaderType == SHADER_TYPE_TEXEL_COPY) ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
875 : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
877 const VkBufferCreateInfo outBufferParams =
879 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
880 DE_NULL, // const void* pNext;
881 0u, // VkBufferCreateFlags flags;
882 m_outBufferAccessRange, // VkDeviceSize size;
883 outBufferUsageFlags, // VkBufferUsageFlags usage;
884 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
885 VK_QUEUE_FAMILY_IGNORED, // deUint32 queueFamilyIndexCount;
886 DE_NULL // const deUint32* pQueueFamilyIndices;
889 m_outBuffer = createBuffer(vk, *m_device, &outBufferParams);
891 outBufferMemoryReqs = getBufferMemoryRequirements(vk, *m_device, *m_outBuffer);
892 m_outBufferAllocSize = outBufferMemoryReqs.size;
893 m_outBufferAlloc = memAlloc.allocate(outBufferMemoryReqs, MemoryRequirement::HostVisible);
895 #ifdef CTS_USES_VULKANSC
896 if (m_context.getTestContext().getCommandLine().isSubProcess())
897 #endif // CTS_USES_VULKANSC
899 // If we are requesting access out of the memory that backs the buffer, make sure the test is able to do so.
900 if (m_accessOutOfBackingMemory)
902 if (m_outBufferAllocSize >= ((RobustBufferAccessTest::s_testArraySize + 1) * RobustBufferAccessTest::s_numberOfBytesAccessed))
904 TCU_THROW(NotSupportedError, "Cannot access beyond the end of the memory that backs the buffer");
909 // Size of the most restrictive bound
910 m_outBufferMaxAccessRange = min(m_outBufferAllocSize, min(outBufferParams.size, m_outBufferAccessRange));
912 VK_CHECK(vk.bindBufferMemory(*m_device, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
913 deMemset(m_outBufferAlloc->getHostPtr(), 0xFF, (size_t)m_outBufferAllocSize);
914 flushMappedMemoryRange(vk, *m_device, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset(), VK_WHOLE_SIZE);
916 log << tcu::TestLog::Message << "outBufferAllocSize = " << m_outBufferAllocSize << tcu::TestLog::EndMessage;
917 log << tcu::TestLog::Message << "outBufferMaxAccessRange = " << m_outBufferMaxAccessRange << tcu::TestLog::EndMessage;
920 // Create buffer for indices/offsets
928 IndicesBuffer indices = { 0, 0 };
930 const VkBufferCreateInfo indicesBufferParams =
932 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
933 DE_NULL, // const void* pNext;
934 0u, // VkBufferCreateFlags flags;
935 sizeof(IndicesBuffer), // VkDeviceSize size;
936 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, // VkBufferUsageFlags usage;
937 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
938 VK_QUEUE_FAMILY_IGNORED, // deUint32 queueFamilyIndexCount;
939 DE_NULL, // const deUint32* pQueueFamilyIndices;
942 m_indicesBuffer = createBuffer(vk, *m_device, &indicesBufferParams);
943 m_indicesBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indicesBuffer), MemoryRequirement::HostVisible);
945 VK_CHECK(vk.bindBufferMemory(*m_device, *m_indicesBuffer, m_indicesBufferAlloc->getMemory(), m_indicesBufferAlloc->getOffset()));
947 if (m_accessOutOfBackingMemory)
949 if (m_bufferAccessType == BUFFER_ACCESS_TYPE_WRITE)
951 indices.outIndex = RobustBufferAccessTest::s_testArraySize - 1;
955 indices.inIndex = RobustBufferAccessTest::s_testArraySize - 1;
959 deMemcpy(m_indicesBufferAlloc->getHostPtr(), &indices, sizeof(IndicesBuffer));
961 flushMappedMemoryRange(vk, *m_device, m_indicesBufferAlloc->getMemory(), m_indicesBufferAlloc->getOffset(), VK_WHOLE_SIZE);
963 log << tcu::TestLog::Message << "inIndex = " << indices.inIndex << tcu::TestLog::EndMessage;
964 log << tcu::TestLog::Message << "outIndex = " << indices.outIndex << tcu::TestLog::EndMessage;
967 // Create descriptor data
969 VkDescriptorType inBufferDescriptorType;
970 VkDescriptorType outBufferDescriptorType;
974 inBufferDescriptorType = readFromStorage ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
975 outBufferDescriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
979 inBufferDescriptorType = readFromStorage ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
980 outBufferDescriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
983 DescriptorPoolBuilder descriptorPoolBuilder;
984 descriptorPoolBuilder.addType(inBufferDescriptorType, 1u);
985 descriptorPoolBuilder.addType(outBufferDescriptorType, 1u);
986 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u);
987 m_descriptorPool = descriptorPoolBuilder.build(vk, *m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
989 DescriptorSetLayoutBuilder setLayoutBuilder;
990 setLayoutBuilder.addSingleBinding(inBufferDescriptorType, VK_SHADER_STAGE_ALL);
991 setLayoutBuilder.addSingleBinding(outBufferDescriptorType, VK_SHADER_STAGE_ALL);
992 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
993 m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device);
995 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
997 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
998 DE_NULL, // const void* pNext;
999 *m_descriptorPool, // VkDescriptorPool descriptorPool;
1000 1u, // deUint32 setLayoutCount;
1001 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts;
1004 m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo);
1006 DescriptorSetUpdateBuilder setUpdateBuilder;
1010 const VkBufferViewCreateInfo inBufferViewCreateInfo =
1012 VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
1013 DE_NULL, // const void* pNext;
1014 0u, // VkBufferViewCreateFlags flags;
1015 *m_inBuffer, // VkBuffer buffer;
1016 m_bufferFormat, // VkFormat format;
1017 0ull, // VkDeviceSize offset;
1018 m_inBufferAccessRange // VkDeviceSize range;
1020 m_inTexelBufferView = createBufferView(vk, *m_device, &inBufferViewCreateInfo, DE_NULL);
1022 const VkBufferViewCreateInfo outBufferViewCreateInfo =
1024 VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
1025 DE_NULL, // const void* pNext;
1026 0u, // VkBufferViewCreateFlags flags;
1027 *m_outBuffer, // VkBuffer buffer;
1028 m_bufferFormat, // VkFormat format;
1029 0ull, // VkDeviceSize offset;
1030 m_outBufferAccessRange, // VkDeviceSize range;
1032 m_outTexelBufferView = createBufferView(vk, *m_device, &outBufferViewCreateInfo, DE_NULL);
1034 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), inBufferDescriptorType, &m_inTexelBufferView.get());
1035 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1), outBufferDescriptorType, &m_outTexelBufferView.get());
1039 const VkDescriptorBufferInfo inBufferDescriptorInfo = makeDescriptorBufferInfo(*m_inBuffer, 0ull, m_inBufferAccessRange);
1040 const VkDescriptorBufferInfo outBufferDescriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, 0ull, m_outBufferAccessRange);
1042 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), inBufferDescriptorType, &inBufferDescriptorInfo);
1043 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1), outBufferDescriptorType, &outBufferDescriptorInfo);
1046 const VkDescriptorBufferInfo indicesBufferDescriptorInfo = makeDescriptorBufferInfo(*m_indicesBuffer, 0ull, 8ull);
1047 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &indicesBufferDescriptorInfo);
1049 setUpdateBuilder.update(vk, *m_device);
1054 const VkFenceCreateInfo fenceParams =
1056 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
1057 DE_NULL, // const void* pNext;
1058 0u // VkFenceCreateFlags flags;
1061 m_fence = createFence(vk, *m_device, &fenceParams);
1065 vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue);
1067 if (m_shaderStage == VK_SHADER_STAGE_COMPUTE_BIT)
1069 m_testEnvironment = de::MovePtr<TestEnvironment>(new ComputeEnvironment(m_context, m_instanceWrapper->instance, m_instanceWrapper->instance.getDriver(), *m_device, *m_descriptorSetLayout, *m_descriptorSet, m_testPipelineRobustness));
1075 const VkVertexInputBindingDescription vertexInputBindingDescription =
1077 0u, // deUint32 binding;
1078 sizeof(tcu::Vec4), // deUint32 strideInBytes;
1079 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
1082 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
1084 0u, // deUint32 location;
1085 0u, // deUint32 binding;
1086 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1087 0u // deUint32 offset;
1090 const Vec4 vertices[] =
1092 Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
1093 Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
1094 Vec4(1.0f, -1.0f, 0.0f, 1.0f),
1097 // Create vertex buffer
1099 const VkDeviceSize vertexBufferSize = (VkDeviceSize)(4u * sizeof(tcu::Vec4));
1100 const VkBufferCreateInfo vertexBufferParams =
1102 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1103 DE_NULL, // const void* pNext;
1104 0u, // VkBufferCreateFlags flags;
1105 vertexBufferSize, // VkDeviceSize size;
1106 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1107 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1108 VK_QUEUE_FAMILY_IGNORED, // deUint32 queueFamilyIndexCount;
1109 DE_NULL // const deUint32* pQueueFamilyIndices;
1112 DE_ASSERT(vertexBufferSize > 0);
1114 m_vertexBuffer = createBuffer(vk, *m_device, &vertexBufferParams);
1115 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexBuffer), MemoryRequirement::HostVisible);
1117 VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
1119 // Load vertices into vertex buffer
1120 deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices, sizeof(tcu::Vec4) * DE_LENGTH_OF_ARRAY(vertices));
1121 flushMappedMemoryRange(vk, *m_device, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1124 const GraphicsEnvironment::DrawConfig drawWithOneVertexBuffer =
1126 std::vector<VkBuffer>(1, *m_vertexBuffer), // std::vector<VkBuffer> vertexBuffers;
1127 DE_LENGTH_OF_ARRAY(vertices), // deUint32 vertexCount;
1128 1, // deUint32 instanceCount;
1129 DE_NULL, // VkBuffer indexBuffer;
1130 0u, // deUint32 indexCount;
1133 m_testEnvironment = de::MovePtr<TestEnvironment>(new GraphicsEnvironment(m_context,
1134 m_instanceWrapper->instance,
1135 m_instanceWrapper->instance.getDriver(),
1137 *m_descriptorSetLayout,
1139 GraphicsEnvironment::VertexBindings(1, vertexInputBindingDescription),
1140 GraphicsEnvironment::VertexAttributes(1, vertexInputAttributeDescription),
1141 drawWithOneVertexBuffer,
1142 m_testPipelineRobustness));
1146 BufferAccessInstance::~BufferAccessInstance(void)
1150 // Verifies if the buffer has the value initialized by BufferAccessInstance::populateReadBuffer at a given offset.
1151 bool BufferAccessInstance::isExpectedValueFromInBuffer (VkDeviceSize offsetInBytes, const void* valuePtr, VkDeviceSize valueSize)
1153 DE_ASSERT(offsetInBytes % 4 == 0);
1154 DE_ASSERT(offsetInBytes < m_inBufferAllocSize);
1156 const deUint32 valueIndex = deUint32(offsetInBytes / 4) + 2;
1158 if (isUintFormat(m_bufferFormat))
1160 return !deMemCmp(valuePtr, &valueIndex, (size_t)valueSize);
1162 else if (isIntFormat(m_bufferFormat))
1164 const deInt32 value = -deInt32(valueIndex);
1165 return !deMemCmp(valuePtr, &value, (size_t)valueSize);
1167 else if (isFloatFormat(m_bufferFormat))
1169 const float value = float(valueIndex);
1170 return !deMemCmp(valuePtr, &value, (size_t)valueSize);
1172 else if (m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1174 const deUint32 r = ((valueIndex + 0) & ((2u << 10) - 1u));
1175 const deUint32 g = ((valueIndex + 1) & ((2u << 10) - 1u));
1176 const deUint32 b = ((valueIndex + 2) & ((2u << 10) - 1u));
1177 const deUint32 a = ((valueIndex + 0) & ((2u << 2) - 1u));
1178 const deUint32 abgr = (a << 30) | (b << 20) | (g << 10) | r;
1180 return !deMemCmp(valuePtr, &abgr, (size_t)valueSize);
1189 bool BufferAccessInstance::isOutBufferValueUnchanged (VkDeviceSize offsetInBytes, VkDeviceSize valueSize)
1191 const deUint8 *const outValuePtr = (deUint8*)m_outBufferAlloc->getHostPtr() + offsetInBytes;
1192 const deUint32 defaultValue = 0xFFFFFFFFu;
1194 return !deMemCmp(outValuePtr, &defaultValue, (size_t)valueSize);
1197 tcu::TestStatus BufferAccessInstance::iterate (void)
1199 const DeviceInterface& vk = *m_deviceDriver;
1200 const vk::VkCommandBuffer cmdBuffer = m_testEnvironment->getCommandBuffer();
1202 // Submit command buffer
1204 const VkSubmitInfo submitInfo =
1206 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
1207 DE_NULL, // const void* pNext;
1208 0u, // deUint32 waitSemaphoreCount;
1209 DE_NULL, // const VkSemaphore* pWaitSemaphores;
1210 DE_NULL, // const VkPIpelineStageFlags* pWaitDstStageMask;
1211 1u, // deUint32 commandBufferCount;
1212 &cmdBuffer, // const VkCommandBuffer* pCommandBuffers;
1213 0u, // deUint32 signalSemaphoreCount;
1214 DE_NULL // const VkSemaphore* pSignalSemaphores;
1217 VK_CHECK(vk.resetFences(*m_device, 1, &m_fence.get()));
1218 VK_CHECK(vk.queueSubmit(m_queue, 1, &submitInfo, *m_fence));
1219 VK_CHECK(vk.waitForFences(*m_device, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
1222 // Prepare result buffer for read
1224 const VkMappedMemoryRange outBufferRange =
1226 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
1227 DE_NULL, // const void* pNext;
1228 m_outBufferAlloc->getMemory(), // VkDeviceMemory mem;
1229 0ull, // VkDeviceSize offset;
1230 m_outBufferAllocSize, // VkDeviceSize size;
1233 VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
1237 return tcu::TestStatus::pass("All values OK");
1239 return tcu::TestStatus::fail("Invalid value(s) found");
1242 bool BufferAccessInstance::verifyResult (void)
1244 std::ostringstream logMsg;
1245 tcu::TestLog& log = m_context.getTestContext().getLog();
1246 const bool isReadAccess = !!(m_bufferAccessType == BUFFER_ACCESS_TYPE_READ || m_bufferAccessType == BUFFER_ACCESS_TYPE_READ_FROM_STORAGE);
1247 const void* inDataPtr = m_inBufferAlloc->getHostPtr();
1248 const void* outDataPtr = m_outBufferAlloc->getHostPtr();
1250 deUint32 valueNdx = 0;
1251 const VkDeviceSize maxAccessRange = isReadAccess ? m_inBufferMaxAccessRange : m_outBufferMaxAccessRange;
1253 for (VkDeviceSize offsetInBytes = 0; offsetInBytes < m_outBufferAllocSize; offsetInBytes += 4)
1255 deUint8* outValuePtr = (deUint8*)outDataPtr + offsetInBytes;
1256 const size_t outValueSize = (size_t)min(4, (m_outBufferAllocSize - offsetInBytes));
1258 if (offsetInBytes >= RobustBufferAccessTest::s_numberOfBytesAccessed)
1260 // The shader will only write 16 values into the result buffer. The rest of the values
1261 // should remain unchanged or may be modified if we are writing out of bounds.
1262 if (!isOutBufferValueUnchanged(offsetInBytes, outValueSize)
1263 && (isReadAccess || !isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, 4)))
1265 logMsg << "\nValue " << valueNdx++ << " has been modified with an unknown value: " << *((deUint32 *)outValuePtr);
1271 const deInt32 distanceToOutOfBounds = (deInt32)maxAccessRange - (deInt32)offsetInBytes;
1272 bool isOutOfBoundsAccess = false;
1274 logMsg << "\n" << valueNdx++ << ": ";
1276 logValue(logMsg, outValuePtr, m_bufferFormat, outValueSize);
1278 if (m_accessOutOfBackingMemory)
1280 isOutOfBoundsAccess = true;
1284 // Check if the shader operation accessed an operand located less than 16 bytes away
1285 // from the out of bounds address.
1287 deUint32 operandSize = 0;
1289 switch (m_shaderType)
1291 case SHADER_TYPE_SCALAR_COPY:
1292 operandSize = 4; // Size of scalar
1295 case SHADER_TYPE_VECTOR_COPY:
1296 operandSize = 4 * ((m_bufferFormat == vk::VK_FORMAT_R64_UINT || m_bufferFormat == vk::VK_FORMAT_R64_SINT) ? 8 : 4);// Size of vec4
1299 case SHADER_TYPE_MATRIX_COPY:
1300 operandSize = 4 * 16; // Size of mat4
1303 case SHADER_TYPE_TEXEL_COPY:
1304 operandSize = mapVkFormat(m_bufferFormat).getPixelSize();
1311 isOutOfBoundsAccess = (maxAccessRange < 16)
1312 || (((offsetInBytes / operandSize + 1) * operandSize) > (maxAccessRange - 16));
1315 if (isOutOfBoundsAccess)
1317 logMsg << " (out of bounds " << (isReadAccess ? "read": "write") << ")";
1319 const bool isValuePartiallyOutOfBounds = ((distanceToOutOfBounds > 0) && ((deUint32)distanceToOutOfBounds < 4));
1320 bool isValidValue = false;
1322 if (isValuePartiallyOutOfBounds && !m_accessOutOfBackingMemory)
1324 // The value is partially out of bounds
1326 bool isOutOfBoundsPartOk = true;
1327 bool isWithinBoundsPartOk = true;
1331 isWithinBoundsPartOk = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, distanceToOutOfBounds);
1332 isOutOfBoundsPartOk = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, (deUint8*)outValuePtr + distanceToOutOfBounds , outValueSize - distanceToOutOfBounds);
1336 isWithinBoundsPartOk = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, distanceToOutOfBounds)
1337 || isOutBufferValueUnchanged(offsetInBytes, distanceToOutOfBounds);
1339 isOutOfBoundsPartOk = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, (deUint8*)outValuePtr + distanceToOutOfBounds, outValueSize - distanceToOutOfBounds)
1340 || isOutBufferValueUnchanged(offsetInBytes + distanceToOutOfBounds, outValueSize - distanceToOutOfBounds);
1343 logMsg << ", first " << distanceToOutOfBounds << " byte(s) " << (isWithinBoundsPartOk ? "OK": "wrong");
1344 logMsg << ", last " << outValueSize - distanceToOutOfBounds << " byte(s) " << (isOutOfBoundsPartOk ? "OK": "wrong");
1346 isValidValue = isWithinBoundsPartOk && isOutOfBoundsPartOk;
1352 isValidValue = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, outValueSize);
1356 isValidValue = isOutBufferValueUnchanged(offsetInBytes, outValueSize);
1360 // Out of bounds writes may modify values withing the memory ranges bound to the buffer
1361 isValidValue = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, outValueSize);
1364 logMsg << ", OK, written within the memory range bound to the buffer";
1371 // Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
1372 // or the maximum representable positive integer value (if the format is integer-based).
1374 const bool canMatchVec4Pattern = (isReadAccess
1375 && !isValuePartiallyOutOfBounds
1376 && (m_shaderType == SHADER_TYPE_VECTOR_COPY || m_shaderType == SHADER_TYPE_TEXEL_COPY)
1377 && ((offsetInBytes / 4 + 1) % 4 == 0 || m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32));
1378 bool matchesVec4Pattern = false;
1380 if (canMatchVec4Pattern)
1382 if (m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1383 matchesVec4Pattern = verifyOutOfBoundsVec4(outValuePtr, m_bufferFormat);
1385 matchesVec4Pattern = verifyOutOfBoundsVec4(reinterpret_cast<deUint32*>(outValuePtr) - 3, m_bufferFormat);
1388 if (!canMatchVec4Pattern || !matchesVec4Pattern)
1390 logMsg << ". Failed: ";
1394 logMsg << "expected value within the buffer range or 0";
1396 if (canMatchVec4Pattern)
1397 logMsg << ", or the [0, 0, 0, x] pattern";
1401 logMsg << "written out of the range";
1408 else // We are within bounds
1412 if (!isExpectedValueFromInBuffer(offsetInBytes, outValuePtr, 4))
1414 logMsg << ", Failed: unexpected value";
1420 // Out of bounds writes may change values within the bounds.
1421 if (!isValueWithinBufferOrZero(inDataPtr, m_inBufferAccessRange, outValuePtr, 4))
1423 logMsg << ", Failed: unexpected value";
1431 log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
1436 // BufferReadInstance
1438 BufferReadInstance::BufferReadInstance (Context& context,
1439 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
1440 Move<VkDevice> device,
1441 #ifndef CTS_USES_VULKANSC
1442 de::MovePtr<vk::DeviceDriver> deviceDriver,
1444 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
1445 #endif // CTS_USES_VULKANSC
1446 ShaderType shaderType,
1447 VkShaderStageFlags shaderStage,
1448 VkFormat bufferFormat,
1449 bool readFromStorage,
1450 VkDeviceSize inBufferAccessRange,
1451 bool accessOutOfBackingMemory,
1452 bool testPipelineRobustness)
1454 : BufferAccessInstance (context, instanceWrapper, device, deviceDriver, shaderType, shaderStage, bufferFormat,
1455 readFromStorage ? BUFFER_ACCESS_TYPE_READ_FROM_STORAGE : BUFFER_ACCESS_TYPE_READ,
1456 inBufferAccessRange,
1457 RobustBufferAccessTest::s_numberOfBytesAccessed, // outBufferAccessRange
1458 accessOutOfBackingMemory,
1459 testPipelineRobustness)
1463 // BufferWriteInstance
1465 BufferWriteInstance::BufferWriteInstance (Context& context,
1466 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
1467 Move<VkDevice> device,
1468 #ifndef CTS_USES_VULKANSC
1469 de::MovePtr<vk::DeviceDriver> deviceDriver,
1471 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
1472 #endif // CTS_USES_VULKANSC
1473 ShaderType shaderType,
1474 VkShaderStageFlags shaderStage,
1475 VkFormat bufferFormat,
1476 VkDeviceSize writeBufferAccessRange,
1477 bool accessOutOfBackingMemory,
1478 bool testPipelineRobustness)
1480 : BufferAccessInstance (context, instanceWrapper, device, deviceDriver, shaderType, shaderStage, bufferFormat,
1481 BUFFER_ACCESS_TYPE_WRITE,
1482 RobustBufferAccessTest::s_numberOfBytesAccessed, // inBufferAccessRange
1483 writeBufferAccessRange,
1484 accessOutOfBackingMemory,
1485 testPipelineRobustness)
1489 // Test node creation functions
1491 static const char* getShaderStageName (VkShaderStageFlagBits shaderStage)
1493 switch (shaderStage)
1495 case VK_SHADER_STAGE_VERTEX_BIT: return "vertex";
1496 case VK_SHADER_STAGE_FRAGMENT_BIT: return "fragment";
1497 case VK_SHADER_STAGE_COMPUTE_BIT: return "compute";
1498 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return "tess_control";
1499 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return "tess_eval";
1500 case VK_SHADER_STAGE_GEOMETRY_BIT: return "geometry";
1509 static void addBufferAccessTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentNode, bool testPipelineRobustness)
1511 struct BufferRangeConfig
1517 const VkShaderStageFlagBits bufferAccessStages[] =
1519 VK_SHADER_STAGE_VERTEX_BIT,
1520 VK_SHADER_STAGE_FRAGMENT_BIT,
1521 VK_SHADER_STAGE_COMPUTE_BIT,
1524 const VkFormat bufferFormats[] =
1530 VK_FORMAT_R32_SFLOAT
1533 const VkFormat texelBufferFormats[] =
1535 VK_FORMAT_R32G32B32A32_SINT,
1536 VK_FORMAT_R32G32B32A32_UINT,
1537 VK_FORMAT_R32G32B32A32_SFLOAT,
1539 VK_FORMAT_A2B10G10R10_UNORM_PACK32
1542 const BufferRangeConfig bufferRangeConfigs[] =
1544 { "range_1_byte", 1ull },
1545 { "range_3_bytes", 3ull },
1546 { "range_4_bytes", 4ull }, // size of float
1547 { "range_32_bytes", 32ull }, // size of half mat4
1550 const BufferRangeConfig texelBufferRangeConfigs[] =
1552 { "range_1_texel", 1u },
1553 { "range_3_texels", 3u },
1556 const char* shaderTypeNames[SHADER_TYPE_COUNT] =
1564 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(bufferAccessStages); stageNdx++)
1566 const VkShaderStageFlagBits stage = bufferAccessStages[stageNdx];
1567 de::MovePtr<tcu::TestCaseGroup> stageTests (new tcu::TestCaseGroup(testCtx, getShaderStageName(stage), ""));
1569 for (int shaderTypeNdx = 0; shaderTypeNdx < SHADER_TYPE_COUNT; shaderTypeNdx++)
1571 const VkFormat* formats;
1572 size_t formatsLength;
1573 const BufferRangeConfig* ranges;
1574 size_t rangesLength;
1575 deUint32 rangeMultiplier;
1576 de::MovePtr<tcu::TestCaseGroup> shaderTypeTests (new tcu::TestCaseGroup(testCtx, shaderTypeNames[shaderTypeNdx], ""));
1578 if ((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY)
1580 formats = texelBufferFormats;
1581 formatsLength = DE_LENGTH_OF_ARRAY(texelBufferFormats);
1583 ranges = texelBufferRangeConfigs;
1584 rangesLength = DE_LENGTH_OF_ARRAY(texelBufferRangeConfigs);
1588 formats = bufferFormats;
1589 formatsLength = DE_LENGTH_OF_ARRAY(bufferFormats);
1591 ranges = bufferRangeConfigs;
1592 rangesLength = DE_LENGTH_OF_ARRAY(bufferRangeConfigs);
1595 for (size_t formatNdx = 0; formatNdx < formatsLength; formatNdx++)
1597 const VkFormat bufferFormat = formats[formatNdx];
1599 rangeMultiplier = ((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY) ? mapVkFormat(bufferFormat).getPixelSize() : 1;
1601 if (!isFloatFormat(bufferFormat) && ((ShaderType)shaderTypeNdx) == SHADER_TYPE_MATRIX_COPY)
1603 // Use SHADER_TYPE_MATRIX_COPY with floating-point formats only
1607 // Avoid too much duplication by excluding certain test cases
1608 if (testPipelineRobustness &&
1609 !(bufferFormat == VK_FORMAT_R32_UINT || bufferFormat == VK_FORMAT_R64_SINT || bufferFormat == VK_FORMAT_R32_SFLOAT || bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32))
1614 const std::string formatName = getFormatName(bufferFormat);
1615 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
1617 de::MovePtr<tcu::TestCaseGroup> uboReadTests (new tcu::TestCaseGroup(testCtx, "oob_uniform_read", ""));
1618 de::MovePtr<tcu::TestCaseGroup> ssboReadTests (new tcu::TestCaseGroup(testCtx, "oob_storage_read", ""));
1619 de::MovePtr<tcu::TestCaseGroup> ssboWriteTests (new tcu::TestCaseGroup(testCtx, "oob_storage_write", ""));
1621 for (size_t rangeNdx = 0; rangeNdx < rangesLength; rangeNdx++)
1623 const BufferRangeConfig& rangeConfig = ranges[rangeNdx];
1624 const VkDeviceSize rangeInBytes = rangeConfig.range * rangeMultiplier;
1626 uboReadTests->addChild(new RobustBufferReadTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, testPipelineRobustness, rangeInBytes, false, false));
1628 // Avoid too much duplication by excluding certain test cases
1629 if (!testPipelineRobustness)
1630 ssboReadTests->addChild(new RobustBufferReadTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, testPipelineRobustness, rangeInBytes, true, false));
1632 ssboWriteTests->addChild(new RobustBufferWriteTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, testPipelineRobustness, rangeInBytes, false));
1636 formatTests->addChild(uboReadTests.release());
1637 formatTests->addChild(ssboReadTests.release());
1638 formatTests->addChild(ssboWriteTests.release());
1640 shaderTypeTests->addChild(formatTests.release());
1643 // Read/write out of the memory that backs the buffer
1645 de::MovePtr<tcu::TestCaseGroup> outOfAllocTests (new tcu::TestCaseGroup(testCtx, "out_of_alloc", ""));
1647 const VkFormat format = (((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY ) ? VK_FORMAT_R32G32B32A32_SFLOAT : VK_FORMAT_R32_SFLOAT);
1649 outOfAllocTests->addChild(new RobustBufferReadTest(testCtx, "oob_uniform_read", "", stage, (ShaderType)shaderTypeNdx, format, testPipelineRobustness, 16, false, true));
1651 // Avoid too much duplication by excluding certain test cases
1652 if (!testPipelineRobustness)
1653 outOfAllocTests->addChild(new RobustBufferReadTest(testCtx, "oob_storage_read", "", stage, (ShaderType)shaderTypeNdx, format, testPipelineRobustness, 16, true, true));
1655 outOfAllocTests->addChild(new RobustBufferWriteTest(testCtx, "oob_storage_write", "", stage, (ShaderType)shaderTypeNdx, format, testPipelineRobustness, 16, true));
1657 shaderTypeTests->addChild(outOfAllocTests.release());
1660 stageTests->addChild(shaderTypeTests.release());
1662 parentNode->addChild(stageTests.release());
1666 tcu::TestCaseGroup* createBufferAccessTests (tcu::TestContext& testCtx)
1668 de::MovePtr<tcu::TestCaseGroup> bufferAccessTests (new tcu::TestCaseGroup(testCtx, "buffer_access", ""));
1670 addBufferAccessTests(testCtx, bufferAccessTests.get(), false);
1672 return bufferAccessTests.release();
1675 #ifndef CTS_USES_VULKANSC
1676 tcu::TestCaseGroup* createPipelineRobustnessBufferAccessTests (tcu::TestContext& testCtx)
1678 de::MovePtr<tcu::TestCaseGroup> bufferAccessTests (new tcu::TestCaseGroup(testCtx, "pipeline_robustness_buffer_access", ""));
1679 addBufferAccessTests(testCtx, bufferAccessTests.get(), true);
1681 return bufferAccessTests.release();