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 \
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
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
vktSpvAsmCrossStageInterfaceTests.hpp
vktSpvAsm16bitStorageTests.cpp
vktSpvAsm16bitStorageTests.hpp
+ vktSpvAsmEmptyStructTests.cpp
+ vktSpvAsmEmptyStructTests.hpp
vktSpvAsmFloatControlsTests.cpp
vktSpvAsmFloatControlsTests.hpp
vktSpvAsmFromHlslTests.cpp
{
}
-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;
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());
{
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;
SpirvVersion spirvVersion;
bool coherentMemory;
bool usesPhysStorageBuffer;
- bool spirvVersion14;
ComputeShaderSpec (void)
: entryPoint ("main")
, spirvVersion (SPIRV_VERSION_1_0)
, coherentMemory (false)
, usesPhysStorageBuffer (false)
- , spirvVersion14 (false)
{}
};
--- /dev/null
+/*------------------------------------------------------------------------
+ * 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
--- /dev/null
+#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
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)
{}
};
#include "vktSpvAsmComputeShaderTestUtil.hpp"
#include "vktSpvAsmFloatControlsTests.hpp"
#include "vktSpvAsmFromHlslTests.hpp"
+#include "vktSpvAsmEmptyStructTests.hpp"
#include "vktSpvAsmGraphicsShaderTestUtil.hpp"
#include "vktSpvAsmVariablePointersTests.hpp"
#include "vktSpvAsmVariableInitTests.hpp"
computeTests->addChild(createPtrAccessChainGroup(testCtx));
computeTests->addChild(createVectorShuffleGroup(testCtx));
computeTests->addChild(createHlslComputeGroup(testCtx));
+ computeTests->addChild(createEmptyStructComputeGroup(testCtx));
computeTests->addChild(create64bitCompareComputeGroup(testCtx));
computeTests->addChild(createOpArrayLengthComputeGroup(testCtx));
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