Add tests for empty structs in UBOs and SSBOs
authorPiotr Byszewski <piotr.byszewski@mobica.com>
Thu, 15 Oct 2020 07:26:11 +0000 (09:26 +0200)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Fri, 20 Nov 2020 10:53:50 +0000 (05:53 -0500)
Components: Vulkan

VK-GL-CTS issue: 2608

Affects:
dEQP-VK.spirv_assembly.*.compute.*

New tests:
dEQP-VK.spirv_assembly.instruction.compute.empty_struct.*

Change-Id: I078881e7b2ce24eaa99c4247901533dfc78c0c57

12 files changed:
AndroidGen.mk
android/cts/master/vk-master-2020-03-01.txt
android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.hpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmEmptyStructTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmEmptyStructTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.hpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
external/vulkancts/mustpass/master/vk-default.txt

index 5fde87e..b0c93b3 100644 (file)
@@ -343,6 +343,7 @@ LOCAL_SRC_FILES := \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmConditionalBranchTests.cpp \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmCrossStageInterfaceTests.cpp \
+       external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmEmptyStructTests.cpp \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmFloatControlsExtensionlessTests.cpp \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmFloatControlsTests.cpp \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmFromHlslTests.cpp \
index 6a98592..91820ee 100644 (file)
@@ -153298,6 +153298,11 @@ dEQP-VK.spirv_assembly.instruction.compute.ptr_access_chain.workgroup_no_stride
 dEQP-VK.spirv_assembly.instruction.compute.ptr_access_chain.workgroup_bad_stride
 dEQP-VK.spirv_assembly.instruction.compute.vector_shuffle.vector_shuffle
 dEQP-VK.spirv_assembly.instruction.compute.hlsl_cases.cbuffer_packing
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_object_ubo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_memory_ubo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_object_ssbo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_memory_ssbo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.pointer_comparison.ssbo
 dEQP-VK.spirv_assembly.instruction.compute.64bit_compare.double.comp_opfordequal_nonan_single
 dEQP-VK.spirv_assembly.instruction.compute.64bit_compare.double.comp_opfordnotequal_nonan_single
 dEQP-VK.spirv_assembly.instruction.compute.64bit_compare.double.comp_opfordlessthan_nonan_single
index 0e46d62..0005c40 100644 (file)
@@ -392920,6 +392920,11 @@ dEQP-VK.spirv_assembly.instruction.compute.ptr_access_chain.workgroup_no_stride
 dEQP-VK.spirv_assembly.instruction.compute.ptr_access_chain.workgroup_bad_stride
 dEQP-VK.spirv_assembly.instruction.compute.vector_shuffle.vector_shuffle
 dEQP-VK.spirv_assembly.instruction.compute.hlsl_cases.cbuffer_packing
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_object_ubo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_memory_ubo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_object_ssbo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_memory_ssbo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.pointer_comparison.ssbo
 dEQP-VK.spirv_assembly.instruction.compute.64bit_compare.double.comp_opfordequal_nonan_single
 dEQP-VK.spirv_assembly.instruction.compute.64bit_compare.double.comp_opfordnotequal_nonan_single
 dEQP-VK.spirv_assembly.instruction.compute.64bit_compare.double.comp_opfordlessthan_nonan_single
index abaae17..c542c6e 100644 (file)
@@ -9,6 +9,8 @@ set(DEQP_VK_SPIRV_ASSEMBLY_SRCS
        vktSpvAsmCrossStageInterfaceTests.hpp
        vktSpvAsm16bitStorageTests.cpp
        vktSpvAsm16bitStorageTests.hpp
+       vktSpvAsmEmptyStructTests.cpp
+       vktSpvAsmEmptyStructTests.hpp
        vktSpvAsmFloatControlsTests.cpp
        vktSpvAsmFloatControlsTests.hpp
        vktSpvAsmFromHlslTests.cpp
index 868267f..eb22247 100644 (file)
@@ -369,67 +369,21 @@ SpvAsmComputeShaderCase::SpvAsmComputeShaderCase (tcu::TestContext& testCtx, con
 {
 }
 
-void SpvAsmComputeShaderCase::initPrograms (SourceCollections& programCollection) const
+void SpvAsmComputeShaderCase::checkSupport(Context& context) const
 {
-       programCollection.spirvAsmSources.add("compute") << m_shaderSpec.assembly.c_str() << SpirVAsmBuildOptions(programCollection.usedVulkanVersion, m_shaderSpec.spirvVersion);
-}
-
-TestInstance* SpvAsmComputeShaderCase::createInstance (Context& ctx) const
-{
-       if (getMinRequiredVulkanVersion(m_shaderSpec.spirvVersion) > ctx.getUsedApiVersion())
+       if (getMinRequiredVulkanVersion(m_shaderSpec.spirvVersion) > context.getUsedApiVersion())
        {
                TCU_THROW(NotSupportedError, std::string("Vulkan higher than or equal to " + getVulkanName(getMinRequiredVulkanVersion(m_shaderSpec.spirvVersion)) + " is required for this test to run").c_str());
        }
-       return new SpvAsmComputeShaderInstance(ctx, m_shaderSpec);
-}
-
-// ComputeShaderTestInstance implementations
-
-SpvAsmComputeShaderInstance::SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec)
-       : TestInstance          (ctx)
-       , m_shaderSpec          (spec)
-{
-}
-
-VkImageUsageFlags getMatchingComputeImageUsageFlags (VkDescriptorType dType)
-{
-       switch (dType)
-       {
-               case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:                  return VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-               case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:                  return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-               case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-               default:                                                                                DE_FATAL("Not implemented");
-       }
-       return (VkImageUsageFlags)0;
-}
-
-tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
-{
-       const deUint32                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
-       const VkDevice&                                         device                          = m_context.getDevice();
-       const DeviceInterface&                          vkdi                            = m_context.getDeviceInterface();
-       Allocator&                                                      allocator                       = m_context.getDefaultAllocator();
-       const VkQueue                                           queue                           = m_context.getUniversalQueue();
-
-       vector<AllocationSp>                            inputAllocs;
-       vector<AllocationSp>                            outputAllocs;
-       vector<BufferHandleSp>                          inputBuffers;
-       vector<ImageHandleSp>                           inputImages;
-       vector<ImageViewHandleSp>                       inputImageViews;
-       vector<SamplerHandleSp>                         inputSamplers;
-       vector<BufferHandleSp>                          outputBuffers;
-       vector<VkDescriptorBufferInfo>          descriptorInfos;
-       vector<VkDescriptorImageInfo>           descriptorImageInfos;
-       vector<VkDescriptorType>                        descriptorTypes;
 
        // Check all required extensions are supported
        for (const auto& ext : m_shaderSpec.extensions)
-               m_context.requireDeviceFunctionality(ext);
+               context.requireDeviceFunctionality(ext);
 
        // Core features
        {
-               const char*                                             unsupportedFeature                      = DE_NULL;
-               vk::VkPhysicalDeviceFeatures    localRequiredCoreFeatures       = m_shaderSpec.requestedVulkanFeatures.coreFeatures;
+               const char*                                             unsupportedFeature = DE_NULL;
+               vk::VkPhysicalDeviceFeatures    localRequiredCoreFeatures = m_shaderSpec.requestedVulkanFeatures.coreFeatures;
 
                // Skip check features not targeted to compute
                localRequiredCoreFeatures.fullDrawIndexUint32                                           = DE_FALSE;
@@ -458,49 +412,94 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
                localRequiredCoreFeatures.sparseBinding                                                         = DE_FALSE;
                localRequiredCoreFeatures.variableMultisampleRate                                       = DE_FALSE;
 
-               if (!isCoreFeaturesSupported(m_context, localRequiredCoreFeatures, &unsupportedFeature))
+               if (!isCoreFeaturesSupported(context, localRequiredCoreFeatures, &unsupportedFeature))
                        TCU_THROW(NotSupportedError, std::string("At least following requested core feature is not supported: ") + unsupportedFeature);
        }
 
        // Extension features
        {
                // 8bit storage features
-               {
-                       if (!is8BitStorageFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.ext8BitStorage))
-                               TCU_THROW(NotSupportedError, "Requested 8bit storage features not supported");
-               }
+               if (!is8BitStorageFeaturesSupported(context, m_shaderSpec.requestedVulkanFeatures.ext8BitStorage))
+                       TCU_THROW(NotSupportedError, "Requested 8bit storage features not supported");
 
                // 16bit storage features
-               {
-                       if (!is16BitStorageFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.ext16BitStorage))
-                               TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported");
-               }
+               if (!is16BitStorageFeaturesSupported(context, m_shaderSpec.requestedVulkanFeatures.ext16BitStorage))
+                       TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported");
 
                // VariablePointers features
-               {
-                       if (!isVariablePointersFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.extVariablePointers))
-                               TCU_THROW(NotSupportedError, "Requested Variable Pointer feature not supported");
-               }
+               if (!isVariablePointersFeaturesSupported(context, m_shaderSpec.requestedVulkanFeatures.extVariablePointers))
+                       TCU_THROW(NotSupportedError, "Requested Variable Pointer feature not supported");
 
                // Float16/Int8 shader features
-               {
-                       if (!isFloat16Int8FeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.extFloat16Int8))
-                               TCU_THROW(NotSupportedError, "Requested 16bit float or 8bit int feature not supported");
-               }
+               if (!isFloat16Int8FeaturesSupported(context, m_shaderSpec.requestedVulkanFeatures.extFloat16Int8))
+                       TCU_THROW(NotSupportedError, "Requested 16bit float or 8bit int feature not supported");
 
                // Vulkan Memory Model features
-               {
-                       if (!isVulkanMemoryModelFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.extVulkanMemoryModel))
-                               TCU_THROW(NotSupportedError, "Requested Vulkan Memory Model feature not supported");
-               }
+               if (!isVulkanMemoryModelFeaturesSupported(context, m_shaderSpec.requestedVulkanFeatures.extVulkanMemoryModel))
+                       TCU_THROW(NotSupportedError, "Requested Vulkan Memory Model feature not supported");
 
                // FloatControls features
-               if (!isFloatControlsFeaturesSupported(m_context, m_shaderSpec.requestedVulkanFeatures.floatControlsProperties))
+               if (!isFloatControlsFeaturesSupported(context, m_shaderSpec.requestedVulkanFeatures.floatControlsProperties))
                        TCU_THROW(NotSupportedError, "Requested Float Controls features not supported");
 
-               if (m_shaderSpec.usesPhysStorageBuffer && !m_context.isBufferDeviceAddressSupported())
+               if (m_shaderSpec.usesPhysStorageBuffer && !context.isBufferDeviceAddressSupported())
                        TCU_THROW(NotSupportedError, "Request physical storage buffer feature not supported");
        }
+}
+
+void SpvAsmComputeShaderCase::initPrograms (SourceCollections& programCollection) const
+{
+       const auto&     extensions              = m_shaderSpec.extensions;
+       const bool      allowSpirv14    = (std::find(extensions.begin(), extensions.end(), "VK_KHR_spirv_1_4") != extensions.end());
+
+       programCollection.spirvAsmSources.add("compute")
+               << m_shaderSpec.assembly.c_str()
+               << SpirVAsmBuildOptions(programCollection.usedVulkanVersion, m_shaderSpec.spirvVersion, allowSpirv14);
+}
+
+TestInstance* SpvAsmComputeShaderCase::createInstance (Context& ctx) const
+{
+       return new SpvAsmComputeShaderInstance(ctx, m_shaderSpec);
+}
+
+// ComputeShaderTestInstance implementations
+
+SpvAsmComputeShaderInstance::SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec)
+       : TestInstance          (ctx)
+       , m_shaderSpec          (spec)
+{
+}
+
+VkImageUsageFlags getMatchingComputeImageUsageFlags (VkDescriptorType dType)
+{
+       switch (dType)
+       {
+               case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:                  return VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+               case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:                  return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+               case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+               default:                                                                                DE_FATAL("Not implemented");
+       }
+       return (VkImageUsageFlags)0;
+}
+
+tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
+{
+       const deUint32                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       const VkDevice&                                         device                          = m_context.getDevice();
+       const DeviceInterface&                          vkdi                            = m_context.getDeviceInterface();
+       Allocator&                                                      allocator                       = m_context.getDefaultAllocator();
+       const VkQueue                                           queue                           = m_context.getUniversalQueue();
+
+       vector<AllocationSp>                            inputAllocs;
+       vector<AllocationSp>                            outputAllocs;
+       vector<BufferHandleSp>                          inputBuffers;
+       vector<ImageHandleSp>                           inputImages;
+       vector<ImageViewHandleSp>                       inputImageViews;
+       vector<SamplerHandleSp>                         inputSamplers;
+       vector<BufferHandleSp>                          outputBuffers;
+       vector<VkDescriptorBufferInfo>          descriptorInfos;
+       vector<VkDescriptorImageInfo>           descriptorImageInfos;
+       vector<VkDescriptorType>                        descriptorTypes;
 
        DE_ASSERT(!m_shaderSpec.outputs.empty());
 
index e46e32b..b19dd04 100644 (file)
@@ -57,6 +57,7 @@ class SpvAsmComputeShaderCase : public TestCase
 {
 public:
                                                SpvAsmComputeShaderCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec);
+       void                            checkSupport                    (Context& context) const;
        void                            initPrograms                    (vk::SourceCollections& programCollection) const;
        TestInstance*           createInstance                  (Context& ctx) const;
 
index 18f2b63..08017ab 100644 (file)
@@ -353,7 +353,6 @@ struct ComputeShaderSpec
        SpirvVersion                                                    spirvVersion;
        bool                                                                    coherentMemory;
        bool                                                                    usesPhysStorageBuffer;
-       bool                                                                    spirvVersion14;
 
                                                                                        ComputeShaderSpec (void)
                                                                                                : entryPoint                                    ("main")
@@ -366,7 +365,6 @@ struct ComputeShaderSpec
                                                                                                , spirvVersion                                  (SPIRV_VERSION_1_0)
                                                                                                , coherentMemory                                (false)
                                                                                                , usesPhysStorageBuffer                 (false)
-                                                                                               , spirvVersion14                                (false)
                                                                                        {}
 };
 
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmEmptyStructTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmEmptyStructTests.cpp
new file mode 100644 (file)
index 0000000..4fc60c5
--- /dev/null
@@ -0,0 +1,312 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2020 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Test copying struct which contains an empty struct.
+                 Test pointer comparisons of empty struct members.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+#include "vktSpvAsmComputeShaderCase.hpp"
+#include "vktSpvAsmEmptyStructTests.hpp"
+#include "tcuStringTemplate.hpp"
+#include "vktTestGroupUtil.hpp"
+#include "vktSpvAsmUtils.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+namespace
+{
+
+bool verifyResult(const std::vector<Resource>&,
+                                 const std::vector<AllocationSp>&      outputAllocs,
+                                 const std::vector<Resource>&          expectedOutputs,
+                                 tcu::TestLog&)
+{
+       for (deUint32 outputNdx = 0; outputNdx < static_cast<deUint32>(outputAllocs.size()); ++outputNdx)
+       {
+               std::vector<deUint8> expectedBytes;
+               expectedOutputs[outputNdx].getBytes(expectedBytes);
+
+               const deUint32  itemCount       = static_cast<deUint32>(expectedBytes.size()) / 4u;
+               const deUint32* returned        = static_cast<const deUint32*>(outputAllocs[outputNdx]->getHostPtr());
+               const deUint32* expected        = reinterpret_cast<const deUint32*>(&expectedBytes.front());
+
+               for (deUint32 i = 0; i < itemCount; ++i)
+               {
+                       // skip items with 0 as this is used to mark empty structure
+                       if (expected[i] == 0)
+                               continue;
+                       if (expected[i] != returned[i])
+                               return false;
+               }
+       }
+       return true;
+}
+
+void addCopyingComputeGroup(tcu::TestCaseGroup* group)
+{
+       const tcu::StringTemplate shaderTemplate(
+               "OpCapability Shader\n"
+
+               "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
+
+               "OpMemoryModel Logical GLSL450\n"
+               "OpEntryPoint GLCompute %main \"main\" %var_id\n"
+               "OpExecutionMode %main LocalSize 1 1 1\n"
+
+               "OpDecorate %var_id BuiltIn GlobalInvocationId\n"
+               "OpDecorate %var_input Binding 0\n"
+               "OpDecorate %var_input DescriptorSet 0\n"
+
+               "OpDecorate %var_outdata Binding 1\n"
+               "OpDecorate %var_outdata DescriptorSet 0\n"
+
+               "OpMemberDecorate %type_container_struct 0 Offset 0\n"
+               "OpMemberDecorate %type_container_struct 1 Offset ${OFFSET_1}\n"
+               "OpMemberDecorate %type_container_struct 2 Offset ${OFFSET_2}\n"
+               "OpMemberDecorate %type_container_struct 3 Offset ${OFFSET_3}\n"
+               "OpDecorate %type_container_struct Block\n"
+
+               + std::string(getComputeAsmCommonTypes()) +
+
+               //struct EmptyStruct {};
+               //struct ContainerStruct {
+               //  int i;
+               //  A a1;
+               //  A a2;
+               //  int j;
+               //};
+               //layout(set=, binding = ) buffer block B b;
+
+               // types
+               "%type_empty_struct                                     = OpTypeStruct\n"
+               "%type_container_struct                         = OpTypeStruct %i32 %type_empty_struct %type_empty_struct %i32\n"
+
+               "%type_container_struct_ubo_ptr         = OpTypePointer Uniform %type_container_struct\n"
+               "%type_container_struct_ssbo_ptr        = OpTypePointer StorageBuffer %type_container_struct\n"
+
+               // variables
+               "%var_id                                                        = OpVariable %uvec3ptr Input\n"
+               "${VARIABLES}\n"
+
+               // void main function
+               "%main                                                          = OpFunction %void None %voidf\n"
+               "%label                                                         = OpLabel\n"
+
+               "${COPYING_METHOD}"
+
+               "OpReturn\n"
+               "OpFunctionEnd\n");
+
+       struct BufferType
+       {
+               std::string                             name;
+               VkDescriptorType                descriptorType;
+               std::vector<deUint32>   offsets;
+               std::vector<int>                input;
+               std::vector<int>                expectedOutput;
+               std::string                             spirvVariables;
+               std::string                             spirvCopyObject;
+       };
+       std::vector<BufferType> bufferTypes
+       {
+               {
+                       "ubo",
+                       VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+
+                       // structure decorated as Block for variable in Uniform storage class
+                       // must follow relaxed uniform buffer layout rules and be aligned to 16
+                       {0, 16, 32, 48},
+                       {2, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 0},
+                       {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0},
+
+                       "%var_input                                             = OpVariable %type_container_struct_ubo_ptr Uniform\n"
+                       "%var_outdata                                   = OpVariable %type_container_struct_ssbo_ptr StorageBuffer\n",
+
+                       "%input_copy                                    = OpCopyObject %type_container_struct_ubo_ptr %var_input\n"
+               },
+               {
+                       "ssbo",
+                       VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+
+                       {0, 4, 8, 12},
+                       {2, 3, 5, 7 },
+                       {2, 0, 0, 7 },
+
+                       "%var_input                                             = OpVariable %type_container_struct_ssbo_ptr StorageBuffer\n"
+                       "%var_outdata                                   = OpVariable %type_container_struct_ssbo_ptr StorageBuffer\n",
+
+                       "%input_copy                                    = OpCopyObject %type_container_struct_ssbo_ptr %var_input\n"
+               }
+       };
+
+       struct CopyingMethod
+       {
+               std::string name;
+               std::string spirvCopyCode;
+       };
+       std::vector<CopyingMethod> copyingMethods
+       {
+               {
+                       "copy_object",
+
+                       "%result                                                = OpLoad %type_container_struct %input_copy\n"
+                       "OpStore %var_outdata %result\n"
+               },
+               {
+                       "copy_memory",
+
+                       "OpCopyMemory %var_outdata %var_input\n"
+               }
+       };
+
+       for (const auto& bufferType : bufferTypes)
+       {
+               for (const auto& copyingMethod : copyingMethods)
+               {
+                       std::string name = copyingMethod.name + "_" + bufferType.name;
+
+                       std::map<std::string, std::string> specializationMap
+                       {
+                               { "OFFSET_1",           de::toString(bufferType.offsets[1]) },
+                               { "OFFSET_2",           de::toString(bufferType.offsets[2]) },
+                               { "OFFSET_3",           de::toString(bufferType.offsets[3]) },
+                               { "VARIABLES",          bufferType.spirvVariables },
+
+                               // NOTE: to simlify code spirvCopyObject is added also when OpCopyMemory is used
+                               { "COPYING_METHOD", bufferType.spirvCopyObject + copyingMethod.spirvCopyCode },
+                       };
+
+                       ComputeShaderSpec spec;
+                       spec.assembly           = shaderTemplate.specialize(specializationMap);
+                       spec.numWorkGroups      = tcu::IVec3(1, 1, 1);
+                       spec.verifyIO           = verifyResult;
+                       spec.inputs.push_back (Resource(BufferSp(new Int32Buffer(bufferType.input)), bufferType.descriptorType));
+                       spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(bufferType.expectedOutput))));
+                       group->addChild(new SpvAsmComputeShaderCase(group->getTestContext(), name.c_str(), "", spec));
+               }
+       }
+}
+
+void addPointerComparisionComputeGroup(tcu::TestCaseGroup* group)
+{
+       // NOTE: pointer comparison is possible only for StorageBuffer storage class
+
+       std::string computeSource =
+               "OpCapability Shader\n"
+               "OpCapability VariablePointersStorageBuffer\n"
+
+               "OpMemoryModel Logical GLSL450\n"
+               "OpEntryPoint GLCompute %main \"main\" %var_id %var_input %var_outdata\n"
+               "OpExecutionMode %main LocalSize 1 1 1\n"
+
+               "OpDecorate %var_id BuiltIn GlobalInvocationId\n"
+               "OpDecorate %var_input Binding 0\n"
+               "OpDecorate %var_input DescriptorSet 0\n"
+
+               "OpDecorate %var_outdata Binding 1\n"
+               "OpDecorate %var_outdata DescriptorSet 0\n"
+
+               "OpMemberDecorate %type_container_struct 0 Offset 0\n"
+               "OpMemberDecorate %type_container_struct 1 Offset 4\n"
+               "OpMemberDecorate %type_container_struct 2 Offset 8\n"
+               "OpMemberDecorate %type_container_struct 3 Offset 12\n"
+               "OpDecorate %type_container_struct Block\n"
+
+               "OpMemberDecorate %type_i32_struct 0 Offset 0\n"
+               "OpDecorate %type_i32_struct Block\n"
+
+               + std::string(getComputeAsmCommonTypes("StorageBuffer")) +
+
+               //struct EmptyStruct {};
+               //struct ContainerStruct {
+               //  int i;
+               //  A a1;
+               //  A a2;
+               //  int j;
+               //};
+               //layout(set=, binding = ) buffer block B b;
+
+               // types
+               "%type_empty_struct                                     = OpTypeStruct\n"
+               "%type_container_struct                         = OpTypeStruct %i32 %type_empty_struct %type_empty_struct %i32\n"
+               "%type_i32_struct                                       = OpTypeStruct %i32\n"
+
+               // constants
+               "%c_i32_0                                                       = OpConstant %i32 0\n"
+               "%c_i32_1                                                       = OpConstant %i32 1\n"
+               "%c_i32_2                                                       = OpConstant %i32 2\n"
+
+               "%type_container_struct_in_ptr          = OpTypePointer StorageBuffer %type_container_struct\n"
+               "%type_i32_struct_out_ptr                       = OpTypePointer StorageBuffer %type_i32_struct\n"
+
+               "%type_func_struct_ptr_ptr                      = OpTypePointer StorageBuffer %type_empty_struct\n"
+
+               // variables
+               "%var_id                                                        = OpVariable %uvec3ptr Input\n"
+               "%var_input                                                     = OpVariable %type_container_struct_in_ptr StorageBuffer\n"
+               "%var_outdata                                           = OpVariable %type_i32_struct_out_ptr StorageBuffer\n"
+
+               // void main function
+               "%main                                                          = OpFunction %void None %voidf\n"
+               "%label                                                         = OpLabel\n"
+
+               // compare pointers to empty structures
+               "%ptr_to_first                                          = OpAccessChain %type_func_struct_ptr_ptr %var_input %c_i32_1\n"
+               "%ptr_to_second                                         = OpAccessChain %type_func_struct_ptr_ptr %var_input %c_i32_2\n"
+               "%pointers_not_equal                            = OpPtrNotEqual %bool %ptr_to_first %ptr_to_second\n"
+               "%result                                                        = OpSelect %i32 %pointers_not_equal %c_i32_1 %c_i32_0\n"
+               "%outloc                                                        = OpAccessChain %i32ptr %var_outdata %c_i32_0\n"
+               "OpStore %outloc %result\n"
+
+               "OpReturn\n"
+               "OpFunctionEnd\n";
+
+       tcu::TestContext&       testCtx                 = group->getTestContext();
+       std::vector<int>        input                   = { 2, 3, 5, 7 };
+       std::vector<int>        expectedOutput  = { 1 };
+
+       ComputeShaderSpec spec;
+       spec.assembly           = computeSource;
+       spec.numWorkGroups      = tcu::IVec3(1, 1, 1);
+       spec.spirvVersion       = SPIRV_VERSION_1_4;
+       spec.requestedVulkanFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER;
+       spec.inputs.push_back (Resource(BufferSp(new Int32Buffer(input))));
+       spec.outputs.push_back(Resource(BufferSp(new Int32Buffer(expectedOutput))));
+       spec.extensions.push_back("VK_KHR_spirv_1_4");
+       group->addChild(new SpvAsmComputeShaderCase(testCtx, "ssbo", "", spec));
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createEmptyStructComputeGroup (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> group   (new tcu::TestCaseGroup(testCtx, "empty_struct", "Tests empty structs in UBOs and SSBOs"));
+
+       addTestGroup(group.get(), "copying",                    "Test copying struct which contains an empty struct",   addCopyingComputeGroup);
+       addTestGroup(group.get(), "pointer_comparison", "Test pointer comparisons of empty struct members",             addPointerComparisionComputeGroup);
+
+       return group.release();
+}
+
+} // SpirVAssembly
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmEmptyStructTests.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmEmptyStructTests.hpp
new file mode 100644 (file)
index 0000000..4e887a9
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _VKTSPVASMEMPTYSTRUCTTESTS_HPP
+#define _VKTSPVASMEMPTYSTRUCTTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2020 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Test copying struct which contains an empty struct.
+                 Test pointer comparisons of empty struct members.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+tcu::TestCaseGroup*    createEmptyStructComputeGroup   (tcu::TestContext& testCtx);
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMEMPTYSTRUCTTESTS_HPP
index cc006f1..f5cdea6 100644 (file)
@@ -99,14 +99,12 @@ struct GraphicsResources
        VerifyIOFunc                            verifyIO;
        GraphicsVerifyBinaryFunc        verifyBinary;
        SpirvVersion                            spirvVersion;
-       bool                                            spirvVersion14;
 
                                                        GraphicsResources()
                                                                : inputFormat           (VK_FORMAT_R32G32B32A32_SFLOAT)
                                                                , verifyIO                      (DE_NULL)
                                                                , verifyBinary          (DE_NULL)
                                                                , spirvVersion          (SPIRV_VERSION_1_0)
-                                                               , spirvVersion14        (false)
                                                        {}
 };
 
index 276bc5c..9ca03b2 100644 (file)
@@ -63,6 +63,7 @@
 #include "vktSpvAsmComputeShaderTestUtil.hpp"
 #include "vktSpvAsmFloatControlsTests.hpp"
 #include "vktSpvAsmFromHlslTests.hpp"
+#include "vktSpvAsmEmptyStructTests.hpp"
 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
 #include "vktSpvAsmVariablePointersTests.hpp"
 #include "vktSpvAsmVariableInitTests.hpp"
@@ -20469,6 +20470,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        computeTests->addChild(createPtrAccessChainGroup(testCtx));
        computeTests->addChild(createVectorShuffleGroup(testCtx));
        computeTests->addChild(createHlslComputeGroup(testCtx));
+       computeTests->addChild(createEmptyStructComputeGroup(testCtx));
        computeTests->addChild(create64bitCompareComputeGroup(testCtx));
        computeTests->addChild(createOpArrayLengthComputeGroup(testCtx));
 
index 3312c1a..06bdfaf 100644 (file)
@@ -392926,6 +392926,11 @@ dEQP-VK.spirv_assembly.instruction.compute.ptr_access_chain.workgroup_no_stride
 dEQP-VK.spirv_assembly.instruction.compute.ptr_access_chain.workgroup_bad_stride
 dEQP-VK.spirv_assembly.instruction.compute.vector_shuffle.vector_shuffle
 dEQP-VK.spirv_assembly.instruction.compute.hlsl_cases.cbuffer_packing
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_object_ubo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_memory_ubo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_object_ssbo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.copying.copy_memory_ssbo
+dEQP-VK.spirv_assembly.instruction.compute.empty_struct.pointer_comparison.ssbo
 dEQP-VK.spirv_assembly.instruction.compute.64bit_compare.double.comp_opfordequal_nonan_single
 dEQP-VK.spirv_assembly.instruction.compute.64bit_compare.double.comp_opfordnotequal_nonan_single
 dEQP-VK.spirv_assembly.instruction.compute.64bit_compare.double.comp_opfordlessthan_nonan_single