From 38cdcf98c372cb8af8a865dc64c2d3e287d3a8ae Mon Sep 17 00:00:00 2001 From: Pyry Haulos Date: Wed, 14 Jun 2017 11:54:31 -0700 Subject: [PATCH] Cherry-pick SPIR-V assembly test improvements These SPIR-V assembly test framework improvements are needed by new SPIR-V tests. Contains following commits, sans new tests: e47e81cda3ab7215d6089f4f5f631fa4f4385e10 ca8cfd0d24bc210c1cfeb3ded0c2c0d2492aa66b 56bd1576eb438e10e8ccb22e17b08354fbf3bac7 56f121e90ff24a88b375db1a74c296d17dd97a74 05e91483c6f2f48b408ed1a638cbb32468ed8dfa fc1e2f0942477676e92f7fe632ef441a90f570f8 318e6d042b1aaa15327342b39967f0ae97d23347 c35c2901d9d604631326eec11b80b3e6b7b7d55f 0d10dbfa6e176e18f69edcace62f921bb5225168 251a30e3cf94411b7453dd4e05cf24e1d45f579e 4fe79607bfac070a32d9554e3705379073e3672b 8977777244ce058cb79e1cf3b43e528322e8308c 6a51980397447d1f726e71d9126e47f84dc80a6f Change-Id: Ibedf226d3160365651155327dac50e8e9987a6d4 --- Android.mk | 2 + .../vulkancts/framework/vulkan/vkBasicTypes.inl | 1 + external/vulkancts/framework/vulkan/vkStrUtil.inl | 1 + .../vulkancts/framework/vulkan/vkStrUtilImpl.inl | 14 + .../vulkancts/framework/vulkan/vkStructTypes.inl | 10 + .../modules/vulkan/spirv_assembly/CMakeLists.txt | 4 + .../spirv_assembly/vktSpvAsmComputeShaderCase.cpp | 216 +- .../spirv_assembly/vktSpvAsmComputeShaderCase.hpp | 28 +- .../vktSpvAsmComputeShaderTestUtil.cpp | 56 +- .../vktSpvAsmComputeShaderTestUtil.hpp | 63 +- .../vktSpvAsmGraphicsShaderTestUtil.cpp | 3490 ++++++++++++++++++++ .../vktSpvAsmGraphicsShaderTestUtil.hpp | 553 ++++ .../spirv_assembly/vktSpvAsmInstructionTests.cpp | 2583 +-------------- .../vulkan/spirv_assembly/vktSpvAsmUtils.cpp | 151 + .../vulkan/spirv_assembly/vktSpvAsmUtils.hpp | 84 + external/vulkancts/scripts/src/vulkan.h.in | 14 + 16 files changed, 4733 insertions(+), 2537 deletions(-) create mode 100644 external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp create mode 100644 external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.hpp create mode 100644 external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.cpp create mode 100644 external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.hpp diff --git a/Android.mk b/Android.mk index 51a82b4..d032bb7 100644 --- a/Android.mk +++ b/Android.mk @@ -855,8 +855,10 @@ LOCAL_SRC_FILES := \ external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesTestsUtil.cpp \ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp \ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp \ + external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp \ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp \ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmTests.cpp \ + external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.cpp \ external/vulkancts/modules/vulkan/ssbo/vktSSBOLayoutCase.cpp \ external/vulkancts/modules/vulkan/ssbo/vktSSBOLayoutTests.cpp \ external/vulkancts/modules/vulkan/synchronization/vktSynchronizationBasicEventTests.cpp \ diff --git a/external/vulkancts/framework/vulkan/vkBasicTypes.inl b/external/vulkancts/framework/vulkan/vkBasicTypes.inl index ca9cf41..ea03621 100644 --- a/external/vulkancts/framework/vulkan/vkBasicTypes.inl +++ b/external/vulkancts/framework/vulkan/vkBasicTypes.inl @@ -157,6 +157,7 @@ enum VkStructureType VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = 1000083000, VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000, VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000, VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000, diff --git a/external/vulkancts/framework/vulkan/vkStrUtil.inl b/external/vulkancts/framework/vulkan/vkStrUtil.inl index cb8ccda..f65183f 100644 --- a/external/vulkancts/framework/vulkan/vkStrUtil.inl +++ b/external/vulkancts/framework/vulkan/vkStrUtil.inl @@ -336,6 +336,7 @@ std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceMemoryPropertie std::ostream& operator<< (std::ostream& s, const VkSparseImageFormatProperties2KHR& value); std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceSparseImageFormatInfo2KHR& value); std::ostream& operator<< (std::ostream& s, const VkPhysicalDevicePushDescriptorPropertiesKHR& value); +std::ostream& operator<< (std::ostream& s, const VkPhysicalDevice16BitStorageFeaturesKHR& value); std::ostream& operator<< (std::ostream& s, const VkRectLayerKHR& value); std::ostream& operator<< (std::ostream& s, const VkPresentRegionKHR& value); std::ostream& operator<< (std::ostream& s, const VkPresentRegionsKHR& value); diff --git a/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl b/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl index e919afc..cfd9ed2 100644 --- a/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl +++ b/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl @@ -170,6 +170,7 @@ const char* getStructureTypeName (VkStructureType value) case VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR: return "VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR"; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR: return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR"; case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR: return "VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR"; case VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR: return "VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR"; case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE: return "VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE"; @@ -3415,6 +3416,19 @@ std::ostream& operator<< (std::ostream& s, const VkPhysicalDevicePushDescriptorP return s; } +std::ostream& operator<< (std::ostream& s, const VkPhysicalDevice16BitStorageFeaturesKHR& value) +{ + s << "VkPhysicalDevice16BitStorageFeaturesKHR = {\n"; + s << "\tsType = " << value.sType << '\n'; + s << "\tpNext = " << value.pNext << '\n'; + s << "\tstorageUniformBufferBlock16 = " << value.storageUniformBufferBlock16 << '\n'; + s << "\tstorageUniform16 = " << value.storageUniform16 << '\n'; + s << "\tstoragePushConstant16 = " << value.storagePushConstant16 << '\n'; + s << "\tstorageInputOutput16 = " << value.storageInputOutput16 << '\n'; + s << '}'; + return s; +} + std::ostream& operator<< (std::ostream& s, const VkRectLayerKHR& value) { s << "VkRectLayerKHR = {\n"; diff --git a/external/vulkancts/framework/vulkan/vkStructTypes.inl b/external/vulkancts/framework/vulkan/vkStructTypes.inl index 6cb7cb2..f01dabc 100644 --- a/external/vulkancts/framework/vulkan/vkStructTypes.inl +++ b/external/vulkancts/framework/vulkan/vkStructTypes.inl @@ -1441,6 +1441,16 @@ struct VkPhysicalDevicePushDescriptorPropertiesKHR deUint32 maxPushDescriptors; }; +struct VkPhysicalDevice16BitStorageFeaturesKHR +{ + VkStructureType sType; + const void* pNext; + VkBool32 storageUniformBufferBlock16; + VkBool32 storageUniform16; + VkBool32 storagePushConstant16; + VkBool32 storageInputOutput16; +}; + struct VkRectLayerKHR { VkOffset2D offset; diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt b/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt index 22eff93..b390b3c 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt @@ -7,10 +7,14 @@ set(DEQP_VK_SPIRV_ASSEMBLY_SRCS vktSpvAsmComputeShaderCase.hpp vktSpvAsmComputeShaderTestUtil.cpp vktSpvAsmComputeShaderTestUtil.hpp + vktSpvAsmGraphicsShaderTestUtil.cpp + vktSpvAsmGraphicsShaderTestUtil.hpp vktSpvAsmInstructionTests.cpp vktSpvAsmInstructionTests.hpp vktSpvAsmTests.cpp vktSpvAsmTests.hpp + vktSpvAsmUtils.cpp + vktSpvAsmUtils.hpp ) set(DEQP_VK_SPIRV_ASSEMBLY_LIBS diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp index be9cb24..4b6e8e0 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp @@ -24,9 +24,11 @@ #include "vktSpvAsmComputeShaderCase.hpp" #include "deSharedPtr.hpp" +#include "deSTLUtil.hpp" #include "vkBuilderUtil.hpp" #include "vkMemUtil.hpp" +#include "vkPlatform.hpp" #include "vkRefUtil.hpp" #include "vkQueryUtil.hpp" #include "vkTypeUtil.hpp" @@ -49,15 +51,24 @@ typedef de::SharedPtr BufferHandleSp; * The memory is created as host visible and passed back as a vk::Allocation * instance via outMemory. *//*--------------------------------------------------------------------*/ -Move createBufferAndBindMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocator& allocator, size_t numBytes, AllocationMp* outMemory) +Move createBufferAndBindMemory (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorType dtype, Allocator& allocator, size_t numBytes, AllocationMp* outMemory) { - const VkBufferCreateInfo bufferCreateInfo = + VkBufferUsageFlags usageBit = (VkBufferUsageFlags)0; + + switch (dtype) + { + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: usageBit = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: usageBit = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; break; + default: DE_ASSERT(false); + } + + const VkBufferCreateInfo bufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType DE_NULL, // pNext 0u, // flags numBytes, // size - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage + usageBit, // usage VK_SHARING_MODE_EXCLUSIVE, // sharingMode 0u, // queueFamilyCount DE_NULL, // pQueueFamilyIndices @@ -90,17 +101,16 @@ void fillMemoryWithValue (const DeviceInterface& vkdi, const VkDevice& device, A } /*--------------------------------------------------------------------*//*! - * \brief Create a descriptor set layout with numBindings descriptors + * \brief Create a descriptor set layout with the given descriptor types * - * All descriptors are created for shader storage buffer objects and - * compute pipeline. + * All descriptors are created for compute pipeline. *//*--------------------------------------------------------------------*/ -Move createDescriptorSetLayout (const DeviceInterface& vkdi, const VkDevice& device, size_t numBindings) +Move createDescriptorSetLayout (const DeviceInterface& vkdi, const VkDevice& device, const vector& dtypes) { DescriptorSetLayoutBuilder builder; - for (size_t bindingNdx = 0; bindingNdx < numBindings; ++bindingNdx) - builder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); + for (size_t bindingNdx = 0; bindingNdx < dtypes.size(); ++bindingNdx) + builder.addSingleBinding(dtypes[bindingNdx], VK_SHADER_STAGE_COMPUTE_BIT); return builder.build(vkdi, device); } @@ -108,9 +118,9 @@ Move createDescriptorSetLayout (const DeviceInterface& vk /*--------------------------------------------------------------------*//*! * \brief Create a pipeline layout with one descriptor set *//*--------------------------------------------------------------------*/ -Move createPipelineLayout (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorSetLayout descriptorSetLayout) +Move createPipelineLayout (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorSetLayout descriptorSetLayout, const vkt::SpirVAssembly::BufferSp& pushConstants) { - const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = + VkPipelineLayoutCreateInfo createInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType DE_NULL, // pNext @@ -121,30 +131,47 @@ Move createPipelineLayout (const DeviceInterface& vkdi, const DE_NULL, // pPushConstantRanges }; - return createPipelineLayout(vkdi, device, &pipelineLayoutCreateInfo); + VkPushConstantRange range = + { + VK_SHADER_STAGE_COMPUTE_BIT, // stageFlags + 0, // offset + 0, // size + }; + + if (pushConstants != DE_NULL) + { + range.size = static_cast(pushConstants->getNumBytes()); + createInfo.pushConstantRangeCount = 1; + createInfo.pPushConstantRanges = ⦥ + } + + return createPipelineLayout(vkdi, device, &createInfo); } /*--------------------------------------------------------------------*//*! - * \brief Create a one-time descriptor pool for one descriptor set - * - * The pool supports numDescriptors storage buffer descriptors. + * \brief Create a one-time descriptor pool for one descriptor set that + * support the given descriptor types. *//*--------------------------------------------------------------------*/ -inline Move createDescriptorPool (const DeviceInterface& vkdi, const VkDevice& device, deUint32 numDescriptors) +inline Move createDescriptorPool (const DeviceInterface& vkdi, const VkDevice& device, const vector& dtypes) { - return DescriptorPoolBuilder() - .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, numDescriptors) - .build(vkdi, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, /* maxSets = */ 1); + DescriptorPoolBuilder builder; + + for (size_t typeNdx = 0; typeNdx < dtypes.size(); ++typeNdx) + builder.addType(dtypes[typeNdx], 1); + + return builder.build(vkdi, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, /* maxSets = */ 1); } /*--------------------------------------------------------------------*//*! * \brief Create a descriptor set * - * The descriptor set's layout should contain numViews descriptors. - * All the descriptors represent buffer views, and they are sequentially - * binded to binding point starting from 0. + * The descriptor set's layout contains the given descriptor types, + * sequentially binded to binding points starting from 0. *//*--------------------------------------------------------------------*/ -Move createDescriptorSet (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorPool pool, VkDescriptorSetLayout layout, size_t numViews, const vector& descriptorInfos) +Move createDescriptorSet (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorPool pool, VkDescriptorSetLayout layout, const vector& dtypes, const vector& descriptorInfos) { + DE_ASSERT(dtypes.size() == descriptorInfos.size()); + const VkDescriptorSetAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, @@ -157,8 +184,8 @@ Move createDescriptorSet (const DeviceInterface& vkdi, const Vk Move descriptorSet = allocateDescriptorSet(vkdi, device, &allocInfo); DescriptorSetUpdateBuilder builder; - for (deUint32 descriptorNdx = 0; descriptorNdx < numViews; ++descriptorNdx) - builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfos[descriptorNdx]); + for (deUint32 descriptorNdx = 0; descriptorNdx < dtypes.size(); ++descriptorNdx) + builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx), dtypes[descriptorNdx], &descriptorInfos[descriptorNdx]); builder.update(vkdi, device); return descriptorSet; @@ -246,18 +273,24 @@ namespace SpirVAssembly class SpvAsmComputeShaderInstance : public TestInstance { public: - SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec); - tcu::TestStatus iterate (void); + SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec, const ComputeTestFeatures features); + tcu::TestStatus iterate (void); private: - const ComputeShaderSpec& m_shaderSpec; + const Unique m_device; + const DeviceDriver m_deviceInterface; + const VkQueue m_queue; + const de::UniquePtr m_allocator; + const ComputeShaderSpec& m_shaderSpec; + const ComputeTestFeatures m_features; }; // ComputeShaderTestCase implementations -SpvAsmComputeShaderCase::SpvAsmComputeShaderCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec) +SpvAsmComputeShaderCase::SpvAsmComputeShaderCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec, const ComputeTestFeatures features) : TestCase (testCtx, name, description) , m_shaderSpec (spec) + , m_features (features) { } @@ -268,40 +301,72 @@ void SpvAsmComputeShaderCase::initPrograms (SourceCollections& programCollection TestInstance* SpvAsmComputeShaderCase::createInstance (Context& ctx) const { - return new SpvAsmComputeShaderInstance(ctx, m_shaderSpec); + return new SpvAsmComputeShaderInstance(ctx, m_shaderSpec, m_features); } // ComputeShaderTestInstance implementations -SpvAsmComputeShaderInstance::SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec) - : TestInstance (ctx) - , m_shaderSpec (spec) +SpvAsmComputeShaderInstance::SpvAsmComputeShaderInstance (Context& ctx, const ComputeShaderSpec& spec, const ComputeTestFeatures features) + : TestInstance (ctx) + , m_device (createDeviceWithExtensions(ctx.getInstanceInterface(), ctx.getPhysicalDevice(), ctx.getUniversalQueueFamilyIndex(), ctx.getDeviceExtensions(), spec.extensions)) + , m_deviceInterface (ctx.getInstanceInterface(), *m_device) + , m_queue (getDeviceQueue(m_deviceInterface, *m_device, ctx.getUniversalQueueFamilyIndex(), 0)) + , m_allocator (createAllocator(ctx.getInstanceInterface(), ctx.getPhysicalDevice(), m_deviceInterface, *m_device)) + , m_shaderSpec (spec) + , m_features (features) { } tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void) { - const DeviceInterface& vkdi = m_context.getDeviceInterface(); - const VkDevice& device = m_context.getDevice(); - Allocator& allocator = m_context.getDefaultAllocator(); + const VkPhysicalDeviceFeatures& features = m_context.getDeviceFeatures(); + const DeviceInterface& vkdi = m_deviceInterface; + const VkDevice& device = *m_device; + Allocator& allocator = *m_allocator; + + if ((m_features == COMPUTE_TEST_USES_INT16 || m_features == COMPUTE_TEST_USES_INT16_INT64) && !features.shaderInt16) + { + TCU_THROW(NotSupportedError, "shaderInt16 feature is not supported"); + } + + if ((m_features == COMPUTE_TEST_USES_INT64 || m_features == COMPUTE_TEST_USES_INT16_INT64) && !features.shaderInt64) + { + TCU_THROW(NotSupportedError, "shaderInt64 feature is not supported"); + } + + { + const InstanceInterface& vki = m_context.getInstanceInterface(); + const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); + + // 16bit storage features + { + if (!is16BitStorageFeaturesSupported(vki, physicalDevice, m_context.getInstanceExtensions(), m_shaderSpec.requestedExtensionFeatures.ext16BitStorage)) + TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported"); + } + } vector inputAllocs; vector outputAllocs; vector inputBuffers; vector outputBuffers; vector descriptorInfos; + vector descriptorTypes; DE_ASSERT(!m_shaderSpec.outputs.empty()); - const size_t numBuffers = m_shaderSpec.inputs.size() + m_shaderSpec.outputs.size(); // Create buffer object, allocate storage, and create view for all input/output buffers. - for (size_t inputNdx = 0; inputNdx < m_shaderSpec.inputs.size(); ++inputNdx) + for (deUint32 inputNdx = 0; inputNdx < m_shaderSpec.inputs.size(); ++inputNdx) { + if (m_shaderSpec.inputTypes.count(inputNdx) != 0) + descriptorTypes.push_back(m_shaderSpec.inputTypes.at(inputNdx)); + else + descriptorTypes.push_back(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + AllocationMp alloc; const BufferSp& input = m_shaderSpec.inputs[inputNdx]; const size_t numBytes = input->getNumBytes(); - BufferHandleUp* buffer = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, allocator, numBytes, &alloc)); + BufferHandleUp* buffer = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descriptorTypes.back(), allocator, numBytes, &alloc)); setMemory(vkdi, device, &*alloc, numBytes, input->data()); descriptorInfos.push_back(vk::makeDescriptorBufferInfo(**buffer, 0u, numBytes)); @@ -309,12 +374,14 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void) inputAllocs.push_back(de::SharedPtr(alloc.release())); } - for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx) + for (deUint32 outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx) { + descriptorTypes.push_back(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + AllocationMp alloc; const BufferSp& output = m_shaderSpec.outputs[outputNdx]; const size_t numBytes = output->getNumBytes(); - BufferHandleUp* buffer = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, allocator, numBytes, &alloc)); + BufferHandleUp* buffer = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descriptorTypes.back(), allocator, numBytes, &alloc)); fillMemoryWithValue(vkdi, device, &*alloc, numBytes, 0xff); descriptorInfos.push_back(vk::makeDescriptorBufferInfo(**buffer, 0u, numBytes)); @@ -324,10 +391,10 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void) // Create layouts and descriptor set. - Unique descriptorSetLayout (createDescriptorSetLayout(vkdi, device, numBuffers)); - Unique pipelineLayout (createPipelineLayout(vkdi, device, *descriptorSetLayout)); - Unique descriptorPool (createDescriptorPool(vkdi, device, (deUint32)numBuffers)); - Unique descriptorSet (createDescriptorSet(vkdi, device, *descriptorPool, *descriptorSetLayout, numBuffers, descriptorInfos)); + Unique descriptorSetLayout (createDescriptorSetLayout(vkdi, device, descriptorTypes)); + Unique pipelineLayout (createPipelineLayout(vkdi, device, *descriptorSetLayout, m_shaderSpec.pushConstants)); + Unique descriptorPool (createDescriptorPool(vkdi, device, descriptorTypes)); + Unique descriptorSet (createDescriptorSet(vkdi, device, *descriptorPool, *descriptorSetLayout, descriptorTypes, descriptorInfos)); // Create compute shader and pipeline. @@ -354,6 +421,13 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void) VK_CHECK(vkdi.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo)); vkdi.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline); vkdi.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL); + if (m_shaderSpec.pushConstants != DE_NULL) + { + const deUint32 size = static_cast(m_shaderSpec.pushConstants->getNumBytes()); + const void* data = m_shaderSpec.pushConstants->data(); + + vkdi.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, /* offset = */ 0, /* size = */ size, data); + } vkdi.cmdDispatch(*cmdBuffer, numWorkGroups.x(), numWorkGroups.y(), numWorkGroups.z()); VK_CHECK(vkdi.endCommandBuffer(*cmdBuffer)); @@ -374,14 +448,14 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void) (const VkSemaphore*)DE_NULL, }; - VK_CHECK(vkdi.queueSubmit(m_context.getUniversalQueue(), 1, &submitInfo, *cmdCompleteFence)); + VK_CHECK(vkdi.queueSubmit(m_queue, 1, &submitInfo, *cmdCompleteFence)); VK_CHECK(vkdi.waitForFences(device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure // Check output. if (m_shaderSpec.verifyIO) { if (!(*m_shaderSpec.verifyIO)(m_shaderSpec.inputs, outputAllocs, m_shaderSpec.outputs, m_context.getTestContext().getLog())) - return tcu::TestStatus::fail("Output doesn't match with expected"); + return tcu::TestStatus(m_shaderSpec.failResult, m_shaderSpec.failMessage); } else { @@ -389,55 +463,11 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void) { const BufferSp& expectedOutput = m_shaderSpec.outputs[outputNdx]; if (deMemCmp(expectedOutput->data(), outputAllocs[outputNdx]->getHostPtr(), expectedOutput->getNumBytes())) - return tcu::TestStatus::fail("Output doesn't match with expected"); + return tcu::TestStatus(m_shaderSpec.failResult, m_shaderSpec.failMessage); } } - return tcu::TestStatus::pass("Ouput match with expected"); -} - -class ConvertTestInstance : public SpvAsmComputeShaderInstance -{ -public: - ConvertTestInstance (Context& ctx, const ComputeShaderSpec& spec, const ConvertTestFeatures features); - tcu::TestStatus iterate (void); -private: - const ConvertTestFeatures m_features; -}; - -ConvertTestInstance::ConvertTestInstance (Context& ctx, const ComputeShaderSpec& spec, const ConvertTestFeatures features) - : SpvAsmComputeShaderInstance (ctx, spec) - , m_features (features) -{ -} - -tcu::TestStatus ConvertTestInstance::iterate (void) -{ - const VkPhysicalDeviceFeatures& features = m_context.getDeviceFeatures(); - - if ((m_features == CONVERT_TEST_USES_INT16 || m_features == CONVERT_TEST_USES_INT16_INT64) && !features.shaderInt16) - { - throw tcu::NotSupportedError("shaderInt16 feature is not supported"); - } - - if ((m_features == CONVERT_TEST_USES_INT64 || m_features == CONVERT_TEST_USES_INT16_INT64) && !features.shaderInt64) - { - throw tcu::NotSupportedError("shaderInt64 feature is not supported"); - } - - return SpvAsmComputeShaderInstance::iterate(); -} - -ConvertTestCase::ConvertTestCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec, const ConvertTestFeatures features) - : SpvAsmComputeShaderCase (testCtx, name, description, spec) - , m_shaderSpec (spec) - , m_features (features) -{ -} - -TestInstance* ConvertTestCase::createInstance (Context& ctx) const -{ - return new ConvertTestInstance(ctx, m_shaderSpec, m_features); + return tcu::TestStatus::pass("Output match with expected"); } } // SpirVAssembly diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.hpp index bd70ffc..50c69e9 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.hpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.hpp @@ -33,32 +33,24 @@ namespace vkt namespace SpirVAssembly { +enum ComputeTestFeatures +{ + COMPUTE_TEST_USES_NONE, + COMPUTE_TEST_USES_INT16, + COMPUTE_TEST_USES_INT64, + COMPUTE_TEST_USES_INT16_INT64, +}; + class SpvAsmComputeShaderCase : public TestCase { public: - SpvAsmComputeShaderCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec); + SpvAsmComputeShaderCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec, const ComputeTestFeatures features = COMPUTE_TEST_USES_NONE); void initPrograms (vk::SourceCollections& programCollection) const; TestInstance* createInstance (Context& ctx) const; private: ComputeShaderSpec m_shaderSpec; -}; - -enum ConvertTestFeatures -{ - CONVERT_TEST_USES_INT16, - CONVERT_TEST_USES_INT64, - CONVERT_TEST_USES_INT16_INT64, -}; - -class ConvertTestCase : public SpvAsmComputeShaderCase -{ -public: - ConvertTestCase (tcu::TestContext& testCtx, const char* name, const char* description, const ComputeShaderSpec& spec, const ConvertTestFeatures features); - TestInstance* createInstance (Context& ctx) const; -private: - ComputeShaderSpec m_shaderSpec; - const ConvertTestFeatures m_features; + const ComputeTestFeatures m_features; }; } // SpirVAssembly diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp index 5727fb5..2d60026 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp @@ -23,4 +23,58 @@ #include "vktSpvAsmComputeShaderTestUtil.hpp" -DE_EMPTY_CPP_FILE +namespace vkt +{ +namespace SpirVAssembly +{ + +const char* getComputeAsmShaderPreamble (void) +{ + return + "OpCapability Shader\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint GLCompute %main \"main\" %id\n" + "OpExecutionMode %main LocalSize 1 1 1\n"; +} + +const char* getComputeAsmCommonTypes (void) +{ + return + "%bool = OpTypeBool\n" + "%void = OpTypeVoid\n" + "%voidf = OpTypeFunction %void\n" + "%u32 = OpTypeInt 32 0\n" + "%i32 = OpTypeInt 32 1\n" + "%f32 = OpTypeFloat 32\n" + "%uvec3 = OpTypeVector %u32 3\n" + "%fvec3 = OpTypeVector %f32 3\n" + "%uvec3ptr = OpTypePointer Input %uvec3\n" + "%i32ptr = OpTypePointer Uniform %i32\n" + "%f32ptr = OpTypePointer Uniform %f32\n" + "%i32arr = OpTypeRuntimeArray %i32\n" + "%f32arr = OpTypeRuntimeArray %f32\n"; +} + +const char* getComputeAsmInputOutputBuffer (void) +{ + return + "%buf = OpTypeStruct %f32arr\n" + "%bufptr = OpTypePointer Uniform %buf\n" + "%indata = OpVariable %bufptr Uniform\n" + "%outdata = OpVariable %bufptr Uniform\n"; +} + +const char* getComputeAsmInputOutputBufferTraits (void) +{ + return + "OpDecorate %buf BufferBlock\n" + "OpDecorate %indata DescriptorSet 0\n" + "OpDecorate %indata Binding 0\n" + "OpDecorate %outdata DescriptorSet 0\n" + "OpDecorate %outdata Binding 1\n" + "OpDecorate %f32arr ArrayStride 4\n" + "OpMemberDecorate %buf 0 Offset 0\n"; +} + +} // SpirVAssembly +} // vkt diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp index 4c6b644..09adf1d 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp @@ -24,13 +24,16 @@ *//*--------------------------------------------------------------------*/ #include "deDefs.h" +#include "deFloat16.h" #include "deSharedPtr.hpp" #include "tcuTestLog.hpp" #include "tcuVector.hpp" #include "vkMemUtil.hpp" +#include "vktSpvAsmUtils.hpp" #include #include +#include using namespace vk; @@ -80,6 +83,10 @@ typedef Buffer Float32Buffer; typedef Buffer Int32Buffer; typedef Buffer Vec4Buffer; +typedef bool (*ComputeVerifyIOFunc) (const std::vector& inputs, + const std::vector& outputAllocations, + const std::vector& expectedOutputs, + tcu::TestLog& log); /*--------------------------------------------------------------------*//*! * \brief Specification for a compute shader. @@ -89,24 +96,54 @@ typedef Buffer Vec4Buffer; *//*--------------------------------------------------------------------*/ struct ComputeShaderSpec { - std::string assembly; - std::string entryPoint; - std::vector inputs; - std::vector outputs; - tcu::IVec3 numWorkGroups; - std::vector specConstants; + std::string assembly; + std::string entryPoint; + std::vector inputs; + // Mapping from input index (in the inputs field) to the descriptor type. + std::map inputTypes; + std::vector outputs; + tcu::IVec3 numWorkGroups; + std::vector specConstants; + BufferSp pushConstants; + std::vector extensions; + ExtensionFeatures requestedExtensionFeatures; + qpTestResult failResult; + std::string failMessage; // If null, a default verification will be performed by comparing the memory pointed to by outputAllocations // and the contents of expectedOutputs. Otherwise the function pointed to by verifyIO will be called. // If true is returned, then the test case is assumed to have passed, if false is returned, then the test - // case is assumed to have failed. - bool (*verifyIO)(const std::vector& inputs, const std::vector& outputAllocations, const std::vector& expectedOutputs, tcu::TestLog& log); - ComputeShaderSpec() - : entryPoint ("main") - , verifyIO (DE_NULL) - {} - + // case is assumed to have failed. Exact meaning of failure can be customized with failResult. + ComputeVerifyIOFunc verifyIO; + + ComputeShaderSpec (void) + : entryPoint ("main") + , pushConstants (DE_NULL) + , requestedExtensionFeatures () + , failResult (QP_TEST_RESULT_FAIL) + , failMessage ("Output doesn't match with expected") + , verifyIO (DE_NULL) + {} }; +/*--------------------------------------------------------------------*//*! + * \brief Helper functions for SPIR-V assembly shared by various tests + *//*--------------------------------------------------------------------*/ + +const char* getComputeAsmShaderPreamble (void); +const char* getComputeAsmCommonTypes (void); + +/*--------------------------------------------------------------------*//*! + * Declares two uniform variables (indata, outdata) of type + * "struct { float[] }". Depends on type "f32arr" (for "float[]"). + *//*--------------------------------------------------------------------*/ +const char* getComputeAsmInputOutputBuffer (void); +/*--------------------------------------------------------------------*//*! + * Declares buffer type and layout for uniform variables indata and + * outdata. Both of them are SSBO bounded to descriptor set 0. + * indata is at binding point 0, while outdata is at 1. + *//*--------------------------------------------------------------------*/ +const char* getComputeAsmInputOutputBufferTraits (void); + } // SpirVAssembly } // vkt diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp new file mode 100644 index 0000000..a62ee13 --- /dev/null +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp @@ -0,0 +1,3490 @@ +/*------------------------------------------------------------------------- + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2017 Google 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 Graphics pipeline for SPIR-V assembly tests + *//*--------------------------------------------------------------------*/ + +#include "vktSpvAsmGraphicsShaderTestUtil.hpp" + +#include "tcuFloat.hpp" +#include "tcuStringTemplate.hpp" + +#include "vkDefs.hpp" +#include "vkMemUtil.hpp" +#include "vkPlatform.hpp" +#include "vkQueryUtil.hpp" +#include "vkRefUtil.hpp" +#include "vkTypeUtil.hpp" + +#include "deRandom.hpp" + +namespace vkt +{ +namespace SpirVAssembly +{ + +using namespace vk; +using std::map; +using std::string; +using std::vector; +using tcu::Float16; +using tcu::Float32; +using tcu::IVec3; +using tcu::IVec4; +using tcu::RGBA; +using tcu::TestLog; +using tcu::TestStatus; +using tcu::Vec4; +using de::UniquePtr; +using tcu::StringTemplate; +using tcu::Vec4; + +deUint32 IFDataType::getElementNumBytes (void) const +{ + if (elementType < NUMBERTYPE_END32) + return 4; + + return 2; +} + +VkFormat IFDataType::getVkFormat (void) const +{ + if (numElements == 1) + { + switch (elementType) + { + case NUMBERTYPE_FLOAT32: return VK_FORMAT_R32_SFLOAT; + case NUMBERTYPE_INT32: return VK_FORMAT_R32_SINT; + case NUMBERTYPE_UINT32: return VK_FORMAT_R32_UINT; + case NUMBERTYPE_FLOAT16: return VK_FORMAT_R16_SFLOAT; + case NUMBERTYPE_INT16: return VK_FORMAT_R16_SINT; + case NUMBERTYPE_UINT16: return VK_FORMAT_R16_UINT; + default: break; + } + } + else if (numElements == 2) + { + switch (elementType) + { + case NUMBERTYPE_FLOAT32: return VK_FORMAT_R32G32_SFLOAT; + case NUMBERTYPE_INT32: return VK_FORMAT_R32G32_SINT; + case NUMBERTYPE_UINT32: return VK_FORMAT_R32G32_UINT; + case NUMBERTYPE_FLOAT16: return VK_FORMAT_R16G16_SFLOAT; + case NUMBERTYPE_INT16: return VK_FORMAT_R16G16_SINT; + case NUMBERTYPE_UINT16: return VK_FORMAT_R16G16_UINT; + default: break; + } + } + else if (numElements == 3) + { + switch (elementType) + { + case NUMBERTYPE_FLOAT32: return VK_FORMAT_R32G32B32_SFLOAT; + case NUMBERTYPE_INT32: return VK_FORMAT_R32G32B32_SINT; + case NUMBERTYPE_UINT32: return VK_FORMAT_R32G32B32_UINT; + case NUMBERTYPE_FLOAT16: return VK_FORMAT_R16G16B16_SFLOAT; + case NUMBERTYPE_INT16: return VK_FORMAT_R16G16B16_SINT; + case NUMBERTYPE_UINT16: return VK_FORMAT_R16G16B16_UINT; + default: break; + } + } + else if (numElements == 4) + { + switch (elementType) + { + case NUMBERTYPE_FLOAT32: return VK_FORMAT_R32G32B32A32_SFLOAT; + case NUMBERTYPE_INT32: return VK_FORMAT_R32G32B32A32_SINT; + case NUMBERTYPE_UINT32: return VK_FORMAT_R32G32B32A32_UINT; + case NUMBERTYPE_FLOAT16: return VK_FORMAT_R16G16B16A16_SFLOAT; + case NUMBERTYPE_INT16: return VK_FORMAT_R16G16B16A16_SINT; + case NUMBERTYPE_UINT16: return VK_FORMAT_R16G16B16A16_UINT; + default: break; + } + } + + DE_ASSERT(false); + return VK_FORMAT_UNDEFINED; +} + +tcu::TextureFormat IFDataType::getTextureFormat (void) const +{ + tcu::TextureFormat::ChannelType ct = tcu::TextureFormat::CHANNELTYPE_LAST; + tcu::TextureFormat::ChannelOrder co = tcu::TextureFormat::CHANNELORDER_LAST; + + switch (elementType) + { + case NUMBERTYPE_FLOAT32: ct = tcu::TextureFormat::FLOAT; break; + case NUMBERTYPE_INT32: ct = tcu::TextureFormat::SIGNED_INT32; break; + case NUMBERTYPE_UINT32: ct = tcu::TextureFormat::UNSIGNED_INT32; break; + case NUMBERTYPE_FLOAT16: ct = tcu::TextureFormat::HALF_FLOAT; break; + case NUMBERTYPE_INT16: ct = tcu::TextureFormat::SIGNED_INT16; break; + case NUMBERTYPE_UINT16: ct = tcu::TextureFormat::UNSIGNED_INT16; break; + default: DE_ASSERT(false); + } + + switch (numElements) + { + case 1: co = tcu::TextureFormat::R; break; + case 2: co = tcu::TextureFormat::RG; break; + case 3: co = tcu::TextureFormat::RGB; break; + case 4: co = tcu::TextureFormat::RGBA; break; + default: DE_ASSERT(false); + } + + return tcu::TextureFormat(co, ct); +} + +string IFDataType::str (void) const +{ + string ret; + + switch (elementType) + { + case NUMBERTYPE_FLOAT32: ret = "f32"; break; + case NUMBERTYPE_INT32: ret = "i32"; break; + case NUMBERTYPE_UINT32: ret = "u32"; break; + case NUMBERTYPE_FLOAT16: ret = "f16"; break; + case NUMBERTYPE_INT16: ret = "i16"; break; + case NUMBERTYPE_UINT16: ret = "u16"; break; + default: DE_ASSERT(false); + } + + if (numElements == 1) + return ret; + + return string("v") + numberToString(numElements) + ret; +} + +VkBufferUsageFlagBits getMatchingBufferUsageFlagBit(VkDescriptorType dType) +{ + switch (dType) + { + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + default: DE_ASSERT(0 && "not implemented"); + } + return (VkBufferUsageFlagBits)0; +} + +InstanceContext::InstanceContext (const RGBA (&inputs)[4], + const RGBA (&outputs)[4], + const map& testCodeFragments_, + const StageToSpecConstantMap& specConstants_, + const PushConstants& pushConsants_, + const GraphicsResources& resources_, + const GraphicsInterfaces& interfaces_, + const vector& extensions_, + const vector& features_, + ExtensionFeatures extensionFeatures_) + : testCodeFragments (testCodeFragments_) + , specConstants (specConstants_) + , hasTessellation (false) + , requiredStages (static_cast(0)) + , requiredDeviceExtensions (extensions_) + , requiredDeviceFeatures (features_) + , requestedExtensionFeatures (extensionFeatures_) + , pushConstants (pushConsants_) + , resources (resources_) + , interfaces (interfaces_) + , failResult (QP_TEST_RESULT_FAIL) + , failMessageTemplate ("${reason}") +{ + inputColors[0] = inputs[0]; + inputColors[1] = inputs[1]; + inputColors[2] = inputs[2]; + inputColors[3] = inputs[3]; + + outputColors[0] = outputs[0]; + outputColors[1] = outputs[1]; + outputColors[2] = outputs[2]; + outputColors[3] = outputs[3]; +} + +InstanceContext::InstanceContext (const InstanceContext& other) + : moduleMap (other.moduleMap) + , testCodeFragments (other.testCodeFragments) + , specConstants (other.specConstants) + , hasTessellation (other.hasTessellation) + , requiredStages (other.requiredStages) + , requiredDeviceExtensions (other.requiredDeviceExtensions) + , requiredDeviceFeatures (other.requiredDeviceFeatures) + , requestedExtensionFeatures (other.requestedExtensionFeatures) + , pushConstants (other.pushConstants) + , resources (other.resources) + , interfaces (other.interfaces) + , failResult (other.failResult) + , failMessageTemplate (other.failMessageTemplate) +{ + inputColors[0] = other.inputColors[0]; + inputColors[1] = other.inputColors[1]; + inputColors[2] = other.inputColors[2]; + inputColors[3] = other.inputColors[3]; + + outputColors[0] = other.outputColors[0]; + outputColors[1] = other.outputColors[1]; + outputColors[2] = other.outputColors[2]; + outputColors[3] = other.outputColors[3]; +} + +string InstanceContext::getSpecializedFailMessage (const string& failureReason) +{ + map parameters; + parameters["reason"] = failureReason; + return StringTemplate(failMessageTemplate).specialize(parameters); +} + +ShaderElement::ShaderElement (const string& moduleName_, + const string& entryPoint_, + VkShaderStageFlagBits shaderStage_) + : moduleName(moduleName_) + , entryName(entryPoint_) + , stage(shaderStage_) +{ +} + +void getDefaultColors (RGBA (&colors)[4]) +{ + colors[0] = RGBA::white(); + colors[1] = RGBA::red(); + colors[2] = RGBA::green(); + colors[3] = RGBA::blue(); +} + +void getHalfColorsFullAlpha (RGBA (&colors)[4]) +{ + colors[0] = RGBA(127, 127, 127, 255); + colors[1] = RGBA(127, 0, 0, 255); + colors[2] = RGBA(0, 127, 0, 255); + colors[3] = RGBA(0, 0, 127, 255); +} + +void getInvertedDefaultColors (RGBA (&colors)[4]) +{ + colors[0] = RGBA(0, 0, 0, 255); + colors[1] = RGBA(0, 255, 255, 255); + colors[2] = RGBA(255, 0, 255, 255); + colors[3] = RGBA(255, 255, 0, 255); +} + +// For the current InstanceContext, constructs the required modules and shader stage create infos. +void createPipelineShaderStages (const DeviceInterface& vk, + const VkDevice vkDevice, + InstanceContext& instance, + Context& context, + vector& modules, + vector& createInfos) +{ + for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx) + { + const ModuleHandleSp mod(new Unique(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0))); + modules.push_back(ModuleHandleSp(mod)); + for (vector::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx) + { + const EntryToStage& stage = *shaderNdx; + const VkPipelineShaderStageCreateInfo shaderParam = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, + stage.second, // VkShaderStageFlagBits stage; + **modules.back(), // VkShaderModule module; + stage.first.c_str(), // const char* pName; + (const VkSpecializationInfo*)DE_NULL, + }; + createInfos.push_back(shaderParam); + } + } +} + +#define SPIRV_ASSEMBLY_TYPES \ + "%void = OpTypeVoid\n" \ + "%bool = OpTypeBool\n" \ + \ + "%i32 = OpTypeInt 32 1\n" \ + "%u32 = OpTypeInt 32 0\n" \ + \ + "%f32 = OpTypeFloat 32\n" \ + "%v2i32 = OpTypeVector %i32 2\n" \ + "%v2u32 = OpTypeVector %u32 2\n" \ + "%v2f32 = OpTypeVector %f32 2\n" \ + "%v3f32 = OpTypeVector %f32 3\n" \ + "%v4i32 = OpTypeVector %i32 4\n" \ + "%v4u32 = OpTypeVector %u32 4\n" \ + "%v4f32 = OpTypeVector %f32 4\n" \ + "%v4bool = OpTypeVector %bool 4\n" \ + \ + "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \ + "%bool_function = OpTypeFunction %bool\n" \ + "%fun = OpTypeFunction %void\n" \ + \ + "%ip_f32 = OpTypePointer Input %f32\n" \ + "%ip_i32 = OpTypePointer Input %i32\n" \ + "%ip_u32 = OpTypePointer Input %u32\n" \ + "%ip_v3f32 = OpTypePointer Input %v3f32\n" \ + "%ip_v2f32 = OpTypePointer Input %v2f32\n" \ + "%ip_v2i32 = OpTypePointer Input %v2i32\n" \ + "%ip_v2u32 = OpTypePointer Input %v2u32\n" \ + "%ip_v4f32 = OpTypePointer Input %v4f32\n" \ + "%ip_v4i32 = OpTypePointer Input %v4i32\n" \ + "%ip_v4u32 = OpTypePointer Input %v4u32\n" \ + \ + "%op_f32 = OpTypePointer Output %f32\n" \ + "%op_i32 = OpTypePointer Output %i32\n" \ + "%op_u32 = OpTypePointer Output %u32\n" \ + "%op_v2f32 = OpTypePointer Output %v2f32\n" \ + "%op_v2i32 = OpTypePointer Output %v2i32\n" \ + "%op_v2u32 = OpTypePointer Output %v2u32\n" \ + "%op_v4f32 = OpTypePointer Output %v4f32\n" \ + "%op_v4i32 = OpTypePointer Output %v4i32\n" \ + "%op_v4u32 = OpTypePointer Output %v4u32\n" \ + \ + "%fp_f32 = OpTypePointer Function %f32\n" \ + "%fp_i32 = OpTypePointer Function %i32\n" \ + "%fp_v4f32 = OpTypePointer Function %v4f32\n" + +#define SPIRV_ASSEMBLY_CONSTANTS \ + "%c_f32_1 = OpConstant %f32 1.0\n" \ + "%c_f32_0 = OpConstant %f32 0.0\n" \ + "%c_f32_0_5 = OpConstant %f32 0.5\n" \ + "%c_f32_n1 = OpConstant %f32 -1.\n" \ + "%c_f32_7 = OpConstant %f32 7.0\n" \ + "%c_f32_8 = OpConstant %f32 8.0\n" \ + "%c_i32_0 = OpConstant %i32 0\n" \ + "%c_i32_1 = OpConstant %i32 1\n" \ + "%c_i32_2 = OpConstant %i32 2\n" \ + "%c_i32_3 = OpConstant %i32 3\n" \ + "%c_i32_4 = OpConstant %i32 4\n" \ + "%c_u32_0 = OpConstant %u32 0\n" \ + "%c_u32_1 = OpConstant %u32 1\n" \ + "%c_u32_2 = OpConstant %u32 2\n" \ + "%c_u32_3 = OpConstant %u32 3\n" \ + "%c_u32_32 = OpConstant %u32 32\n" \ + "%c_u32_4 = OpConstant %u32 4\n" \ + "%c_u32_31_bits = OpConstant %u32 0x7FFFFFFF\n" \ + "%c_v4f32_1_1_1_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" \ + "%c_v4f32_1_0_0_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_1\n" \ + "%c_v4f32_0_5_0_5_0_5_0_5 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5\n" + +#define SPIRV_ASSEMBLY_ARRAYS \ + "%a1f32 = OpTypeArray %f32 %c_u32_1\n" \ + "%a2f32 = OpTypeArray %f32 %c_u32_2\n" \ + "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n" \ + "%a4f32 = OpTypeArray %f32 %c_u32_4\n" \ + "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n" \ + "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n" \ + "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n" \ + "%op_a2f32 = OpTypePointer Output %a2f32\n" \ + "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n" \ + "%op_a4f32 = OpTypePointer Output %a4f32\n" + +// Creates vertex-shader assembly by specializing a boilerplate StringTemplate +// on fragments, which must (at least) map "testfun" to an OpFunction definition +// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed +// with "BP_" to avoid collisions with fragments. +// +// It corresponds roughly to this GLSL: +//; +// layout(location = 0) in vec4 position; +// layout(location = 1) in vec4 color; +// layout(location = 1) out highp vec4 vtxColor; +// void main (void) { gl_Position = position; vtxColor = test_func(color); } +string makeVertexShaderAssembly(const map& fragments) +{ +// \todo [2015-11-23 awoloszyn] Remove OpName once these have stabalized + static const char vertexShaderBoilerplate[] = + "OpCapability Shader\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "${capability:opt}\n" + "${extension:opt}\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Vertex %main \"main\" %BP_stream %BP_position %BP_vtx_color %BP_color %BP_gl_VertexIndex %BP_gl_InstanceIndex ${IF_entrypoint:opt} \n" + "${debug:opt}\n" + "OpName %main \"main\"\n" + "OpName %BP_gl_PerVertex \"gl_PerVertex\"\n" + "OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n" + "OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n" + "OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n" + "OpName %test_code \"testfun(vf4;\"\n" + "OpName %BP_stream \"\"\n" + "OpName %BP_position \"position\"\n" + "OpName %BP_vtx_color \"vtxColor\"\n" + "OpName %BP_color \"color\"\n" + "OpName %BP_gl_VertexIndex \"gl_VertexIndex\"\n" + "OpName %BP_gl_InstanceIndex \"gl_InstanceIndex\"\n" + "OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n" + "OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n" + "OpDecorate %BP_gl_PerVertex Block\n" + "OpDecorate %BP_position Location 0\n" + "OpDecorate %BP_vtx_color Location 1\n" + "OpDecorate %BP_color Location 1\n" + "OpDecorate %BP_gl_VertexIndex BuiltIn VertexIndex\n" + "OpDecorate %BP_gl_InstanceIndex BuiltIn InstanceIndex\n" + "${IF_decoration:opt}\n" + "${decoration:opt}\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_op_gl_PerVertex = OpTypePointer Output %BP_gl_PerVertex\n" + "%BP_stream = OpVariable %BP_op_gl_PerVertex Output\n" + "%BP_position = OpVariable %ip_v4f32 Input\n" + "%BP_vtx_color = OpVariable %op_v4f32 Output\n" + "%BP_color = OpVariable %ip_v4f32 Input\n" + "%BP_gl_VertexIndex = OpVariable %ip_i32 Input\n" + "%BP_gl_InstanceIndex = OpVariable %ip_i32 Input\n" + "${pre_main:opt}\n" + "${IF_variable:opt}\n" + "%main = OpFunction %void None %fun\n" + "%BP_label = OpLabel\n" + "${IF_carryforward:opt}\n" + "%BP_pos = OpLoad %v4f32 %BP_position\n" + "%BP_gl_pos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n" + "OpStore %BP_gl_pos %BP_pos\n" + "%BP_col = OpLoad %v4f32 %BP_color\n" + "%BP_col_transformed = OpFunctionCall %v4f32 %test_code %BP_col\n" + "OpStore %BP_vtx_color %BP_col_transformed\n" + "OpReturn\n" + "OpFunctionEnd\n" + "${interface_op_func:opt}\n" + + "%isUniqueIdZero = OpFunction %bool None %bool_function\n" + "%getId_label = OpLabel\n" + "%vert_id = OpLoad %i32 %BP_gl_VertexIndex\n" + "%is_id_0 = OpIEqual %bool %vert_id %c_i32_0\n" + "OpReturnValue %is_id_0\n" + "OpFunctionEnd\n" + + "${testfun}\n"; + return tcu::StringTemplate(vertexShaderBoilerplate).specialize(fragments); +} + +// Creates tess-control-shader assembly by specializing a boilerplate +// StringTemplate on fragments, which must (at least) map "testfun" to an +// OpFunction definition for %test_code that takes and returns a %v4f32. +// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments. +// +// It roughly corresponds to the following GLSL. +// +// #version 450 +// layout(vertices = 3) out; +// layout(location = 1) in vec4 in_color[]; +// layout(location = 1) out vec4 out_color[]; +// +// void main() { +// out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]); +// gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; +// if (gl_InvocationID == 0) { +// gl_TessLevelOuter[0] = 1.0; +// gl_TessLevelOuter[1] = 1.0; +// gl_TessLevelOuter[2] = 1.0; +// gl_TessLevelInner[0] = 1.0; +// } +// } +string makeTessControlShaderAssembly (const map& fragments) +{ + static const char tessControlShaderBoilerplate[] = + "OpCapability Tessellation\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "${capability:opt}\n" + "${extension:opt}\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint TessellationControl %BP_main \"main\" %BP_out_color %BP_gl_InvocationID %BP_in_color %BP_gl_out %BP_gl_in %BP_gl_TessLevelOuter %BP_gl_TessLevelInner ${IF_entrypoint:opt} \n" + "OpExecutionMode %BP_main OutputVertices 3\n" + "${debug:opt}\n" + "OpName %BP_main \"main\"\n" + "OpName %test_code \"testfun(vf4;\"\n" + "OpName %BP_out_color \"out_color\"\n" + "OpName %BP_gl_InvocationID \"gl_InvocationID\"\n" + "OpName %BP_in_color \"in_color\"\n" + "OpName %BP_gl_PerVertex \"gl_PerVertex\"\n" + "OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n" + "OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n" + "OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n" + "OpName %BP_gl_out \"gl_out\"\n" + "OpName %BP_gl_PVOut \"gl_PerVertex\"\n" + "OpMemberName %BP_gl_PVOut 0 \"gl_Position\"\n" + "OpMemberName %BP_gl_PVOut 1 \"gl_PointSize\"\n" + "OpMemberName %BP_gl_PVOut 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_gl_PVOut 3 \"gl_CullDistance\"\n" + "OpName %BP_gl_in \"gl_in\"\n" + "OpName %BP_gl_TessLevelOuter \"gl_TessLevelOuter\"\n" + "OpName %BP_gl_TessLevelInner \"gl_TessLevelInner\"\n" + "OpDecorate %BP_out_color Location 1\n" + "OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n" + "OpDecorate %BP_in_color Location 1\n" + "OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n" + "OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n" + "OpDecorate %BP_gl_PerVertex Block\n" + "OpMemberDecorate %BP_gl_PVOut 0 BuiltIn Position\n" + "OpMemberDecorate %BP_gl_PVOut 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_gl_PVOut 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_gl_PVOut 3 BuiltIn CullDistance\n" + "OpDecorate %BP_gl_PVOut Block\n" + "OpDecorate %BP_gl_TessLevelOuter Patch\n" + "OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n" + "OpDecorate %BP_gl_TessLevelInner Patch\n" + "OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n" + "${IF_decoration:opt}\n" + "${decoration:opt}\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%BP_out_color = OpVariable %op_a3v4f32 Output\n" + "%BP_gl_InvocationID = OpVariable %ip_i32 Input\n" + "%BP_in_color = OpVariable %ip_a32v4f32 Input\n" + "%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_a3_gl_PerVertex = OpTypeArray %BP_gl_PerVertex %c_u32_3\n" + "%BP_op_a3_gl_PerVertex = OpTypePointer Output %BP_a3_gl_PerVertex\n" + "%BP_gl_out = OpVariable %BP_op_a3_gl_PerVertex Output\n" + "%BP_gl_PVOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_a32_gl_PVOut = OpTypeArray %BP_gl_PVOut %c_u32_32\n" + "%BP_ip_a32_gl_PVOut = OpTypePointer Input %BP_a32_gl_PVOut\n" + "%BP_gl_in = OpVariable %BP_ip_a32_gl_PVOut Input\n" + "%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" + "%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n" + "${pre_main:opt}\n" + "${IF_variable:opt}\n" + + "%BP_main = OpFunction %void None %fun\n" + "%BP_label = OpLabel\n" + "%BP_gl_Invoc = OpLoad %i32 %BP_gl_InvocationID\n" + "${IF_carryforward:opt}\n" + "%BP_in_col_loc = OpAccessChain %ip_v4f32 %BP_in_color %BP_gl_Invoc\n" + "%BP_out_col_loc = OpAccessChain %op_v4f32 %BP_out_color %BP_gl_Invoc\n" + "%BP_in_col_val = OpLoad %v4f32 %BP_in_col_loc\n" + "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_col_val\n" + "OpStore %BP_out_col_loc %BP_clr_transformed\n" + + "%BP_in_pos_loc = OpAccessChain %ip_v4f32 %BP_gl_in %BP_gl_Invoc %c_i32_0\n" + "%BP_out_pos_loc = OpAccessChain %op_v4f32 %BP_gl_out %BP_gl_Invoc %c_i32_0\n" + "%BP_in_pos_val = OpLoad %v4f32 %BP_in_pos_loc\n" + "OpStore %BP_out_pos_loc %BP_in_pos_val\n" + + "%BP_cmp = OpIEqual %bool %BP_gl_Invoc %c_i32_0\n" + "OpSelectionMerge %BP_merge_label None\n" + "OpBranchConditional %BP_cmp %BP_if_label %BP_merge_label\n" + "%BP_if_label = OpLabel\n" + "%BP_gl_TessLevelOuterPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n" + "%BP_gl_TessLevelOuterPos_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n" + "%BP_gl_TessLevelOuterPos_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n" + "%BP_gl_TessLevelInnerPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n" + "OpStore %BP_gl_TessLevelOuterPos_0 %c_f32_1\n" + "OpStore %BP_gl_TessLevelOuterPos_1 %c_f32_1\n" + "OpStore %BP_gl_TessLevelOuterPos_2 %c_f32_1\n" + "OpStore %BP_gl_TessLevelInnerPos_0 %c_f32_1\n" + "OpBranch %BP_merge_label\n" + "%BP_merge_label = OpLabel\n" + "OpReturn\n" + "OpFunctionEnd\n" + "${interface_op_func:opt}\n" + + "%isUniqueIdZero = OpFunction %bool None %bool_function\n" + "%getId_label = OpLabel\n" + "%invocation_id = OpLoad %i32 %BP_gl_InvocationID\n" + "%is_id_0 = OpIEqual %bool %invocation_id %c_i32_0\n" + "OpReturnValue %is_id_0\n" + "OpFunctionEnd\n" + + "${testfun}\n"; + return tcu::StringTemplate(tessControlShaderBoilerplate).specialize(fragments); +} + +// Creates tess-evaluation-shader assembly by specializing a boilerplate +// StringTemplate on fragments, which must (at least) map "testfun" to an +// OpFunction definition for %test_code that takes and returns a %v4f32. +// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments. +// +// It roughly corresponds to the following glsl. +// +// #version 450 +// +// layout(triangles, equal_spacing, ccw) in; +// layout(location = 1) in vec4 in_color[]; +// layout(location = 1) out vec4 out_color; +// +// #define interpolate(val) +// vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] + +// vec4(gl_TessCoord.z) * val[2] +// +// void main() { +// gl_Position = vec4(gl_TessCoord.x) * gl_in[0].gl_Position + +// vec4(gl_TessCoord.y) * gl_in[1].gl_Position + +// vec4(gl_TessCoord.z) * gl_in[2].gl_Position; +// out_color = testfun(interpolate(in_color)); +// } +string makeTessEvalShaderAssembly(const map& fragments) +{ + static const char tessEvalBoilerplate[] = + "OpCapability Tessellation\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "${capability:opt}\n" + "${extension:opt}\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint TessellationEvaluation %BP_main \"main\" %BP_stream %BP_gl_TessCoord %BP_gl_PrimitiveID %BP_gl_in %BP_out_color %BP_in_color ${IF_entrypoint:opt} \n" + "OpExecutionMode %BP_main Triangles\n" + "OpExecutionMode %BP_main SpacingEqual\n" + "OpExecutionMode %BP_main VertexOrderCcw\n" + "${debug:opt}\n" + "OpName %BP_main \"main\"\n" + "OpName %test_code \"testfun(vf4;\"\n" + "OpName %BP_gl_PerVertexOut \"gl_PerVertex\"\n" + "OpMemberName %BP_gl_PerVertexOut 0 \"gl_Position\"\n" + "OpMemberName %BP_gl_PerVertexOut 1 \"gl_PointSize\"\n" + "OpMemberName %BP_gl_PerVertexOut 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_gl_PerVertexOut 3 \"gl_CullDistance\"\n" + "OpName %BP_stream \"\"\n" + "OpName %BP_gl_TessCoord \"gl_TessCoord\"\n" + "OpName %BP_gl_PerVertexIn \"gl_PerVertex\"\n" + "OpName %BP_gl_PrimitiveID \"gl_PrimitiveID\"\n" + "OpMemberName %BP_gl_PerVertexIn 0 \"gl_Position\"\n" + "OpMemberName %BP_gl_PerVertexIn 1 \"gl_PointSize\"\n" + "OpMemberName %BP_gl_PerVertexIn 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_gl_PerVertexIn 3 \"gl_CullDistance\"\n" + "OpName %BP_gl_in \"gl_in\"\n" + "OpName %BP_out_color \"out_color\"\n" + "OpName %BP_in_color \"in_color\"\n" + "OpMemberDecorate %BP_gl_PerVertexOut 0 BuiltIn Position\n" + "OpMemberDecorate %BP_gl_PerVertexOut 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_gl_PerVertexOut 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_gl_PerVertexOut 3 BuiltIn CullDistance\n" + "OpDecorate %BP_gl_PerVertexOut Block\n" + "OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n" + "OpDecorate %BP_gl_TessCoord BuiltIn TessCoord\n" + "OpMemberDecorate %BP_gl_PerVertexIn 0 BuiltIn Position\n" + "OpMemberDecorate %BP_gl_PerVertexIn 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_gl_PerVertexIn 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_gl_PerVertexIn 3 BuiltIn CullDistance\n" + "OpDecorate %BP_gl_PerVertexIn Block\n" + "OpDecorate %BP_out_color Location 1\n" + "OpDecorate %BP_in_color Location 1\n" + "${IF_decoration:opt}\n" + "${decoration:opt}\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%BP_gl_PerVertexOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_op_gl_PerVertexOut = OpTypePointer Output %BP_gl_PerVertexOut\n" + "%BP_stream = OpVariable %BP_op_gl_PerVertexOut Output\n" + "%BP_gl_TessCoord = OpVariable %ip_v3f32 Input\n" + "%BP_gl_PrimitiveID = OpVariable %op_i32 Input\n" + "%BP_gl_PerVertexIn = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_a32_gl_PerVertexIn = OpTypeArray %BP_gl_PerVertexIn %c_u32_32\n" + "%BP_ip_a32_gl_PerVertexIn = OpTypePointer Input %BP_a32_gl_PerVertexIn\n" + "%BP_gl_in = OpVariable %BP_ip_a32_gl_PerVertexIn Input\n" + "%BP_out_color = OpVariable %op_v4f32 Output\n" + "%BP_in_color = OpVariable %ip_a32v4f32 Input\n" + "${pre_main:opt}\n" + "${IF_variable:opt}\n" + "%BP_main = OpFunction %void None %fun\n" + "%BP_label = OpLabel\n" + "${IF_carryforward:opt}\n" + "%BP_gl_TC_0 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n" + "%BP_gl_TC_1 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n" + "%BP_gl_TC_2 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n" + "%BP_gl_in_gl_Pos_0 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n" + "%BP_gl_in_gl_Pos_1 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n" + "%BP_gl_in_gl_Pos_2 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n" + + "%BP_gl_OPos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n" + "%BP_in_color_0 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n" + "%BP_in_color_1 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n" + "%BP_in_color_2 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n" + + "%BP_TC_W_0 = OpLoad %f32 %BP_gl_TC_0\n" + "%BP_TC_W_1 = OpLoad %f32 %BP_gl_TC_1\n" + "%BP_TC_W_2 = OpLoad %f32 %BP_gl_TC_2\n" + "%BP_v4f32_TC_0 = OpCompositeConstruct %v4f32 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0\n" + "%BP_v4f32_TC_1 = OpCompositeConstruct %v4f32 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1\n" + "%BP_v4f32_TC_2 = OpCompositeConstruct %v4f32 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2\n" + + "%BP_gl_IP_0 = OpLoad %v4f32 %BP_gl_in_gl_Pos_0\n" + "%BP_gl_IP_1 = OpLoad %v4f32 %BP_gl_in_gl_Pos_1\n" + "%BP_gl_IP_2 = OpLoad %v4f32 %BP_gl_in_gl_Pos_2\n" + + "%BP_IP_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_gl_IP_0\n" + "%BP_IP_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_gl_IP_1\n" + "%BP_IP_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_gl_IP_2\n" + + "%BP_pos_sum_0 = OpFAdd %v4f32 %BP_IP_W_0 %BP_IP_W_1\n" + "%BP_pos_sum_1 = OpFAdd %v4f32 %BP_pos_sum_0 %BP_IP_W_2\n" + + "OpStore %BP_gl_OPos %BP_pos_sum_1\n" + + "%BP_IC_0 = OpLoad %v4f32 %BP_in_color_0\n" + "%BP_IC_1 = OpLoad %v4f32 %BP_in_color_1\n" + "%BP_IC_2 = OpLoad %v4f32 %BP_in_color_2\n" + + "%BP_IC_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_IC_0\n" + "%BP_IC_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_IC_1\n" + "%BP_IC_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_IC_2\n" + + "%BP_col_sum_0 = OpFAdd %v4f32 %BP_IC_W_0 %BP_IC_W_1\n" + "%BP_col_sum_1 = OpFAdd %v4f32 %BP_col_sum_0 %BP_IC_W_2\n" + + "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_col_sum_1\n" + + "OpStore %BP_out_color %BP_clr_transformed\n" + "OpReturn\n" + "OpFunctionEnd\n" + "${interface_op_func:opt}\n" + + "%isUniqueIdZero = OpFunction %bool None %bool_function\n" + "%getId_label = OpLabel\n" + "%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n" + "%is_id_0 = OpIEqual %bool %primitive_id %c_i32_0\n" + "OpReturnValue %is_id_0\n" + "OpFunctionEnd\n" + + "${testfun}\n"; + return tcu::StringTemplate(tessEvalBoilerplate).specialize(fragments); +} + +// Creates geometry-shader assembly by specializing a boilerplate StringTemplate +// on fragments, which must (at least) map "testfun" to an OpFunction definition +// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed +// with "BP_" to avoid collisions with fragments. +// +// Derived from this GLSL: +// +// #version 450 +// layout(triangles) in; +// layout(triangle_strip, max_vertices = 3) out; +// +// layout(location = 1) in vec4 in_color[]; +// layout(location = 1) out vec4 out_color; +// +// void main() { +// gl_Position = gl_in[0].gl_Position; +// out_color = test_fun(in_color[0]); +// EmitVertex(); +// gl_Position = gl_in[1].gl_Position; +// out_color = test_fun(in_color[1]); +// EmitVertex(); +// gl_Position = gl_in[2].gl_Position; +// out_color = test_fun(in_color[2]); +// EmitVertex(); +// EndPrimitive(); +// } +string makeGeometryShaderAssembly(const map& fragments) +{ + static const char geometryShaderBoilerplate[] = + "OpCapability Geometry\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "${capability:opt}\n" + "${extension:opt}\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Geometry %BP_main \"main\" %BP_out_gl_position %BP_gl_PrimitiveID %BP_gl_in %BP_out_color %BP_in_color ${IF_entrypoint:opt} \n" + "OpExecutionMode %BP_main Triangles\n" + "OpExecutionMode %BP_main OutputTriangleStrip\n" + "OpExecutionMode %BP_main OutputVertices 3\n" + "${debug:opt}\n" + "OpName %BP_main \"main\"\n" + "OpName %BP_gl_PrimitiveID \"gl_PrimitiveID\"\n" + "OpName %BP_per_vertex_in \"gl_PerVertex\"\n" + "OpMemberName %BP_per_vertex_in 0 \"gl_Position\"\n" + "OpMemberName %BP_per_vertex_in 1 \"gl_PointSize\"\n" + "OpMemberName %BP_per_vertex_in 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_per_vertex_in 3 \"gl_CullDistance\"\n" + "OpName %BP_gl_in \"gl_in\"\n" + "OpName %BP_out_color \"out_color\"\n" + "OpName %BP_in_color \"in_color\"\n" + "OpName %test_code \"testfun(vf4;\"\n" + "OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n" + "OpDecorate %BP_out_gl_position BuiltIn Position\n" + "OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n" + "OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n" + "OpDecorate %BP_per_vertex_in Block\n" + "OpDecorate %BP_out_color Location 1\n" + "OpDecorate %BP_in_color Location 1\n" + "${IF_decoration:opt}\n" + "${decoration:opt}\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n" + "%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n" + + "%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n" + "%BP_out_color = OpVariable %op_v4f32 Output\n" + "%BP_in_color = OpVariable %ip_a3v4f32 Input\n" + "%BP_gl_PrimitiveID = OpVariable %ip_i32 Input\n" + "%BP_out_gl_position = OpVariable %op_v4f32 Output\n" + "${pre_main:opt}\n" + "${IF_variable:opt}\n" + + "%BP_main = OpFunction %void None %fun\n" + "%BP_label = OpLabel\n" + + "${IF_carryforward:opt}\n" + + "%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n" + "%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n" + "%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n" + + "%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n" + "%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n" + "%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n" + + "%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n" + "%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n" + "%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n" + + "%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n" + "%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n" + "%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n" + + "%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n" + "%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n" + "%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n" + + + "OpStore %BP_out_gl_position %BP_in_position_0\n" + "OpStore %BP_out_color %BP_transformed_in_color_0\n" + "OpEmitVertex\n" + + "OpStore %BP_out_gl_position %BP_in_position_1\n" + "OpStore %BP_out_color %BP_transformed_in_color_1\n" + "OpEmitVertex\n" + + "OpStore %BP_out_gl_position %BP_in_position_2\n" + "OpStore %BP_out_color %BP_transformed_in_color_2\n" + "OpEmitVertex\n" + + "OpEndPrimitive\n" + "OpReturn\n" + "OpFunctionEnd\n" + "${interface_op_func:opt}\n" + + "%isUniqueIdZero = OpFunction %bool None %bool_function\n" + "%getId_label = OpLabel\n" + "%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n" + "%is_id_0 = OpIEqual %bool %primitive_id %c_i32_0\n" + "OpReturnValue %is_id_0\n" + "OpFunctionEnd\n" + + "${testfun}\n"; + return tcu::StringTemplate(geometryShaderBoilerplate).specialize(fragments); +} + +// Creates fragment-shader assembly by specializing a boilerplate StringTemplate +// on fragments, which must (at least) map "testfun" to an OpFunction definition +// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed +// with "BP_" to avoid collisions with fragments. +// +// Derived from this GLSL: +// +// layout(location = 1) in highp vec4 vtxColor; +// layout(location = 0) out highp vec4 fragColor; +// highp vec4 testfun(highp vec4 x) { return x; } +// void main(void) { fragColor = testfun(vtxColor); } +// +// with modifications including passing vtxColor by value and ripping out +// testfun() definition. +string makeFragmentShaderAssembly(const map& fragments) +{ + static const char fragmentShaderBoilerplate[] = + "OpCapability Shader\n" + "${capability:opt}\n" + "${extension:opt}\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor %BP_gl_FragCoord ${IF_entrypoint:opt} \n" + "OpExecutionMode %BP_main OriginUpperLeft\n" + "${debug:opt}\n" + "OpName %BP_main \"main\"\n" + "OpName %BP_gl_FragCoord \"fragCoord\"\n" + "OpName %BP_fragColor \"fragColor\"\n" + "OpName %BP_vtxColor \"vtxColor\"\n" + "OpName %test_code \"testfun(vf4;\"\n" + "OpDecorate %BP_fragColor Location 0\n" + "OpDecorate %BP_vtxColor Location 1\n" + "OpDecorate %BP_gl_FragCoord BuiltIn FragCoord\n" + "${IF_decoration:opt}\n" + "${decoration:opt}\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%BP_gl_FragCoord = OpVariable %ip_v4f32 Input\n" + "%BP_fragColor = OpVariable %op_v4f32 Output\n" + "%BP_vtxColor = OpVariable %ip_v4f32 Input\n" + "${pre_main:opt}\n" + "${IF_variable:opt}\n" + "%BP_main = OpFunction %void None %fun\n" + "%BP_label_main = OpLabel\n" + "${IF_carryforward:opt}\n" + "%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n" + "%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n" + "OpStore %BP_fragColor %BP_tmp2\n" + "OpReturn\n" + "OpFunctionEnd\n" + "${interface_op_func:opt}\n" + + "%isUniqueIdZero = OpFunction %bool None %bool_function\n" + "%getId_label = OpLabel\n" + "%loc_x_coord = OpAccessChain %ip_f32 %BP_gl_FragCoord %c_i32_0\n" + "%loc_y_coord = OpAccessChain %ip_f32 %BP_gl_FragCoord %c_i32_1\n" + "%x_coord = OpLoad %f32 %loc_x_coord\n" + "%y_coord = OpLoad %f32 %loc_y_coord\n" + "%is_x_idx0 = OpFOrdEqual %bool %x_coord %c_f32_0_5\n" + "%is_y_idx0 = OpFOrdEqual %bool %y_coord %c_f32_0_5\n" + "%is_frag_0 = OpLogicalAnd %bool %is_x_idx0 %is_y_idx0\n" + "OpReturnValue %is_frag_0\n" + "OpFunctionEnd\n" + + "${testfun}\n"; + return tcu::StringTemplate(fragmentShaderBoilerplate).specialize(fragments); +} + +// Creates mappings from placeholders to pass-through shader code which copies +// the input to the output faithfully. +map passthruInterface(const IFDataType& data_type) +{ + const string var_type = data_type.str(); + map fragments = passthruFragments(); + const string functype = string("%") + var_type + "_" + var_type + "_function"; + + fragments["interface_op_func"] = + string("%interface_op_func = OpFunction %") + var_type + " None " + functype + "\n" + " %io_param1 = OpFunctionParameter %" + var_type + "\n" + " %IF_label = OpLabel\n" + " OpReturnValue %io_param1\n" + " OpFunctionEnd\n"; + fragments["input_type"] = var_type; + fragments["output_type"] = var_type; + fragments["pre_main"] = ""; + + if (!data_type.elementIs32bit()) + { + if (data_type.elementType == NUMBERTYPE_FLOAT16) + { + fragments["pre_main"] += "%f16 = OpTypeFloat 16\n"; + } + else if (data_type.elementType == NUMBERTYPE_INT16) + { + fragments["pre_main"] += "%i16 = OpTypeInt 16 1\n"; + } + else + { + fragments["pre_main"] += "%u16 = OpTypeInt 16 0\n"; + } + + fragments["capability"] = "OpCapability StorageInputOutput16\n"; + + if (data_type.isVector()) + { + fragments["pre_main"] += "%" + var_type + " = OpTypeVector %" + IFDataType(1, data_type.elementType).str() + " " + numberToString(data_type.numElements) + "\n"; + } + + fragments["pre_main"] += + "%ip_" + var_type + " = OpTypePointer Input %" + var_type + "\n" + "%op_" + var_type + " = OpTypePointer Output %" + var_type + "\n"; + } + + fragments["pre_main"] += + functype + " = OpTypeFunction %" + var_type + " %" + var_type + "\n" + "%a3" + var_type + " = OpTypeArray %" + var_type + " %c_i32_3\n" + "%ip_a3" + var_type + " = OpTypePointer Input %a3" + var_type + "\n" + "%op_a3" + var_type + " = OpTypePointer Output %a3" + var_type + "\n"; + + return fragments; +} + +// Returns mappings from interface placeholders to their concrete values. +// +// The concrete values should be specialized again to provide ${input_type} +// and ${output_type}. +// +// %ip_${input_type} and %op_${output_type} should also be defined in the final code. +map fillInterfacePlaceholderVert (void) +{ + map fragments ; + + fragments["IF_entrypoint"] = "%IF_input %IF_output"; + fragments["IF_variable"] = + " %IF_input = OpVariable %ip_${input_type} Input\n" + "%IF_output = OpVariable %op_${output_type} Output\n"; + fragments["IF_decoration"] = + "OpDecorate %IF_input Location 2\n" + "OpDecorate %IF_output Location 2\n"; + fragments["IF_carryforward"] = + "%IF_input_val = OpLoad %${input_type} %IF_input\n" + " %IF_result = OpFunctionCall %${output_type} %interface_op_func %IF_input_val\n" + " OpStore %IF_output %IF_result\n"; + + // Make sure the rest still need to be instantialized. + fragments["capability"] = "${capability:opt}"; + fragments["extension"] = "${extension:opt}"; + fragments["debug"] = "${debug:opt}"; + fragments["decoration"] = "${decoration:opt}"; + fragments["pre_main"] = "${pre_main:opt}"; + fragments["testfun"] = "${testfun}"; + fragments["interface_op_func"] = "${interface_op_func}"; + + return fragments; +} + +// Returns mappings from interface placeholders to their concrete values. +// +// The concrete values should be specialized again to provide ${input_type} +// and ${output_type}. +// +// %ip_${input_type} and %op_${output_type} should also be defined in the final code. +map fillInterfacePlaceholderFrag (void) +{ + map fragments ; + + fragments["IF_entrypoint"] = "%IF_input %IF_output"; + fragments["IF_variable"] = + " %IF_input = OpVariable %ip_${input_type} Input\n" + "%IF_output = OpVariable %op_${output_type} Output\n"; + fragments["IF_decoration"] = + "OpDecorate %IF_input Location 2\n" + "OpDecorate %IF_output Location 1\n"; // Fragment shader should write to location #1. + fragments["IF_carryforward"] = + "%IF_input_val = OpLoad %${input_type} %IF_input\n" + " %IF_result = OpFunctionCall %${output_type} %interface_op_func %IF_input_val\n" + " OpStore %IF_output %IF_result\n"; + + // Make sure the rest still need to be instantialized. + fragments["capability"] = "${capability:opt}"; + fragments["extension"] = "${extension:opt}"; + fragments["debug"] = "${debug:opt}"; + fragments["decoration"] = "${decoration:opt}"; + fragments["pre_main"] = "${pre_main:opt}"; + fragments["testfun"] = "${testfun}"; + fragments["interface_op_func"] = "${interface_op_func}"; + + return fragments; +} + +// Returns mappings from interface placeholders to their concrete values. +// +// The concrete values should be specialized again to provide ${input_type} +// and ${output_type}. +// +// %ip_${input_type}, %op_${output_type}, %ip_a3${input_type}, and $op_a3${output_type} +// should also be defined in the final code. +map fillInterfacePlaceholderTessCtrl (void) +{ + map fragments ; + + fragments["IF_entrypoint"] = "%IF_input %IF_output"; + fragments["IF_variable"] = + " %IF_input = OpVariable %ip_a3${input_type} Input\n" + "%IF_output = OpVariable %op_a3${output_type} Output\n"; + fragments["IF_decoration"] = + "OpDecorate %IF_input Location 2\n" + "OpDecorate %IF_output Location 2\n"; + fragments["IF_carryforward"] = + " %IF_input_ptr0 = OpAccessChain %ip_${input_type} %IF_input %c_i32_0\n" + " %IF_input_ptr1 = OpAccessChain %ip_${input_type} %IF_input %c_i32_1\n" + " %IF_input_ptr2 = OpAccessChain %ip_${input_type} %IF_input %c_i32_2\n" + "%IF_output_ptr0 = OpAccessChain %op_${output_type} %IF_output %c_i32_0\n" + "%IF_output_ptr1 = OpAccessChain %op_${output_type} %IF_output %c_i32_1\n" + "%IF_output_ptr2 = OpAccessChain %op_${output_type} %IF_output %c_i32_2\n" + "%IF_input_val0 = OpLoad %${input_type} %IF_input_ptr0\n" + "%IF_input_val1 = OpLoad %${input_type} %IF_input_ptr1\n" + "%IF_input_val2 = OpLoad %${input_type} %IF_input_ptr2\n" + "%IF_input_res0 = OpFunctionCall %${output_type} %interface_op_func %IF_input_val0\n" + "%IF_input_res1 = OpFunctionCall %${output_type} %interface_op_func %IF_input_val1\n" + "%IF_input_res2 = OpFunctionCall %${output_type} %interface_op_func %IF_input_val2\n" + "OpStore %IF_output_ptr0 %IF_input_res0\n" + "OpStore %IF_output_ptr1 %IF_input_res1\n" + "OpStore %IF_output_ptr2 %IF_input_res2\n"; + + // Make sure the rest still need to be instantialized. + fragments["capability"] = "${capability:opt}"; + fragments["extension"] = "${extension:opt}"; + fragments["debug"] = "${debug:opt}"; + fragments["decoration"] = "${decoration:opt}"; + fragments["pre_main"] = "${pre_main:opt}"; + fragments["testfun"] = "${testfun}"; + fragments["interface_op_func"] = "${interface_op_func}"; + + return fragments; +} + +// Returns mappings from interface placeholders to their concrete values. +// +// The concrete values should be specialized again to provide ${input_type} +// and ${output_type}. +// +// %ip_${input_type}, %op_${output_type}, %ip_a3${input_type}, and $op_a3${output_type} +// should also be defined in the final code. +map fillInterfacePlaceholderTessEvalGeom (void) +{ + map fragments ; + + fragments["IF_entrypoint"] = "%IF_input %IF_output"; + fragments["IF_variable"] = + " %IF_input = OpVariable %ip_a3${input_type} Input\n" + "%IF_output = OpVariable %op_${output_type} Output\n"; + fragments["IF_decoration"] = + "OpDecorate %IF_input Location 2\n" + "OpDecorate %IF_output Location 2\n"; + fragments["IF_carryforward"] = + // Only get the first value since all three values are the same anyway. + " %IF_input_ptr0 = OpAccessChain %ip_${input_type} %IF_input %c_i32_0\n" + " %IF_input_val0 = OpLoad %${input_type} %IF_input_ptr0\n" + " %IF_input_res0 = OpFunctionCall %${output_type} %interface_op_func %IF_input_val0\n" + "OpStore %IF_output %IF_input_res0\n"; + + // Make sure the rest still need to be instantialized. + fragments["capability"] = "${capability:opt}"; + fragments["extension"] = "${extension:opt}"; + fragments["debug"] = "${debug:opt}"; + fragments["decoration"] = "${decoration:opt}"; + fragments["pre_main"] = "${pre_main:opt}"; + fragments["testfun"] = "${testfun}"; + fragments["interface_op_func"] = "${interface_op_func}"; + + return fragments; +} + +map passthruFragments(void) +{ + map fragments; + fragments["testfun"] = + // A %test_code function that returns its argument unchanged. + "%test_code = OpFunction %v4f32 None %v4f32_function\n" + "%param1 = OpFunctionParameter %v4f32\n" + "%label_testfun = OpLabel\n" + "OpReturnValue %param1\n" + "OpFunctionEnd\n"; + return fragments; +} + +// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. +// Vertex shader gets custom code from context, the rest are pass-through. +void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context) +{ + if (!context.interfaces.empty()) + { + // Inject boilerplate code to wire up additional input/output variables between stages. + // Just copy the contents in input variable to output variable in all stages except + // the customized stage. + dst.spirvAsmSources.add("vert") << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(context.testCodeFragments); + dst.spirvAsmSources.add("frag") << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())); + } else { + map passthru = passthruFragments(); + + dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(context.testCodeFragments); + dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); + } +} + +// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. +// Tessellation control shader gets custom code from context, the rest are +// pass-through. +void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context) +{ + if (!context.interfaces.empty()) + { + // Inject boilerplate code to wire up additional input/output variables between stages. + // Just copy the contents in input variable to output variable in all stages except + // the customized stage. + dst.spirvAsmSources.add("vert") << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())); + dst.spirvAsmSources.add("tessc") << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(context.testCodeFragments); + dst.spirvAsmSources.add("tesse") << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(passthruInterface(context.interfaces.getOutputType())); + dst.spirvAsmSources.add("frag") << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())); + } + else + { + map passthru = passthruFragments(); + + dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); + dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(context.testCodeFragments); + dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru); + dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); + } +} + +// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. +// Tessellation evaluation shader gets custom code from context, the rest are +// pass-through. +void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context) +{ + if (!context.interfaces.empty()) + { + // Inject boilerplate code to wire up additional input/output variables between stages. + // Just copy the contents in input variable to output variable in all stages except + // the customized stage. + dst.spirvAsmSources.add("vert") << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())); + dst.spirvAsmSources.add("tessc") << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(passthruInterface(context.interfaces.getInputType())); + dst.spirvAsmSources.add("tesse") << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments); + dst.spirvAsmSources.add("frag") << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())); + } + else + { + map passthru = passthruFragments(); + dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); + dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru); + dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(context.testCodeFragments); + dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); + } +} + +// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. +// Geometry shader gets custom code from context, the rest are pass-through. +void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context) +{ + if (!context.interfaces.empty()) + { + // Inject boilerplate code to wire up additional input/output variables between stages. + // Just copy the contents in input variable to output variable in all stages except + // the customized stage. + dst.spirvAsmSources.add("vert") << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())); + dst.spirvAsmSources.add("geom") << StringTemplate(makeGeometryShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments); + dst.spirvAsmSources.add("frag") << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())); + } + else + { + map passthru = passthruFragments(); + dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); + dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(context.testCodeFragments); + dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); + } +} + +// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. +// Fragment shader gets custom code from context, the rest are pass-through. +void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context) +{ + if (!context.interfaces.empty()) + { + // Inject boilerplate code to wire up additional input/output variables between stages. + // Just copy the contents in input variable to output variable in all stages except + // the customized stage. + dst.spirvAsmSources.add("vert") << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())); + dst.spirvAsmSources.add("frag") << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(context.testCodeFragments); + } + else + { + map passthru = passthruFragments(); + dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); + dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(context.testCodeFragments); + } +} + +void createCombinedModule(vk::SourceCollections& dst, InstanceContext) +{ + // \todo [2015-12-07 awoloszyn] Make tessellation / geometry conditional + // \todo [2015-12-07 awoloszyn] Remove OpName and OpMemberName at some point + dst.spirvAsmSources.add("module") << + "OpCapability Shader\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "OpCapability Geometry\n" + "OpCapability Tessellation\n" + "OpMemoryModel Logical GLSL450\n" + + "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\n" + "OpEntryPoint Geometry %geom_main \"main\" %geom_out_gl_position %geom_gl_in %geom_out_color %geom_in_color\n" + "OpEntryPoint TessellationControl %tessc_main \"main\" %tessc_out_color %tessc_gl_InvocationID %tessc_in_color %tessc_out_position %tessc_in_position %tessc_gl_TessLevelOuter %tessc_gl_TessLevelInner\n" + "OpEntryPoint TessellationEvaluation %tesse_main \"main\" %tesse_stream %tesse_gl_tessCoord %tesse_in_position %tesse_out_color %tesse_in_color \n" + "OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n" + + "OpExecutionMode %geom_main Triangles\n" + "OpExecutionMode %geom_main OutputTriangleStrip\n" + "OpExecutionMode %geom_main OutputVertices 3\n" + + "OpExecutionMode %tessc_main OutputVertices 3\n" + + "OpExecutionMode %tesse_main Triangles\n" + "OpExecutionMode %tesse_main SpacingEqual\n" + "OpExecutionMode %tesse_main VertexOrderCcw\n" + + "OpExecutionMode %frag_main OriginUpperLeft\n" + + "OpName %vert_main \"main\"\n" + "OpName %vert_vtxPosition \"vtxPosition\"\n" + "OpName %vert_Position \"position\"\n" + "OpName %vert_vtxColor \"vtxColor\"\n" + "OpName %vert_color \"color\"\n" + "OpName %vert_vertex_id \"gl_VertexIndex\"\n" + "OpName %vert_instance_id \"gl_InstanceIndex\"\n" + "OpName %geom_main \"main\"\n" + "OpName %geom_per_vertex_in \"gl_PerVertex\"\n" + "OpMemberName %geom_per_vertex_in 0 \"gl_Position\"\n" + "OpMemberName %geom_per_vertex_in 1 \"gl_PointSize\"\n" + "OpMemberName %geom_per_vertex_in 2 \"gl_ClipDistance\"\n" + "OpMemberName %geom_per_vertex_in 3 \"gl_CullDistance\"\n" + "OpName %geom_gl_in \"gl_in\"\n" + "OpName %geom_out_color \"out_color\"\n" + "OpName %geom_in_color \"in_color\"\n" + "OpName %tessc_main \"main\"\n" + "OpName %tessc_out_color \"out_color\"\n" + "OpName %tessc_gl_InvocationID \"gl_InvocationID\"\n" + "OpName %tessc_in_color \"in_color\"\n" + "OpName %tessc_out_position \"out_position\"\n" + "OpName %tessc_in_position \"in_position\"\n" + "OpName %tessc_gl_TessLevelOuter \"gl_TessLevelOuter\"\n" + "OpName %tessc_gl_TessLevelInner \"gl_TessLevelInner\"\n" + "OpName %tesse_main \"main\"\n" + "OpName %tesse_per_vertex_out \"gl_PerVertex\"\n" + "OpMemberName %tesse_per_vertex_out 0 \"gl_Position\"\n" + "OpMemberName %tesse_per_vertex_out 1 \"gl_PointSize\"\n" + "OpMemberName %tesse_per_vertex_out 2 \"gl_ClipDistance\"\n" + "OpMemberName %tesse_per_vertex_out 3 \"gl_CullDistance\"\n" + "OpName %tesse_stream \"\"\n" + "OpName %tesse_gl_tessCoord \"gl_TessCoord\"\n" + "OpName %tesse_in_position \"in_position\"\n" + "OpName %tesse_out_color \"out_color\"\n" + "OpName %tesse_in_color \"in_color\"\n" + "OpName %frag_main \"main\"\n" + "OpName %frag_fragColor \"fragColor\"\n" + "OpName %frag_vtxColor \"vtxColor\"\n" + + "; Vertex decorations\n" + "OpDecorate %vert_vtxPosition Location 2\n" + "OpDecorate %vert_Position Location 0\n" + "OpDecorate %vert_vtxColor Location 1\n" + "OpDecorate %vert_color Location 1\n" + "OpDecorate %vert_vertex_id BuiltIn VertexIndex\n" + "OpDecorate %vert_instance_id BuiltIn InstanceIndex\n" + + "; Geometry decorations\n" + "OpDecorate %geom_out_gl_position BuiltIn Position\n" + "OpMemberDecorate %geom_per_vertex_in 0 BuiltIn Position\n" + "OpMemberDecorate %geom_per_vertex_in 1 BuiltIn PointSize\n" + "OpMemberDecorate %geom_per_vertex_in 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %geom_per_vertex_in 3 BuiltIn CullDistance\n" + "OpDecorate %geom_per_vertex_in Block\n" + "OpDecorate %geom_out_color Location 1\n" + "OpDecorate %geom_in_color Location 1\n" + + "; Tessellation Control decorations\n" + "OpDecorate %tessc_out_color Location 1\n" + "OpDecorate %tessc_gl_InvocationID BuiltIn InvocationId\n" + "OpDecorate %tessc_in_color Location 1\n" + "OpDecorate %tessc_out_position Location 2\n" + "OpDecorate %tessc_in_position Location 2\n" + "OpDecorate %tessc_gl_TessLevelOuter Patch\n" + "OpDecorate %tessc_gl_TessLevelOuter BuiltIn TessLevelOuter\n" + "OpDecorate %tessc_gl_TessLevelInner Patch\n" + "OpDecorate %tessc_gl_TessLevelInner BuiltIn TessLevelInner\n" + + "; Tessellation Evaluation decorations\n" + "OpMemberDecorate %tesse_per_vertex_out 0 BuiltIn Position\n" + "OpMemberDecorate %tesse_per_vertex_out 1 BuiltIn PointSize\n" + "OpMemberDecorate %tesse_per_vertex_out 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %tesse_per_vertex_out 3 BuiltIn CullDistance\n" + "OpDecorate %tesse_per_vertex_out Block\n" + "OpDecorate %tesse_gl_tessCoord BuiltIn TessCoord\n" + "OpDecorate %tesse_in_position Location 2\n" + "OpDecorate %tesse_out_color Location 1\n" + "OpDecorate %tesse_in_color Location 1\n" + + "; Fragment decorations\n" + "OpDecorate %frag_fragColor Location 0\n" + "OpDecorate %frag_vtxColor Location 1\n" + + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + + "; Vertex Variables\n" + "%vert_vtxPosition = OpVariable %op_v4f32 Output\n" + "%vert_Position = OpVariable %ip_v4f32 Input\n" + "%vert_vtxColor = OpVariable %op_v4f32 Output\n" + "%vert_color = OpVariable %ip_v4f32 Input\n" + "%vert_vertex_id = OpVariable %ip_i32 Input\n" + "%vert_instance_id = OpVariable %ip_i32 Input\n" + + "; Geometry Variables\n" + "%geom_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%geom_a3_per_vertex_in = OpTypeArray %geom_per_vertex_in %c_u32_3\n" + "%geom_ip_a3_per_vertex_in = OpTypePointer Input %geom_a3_per_vertex_in\n" + "%geom_gl_in = OpVariable %geom_ip_a3_per_vertex_in Input\n" + "%geom_out_color = OpVariable %op_v4f32 Output\n" + "%geom_in_color = OpVariable %ip_a3v4f32 Input\n" + "%geom_out_gl_position = OpVariable %op_v4f32 Output\n" + + "; Tessellation Control Variables\n" + "%tessc_out_color = OpVariable %op_a3v4f32 Output\n" + "%tessc_gl_InvocationID = OpVariable %ip_i32 Input\n" + "%tessc_in_color = OpVariable %ip_a32v4f32 Input\n" + "%tessc_out_position = OpVariable %op_a3v4f32 Output\n" + "%tessc_in_position = OpVariable %ip_a32v4f32 Input\n" + "%tessc_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" + "%tessc_gl_TessLevelInner = OpVariable %op_a2f32 Output\n" + + "; Tessellation Evaluation Decorations\n" + "%tesse_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%tesse_op_per_vertex_out = OpTypePointer Output %tesse_per_vertex_out\n" + "%tesse_stream = OpVariable %tesse_op_per_vertex_out Output\n" + "%tesse_gl_tessCoord = OpVariable %ip_v3f32 Input\n" + "%tesse_in_position = OpVariable %ip_a32v4f32 Input\n" + "%tesse_out_color = OpVariable %op_v4f32 Output\n" + "%tesse_in_color = OpVariable %ip_a32v4f32 Input\n" + + "; Fragment Variables\n" + "%frag_fragColor = OpVariable %op_v4f32 Output\n" + "%frag_vtxColor = OpVariable %ip_v4f32 Input\n" + + "; Vertex Entry\n" + "%vert_main = OpFunction %void None %fun\n" + "%vert_label = OpLabel\n" + "%vert_tmp_position = OpLoad %v4f32 %vert_Position\n" + "OpStore %vert_vtxPosition %vert_tmp_position\n" + "%vert_tmp_color = OpLoad %v4f32 %vert_color\n" + "OpStore %vert_vtxColor %vert_tmp_color\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "; Geometry Entry\n" + "%geom_main = OpFunction %void None %fun\n" + "%geom_label = OpLabel\n" + "%geom_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_0 %c_i32_0\n" + "%geom_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_1 %c_i32_0\n" + "%geom_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_2 %c_i32_0\n" + "%geom_in_position_0 = OpLoad %v4f32 %geom_gl_in_0_gl_position\n" + "%geom_in_position_1 = OpLoad %v4f32 %geom_gl_in_1_gl_position\n" + "%geom_in_position_2 = OpLoad %v4f32 %geom_gl_in_2_gl_position \n" + "%geom_in_color_0_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_0\n" + "%geom_in_color_1_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_1\n" + "%geom_in_color_2_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_2\n" + "%geom_in_color_0 = OpLoad %v4f32 %geom_in_color_0_ptr\n" + "%geom_in_color_1 = OpLoad %v4f32 %geom_in_color_1_ptr\n" + "%geom_in_color_2 = OpLoad %v4f32 %geom_in_color_2_ptr\n" + "OpStore %geom_out_gl_position %geom_in_position_0\n" + "OpStore %geom_out_color %geom_in_color_0\n" + "OpEmitVertex\n" + "OpStore %geom_out_gl_position %geom_in_position_1\n" + "OpStore %geom_out_color %geom_in_color_1\n" + "OpEmitVertex\n" + "OpStore %geom_out_gl_position %geom_in_position_2\n" + "OpStore %geom_out_color %geom_in_color_2\n" + "OpEmitVertex\n" + "OpEndPrimitive\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "; Tessellation Control Entry\n" + "%tessc_main = OpFunction %void None %fun\n" + "%tessc_label = OpLabel\n" + "%tessc_invocation_id = OpLoad %i32 %tessc_gl_InvocationID\n" + "%tessc_in_color_ptr = OpAccessChain %ip_v4f32 %tessc_in_color %tessc_invocation_id\n" + "%tessc_in_position_ptr = OpAccessChain %ip_v4f32 %tessc_in_position %tessc_invocation_id\n" + "%tessc_in_color_val = OpLoad %v4f32 %tessc_in_color_ptr\n" + "%tessc_in_position_val = OpLoad %v4f32 %tessc_in_position_ptr\n" + "%tessc_out_color_ptr = OpAccessChain %op_v4f32 %tessc_out_color %tessc_invocation_id\n" + "%tessc_out_position_ptr = OpAccessChain %op_v4f32 %tessc_out_position %tessc_invocation_id\n" + "OpStore %tessc_out_color_ptr %tessc_in_color_val\n" + "OpStore %tessc_out_position_ptr %tessc_in_position_val\n" + "%tessc_is_first_invocation = OpIEqual %bool %tessc_invocation_id %c_i32_0\n" + "OpSelectionMerge %tessc_merge_label None\n" + "OpBranchConditional %tessc_is_first_invocation %tessc_first_invocation %tessc_merge_label\n" + "%tessc_first_invocation = OpLabel\n" + "%tessc_tess_outer_0 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_0\n" + "%tessc_tess_outer_1 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_1\n" + "%tessc_tess_outer_2 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_2\n" + "%tessc_tess_inner = OpAccessChain %op_f32 %tessc_gl_TessLevelInner %c_i32_0\n" + "OpStore %tessc_tess_outer_0 %c_f32_1\n" + "OpStore %tessc_tess_outer_1 %c_f32_1\n" + "OpStore %tessc_tess_outer_2 %c_f32_1\n" + "OpStore %tessc_tess_inner %c_f32_1\n" + "OpBranch %tessc_merge_label\n" + "%tessc_merge_label = OpLabel\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "; Tessellation Evaluation Entry\n" + "%tesse_main = OpFunction %void None %fun\n" + "%tesse_label = OpLabel\n" + "%tesse_tc_0_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_0\n" + "%tesse_tc_1_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_1\n" + "%tesse_tc_2_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_2\n" + "%tesse_tc_0 = OpLoad %f32 %tesse_tc_0_ptr\n" + "%tesse_tc_1 = OpLoad %f32 %tesse_tc_1_ptr\n" + "%tesse_tc_2 = OpLoad %f32 %tesse_tc_2_ptr\n" + "%tesse_in_pos_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_0\n" + "%tesse_in_pos_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_1\n" + "%tesse_in_pos_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_2\n" + "%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n" + "%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n" + "%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n" + "%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_0 %tesse_tc_0\n" + "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_1 %tesse_tc_1\n" + "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_2 %tesse_tc_2\n" + "%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n" + "%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n" + "%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n" + "OpStore %tesse_out_pos_ptr %tesse_computed_out\n" + "%tesse_in_clr_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_0\n" + "%tesse_in_clr_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_1\n" + "%tesse_in_clr_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_2\n" + "%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n" + "%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n" + "%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n" + "%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_0 %tesse_tc_0\n" + "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_1 %tesse_tc_1\n" + "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_2 %tesse_tc_2\n" + "%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n" + "%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n" + "OpStore %tesse_out_color %tesse_computed_clr\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "; Fragment Entry\n" + "%frag_main = OpFunction %void None %fun\n" + "%frag_label_main = OpLabel\n" + "%frag_tmp1 = OpLoad %v4f32 %frag_vtxColor\n" + "OpStore %frag_fragColor %frag_tmp1\n" + "OpReturn\n" + "OpFunctionEnd\n"; +} + +void createMultipleEntries(vk::SourceCollections& dst, InstanceContext) +{ + dst.spirvAsmSources.add("vert") << + // This module contains 2 vertex shaders. One that is a passthrough + // and a second that inverts the color of the output (1.0 - color). + "OpCapability Shader\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n" + "OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n" + + "OpName %main \"vert1\"\n" + "OpName %main2 \"vert2\"\n" + "OpName %vtxPosition \"vtxPosition\"\n" + "OpName %Position \"position\"\n" + "OpName %vtxColor \"vtxColor\"\n" + "OpName %color \"color\"\n" + "OpName %vertex_id \"gl_VertexIndex\"\n" + "OpName %instance_id \"gl_InstanceIndex\"\n" + + "OpDecorate %vtxPosition Location 2\n" + "OpDecorate %Position Location 0\n" + "OpDecorate %vtxColor Location 1\n" + "OpDecorate %color Location 1\n" + "OpDecorate %vertex_id BuiltIn VertexIndex\n" + "OpDecorate %instance_id BuiltIn InstanceIndex\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" + "%vtxPosition = OpVariable %op_v4f32 Output\n" + "%Position = OpVariable %ip_v4f32 Input\n" + "%vtxColor = OpVariable %op_v4f32 Output\n" + "%color = OpVariable %ip_v4f32 Input\n" + "%vertex_id = OpVariable %ip_i32 Input\n" + "%instance_id = OpVariable %ip_i32 Input\n" + + "%main = OpFunction %void None %fun\n" + "%label = OpLabel\n" + "%tmp_position = OpLoad %v4f32 %Position\n" + "OpStore %vtxPosition %tmp_position\n" + "%tmp_color = OpLoad %v4f32 %color\n" + "OpStore %vtxColor %tmp_color\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "%main2 = OpFunction %void None %fun\n" + "%label2 = OpLabel\n" + "%tmp_position2 = OpLoad %v4f32 %Position\n" + "OpStore %vtxPosition %tmp_position2\n" + "%tmp_color2 = OpLoad %v4f32 %color\n" + "%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n" + "%tmp_color4 = OpVectorInsertDynamic %v4f32 %tmp_color3 %c_f32_1 %c_i32_3\n" + "OpStore %vtxColor %tmp_color4\n" + "OpReturn\n" + "OpFunctionEnd\n"; + + dst.spirvAsmSources.add("frag") << + // This is a single module that contains 2 fragment shaders. + // One that passes color through and the other that inverts the output + // color (1.0 - color). + "OpCapability Shader\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n" + "OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n" + "OpExecutionMode %main OriginUpperLeft\n" + "OpExecutionMode %main2 OriginUpperLeft\n" + + "OpName %main \"frag1\"\n" + "OpName %main2 \"frag2\"\n" + "OpName %fragColor \"fragColor\"\n" + "OpName %vtxColor \"vtxColor\"\n" + "OpDecorate %fragColor Location 0\n" + "OpDecorate %vtxColor Location 1\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" + "%fragColor = OpVariable %op_v4f32 Output\n" + "%vtxColor = OpVariable %ip_v4f32 Input\n" + + "%main = OpFunction %void None %fun\n" + "%label_main = OpLabel\n" + "%tmp1 = OpLoad %v4f32 %vtxColor\n" + "OpStore %fragColor %tmp1\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "%main2 = OpFunction %void None %fun\n" + "%label_main2 = OpLabel\n" + "%tmp2 = OpLoad %v4f32 %vtxColor\n" + "%tmp3 = OpFSub %v4f32 %cval %tmp2\n" + "%tmp4 = OpVectorInsertDynamic %v4f32 %tmp3 %c_f32_1 %c_i32_3\n" + "OpStore %fragColor %tmp4\n" + "OpReturn\n" + "OpFunctionEnd\n"; + + dst.spirvAsmSources.add("geom") << + "OpCapability Geometry\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n" + "OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n" + "OpExecutionMode %geom1_main Triangles\n" + "OpExecutionMode %geom2_main Triangles\n" + "OpExecutionMode %geom1_main OutputTriangleStrip\n" + "OpExecutionMode %geom2_main OutputTriangleStrip\n" + "OpExecutionMode %geom1_main OutputVertices 3\n" + "OpExecutionMode %geom2_main OutputVertices 3\n" + "OpName %geom1_main \"geom1\"\n" + "OpName %geom2_main \"geom2\"\n" + "OpName %per_vertex_in \"gl_PerVertex\"\n" + "OpMemberName %per_vertex_in 0 \"gl_Position\"\n" + "OpMemberName %per_vertex_in 1 \"gl_PointSize\"\n" + "OpMemberName %per_vertex_in 2 \"gl_ClipDistance\"\n" + "OpMemberName %per_vertex_in 3 \"gl_CullDistance\"\n" + "OpName %gl_in \"gl_in\"\n" + "OpName %out_color \"out_color\"\n" + "OpName %in_color \"in_color\"\n" + "OpDecorate %out_gl_position BuiltIn Position\n" + "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n" + "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n" + "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n" + "OpDecorate %per_vertex_in Block\n" + "OpDecorate %out_color Location 1\n" + "OpDecorate %in_color Location 1\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" + "%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n" + "%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n" + "%gl_in = OpVariable %ip_a3_per_vertex_in Input\n" + "%out_color = OpVariable %op_v4f32 Output\n" + "%in_color = OpVariable %ip_a3v4f32 Input\n" + "%out_gl_position = OpVariable %op_v4f32 Output\n" + + "%geom1_main = OpFunction %void None %fun\n" + "%geom1_label = OpLabel\n" + "%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n" + "%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n" + "%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n" + "%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n" + "%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n" + "%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n" + "%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" + "%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" + "%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" + "%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n" + "%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n" + "%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n" + "OpStore %out_gl_position %geom1_in_position_0\n" + "OpStore %out_color %geom1_in_color_0\n" + "OpEmitVertex\n" + "OpStore %out_gl_position %geom1_in_position_1\n" + "OpStore %out_color %geom1_in_color_1\n" + "OpEmitVertex\n" + "OpStore %out_gl_position %geom1_in_position_2\n" + "OpStore %out_color %geom1_in_color_2\n" + "OpEmitVertex\n" + "OpEndPrimitive\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "%geom2_main = OpFunction %void None %fun\n" + "%geom2_label = OpLabel\n" + "%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n" + "%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n" + "%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n" + "%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n" + "%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n" + "%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n" + "%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" + "%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" + "%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" + "%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n" + "%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n" + "%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n" + "%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n" + "%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n" + "%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n" + "%geom2_transformed_in_color_0_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_0 %c_f32_1 %c_i32_3\n" + "%geom2_transformed_in_color_1_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_1 %c_f32_1 %c_i32_3\n" + "%geom2_transformed_in_color_2_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_2 %c_f32_1 %c_i32_3\n" + "OpStore %out_gl_position %geom2_in_position_0\n" + "OpStore %out_color %geom2_transformed_in_color_0_a\n" + "OpEmitVertex\n" + "OpStore %out_gl_position %geom2_in_position_1\n" + "OpStore %out_color %geom2_transformed_in_color_1_a\n" + "OpEmitVertex\n" + "OpStore %out_gl_position %geom2_in_position_2\n" + "OpStore %out_color %geom2_transformed_in_color_2_a\n" + "OpEmitVertex\n" + "OpEndPrimitive\n" + "OpReturn\n" + "OpFunctionEnd\n"; + + dst.spirvAsmSources.add("tessc") << + "OpCapability Tessellation\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n" + "OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n" + "OpExecutionMode %tessc1_main OutputVertices 3\n" + "OpExecutionMode %tessc2_main OutputVertices 3\n" + "OpName %tessc1_main \"tessc1\"\n" + "OpName %tessc2_main \"tessc2\"\n" + "OpName %out_color \"out_color\"\n" + "OpName %gl_InvocationID \"gl_InvocationID\"\n" + "OpName %in_color \"in_color\"\n" + "OpName %out_position \"out_position\"\n" + "OpName %in_position \"in_position\"\n" + "OpName %gl_TessLevelOuter \"gl_TessLevelOuter\"\n" + "OpName %gl_TessLevelInner \"gl_TessLevelInner\"\n" + "OpDecorate %out_color Location 1\n" + "OpDecorate %gl_InvocationID BuiltIn InvocationId\n" + "OpDecorate %in_color Location 1\n" + "OpDecorate %out_position Location 2\n" + "OpDecorate %in_position Location 2\n" + "OpDecorate %gl_TessLevelOuter Patch\n" + "OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n" + "OpDecorate %gl_TessLevelInner Patch\n" + "OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" + "%out_color = OpVariable %op_a3v4f32 Output\n" + "%gl_InvocationID = OpVariable %ip_i32 Input\n" + "%in_color = OpVariable %ip_a32v4f32 Input\n" + "%out_position = OpVariable %op_a3v4f32 Output\n" + "%in_position = OpVariable %ip_a32v4f32 Input\n" + "%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" + "%gl_TessLevelInner = OpVariable %op_a2f32 Output\n" + + "%tessc1_main = OpFunction %void None %fun\n" + "%tessc1_label = OpLabel\n" + "%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n" + "%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n" + "%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n" + "%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n" + "%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n" + "%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n" + "%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n" + "OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n" + "OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n" + "%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n" + "OpSelectionMerge %tessc1_merge_label None\n" + "OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n" + "%tessc1_first_invocation = OpLabel\n" + "%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n" + "%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n" + "%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n" + "%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n" + "OpStore %tessc1_tess_outer_0 %c_f32_1\n" + "OpStore %tessc1_tess_outer_1 %c_f32_1\n" + "OpStore %tessc1_tess_outer_2 %c_f32_1\n" + "OpStore %tessc1_tess_inner %c_f32_1\n" + "OpBranch %tessc1_merge_label\n" + "%tessc1_merge_label = OpLabel\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "%tessc2_main = OpFunction %void None %fun\n" + "%tessc2_label = OpLabel\n" + "%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n" + "%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n" + "%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n" + "%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n" + "%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n" + "%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n" + "%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n" + "%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n" + "%tessc2_transformed_color_a = OpVectorInsertDynamic %v4f32 %tessc2_transformed_color %c_f32_1 %c_i32_3\n" + "OpStore %tessc2_out_color_ptr %tessc2_transformed_color_a\n" + "OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n" + "%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n" + "OpSelectionMerge %tessc2_merge_label None\n" + "OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n" + "%tessc2_first_invocation = OpLabel\n" + "%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n" + "%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n" + "%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n" + "%tessc2_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n" + "OpStore %tessc2_tess_outer_0 %c_f32_1\n" + "OpStore %tessc2_tess_outer_1 %c_f32_1\n" + "OpStore %tessc2_tess_outer_2 %c_f32_1\n" + "OpStore %tessc2_tess_inner %c_f32_1\n" + "OpBranch %tessc2_merge_label\n" + "%tessc2_merge_label = OpLabel\n" + "OpReturn\n" + "OpFunctionEnd\n"; + + dst.spirvAsmSources.add("tesse") << + "OpCapability Tessellation\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n" + "OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n" + "OpExecutionMode %tesse1_main Triangles\n" + "OpExecutionMode %tesse1_main SpacingEqual\n" + "OpExecutionMode %tesse1_main VertexOrderCcw\n" + "OpExecutionMode %tesse2_main Triangles\n" + "OpExecutionMode %tesse2_main SpacingEqual\n" + "OpExecutionMode %tesse2_main VertexOrderCcw\n" + "OpName %tesse1_main \"tesse1\"\n" + "OpName %tesse2_main \"tesse2\"\n" + "OpName %per_vertex_out \"gl_PerVertex\"\n" + "OpMemberName %per_vertex_out 0 \"gl_Position\"\n" + "OpMemberName %per_vertex_out 1 \"gl_PointSize\"\n" + "OpMemberName %per_vertex_out 2 \"gl_ClipDistance\"\n" + "OpMemberName %per_vertex_out 3 \"gl_CullDistance\"\n" + "OpName %stream \"\"\n" + "OpName %gl_tessCoord \"gl_TessCoord\"\n" + "OpName %in_position \"in_position\"\n" + "OpName %out_color \"out_color\"\n" + "OpName %in_color \"in_color\"\n" + "OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n" + "OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n" + "OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n" + "OpDecorate %per_vertex_out Block\n" + "OpDecorate %gl_tessCoord BuiltIn TessCoord\n" + "OpDecorate %in_position Location 2\n" + "OpDecorate %out_color Location 1\n" + "OpDecorate %in_color Location 1\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" + "%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n" + "%stream = OpVariable %op_per_vertex_out Output\n" + "%gl_tessCoord = OpVariable %ip_v3f32 Input\n" + "%in_position = OpVariable %ip_a32v4f32 Input\n" + "%out_color = OpVariable %op_v4f32 Output\n" + "%in_color = OpVariable %ip_a32v4f32 Input\n" + + "%tesse1_main = OpFunction %void None %fun\n" + "%tesse1_label = OpLabel\n" + "%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n" + "%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n" + "%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n" + "%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n" + "%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n" + "%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n" + "%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n" + "%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n" + "%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n" + "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n" + "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n" + "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n" + "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n" + "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n" + "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n" + "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n" + "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n" + "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n" + "OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n" + "%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" + "%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" + "%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" + "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n" + "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n" + "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n" + "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n" + "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n" + "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n" + "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n" + "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n" + "OpStore %out_color %tesse1_computed_clr\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "%tesse2_main = OpFunction %void None %fun\n" + "%tesse2_label = OpLabel\n" + "%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n" + "%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n" + "%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n" + "%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n" + "%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n" + "%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n" + "%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n" + "%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n" + "%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n" + "%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n" + "%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n" + "%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n" + "%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_0 %tesse2_tc_0\n" + "%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_1 %tesse2_tc_1\n" + "%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_2 %tesse2_tc_2\n" + "%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n" + "%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n" + "%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n" + "OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n" + "%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" + "%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" + "%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" + "%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n" + "%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n" + "%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n" + "%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_0 %tesse2_tc_0\n" + "%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_1 %tesse2_tc_1\n" + "%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_2 %tesse2_tc_2\n" + "%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n" + "%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n" + "%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n" + "%tesse2_clr_transformed_a = OpVectorInsertDynamic %v4f32 %tesse2_clr_transformed %c_f32_1 %c_i32_3\n" + "OpStore %out_color %tesse2_clr_transformed_a\n" + "OpReturn\n" + "OpFunctionEnd\n"; +} + +bool compare16BitFloat (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log) +{ + // We only support RTE, RTZ, or both. + DE_ASSERT(static_cast(flags) > 0 && static_cast(flags) < 4); + + const Float32 originalFloat (original); + const Float16 returnedFloat (returned); + + // Zero are turned into zero under both RTE and RTZ. + if (originalFloat.isZero()) + { + if (returnedFloat.isZero()) + return true; + + log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage; + return false; + } + + // Inf are always turned into Inf with the same sign, too. + if (originalFloat.isInf()) + { + if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit()) + return true; + + log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage; + return false; + } + + // NaN are always turned into NaN, too. + if (originalFloat.isNaN()) + { + if (returnedFloat.isNaN()) + return true; + + log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage; + return false; + } + + // Check all rounding modes + for (int bitNdx = 0; bitNdx < 2; ++bitNdx) + { + if ((flags & (1u << bitNdx)) == 0) + continue; // This rounding mode is not selected. + + const Float16 expectedFloat (deFloat32To16Round(original, deRoundingMode(bitNdx))); + + // Denormalized numbers can be flushed to zero. + if (expectedFloat.isDenorm() && returnedFloat.isZero()) + return true; + + // If not matched in the above cases, they should have the same bit pattern. + if (expectedFloat.bits() == returnedFloat.bits()) + return true; + } + + log << TestLog::Message << "Error: found unmatched 32-bit and 16-bit floats: " << originalFloat.bits() << " vs " << returned << TestLog::EndMessage; + return false; +} + +bool compare32BitFloat (float expected, float returned, tcu::TestLog& log) +{ + const Float32 expectedFloat (expected); + const Float32 returnedFloat (returned); + + // Denormalized numbers can be flushed to zero + if (expectedFloat.isDenorm() && returnedFloat.isZero()) + return true; + + if (expectedFloat.isNaN()) + { + if (returnedFloat.isNaN()) + return true; + + log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage; + return false; + } + + if (returned == expected) + return true; + + log << TestLog::Message << "Error: found unmatched 32-bit float: expected " << expectedFloat.bits() << " vs. returned " << returnedFloat.bits() << TestLog::EndMessage; + return false; +} + +Move createBufferForResource(const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, deUint32 queueFamilyIndex) +{ + const VkBufferCreateInfo resourceBufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType + DE_NULL, // pNext + (VkBufferCreateFlags)0, // flags + (VkDeviceSize)resource.second->getNumBytes(), // size + (VkBufferUsageFlags)getMatchingBufferUsageFlagBit(resource.first), // usage + VK_SHARING_MODE_EXCLUSIVE, // sharingMode + 1u, // queueFamilyCount + &queueFamilyIndex, // pQueueFamilyIndices + }; + + return createBuffer(vk, vkDevice, &resourceBufferParams); +} + +TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance) +{ + const InstanceInterface& vkInstance = context.getInstanceInterface(); + const VkPhysicalDevice vkPhysicalDevice = context.getPhysicalDevice(); + const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); + // Create a dedicated logic device with required extensions enabled for this test case. + const Unique vkDevice (createDeviceWithExtensions(vkInstance, vkPhysicalDevice, queueFamilyIndex, context.getDeviceExtensions(), instance.requiredDeviceExtensions)); + const DeviceDriver vk (vkInstance, *vkDevice); + const VkQueue queue = getDeviceQueue(vk, *vkDevice, queueFamilyIndex, 0); + const tcu::UVec2 renderSize (256, 256); + vector modules; + map moduleByStage; + const int testSpecificSeed = 31354125; + const int seed = context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed; + bool supportsGeometry = false; + bool supportsTessellation = false; + bool hasTessellation = false; + const bool hasPushConstants = !instance.pushConstants.empty(); + const deUint32 numResources = static_cast(instance.resources.inputs.size() + instance.resources.outputs.size()); + const bool needInterface = !instance.interfaces.empty(); + const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures(); + const de::UniquePtr allocatorUptr (createAllocator(vkInstance, vkPhysicalDevice, vk, *vkDevice)); + Allocator& allocator = *allocatorUptr; + + supportsGeometry = features.geometryShader == VK_TRUE; + supportsTessellation = features.tessellationShader == VK_TRUE; + hasTessellation = (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) || + (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); + + if (hasTessellation && !supportsTessellation) + { + throw tcu::NotSupportedError(std::string("Tessellation not supported")); + } + + if ((instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT) && + !supportsGeometry) + { + throw tcu::NotSupportedError(std::string("Geometry not supported")); + } + + { + for (deUint32 featureNdx = 0; featureNdx < instance.requiredDeviceFeatures.size(); ++featureNdx) + { + const string& feature = instance.requiredDeviceFeatures[featureNdx]; + + if (feature == "shaderInt16") + { + if (features.shaderInt16 != VK_TRUE) + throw tcu::NotSupportedError(std::string("Device feature not supported: ") + feature); + } + else + { + throw tcu::InternalError(std::string("Unimplemented physical device feature: ") + feature); + } + } + } + + // 16bit storage features + { + if (!is16BitStorageFeaturesSupported(vkInstance, vkPhysicalDevice, context.getInstanceExtensions(), instance.requestedExtensionFeatures.ext16BitStorage)) + TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported"); + } + + de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4); + de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4); + const Vec4 vertexData[] = + { + // Upper left corner: + Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), + Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), + Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(), + + // Upper right corner: + Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), + Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), + Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(), + + // Lower left corner: + Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(), + Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), + Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), + + // Lower right corner: + Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(), + Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(), + Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec() + }; + const size_t singleVertexDataSize = 2 * sizeof(Vec4); + const size_t vertexCount = sizeof(vertexData) / singleVertexDataSize; + + Move vertexInputBuffer ; + de::MovePtr vertexInputMemory ; + Move fragOutputBuffer ; + de::MovePtr fragOutputMemory ; + Move fragOutputImage ; + de::MovePtr fragOutputImageMemory ; + Move fragOutputImageView ; + + const VkBufferCreateInfo vertexBufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyCount; + &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; + }; + const Unique vertexBuffer (createBuffer(vk, *vkDevice, &vertexBufferParams)); + const UniquePtr vertexBufferMemory (allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *vertexBuffer), MemoryRequirement::HostVisible)); + + VK_CHECK(vk.bindBufferMemory(*vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset())); + + const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y()); + const VkBufferCreateInfo readImageBufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + imageSizeBytes, // VkDeviceSize size; + VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyCount; + &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; + }; + const Unique readImageBuffer (createBuffer(vk, *vkDevice, &readImageBufferParams)); + const UniquePtr readImageBufferMemory (allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *readImageBuffer), MemoryRequirement::HostVisible)); + + VK_CHECK(vk.bindBufferMemory(*vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset())); + + VkImageCreateInfo imageParams = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; + { renderSize.x(), renderSize.y(), 1 }, // VkExtent3D extent; + 1u, // deUint32 mipLevels; + 1u, // deUint32 arraySize; + VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyCount; + &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + + const Unique image (createImage(vk, *vkDevice, &imageParams)); + const UniquePtr imageMemory (allocator.allocate(getImageMemoryRequirements(vk, *vkDevice, *image), MemoryRequirement::Any)); + + VK_CHECK(vk.bindImageMemory(*vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset())); + + if (needInterface) + { + // The pipeline renders four triangles, each with three vertexes. + // Test instantialization only provides four data points, each + // for one triangle. So we need allocate space of three times of + // input buffer's size. + const deUint32 inputNumBytes = deUint32(instance.interfaces.getInputBuffer()->getNumBytes() * 3); + // Create an additional buffer and backing memory for one input variable. + const VkBufferCreateInfo vertexInputParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + inputNumBytes, // VkDeviceSize size; + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyCount; + &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; + }; + + vertexInputBuffer = createBuffer(vk, *vkDevice, &vertexInputParams); + vertexInputMemory = allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *vertexInputBuffer), MemoryRequirement::HostVisible); + VK_CHECK(vk.bindBufferMemory(*vkDevice, *vertexInputBuffer, vertexInputMemory->getMemory(), vertexInputMemory->getOffset())); + + // Create an additional buffer and backing memory for an output variable. + const VkDeviceSize fragOutputImgSize = (VkDeviceSize)(instance.interfaces.getOutputType().getNumBytes() * renderSize.x() * renderSize.y()); + const VkBufferCreateInfo fragOutputParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + fragOutputImgSize, // VkDeviceSize size; + VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyCount; + &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; + }; + fragOutputBuffer = createBuffer(vk, *vkDevice, &fragOutputParams); + fragOutputMemory = allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *fragOutputBuffer), MemoryRequirement::HostVisible); + VK_CHECK(vk.bindBufferMemory(*vkDevice, *fragOutputBuffer, fragOutputMemory->getMemory(), fragOutputMemory->getOffset())); + + // Create an additional image and backing memory for attachment. + // Reuse the previous imageParams since we only need to change the image format. + imageParams.format = instance.interfaces.getOutputType().getVkFormat(); + fragOutputImage = createImage(vk, *vkDevice, &imageParams); + fragOutputImageMemory = allocator.allocate(getImageMemoryRequirements(vk, *vkDevice, *fragOutputImage), MemoryRequirement::Any); + + VK_CHECK(vk.bindImageMemory(*vkDevice, *fragOutputImage, fragOutputImageMemory->getMemory(), fragOutputImageMemory->getOffset())); + } + + vector colorAttDescs ; + vector colorAttRefs ; + { + const VkAttachmentDescription attDesc = + { + 0u, // VkAttachmentDescriptionFlags flags; + VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; + }; + colorAttDescs.push_back(attDesc); + + const VkAttachmentReference attRef = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; + }; + colorAttRefs.push_back(attRef); + } + + if (needInterface) + { + const VkAttachmentDescription attDesc = + { + 0u, // VkAttachmentDescriptionFlags flags; + instance.interfaces.getOutputType().getVkFormat(), // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; + }; + colorAttDescs.push_back(attDesc); + + const VkAttachmentReference attRef = + { + 1u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; + }; + colorAttRefs.push_back(attRef); + } + + VkSubpassDescription subpassDesc = + { + 0u, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + 0u, // deUint32 inputCount; + DE_NULL, // const VkAttachmentReference* pInputAttachments; + 1u, // deUint32 colorCount; + colorAttRefs.data(), // const VkAttachmentReference* pColorAttachments; + DE_NULL, // const VkAttachmentReference* pResolveAttachments; + DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; + 0u, // deUint32 preserveCount; + DE_NULL, // const VkAttachmentReference* pPreserveAttachments; + + }; + VkRenderPassCreateInfo renderPassParams = + { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkRenderPassCreateFlags)0, + 1u, // deUint32 attachmentCount; + colorAttDescs.data(), // const VkAttachmentDescription* pAttachments; + 1u, // deUint32 subpassCount; + &subpassDesc, // const VkSubpassDescription* pSubpasses; + 0u, // deUint32 dependencyCount; + DE_NULL, // const VkSubpassDependency* pDependencies; + }; + + if (needInterface) + { + subpassDesc.colorAttachmentCount += 1; + renderPassParams.attachmentCount += 1; + } + + const Unique renderPass (createRenderPass(vk, *vkDevice, &renderPassParams)); + + const VkImageViewCreateInfo colorAttViewParams = + { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkImageViewCreateFlags flags; + *image, // VkImage image; + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; + VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; + { + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A + }, // VkChannelMapping channels; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; + 0u, // deUint32 baseMipLevel; + 1u, // deUint32 mipLevels; + 0u, // deUint32 baseArrayLayer; + 1u, // deUint32 arraySize; + }, // VkImageSubresourceRange subresourceRange; + }; + const Unique colorAttView (createImageView(vk, *vkDevice, &colorAttViewParams)); + + vector attViews ; + attViews.push_back(*colorAttView); + + // Handle resources requested by the test instantiation. + const deUint32 numInResources = static_cast(instance.resources.inputs.size()); + const deUint32 numOutResources = static_cast(instance.resources.outputs.size()); + // These variables should be placed out of the following if block to avoid deallocation after out of scope. + vector inResourceMemories ; + vector outResourceMemories ; + vector inResourceBuffers ; + vector outResourceBuffers ; + Move descriptorPool ; + Move setLayout ; + VkDescriptorSetLayout rawSetLayout = DE_NULL; + VkDescriptorSet rawSet = DE_NULL; + + if (numResources != 0) + { + vector setLayoutBindings ; + vector poolSizes ; + + setLayoutBindings.reserve(numResources); + poolSizes.reserve(numResources); + + // Process all input resources. + for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx) + { + const Resource& resource = instance.resources.inputs[inputNdx]; + // Create buffer and allocate memory. + Move resourceBuffer = createBufferForResource(vk, *vkDevice, resource, queueFamilyIndex); + de::MovePtr resourceMemory = allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *resourceBuffer), MemoryRequirement::HostVisible); + + VK_CHECK(vk.bindBufferMemory(*vkDevice, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset())); + + // Copy data to memory. + const VkMappedMemoryRange range = + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + DE_NULL, // const void* pNext; + resourceMemory->getMemory(), // VkDeviceMemory mem; + 0, // VkDeviceSize offset; + VK_WHOLE_SIZE, // VkDeviceSize size; + }; + + deMemcpy(resourceMemory->getHostPtr(), resource.second->data(), resource.second->getNumBytes()); + VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range)); + + inResourceMemories.push_back(AllocationSp(resourceMemory.release())); + inResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer))); + + // Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool. + const VkDescriptorSetLayoutBinding binding = + { + inputNdx, // binding + resource.first, // descriptorType + 1u, // descriptorCount + VK_SHADER_STAGE_ALL_GRAPHICS, // stageFlags + DE_NULL, // pImmutableSamplers + }; + setLayoutBindings.push_back(binding); + + // Note: the following code doesn't check and unify descriptors of the same type. + const VkDescriptorPoolSize poolSize = + { + resource.first, // type + 1u, // descriptorCount + }; + poolSizes.push_back(poolSize); + } + + // Process all output resources. + for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx) + { + const Resource& resource = instance.resources.outputs[outputNdx]; + // Create buffer and allocate memory. + Move resourceBuffer = createBufferForResource(vk, *vkDevice, resource, queueFamilyIndex); + de::MovePtr resourceMemory = allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *resourceBuffer), MemoryRequirement::HostVisible); + + VK_CHECK(vk.bindBufferMemory(*vkDevice, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset())); + + // Fill memory with all ones. + const VkMappedMemoryRange range = + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + DE_NULL, // const void* pNext; + resourceMemory->getMemory(), // VkDeviceMemory mem; + 0, // VkDeviceSize offset; + VK_WHOLE_SIZE, // VkDeviceSize size; + }; + + deMemset((deUint8*)resourceMemory->getHostPtr(), 0xff, resource.second->getNumBytes()); + VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range)); + + outResourceMemories.push_back(AllocationSp(resourceMemory.release())); + outResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer))); + + // Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool. + const VkDescriptorSetLayoutBinding binding = + { + numInResources + outputNdx, // binding + resource.first, // descriptorType + 1u, // descriptorCount + VK_SHADER_STAGE_ALL_GRAPHICS, // stageFlags + DE_NULL, // pImmutableSamplers + }; + setLayoutBindings.push_back(binding); + + // Note: the following code doesn't check and unify descriptors of the same type. + const VkDescriptorPoolSize poolSize = + { + resource.first, // type + 1u, // descriptorCount + }; + poolSizes.push_back(poolSize); + } + + // Create descriptor set layout, descriptor pool, and allocate descriptor set. + const VkDescriptorSetLayoutCreateInfo setLayoutParams = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType + DE_NULL, // pNext + (VkDescriptorSetLayoutCreateFlags)0, // flags + numResources, // bindingCount + setLayoutBindings.data(), // pBindings + }; + setLayout = createDescriptorSetLayout(vk, *vkDevice, &setLayoutParams); + rawSetLayout = *setLayout; + + const VkDescriptorPoolCreateInfo poolParams = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType + DE_NULL, // pNext + (VkDescriptorPoolCreateFlags)0, // flags + 1u, // maxSets + numResources, // poolSizeCount + poolSizes.data(), // pPoolSizes + }; + descriptorPool = createDescriptorPool(vk, *vkDevice, &poolParams); + + const VkDescriptorSetAllocateInfo setAllocParams = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType + DE_NULL, // pNext + *descriptorPool, // descriptorPool + 1u, // descriptorSetCount + &rawSetLayout, // pSetLayouts + }; + VK_CHECK(vk.allocateDescriptorSets(*vkDevice, &setAllocParams, &rawSet)); + + // Update descriptor set. + vector writeSpecs ; + vector dBufferInfos ; + + writeSpecs.reserve(numResources); + dBufferInfos.reserve(numResources); + + for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx) + { + const VkDescriptorBufferInfo bufInfo = + { + **inResourceBuffers[inputNdx], // buffer + 0, // offset + VK_WHOLE_SIZE, // size + }; + dBufferInfos.push_back(bufInfo); + + const VkWriteDescriptorSet writeSpec = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType + DE_NULL, // pNext + rawSet, // dstSet + inputNdx, // binding + 0, // dstArrayElement + 1u, // descriptorCount + instance.resources.inputs[inputNdx].first, // descriptorType + DE_NULL, // pImageInfo + &dBufferInfos.back(), // pBufferInfo + DE_NULL, // pTexelBufferView + }; + writeSpecs.push_back(writeSpec); + } + for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx) + { + const VkDescriptorBufferInfo bufInfo = + { + **outResourceBuffers[outputNdx], // buffer + 0, // offset + VK_WHOLE_SIZE, // size + }; + dBufferInfos.push_back(bufInfo); + + const VkWriteDescriptorSet writeSpec = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType + DE_NULL, // pNext + rawSet, // dstSet + numInResources + outputNdx, // binding + 0, // dstArrayElement + 1u, // descriptorCount + instance.resources.outputs[outputNdx].first, // descriptorType + DE_NULL, // pImageInfo + &dBufferInfos.back(), // pBufferInfo + DE_NULL, // pTexelBufferView + }; + writeSpecs.push_back(writeSpec); + } + vk.updateDescriptorSets(*vkDevice, numResources, writeSpecs.data(), 0, DE_NULL); + } + + // Pipeline layout + VkPipelineLayoutCreateInfo pipelineLayoutParams = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineLayoutCreateFlags)0, + 0u, // deUint32 descriptorSetCount; + DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; + 0u, // deUint32 pushConstantRangeCount; + DE_NULL, // const VkPushConstantRange* pPushConstantRanges; + }; + + VkPushConstantRange pushConstantRange = + { + VK_SHADER_STAGE_ALL_GRAPHICS, // VkShaderStageFlags stageFlags; + 0, // uint32_t offset; + 0, // uint32_t size; + }; + if (hasPushConstants) + { + pushConstantRange.size = static_cast(instance.pushConstants.getBuffer()->getNumBytes()); + pipelineLayoutParams.pushConstantRangeCount = 1; + pipelineLayoutParams.pPushConstantRanges = &pushConstantRange; + } + if (numResources != 0) + { + // Update pipeline layout with the descriptor set layout. + pipelineLayoutParams.setLayoutCount = 1; + pipelineLayoutParams.pSetLayouts = &rawSetLayout; + } + const Unique pipelineLayout (createPipelineLayout(vk, *vkDevice, &pipelineLayoutParams)); + + // Pipeline + vector shaderStageParams; + // We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline(). + vector > specConstantEntries; + vector specializationInfos; + createPipelineShaderStages(vk, *vkDevice, instance, context, modules, shaderStageParams); + + // And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents. + specConstantEntries.reserve(shaderStageParams.size()); + specializationInfos.reserve(shaderStageParams.size()); + + // Patch the specialization info field in PipelineShaderStageCreateInfos. + for (vector::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo) + { + const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage); + + if (stageIt != instance.specConstants.end()) + { + const size_t numSpecConstants = stageIt->second.size(); + vector entries; + VkSpecializationInfo specInfo; + + entries.resize(numSpecConstants); + + // Only support 32-bit integers as spec constants now. And their constant IDs are numbered sequentially starting from 0. + for (size_t ndx = 0; ndx < numSpecConstants; ++ndx) + { + entries[ndx].constantID = (deUint32)ndx; + entries[ndx].offset = deUint32(ndx * sizeof(deInt32)); + entries[ndx].size = sizeof(deInt32); + } + + specConstantEntries.push_back(entries); + + specInfo.mapEntryCount = (deUint32)numSpecConstants; + specInfo.pMapEntries = specConstantEntries.back().data(); + specInfo.dataSize = numSpecConstants * sizeof(deInt32); + specInfo.pData = stageIt->second.data(); + specializationInfos.push_back(specInfo); + + stageInfo->pSpecializationInfo = &specializationInfos.back(); + } + } + const VkPipelineDepthStencilStateCreateInfo depthStencilParams = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineDepthStencilStateCreateFlags)0, + DE_FALSE, // deUint32 depthTestEnable; + DE_FALSE, // deUint32 depthWriteEnable; + VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp; + DE_FALSE, // deUint32 depthBoundsTestEnable; + DE_FALSE, // deUint32 stencilTestEnable; + { + VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp; + VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp; + VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp; + VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp; + 0u, // deUint32 stencilCompareMask; + 0u, // deUint32 stencilWriteMask; + 0u, // deUint32 stencilReference; + }, // VkStencilOpState front; + { + VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp; + VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp; + VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp; + VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp; + 0u, // deUint32 stencilCompareMask; + 0u, // deUint32 stencilWriteMask; + 0u, // deUint32 stencilReference; + }, // VkStencilOpState back; + -1.0f, // float minDepthBounds; + +1.0f, // float maxDepthBounds; + }; + const VkViewport viewport0 = + { + 0.0f, // float originX; + 0.0f, // float originY; + (float)renderSize.x(), // float width; + (float)renderSize.y(), // float height; + 0.0f, // float minDepth; + 1.0f, // float maxDepth; + }; + const VkRect2D scissor0 = + { + { + 0u, // deInt32 x; + 0u, // deInt32 y; + }, // VkOffset2D offset; + { + renderSize.x(), // deInt32 width; + renderSize.y(), // deInt32 height; + }, // VkExtent2D extent; + }; + const VkPipelineViewportStateCreateInfo viewportParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineViewportStateCreateFlags)0, + 1u, // deUint32 viewportCount; + &viewport0, + 1u, + &scissor0 + }; + const VkSampleMask sampleMask = ~0u; + const VkPipelineMultisampleStateCreateInfo multisampleParams = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineMultisampleStateCreateFlags)0, + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterSamples; + DE_FALSE, // deUint32 sampleShadingEnable; + 0.0f, // float minSampleShading; + &sampleMask, // const VkSampleMask* pSampleMask; + DE_FALSE, // VkBool32 alphaToCoverageEnable; + DE_FALSE, // VkBool32 alphaToOneEnable; + }; + const VkPipelineRasterizationStateCreateInfo rasterParams = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineRasterizationStateCreateFlags)0, + DE_TRUE, // deUint32 depthClipEnable; + DE_FALSE, // deUint32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkFillMode fillMode; + VK_CULL_MODE_NONE, // VkCullMode cullMode; + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBias; + 0.0f, // float depthBiasClamp; + 0.0f, // float slopeScaledDepthBias; + 1.0f, // float lineWidth; + }; + const VkPrimitiveTopology topology = hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineInputAssemblyStateCreateFlags)0, + topology, // VkPrimitiveTopology topology; + DE_FALSE, // deUint32 primitiveRestartEnable; + }; + + vector vertexBindings; + vector vertexAttribs; + + const VkVertexInputBindingDescription vertexBinding0 = + { + 0u, // deUint32 binding; + deUint32(singleVertexDataSize), // deUint32 strideInBytes; + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate; + }; + vertexBindings.push_back(vertexBinding0); + + { + VkVertexInputAttributeDescription attr0 = + { + 0u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + 0u // deUint32 offsetInBytes; + }; + vertexAttribs.push_back(attr0); + + VkVertexInputAttributeDescription attr1 = + { + 1u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + sizeof(Vec4), // deUint32 offsetInBytes; + }; + vertexAttribs.push_back(attr1); + }; + + // If the test instantiation has additional input/output interface variables, we need to create additional bindings. + // Right now we only support one additional input varible for the vertex stage, and that will be bound to binding #1 + // with location #2. + if (needInterface) + { + const VkVertexInputBindingDescription vertexBinding1 = + { + 1u, // deUint32 binding; + instance.interfaces.getInputType().getNumBytes(), // deUint32 strideInBytes; + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate; + }; + vertexBindings.push_back(vertexBinding1); + + VkVertexInputAttributeDescription attr = + { + 2u, // deUint32 location; + 1u, // deUint32 binding; + instance.interfaces.getInputType().getVkFormat(), // VkFormat format; + 0, // deUint32 offsetInBytes; + }; + vertexAttribs.push_back(attr); + } + + VkPipelineVertexInputStateCreateInfo vertexInputStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineVertexInputStateCreateFlags)0, + 1u, // deUint32 bindingCount; + vertexBindings.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + 2u, // deUint32 attributeCount; + vertexAttribs.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + if (needInterface) + { + vertexInputStateParams.vertexBindingDescriptionCount += 1; + vertexInputStateParams.vertexAttributeDescriptionCount += 1; + } + + vector attBlendStates ; + const VkPipelineColorBlendAttachmentState attBlendState = + { + DE_FALSE, // deUint32 blendEnable; + VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor; + VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor; + VK_BLEND_OP_ADD, // VkBlendOp blendOpColor; + VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha; + VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha; + VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha; + (VK_COLOR_COMPONENT_R_BIT| + VK_COLOR_COMPONENT_G_BIT| + VK_COLOR_COMPONENT_B_BIT| + VK_COLOR_COMPONENT_A_BIT), // VkChannelFlags channelWriteMask; + }; + attBlendStates.push_back(attBlendState); + + if (needInterface) + attBlendStates.push_back(attBlendState); + + VkPipelineColorBlendStateCreateInfo blendParams = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineColorBlendStateCreateFlags)0, + DE_FALSE, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // deUint32 attachmentCount; + attBlendStates.data(), // const VkPipelineColorBlendAttachmentState* pAttachments; + { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4]; + }; + if (needInterface) + { + blendParams.attachmentCount += 1; + } + const VkPipelineTessellationStateCreateInfo tessellationState = + { + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, + DE_NULL, + (VkPipelineTessellationStateCreateFlags)0, + 3u + }; + + const VkPipelineTessellationStateCreateInfo* tessellationInfo = hasTessellation ? &tessellationState: DE_NULL; + const VkGraphicsPipelineCreateInfo pipelineParams = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineCreateFlags flags; + (deUint32)shaderStageParams.size(), // deUint32 stageCount; + &shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &inputAssemblyParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + tessellationInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &viewportParams, // const VkPipelineViewportStateCreateInfo* pViewportState; + &rasterParams, // const VkPipelineRasterStateCreateInfo* pRasterState; + &multisampleParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + &depthStencilParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &blendParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + *pipelineLayout, // VkPipelineLayout layout; + *renderPass, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + DE_NULL, // VkPipeline basePipelineHandle; + 0u, // deInt32 basePipelineIndex; + }; + + const Unique pipeline (createGraphicsPipeline(vk, *vkDevice, DE_NULL, &pipelineParams)); + + if (needInterface) + { + const VkImageViewCreateInfo fragOutputViewParams = + { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkImageViewCreateFlags flags; + *fragOutputImage, // VkImage image; + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; + instance.interfaces.getOutputType().getVkFormat(), // VkFormat format; + { + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A + }, // VkChannelMapping channels; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; + 0u, // deUint32 baseMipLevel; + 1u, // deUint32 mipLevels; + 0u, // deUint32 baseArrayLayer; + 1u, // deUint32 arraySize; + }, // VkImageSubresourceRange subresourceRange; + }; + fragOutputImageView = createImageView(vk, *vkDevice, &fragOutputViewParams); + attViews.push_back(*fragOutputImageView); + } + + // Framebuffer + VkFramebufferCreateInfo framebufferParams = + { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkFramebufferCreateFlags)0, + *renderPass, // VkRenderPass renderPass; + 1u, // deUint32 attachmentCount; + attViews.data(), // const VkImageView* pAttachments; + (deUint32)renderSize.x(), // deUint32 width; + (deUint32)renderSize.y(), // deUint32 height; + 1u, // deUint32 layers; + }; + + if (needInterface) + framebufferParams.attachmentCount += 1; + + const Unique framebuffer (createFramebuffer(vk, *vkDevice, &framebufferParams)); + + const Unique cmdPool (createCommandPool(vk, *vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); + + // Command buffer + const Unique cmdBuf (allocateCommandBuffer(vk, *vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); + + const VkCommandBufferBeginInfo cmdBufBeginParams = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkCommandBufferUsageFlags)0, + (const VkCommandBufferInheritanceInfo*)DE_NULL, + }; + + // Record commands + VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams)); + + { + const VkMemoryBarrier vertFlushBarrier = + { + VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_HOST_WRITE_BIT, // VkMemoryOutputFlags outputMask; + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkMemoryInputFlags inputMask; + }; + vector colorAttBarriers ; + + VkImageMemoryBarrier imgBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkMemoryOutputFlags outputMask; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryInputFlags inputMask; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; + queueFamilyIndex, // deUint32 srcQueueFamilyIndex; + queueFamilyIndex, // deUint32 destQueueFamilyIndex; + *image, // VkImage image; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; + 0u, // deUint32 baseMipLevel; + 1u, // deUint32 mipLevels; + 0u, // deUint32 baseArraySlice; + 1u, // deUint32 arraySize; + } // VkImageSubresourceRange subresourceRange; + }; + colorAttBarriers.push_back(imgBarrier); + if (needInterface) + { + imgBarrier.image = *fragOutputImage; + colorAttBarriers.push_back(imgBarrier); + vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 2, colorAttBarriers.data()); + } + else + { + vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, colorAttBarriers.data()); + } + } + + { + vector clearValue ; + clearValue.push_back(makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f)); + if (needInterface) + { + clearValue.push_back(makeClearValueColorU32(0, 0, 0, 0)); + } + VkRenderPassBeginInfo passBeginParams = + { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + *renderPass, // VkRenderPass renderPass; + *framebuffer, // VkFramebuffer framebuffer; + { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea; + 1u, // deUint32 clearValueCount; + clearValue.data(), // const VkClearValue* pClearValues; + }; + if (needInterface) + { + passBeginParams.clearValueCount += 1; + } + vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE); + } + + vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); + { + const VkDeviceSize bindingOffset = 0; + vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset); + } + if (needInterface) + { + const VkDeviceSize bindingOffset = 0; + vk.cmdBindVertexBuffers(*cmdBuf, 1u, 1u, &vertexInputBuffer.get(), &bindingOffset); + } + if (hasPushConstants) + { + const deUint32 size = static_cast(instance.pushConstants.getBuffer()->getNumBytes()); + const void* data = instance.pushConstants.getBuffer()->data(); + + vk.cmdPushConstants(*cmdBuf, *pipelineLayout, VK_SHADER_STAGE_ALL_GRAPHICS, 0, size, data); + } + if (numResources != 0) + { + // Bind to set number 0. + vk.cmdBindDescriptorSets(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &rawSet, 0, DE_NULL); + } + vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/); + vk.cmdEndRenderPass(*cmdBuf); + + { + vector renderFinishBarrier; + VkImageMemoryBarrier imgBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryOutputFlags outputMask; + VK_ACCESS_TRANSFER_READ_BIT, // VkMemoryInputFlags inputMask; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; + queueFamilyIndex, // deUint32 srcQueueFamilyIndex; + queueFamilyIndex, // deUint32 destQueueFamilyIndex; + *image, // VkImage image; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; + 0u, // deUint32 baseMipLevel; + 1u, // deUint32 mipLevels; + 0u, // deUint32 baseArraySlice; + 1u, // deUint32 arraySize; + } // VkImageSubresourceRange subresourceRange; + }; + renderFinishBarrier.push_back(imgBarrier); + + if (needInterface) + { + imgBarrier.image = *fragOutputImage; + renderFinishBarrier.push_back(imgBarrier); + vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 2, renderFinishBarrier.data()); + } + else + { + vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, renderFinishBarrier.data()); + } + } + + { + const VkBufferImageCopy copyParams = + { + (VkDeviceSize)0u, // VkDeviceSize bufferOffset; + (deUint32)renderSize.x(), // deUint32 bufferRowLength; + (deUint32)renderSize.y(), // deUint32 bufferImageHeight; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; + 0u, // deUint32 mipLevel; + 0u, // deUint32 arrayLayer; + 1u, // deUint32 arraySize; + }, // VkImageSubresourceCopy imageSubresource; + { 0u, 0u, 0u }, // VkOffset3D imageOffset; + { renderSize.x(), renderSize.y(), 1u } // VkExtent3D imageExtent; + }; + vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params); + + if (needInterface) + { + vk.cmdCopyImageToBuffer(*cmdBuf, *fragOutputImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *fragOutputBuffer, 1u, ©Params); + } + } + + { + vector cpFinishBarriers ; + VkBufferMemoryBarrier copyFinishBarrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask; + VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask; + queueFamilyIndex, // deUint32 srcQueueFamilyIndex; + queueFamilyIndex, // deUint32 destQueueFamilyIndex; + *readImageBuffer, // VkBuffer buffer; + 0u, // VkDeviceSize offset; + imageSizeBytes // VkDeviceSize size; + }; + cpFinishBarriers.push_back(copyFinishBarrier); + + if (needInterface) + { + copyFinishBarrier.buffer = *fragOutputBuffer; + copyFinishBarrier.size = VK_WHOLE_SIZE; + cpFinishBarriers.push_back(copyFinishBarrier); + + vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 2, cpFinishBarriers.data(), 0, (const VkImageMemoryBarrier*)DE_NULL); + } + else + { + vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, cpFinishBarriers.data(), 0, (const VkImageMemoryBarrier*)DE_NULL); + } + } + + VK_CHECK(vk.endCommandBuffer(*cmdBuf)); + + // Upload vertex data + { + const VkMappedMemoryRange range = + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + DE_NULL, // const void* pNext; + vertexBufferMemory->getMemory(), // VkDeviceMemory mem; + 0, // VkDeviceSize offset; + (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; + }; + void* vertexBufPtr = vertexBufferMemory->getHostPtr(); + + deMemcpy(vertexBufPtr, &vertexData[0], sizeof(vertexData)); + VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range)); + } + + if (needInterface) + { + const deUint32 typNumBytes = instance.interfaces.getInputType().getNumBytes(); + const deUint32 bufNumBytes = static_cast(instance.interfaces.getInputBuffer()->getNumBytes()); + + // Require that the test instantation provides four output values. + DE_ASSERT(bufNumBytes == 4 * typNumBytes); + + // We have four triangles. Because interpolation happens before executing the fragment shader, + // we need to provide the same vertex attribute for the same triangle. That means, duplicate each + // value three times for all four values. + + const deUint8* provided = static_cast(instance.interfaces.getInputBuffer()->data()); + vector data; + + data.reserve(3 * bufNumBytes); + + for (deUint32 offset = 0; offset < bufNumBytes; offset += typNumBytes) + for (deUint32 vertexNdx = 0; vertexNdx < 3; ++vertexNdx) + for (deUint32 byteNdx = 0; byteNdx < typNumBytes; ++byteNdx) + data.push_back(provided[offset + byteNdx]); + + deMemcpy(vertexInputMemory->getHostPtr(), data.data(), data.size()); + + const VkMappedMemoryRange range = + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + DE_NULL, // const void* pNext; + vertexInputMemory->getMemory(), // VkDeviceMemory mem; + 0, // VkDeviceSize offset; + VK_WHOLE_SIZE, // VkDeviceSize size; + }; + + VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range)); + } + + // Submit & wait for completion + { + const VkFenceCreateInfo fenceParams = + { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkFenceCreateFlags flags; + }; + const Unique fence (createFence(vk, *vkDevice, &fenceParams)); + const VkSubmitInfo submitInfo = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, + DE_NULL, + 0u, + (const VkSemaphore*)DE_NULL, + (const VkPipelineStageFlags*)DE_NULL, + 1u, + &cmdBuf.get(), + 0u, + (const VkSemaphore*)DE_NULL, + }; + + VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); + VK_CHECK(vk.waitForFences(*vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull)); + } + + const void* imagePtr = readImageBufferMemory->getHostPtr(); + const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), + renderSize.x(), renderSize.y(), 1, imagePtr); + // Log image + { + const VkMappedMemoryRange range = + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + DE_NULL, // const void* pNext; + readImageBufferMemory->getMemory(), // VkDeviceMemory mem; + 0, // VkDeviceSize offset; + imageSizeBytes, // VkDeviceSize size; + }; + + VK_CHECK(vk.invalidateMappedMemoryRanges(*vkDevice, 1u, &range)); + context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer); + } + + { // Make sure all output resources are ready. + for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx) + { + const VkMappedMemoryRange range = + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + DE_NULL, // const void* pNext; + outResourceMemories[outputNdx]->getMemory(), // VkDeviceMemory mem; + 0, // VkDeviceSize offset; + VK_WHOLE_SIZE, // VkDeviceSize size; + }; + + VK_CHECK(vk.invalidateMappedMemoryRanges(*vkDevice, 1u, &range)); + } + } + + const RGBA threshold(1, 1, 1, 1); + + const RGBA upperLeft(pixelBuffer.getPixel(1, 1)); + if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold)) + return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper left corner mismatch")); + + const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1)); + if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold)) + return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper right corner mismatch")); + + const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1)); + if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold)) + return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower left corner mismatch")); + + const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1)); + if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold)) + return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower right corner mismatch")); + + // Check that the contents in the ouput variable matches expected. + if (needInterface) + { + const IFDataType& outputType = instance.interfaces.getOutputType(); + const void* inputData = instance.interfaces.getInputBuffer()->data(); + const void* outputData = instance.interfaces.getOutputBuffer()->data(); + vector > positions; + const tcu::ConstPixelBufferAccess fragOutputBufferAccess (outputType.getTextureFormat(), renderSize.x(), renderSize.y(), 1, fragOutputMemory->getHostPtr()); + + positions.push_back(std::make_pair(1, 1)); + positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, 1)); + positions.push_back(std::make_pair(1, fragOutputBufferAccess.getHeight() - 1)); + positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, fragOutputBufferAccess.getHeight() - 1)); + + for (deUint32 posNdx = 0; posNdx < positions.size(); ++posNdx) + { + const int x = positions[posNdx].first; + const int y = positions[posNdx].second; + bool equal = true; + + if (outputType.elementType == NUMBERTYPE_FLOAT32) + { + const float* expected = static_cast(outputData) + posNdx * outputType.numElements; + const float* actual = static_cast(fragOutputBufferAccess.getPixelPtr(x, y)); + + for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx) + if (!compare32BitFloat(expected[eleNdx], actual[eleNdx], context.getTestContext().getLog())) + equal = false; + } + else if (outputType.elementType == NUMBERTYPE_INT32) + { + const deInt32* expected = static_cast(outputData) + posNdx * outputType.numElements; + const deInt32* actual = static_cast(fragOutputBufferAccess.getPixelPtr(x, y)); + + for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx) + if (expected[eleNdx] != actual[eleNdx]) + equal = false; + } + else if (outputType.elementType == NUMBERTYPE_UINT32) + { + const deUint32* expected = static_cast(outputData) + posNdx * outputType.numElements; + const deUint32* actual = static_cast(fragOutputBufferAccess.getPixelPtr(x, y)); + + for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx) + if (expected[eleNdx] != actual[eleNdx]) + equal = false; + } + else if (outputType.elementType == NUMBERTYPE_FLOAT16) + { + const float* original = static_cast(inputData) + posNdx * outputType.numElements; + const deFloat16* actual = static_cast(fragOutputBufferAccess.getPixelPtr(x, y)); + + for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx) + if (!compare16BitFloat(original[eleNdx], actual[eleNdx], instance.interfaces.getRoundingMode(), context.getTestContext().getLog())) + equal = false; + } + else if (outputType.elementType == NUMBERTYPE_INT16) + { + const deInt16* expected = static_cast(outputData) + posNdx * outputType.numElements; + const deInt16* actual = static_cast(fragOutputBufferAccess.getPixelPtr(x, y)); + + for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx) + if (expected[eleNdx] != actual[eleNdx]) + equal = false; + } + else if (outputType.elementType == NUMBERTYPE_UINT16) + { + const deUint16* expected = static_cast(outputData) + posNdx * outputType.numElements; + const deUint16* actual = static_cast(fragOutputBufferAccess.getPixelPtr(x, y)); + + for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx) + if (expected[eleNdx] != actual[eleNdx]) + equal = false; + } + else { + DE_ASSERT(0 && "unhandled type"); + } + + if (!equal) + return TestStatus(instance.failResult, instance.getSpecializedFailMessage("fragment output dat point #" + numberToString(posNdx) + " mismatch")); + } + } + + // Check the contents in output resources match with expected. + for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx) + { + const BufferSp& expected = instance.resources.outputs[outputNdx].second; + + if (instance.resources.verifyIO != DE_NULL) + { + if (!(*instance.resources.verifyIO)(instance.resources.inputs, outResourceMemories, instance.resources.outputs, context.getTestContext().getLog())) + return tcu::TestStatus::fail("Resource returned doesn't match with expected"); + } + else + { + if (deMemCmp(expected->data(), outResourceMemories[outputNdx]->getHostPtr(), expected->getNumBytes())) + return tcu::TestStatus::fail("Resource returned doesn't match bitwisely with expected"); + } + } + + return TestStatus::pass("Rendered output matches input"); +} + +void createTestsForAllStages (const std::string& name, + const RGBA (&inputColors)[4], + const RGBA (&outputColors)[4], + const map& testCodeFragments, + const vector& specConstants, + const PushConstants& pushConstants, + const GraphicsResources& resources, + const GraphicsInterfaces& interfaces, + const vector& extensions, + const vector& features, + ExtensionFeatures extensionFeatures, + tcu::TestCaseGroup* tests, + const qpTestResult failResult, + const string& failMessageTemplate) +{ + const ShaderElement vertFragPipelineStages[] = + { + ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), + ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), + }; + + const ShaderElement tessPipelineStages[] = + { + ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), + ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), + ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), + ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), + }; + + const ShaderElement geomPipelineStages[] = + { + ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), + ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT), + ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), + }; + + StageToSpecConstantMap specConstantMap; + + specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = specConstants; + addFunctionCaseWithPrograms( + tests, name + "_vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline, + createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments, + specConstantMap, pushConstants, resources, interfaces, extensions, features, extensionFeatures, failResult, failMessageTemplate)); + + specConstantMap.clear(); + specConstantMap[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] = specConstants; + addFunctionCaseWithPrograms( + tests, name + "_tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline, + createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments, + specConstantMap, pushConstants, resources, interfaces, extensions, features, extensionFeatures, failResult, failMessageTemplate)); + + specConstantMap.clear(); + specConstantMap[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = specConstants; + addFunctionCaseWithPrograms( + tests, name + "_tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline, + createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments, + specConstantMap, pushConstants, resources, interfaces, extensions, features, extensionFeatures, failResult, failMessageTemplate)); + + specConstantMap.clear(); + specConstantMap[VK_SHADER_STAGE_GEOMETRY_BIT] = specConstants; + addFunctionCaseWithPrograms( + tests, name + "_geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline, + createInstanceContext(geomPipelineStages, inputColors, outputColors, testCodeFragments, + specConstantMap, pushConstants, resources, interfaces, extensions, features, extensionFeatures, failResult, failMessageTemplate)); + + specConstantMap.clear(); + specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = specConstants; + addFunctionCaseWithPrograms( + tests, name + "_frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline, + createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments, + specConstantMap, pushConstants, resources, interfaces, extensions, features, extensionFeatures, failResult, failMessageTemplate)); +} + +void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const map& fragments) +{ + RGBA defaultColors[4]; + getDefaultColors(defaultColors); + const ShaderElement pipelineStages[] = + { + ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), + ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), + ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), + ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), + }; + + addFunctionCaseWithPrograms( + group, name, "", addShaderCodeCustomTessControl, + runAndVerifyDefaultPipeline, createInstanceContext( + pipelineStages, defaultColors, defaultColors, fragments, + StageToSpecConstantMap(), PushConstants(), GraphicsResources(), + GraphicsInterfaces(), vector(), vector(), + ExtensionFeatures())); +} + +} // SpirVAssembly +} // vkt diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.hpp new file mode 100644 index 0000000..1f0f020 --- /dev/null +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.hpp @@ -0,0 +1,553 @@ +#ifndef _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP +#define _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP +/*------------------------------------------------------------------------- + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2017 Google 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 Graphics pipeline and helper functions for SPIR-V assembly tests + *//*--------------------------------------------------------------------*/ + +#include "tcuCommandLine.hpp" +#include "tcuRGBA.hpp" + +#include "vkPrograms.hpp" +#include "vktSpvAsmComputeShaderTestUtil.hpp" +#include "vktSpvAsmUtils.hpp" +#include "vktTestCaseUtil.hpp" + +#include "deRandom.hpp" +#include "deSharedPtr.hpp" + +#include +#include +#include +#include + +namespace vkt +{ +namespace SpirVAssembly +{ + +typedef vk::Unique BufferHandleUp; +typedef de::SharedPtr BufferHandleSp; +typedef vk::Unique ModuleHandleUp; +typedef de::SharedPtr ModuleHandleSp; +typedef std::pair EntryToStage; +typedef std::map > ModuleMap; +typedef std::map > StageToSpecConstantMap; +typedef std::pair Resource; + +enum NumberType +{ + NUMBERTYPE_INT32, + NUMBERTYPE_UINT32, + NUMBERTYPE_FLOAT32, + NUMBERTYPE_END32, // Marks the end of 32-bit scalar types + NUMBERTYPE_INT16, + NUMBERTYPE_UINT16, + NUMBERTYPE_FLOAT16, +}; + +typedef enum RoundingModeFlags_e +{ + ROUNDINGMODE_RTE = 0x1, // Round to nearest even + ROUNDINGMODE_RTZ = 0x2, // Round to zero +} RoundingModeFlags; + +typedef bool (*GraphicsVerifyIOFunc) (const std::vector& inputs, + const std::vector& outputAllocations, + const std::vector& expectedOutputs, + tcu::TestLog& log); + +// Resources used by graphics-pipeline-based tests. +struct GraphicsResources +{ + // Resources used as inputs. + std::vector inputs; + // Resources used as outputs. The data supplied will be used as + // the expected outputs for the corresponding bindings by default. + // If other behaviors are needed, please provide a custom verifyIO. + std::vector outputs; + // If null, a default verification will be performed by comparing the + // memory pointed to by outputAllocations and the contents of + // expectedOutputs. Otherwise the function pointed to by verifyIO will + // be called. If true is returned, then the test case is assumed to + // have passed, if false is returned, then the test case is assumed + // to have failed. + GraphicsVerifyIOFunc verifyIO; + + GraphicsResources() + : verifyIO (DE_NULL) + {} +}; + +// Interface data type. +struct IFDataType +{ + IFDataType (deUint32 numE, NumberType elementT) + : numElements (numE) + , elementType (elementT) + { + DE_ASSERT(numE > 0 && numE < 5); + DE_ASSERT(elementT != NUMBERTYPE_END32); + } + + IFDataType (const IFDataType& that) + : numElements (that.numElements) + , elementType (that.elementType) + {} + + deUint32 getElementNumBytes (void) const; + deUint32 getNumBytes (void) const { return numElements * getElementNumBytes(); } + + vk::VkFormat getVkFormat (void) const; + + tcu::TextureFormat getTextureFormat (void) const; + + std::string str (void) const; + + bool elementIs32bit (void) const { return elementType < NUMBERTYPE_END32; } + bool isVector (void) const { return numElements > 1; } + + deUint32 numElements; + NumberType elementType; +}; + +typedef std::pair Interface; + +// Interface variables used by graphics-pipeline-based tests. +class GraphicsInterfaces +{ +public: + GraphicsInterfaces () + : rndMode (static_cast(0)) + {} + + GraphicsInterfaces (const GraphicsInterfaces& that) + : inputs (that.inputs) + , outputs (that.outputs) + , rndMode (that.rndMode) + {} + + void setInputOutput (const Interface& input, const Interface& output) + { + inputs.clear(); + outputs.clear(); + inputs.push_back(input); + outputs.push_back(output); + } + + const IFDataType& getInputType (void) const + { + DE_ASSERT(inputs.size() == 1); + return inputs.front().first; + } + + const IFDataType& getOutputType (void) const + { + DE_ASSERT(outputs.size() == 1); + return outputs.front().first; + } + + const BufferSp& getInputBuffer (void) const + { + DE_ASSERT(inputs.size() == 1); + return inputs.front().second; + } + + const BufferSp& getOutputBuffer (void) const + { + DE_ASSERT(outputs.size() == 1); + return outputs.front().second; + } + + bool empty (void) const + { + return inputs.size() == 0; + } + + void setRoundingMode (RoundingModeFlags flag) + { + rndMode = flag; + } + RoundingModeFlags getRoundingMode (void) const + { + return rndMode; + } +private: + // vector acts as a null-able Interface here. Canonically we should use + // std::unique_ptr, but sadly we cannot leverage C++11 in dEQP. dEQP has its own + // de::UniquePtr, but still cumbersome to use in InstanceContext and do copies + // at various places. + // Public methods should make sure that there are less than two elements in both + // members and both members have the same number of elements. + std::vector inputs; + std::vector outputs; + RoundingModeFlags rndMode; + +}; + +struct PushConstants +{ +public: + PushConstants (void) + {} + + PushConstants (const PushConstants& that) + : pcs (that.pcs) + {} + + void setPushConstant (const BufferSp& pc) + { + pcs.clear(); + pcs.push_back(pc); + } + + bool empty (void) const + { + return pcs.empty(); + } + + const BufferSp& getBuffer(void) const + { + DE_ASSERT(pcs.size() == 1); + return pcs[0]; + } + +private: + // Right now we only support one field in the push constant block. + std::vector pcs; +}; + +// Returns the corresponding buffer usage flag bit for the given descriptor type. +VkBufferUsageFlagBits getMatchingBufferUsageFlagBit(VkDescriptorType dType); + +// Context for a specific test instantiation. For example, an instantiation +// may test colors yellow/magenta/cyan/mauve in a tesselation shader +// with an entry point named 'main_to_the_main' +struct InstanceContext +{ + // Map of modules to what entry_points we care to use from those modules. + ModuleMap moduleMap; + tcu::RGBA inputColors[4]; + tcu::RGBA outputColors[4]; + // Concrete SPIR-V code to test via boilerplate specialization. + std::map testCodeFragments; + StageToSpecConstantMap specConstants; + bool hasTessellation; + vk::VkShaderStageFlagBits requiredStages; + std::vector requiredDeviceExtensions; + std::vector requiredDeviceFeatures; + ExtensionFeatures requestedExtensionFeatures; + PushConstants pushConstants; + // Possible resources used by the graphics pipeline. + // If it is not empty, a single descriptor set (number 0) will be allocated + // to point to all resources specified. Binding numbers are allocated in + // accord with the resources' order in the vector; outputs are allocated + // after inputs. + GraphicsResources resources; + // Possible interface variables use by the graphics pipeline. + // If it is not empty, input/output variables will be set up for shader stages + // in the test. Both the input and output variable will take location #2 in the + // pipeline for all stages, except that the output variable in the fragment + // stage will take location #1. + GraphicsInterfaces interfaces; + qpTestResult failResult; + std::string failMessageTemplate; //!< ${reason} in the template will be replaced with a detailed failure message + + InstanceContext (const tcu::RGBA (&inputs)[4], + const tcu::RGBA (&outputs)[4], + const std::map& testCodeFragments_, + const StageToSpecConstantMap& specConstants_, + const PushConstants& pushConsants_, + const GraphicsResources& resources_, + const GraphicsInterfaces& interfaces_, + const std::vector& extensions_, + const std::vector& features_, + ExtensionFeatures extFeatures_); + + InstanceContext (const InstanceContext& other); + + std::string getSpecializedFailMessage (const std::string& failureReason); +}; + +// A description of a shader to be used for a single stage of the graphics pipeline. +struct ShaderElement +{ + // The module that contains this shader entrypoint. + std::string moduleName; + + // The name of the entrypoint. + std::string entryName; + + // Which shader stage this entry point represents. + vk::VkShaderStageFlagBits stage; + + ShaderElement (const std::string& moduleName_, const std::string& entryPoint_, vk::VkShaderStageFlagBits shaderStage_); +}; + +template +const std::string numberToString (T number) +{ + std::stringstream ss; + ss << number; + return ss.str(); +} + +// Performs a bitwise copy of source to the destination type Dest. +template +Dest bitwiseCast(Src source) +{ + Dest dest; + DE_STATIC_ASSERT(sizeof(source) == sizeof(dest)); + deMemcpy(&dest, &source, sizeof(dest)); + return dest; +} + +template T randomScalar (de::Random& rnd, T minValue, T maxValue); +template<> inline float randomScalar (de::Random& rnd, float minValue, float maxValue) { return rnd.getFloat(minValue, maxValue); } +template<> inline deInt32 randomScalar (de::Random& rnd, deInt32 minValue, deInt32 maxValue) { return rnd.getInt(minValue, maxValue); } + + +void getDefaultColors (tcu::RGBA (&colors)[4]); + +void getHalfColorsFullAlpha (tcu::RGBA (&colors)[4]); + +void getInvertedDefaultColors (tcu::RGBA (&colors)[4]); + +// Creates fragments that specialize into a simple pass-through shader (of any kind). +std::map passthruFragments(void); + +void createCombinedModule(vk::SourceCollections& dst, InstanceContext); + +// This has two shaders of each stage. The first +// is a passthrough, the second inverts the color. +void createMultipleEntries(vk::SourceCollections& dst, InstanceContext); + +// Turns a statically sized array of ShaderElements into an instance-context +// by setting up the mapping of modules to their contained shaders and stages. +// The inputs and expected outputs are given by inputColors and outputColors +template +InstanceContext createInstanceContext (const ShaderElement (&elements)[N], + const tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments, + const StageToSpecConstantMap& specConstants, + const PushConstants& pushConstants, + const GraphicsResources& resources, + const GraphicsInterfaces& interfaces, + const std::vector& extensions, + const std::vector& features, + ExtensionFeatures extensionFeatures, + const qpTestResult failResult = QP_TEST_RESULT_FAIL, + const std::string& failMessageTemplate = std::string()) +{ + InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources, interfaces, extensions, features, extensionFeatures); + for (size_t i = 0; i < N; ++i) + { + ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage)); + ctx.requiredStages = static_cast(ctx.requiredStages | elements[i].stage); + } + ctx.failResult = failResult; + if (!failMessageTemplate.empty()) + ctx.failMessageTemplate = failMessageTemplate; + return ctx; +} + +// The same as createInstanceContext above, without extensions, spec constants, and resources. +template +inline InstanceContext createInstanceContext (const ShaderElement (&elements)[N], + tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments) +{ + return createInstanceContext(elements, inputColors, outputColors, testCodeFragments, + StageToSpecConstantMap(), PushConstants(), GraphicsResources(), + GraphicsInterfaces(), std::vector(), std::vector(), + ExtensionFeatures()); +} + +// The same as createInstanceContext above, but with default colors. +template +InstanceContext createInstanceContext (const ShaderElement (&elements)[N], + const std::map& testCodeFragments) +{ + tcu::RGBA defaultColors[4]; + getDefaultColors(defaultColors); + return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments); +} + + +void createTestsForAllStages (const std::string& name, + const tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments, + const std::vector& specConstants, + const PushConstants& pushConstants, + const GraphicsResources& resources, + const GraphicsInterfaces& interfaces, + const std::vector& extensions, + const std::vector& features, + ExtensionFeatures extensionFeatures, + tcu::TestCaseGroup* tests, + const qpTestResult failResult = QP_TEST_RESULT_FAIL, + const std::string& failMessageTemplate = std::string()); + +inline void createTestsForAllStages (const std::string& name, + const tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments, + tcu::TestCaseGroup* tests, + const qpTestResult failResult = QP_TEST_RESULT_FAIL, + const std::string& failMessageTemplate = std::string()) +{ + std::vector noSpecConstants; + PushConstants noPushConstants; + GraphicsResources noResources; + GraphicsInterfaces noInterfaces; + std::vector noExtensions; + std::vector noFeatures; + + createTestsForAllStages( + name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants, + noResources, noInterfaces, noExtensions, noFeatures, ExtensionFeatures(), + tests, failResult, failMessageTemplate); +} + +inline void createTestsForAllStages (const std::string& name, + const tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments, + const std::vector& specConstants, + tcu::TestCaseGroup* tests, + const qpTestResult failResult = QP_TEST_RESULT_FAIL, + const std::string& failMessageTemplate = std::string()) +{ + PushConstants noPushConstants; + GraphicsResources noResources; + GraphicsInterfaces noInterfaces; + std::vector noExtensions; + std::vector noFeatures; + + createTestsForAllStages( + name, inputColors, outputColors, testCodeFragments, specConstants, noPushConstants, + noResources, noInterfaces, noExtensions, noFeatures, ExtensionFeatures(), + tests, failResult, failMessageTemplate); +} + +inline void createTestsForAllStages (const std::string& name, + const tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments, + const GraphicsResources& resources, + const std::vector& extensions, + tcu::TestCaseGroup* tests, + ExtensionFeatures extensionFeatures = ExtensionFeatures(), + const qpTestResult failResult = QP_TEST_RESULT_FAIL, + const std::string& failMessageTemplate = std::string()) +{ + std::vector noSpecConstants; + PushConstants noPushConstants; + GraphicsInterfaces noInterfaces; + std::vector noFeatures; + + createTestsForAllStages( + name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants, + resources, noInterfaces, extensions, noFeatures, extensionFeatures, + tests, failResult, failMessageTemplate); +} + +inline void createTestsForAllStages (const std::string& name, + const tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments, + const GraphicsInterfaces interfaces, + const std::vector& extensions, + tcu::TestCaseGroup* tests, + ExtensionFeatures extensionFeatures = ExtensionFeatures(), + const qpTestResult failResult = QP_TEST_RESULT_FAIL, + const std::string& failMessageTemplate = std::string()) +{ + GraphicsResources noResources; + std::vector noSpecConstants; + std::vector noFeatures; + PushConstants noPushConstants; + + createTestsForAllStages( + name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants, + noResources, interfaces, extensions, noFeatures, extensionFeatures, + tests, failResult, failMessageTemplate); +} + +inline void createTestsForAllStages (const std::string& name, + const tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments, + const PushConstants& pushConstants, + const GraphicsResources& resources, + const std::vector& extensions, + tcu::TestCaseGroup* tests, + ExtensionFeatures extensionFeatures = ExtensionFeatures(), + const qpTestResult failResult = QP_TEST_RESULT_FAIL, + const std::string& failMessageTemplate = std::string()) +{ + std::vector noSpecConstants; + GraphicsInterfaces noInterfaces; + std::vector noFeatures; + + createTestsForAllStages( + name, inputColors, outputColors, testCodeFragments, noSpecConstants, pushConstants, + resources, noInterfaces, extensions, noFeatures, extensionFeatures, + tests, failResult, failMessageTemplate); +} + +// Sets up and runs a Vulkan pipeline, then spot-checks the resulting image. +// Feeds the pipeline a set of colored triangles, which then must occur in the +// rendered image. The surface is cleared before executing the pipeline, so +// whatever the shaders draw can be directly spot-checked. +tcu::TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance); + +// Adds a new test to group using custom fragments for the tessellation-control +// stage and passthrough fragments for all other stages. Uses default colors +// for input and expected output. +void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const std::map& fragments); + +// Given the original 32-bit float value, computes the corresponding 16-bit +// float value under the given rounding mode flags and compares with the +// returned 16-bit float value. Returns true if they are considered as equal. +// +// The following equivalence criteria are respected: +// * Positive and negative zeros are considered equivalent. +// * Denormalized floats are allowed to be flushed to zeros. +// * Different bit patterns of NaNs are allowed. +// * For the rest, require exactly the same bit pattern. +bool compare16BitFloat (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log); + +// Compare the returned 32-bit float against its expected value. +// +// The following equivalence criteria are respected: +// * Denormalized floats are allowed to be flushed to zeros. +// * Different bit patterns of NaNs/Infs are allowed. +// * For the rest, use C++ float equivalence check. +bool compare32BitFloat (float expected, float returned, tcu::TestLog& log); + +} // SpirVAssembly +} // vkt + +#endif // _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp index 5aafc4b..d253359 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp @@ -3,6 +3,7 @@ * ------------------------ * * Copyright (c) 2015 Google Inc. + * Copyright (c) 2016 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. @@ -49,6 +50,7 @@ #include "vktSpvAsmComputeShaderCase.hpp" #include "vktSpvAsmComputeShaderTestUtil.hpp" +#include "vktSpvAsmGraphicsShaderTestUtil.hpp" #include "vktTestCaseUtil.hpp" #include @@ -56,6 +58,7 @@ #include #include #include +#include namespace vkt { @@ -79,13 +82,6 @@ using de::UniquePtr; using tcu::StringTemplate; using tcu::Vec4; -typedef Unique ModuleHandleUp; -typedef de::SharedPtr ModuleHandleSp; - -template T randomScalar (de::Random& rnd, T minValue, T maxValue); -template<> inline float randomScalar (de::Random& rnd, float minValue, float maxValue) { return rnd.getFloat(minValue, maxValue); } -template<> inline deInt32 randomScalar (de::Random& rnd, deInt32 minValue, deInt32 maxValue) { return rnd.getInt(minValue, maxValue); } - template static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0) { @@ -94,6 +90,22 @@ static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* ds typedPtr[offset + ndx] = randomScalar(rnd, minValue, maxValue); } +// Filter is a function that returns true if a value should pass, false otherwise. +template +static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, FilterT filter, int offset = 0) +{ + T* const typedPtr = (T*)dst; + T value; + for (int ndx = 0; ndx < numValues; ndx++) + { + do + value = randomScalar(rnd, minValue, maxValue); + while (!filter(value)); + + typedPtr[offset + ndx] = value; + } +} + static void floorAll (vector& values) { for (size_t i = 0; i < values.size(); i++) @@ -132,45 +144,6 @@ struct CaseParameter // output_data.elements[x] = -input_data.elements[x]; // } -static const char* const s_ShaderPreamble = - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint GLCompute %main \"main\" %id\n" - "OpExecutionMode %main LocalSize 1 1 1\n"; - -static const char* const s_CommonTypes = - "%bool = OpTypeBool\n" - "%void = OpTypeVoid\n" - "%voidf = OpTypeFunction %void\n" - "%u32 = OpTypeInt 32 0\n" - "%i32 = OpTypeInt 32 1\n" - "%f32 = OpTypeFloat 32\n" - "%uvec3 = OpTypeVector %u32 3\n" - "%fvec3 = OpTypeVector %f32 3\n" - "%uvec3ptr = OpTypePointer Input %uvec3\n" - "%i32ptr = OpTypePointer Uniform %i32\n" - "%f32ptr = OpTypePointer Uniform %f32\n" - "%i32arr = OpTypeRuntimeArray %i32\n" - "%f32arr = OpTypeRuntimeArray %f32\n"; - -// Declares two uniform variables (indata, outdata) of type "struct { float[] }". Depends on type "f32arr" (for "float[]"). -static const char* const s_InputOutputBuffer = - "%buf = OpTypeStruct %f32arr\n" - "%bufptr = OpTypePointer Uniform %buf\n" - "%indata = OpVariable %bufptr Uniform\n" - "%outdata = OpVariable %bufptr Uniform\n"; - -// Declares buffer type and layout for uniform variables indata and outdata. Both of them are SSBO bounded to descriptor set 0. -// indata is at binding point 0, while outdata is at 1. -static const char* const s_InputOutputBufferTraits = - "OpDecorate %buf BufferBlock\n" - "OpDecorate %indata DescriptorSet 0\n" - "OpDecorate %indata Binding 0\n" - "OpDecorate %outdata DescriptorSet 0\n" - "OpDecorate %outdata Binding 1\n" - "OpDecorate %f32arr ArrayStride 4\n" - "OpMemberDecorate %buf 0 Offset 0\n"; - tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx) { de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opnop", "Test the OpNop instruction")); @@ -186,7 +159,7 @@ tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx) negativeFloats[ndx] = -positiveFloats[ndx]; spec.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -194,9 +167,9 @@ tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) - + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -276,7 +249,7 @@ tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx) const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -297,7 +270,7 @@ tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx) "OpMemberDecorate %buf 0 Offset 0\n" "OpMemberDecorate %buf2 0 Offset 0\n" - + string(s_CommonTypes) + + + string(getComputeAsmCommonTypes()) + "%buf = OpTypeStruct %f32arr\n" "%bufptr = OpTypePointer Uniform %buf\n" @@ -399,7 +372,7 @@ tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx) const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -419,7 +392,7 @@ tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx) "OpMemberDecorate %sumbuf 0 Coherent\n" "OpMemberDecorate %sumbuf 0 Offset 0\n" - + string(s_CommonTypes) + + + string(getComputeAsmCommonTypes()) + "%buf = OpTypeStruct %i32arr\n" "%bufptr = OpTypePointer Uniform %buf\n" @@ -514,7 +487,7 @@ tcu::TestCaseGroup* createOpLineGroup (tcu::TestContext& testCtx) negativeFloats[ndx] = -positiveFloats[ndx]; spec.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "%fname1 = OpString \"negateInputs.comp\"\n" "%fname2 = OpString \"negateInputs\"\n" @@ -525,11 +498,11 @@ tcu::TestCaseGroup* createOpLineGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + + + string(getComputeAsmInputOutputBufferTraits()) + "OpLine %fname1 0 0\n" // At the earliest possible position - + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "OpLine %fname1 0 1\n" // Multiple OpLines in sequence "OpLine %fname2 1 0\n" // Different filenames @@ -578,7 +551,7 @@ tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx) negativeFloats[ndx] = -positiveFloats[ndx]; spec.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "%fname = OpString \"negateInputs.comp\"\n" @@ -588,11 +561,11 @@ tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + + + string(getComputeAsmInputOutputBufferTraits()) + "OpNoLine\n" // At the earliest possible position, without preceding OpLine - + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "OpLine %fname 0 1\n" "OpNoLine\n" // Immediately following a preceding OpLine @@ -659,7 +632,7 @@ tcu::TestCaseGroup* createNoContractionGroup (tcu::TestContext& testCtx) vector inputFloats2 (numElements, 0); vector outputFloats (numElements, 0); const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" @@ -678,7 +651,7 @@ tcu::TestCaseGroup* createNoContractionGroup (tcu::TestContext& testCtx) "OpDecorate %f32arr ArrayStride 4\n" "OpMemberDecorate %buf 0 Offset 0\n" - + string(s_CommonTypes) + + + string(getComputeAsmCommonTypes()) + "%buf = OpTypeStruct %f32arr\n" "%bufptr = OpTypePointer Uniform %buf\n" @@ -786,7 +759,7 @@ tcu::TestCaseGroup* createOpFRemGroup (tcu::TestContext& testCtx) } spec.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" @@ -803,7 +776,7 @@ tcu::TestCaseGroup* createOpFRemGroup (tcu::TestContext& testCtx) "OpDecorate %f32arr ArrayStride 4\n" "OpMemberDecorate %buf 0 Offset 0\n" - + string(s_CommonTypes) + + + string(getComputeAsmCommonTypes()) + "%buf = OpTypeStruct %f32arr\n" "%bufptr = OpTypePointer Uniform %buf\n" @@ -860,7 +833,7 @@ tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx) outputFloats1[ndx] = inputFloats1[ndx] + Vec4(0.f, 0.5f, 1.5f, 2.5f); spec1.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" @@ -868,7 +841,7 @@ tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" "OpDecorate %vec4arr ArrayStride 16\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + "%vec4 = OpTypeVector %f32 4\n" "%vec4ptr_u = OpTypePointer Uniform %vec4\n" @@ -918,7 +891,7 @@ tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx) outputFloats2[ndx] = inputFloats2[ndx]; spec2.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" @@ -926,7 +899,7 @@ tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" "OpDecorate %f32arr100 ArrayStride 4\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + "%hundred = OpConstant %u32 100\n" "%f32arr100 = OpTypeArray %f32 %hundred\n" @@ -967,7 +940,7 @@ tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx) outputFloats3[ndx] = inputFloats3[ndx]; spec3.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" @@ -978,7 +951,7 @@ tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx) "OpMemberDecorate %buf 2 Offset 32\n" "OpMemberDecorate %buf 3 Offset 48\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + "%vec4 = OpTypeVector %f32 4\n" "%buf = OpTypeStruct %vec4 %vec4 %vec4 %vec4\n" @@ -1015,14 +988,14 @@ tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx) outputFloats4[ndx] = -inputFloats4[ndx]; spec4.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%f32ptr_f = OpTypePointer Function %f32\n" "%id = OpVariable %uvec3ptr Input\n" @@ -1069,21 +1042,21 @@ tcu::TestCaseGroup* createOpCopyObjectGroup (tcu::TestContext& testCtx) outputFloats[ndx] = inputFloats[ndx] + 7.5f; spec.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + "%fmat = OpTypeMatrix %fvec3 3\n" "%three = OpConstant %u32 3\n" "%farr = OpTypeArray %f32 %three\n" "%fst = OpTypeStruct %f32 %f32\n" - + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -1182,7 +1155,7 @@ tcu::TestCaseGroup* createOpUnreachableGroup (tcu::TestContext& testCtx) negativeFloats[ndx] = -positiveFloats[ndx]; spec.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -1193,7 +1166,7 @@ tcu::TestCaseGroup* createOpUnreachableGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + "%u32ptr = OpTypePointer Function %u32\n" "%uintfuint = OpTypeFunction %u32 %u32ptr\n" @@ -1209,7 +1182,7 @@ tcu::TestCaseGroup* createOpUnreachableGroup (tcu::TestContext& testCtx) "%hundred = OpConstant %u32 100\n" "%thousand = OpConstant %u32 1000\n" - + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBuffer()) + // Main() "%main = OpFunction %void None %voidf\n" @@ -1336,7 +1309,7 @@ tcu::TestCaseGroup* createDecorationGroupGroup (tcu::TestContext& testCtx) outputFloats[ndx] = inputFloats0[ndx] + inputFloats1[ndx] + inputFloats2[ndx] + inputFloats3[ndx] + inputFloats4[ndx]; spec.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -1388,7 +1361,7 @@ tcu::TestCaseGroup* createDecorationGroupGroup (tcu::TestContext& testCtx) "OpGroupDecorate %group3 %indata4\n" "OpDecorate %indata4 Binding 4\n" - + string(s_CommonTypes) + + + string(getComputeAsmCommonTypes()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -1491,7 +1464,7 @@ tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx) vector outputInts3 (numElements, 0); vector outputInts4 (numElements, 0); const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" @@ -1501,7 +1474,7 @@ tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx) "OpDecorate %sc_1 SpecId 1\n" "OpDecorate %i32arr ArrayStride 4\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + "%buf = OpTypeStruct %i32arr\n" "%bufptr = OpTypePointer Uniform %buf\n" @@ -1598,7 +1571,7 @@ tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx) ComputeShaderSpec spec; spec.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" @@ -1609,7 +1582,7 @@ tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx) "OpDecorate %sc_2 SpecId 2\n" "OpDecorate %i32arr ArrayStride 4\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + "%ivec3 = OpTypeVector %i32 3\n" "%buf = OpTypeStruct %i32arr\n" @@ -1690,7 +1663,7 @@ tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx) } spec1.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -1698,7 +1671,7 @@ tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -1750,14 +1723,14 @@ tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx) group->addChild(new SpvAsmComputeShaderCase(testCtx, "block", "out-of-order and unreachable blocks for OpPhi", spec1)); spec2.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -1794,14 +1767,14 @@ tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx) group->addChild(new SpvAsmComputeShaderCase(testCtx, "induction", "The usual way induction variables are handled in LLVM IR", spec2)); spec3.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%f32ptr_f = OpTypePointer Function %f32\n" "%id = OpVariable %uvec3ptr Input\n" @@ -1896,7 +1869,7 @@ tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx) } spec.assembly = - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -1904,12 +1877,12 @@ tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + "%u32ptr = OpTypePointer Function %u32\n" "%u32ptr_input = OpTypePointer Input %u32\n" - + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -2053,7 +2026,7 @@ tcu::TestCaseGroup* createMultipleShaderGroup (tcu::TestContext& testCtx) "OpMemberDecorate %vert_builtin_st 1 BuiltIn PointSize\n" "OpMemberDecorate %vert_builtin_st 2 BuiltIn ClipDistance\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%zero = OpConstant %i32 0\n" "%one = OpConstant %u32 1\n" @@ -2163,7 +2136,7 @@ tcu::TestCaseGroup* createOpSourceGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -2246,7 +2219,7 @@ tcu::TestCaseGroup* createOpSourceExtensionGroup (tcu::TestContext& testCtx) vector inputFloats (numElements, 0); vector outputFloats (numElements, 0); const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSourceExtension \"${EXTENSION}\"\n" @@ -2255,7 +2228,7 @@ tcu::TestCaseGroup* createOpSourceExtensionGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -2310,7 +2283,7 @@ tcu::TestCaseGroup* createOpConstantNullGroup (tcu::TestContext& testCtx) vector positiveFloats (numElements, 0); vector negativeFloats (numElements, 0); const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -2318,17 +2291,9 @@ tcu::TestCaseGroup* createOpConstantNullGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + - "%uvec2 = OpTypeVector %u32 2\n" - "%bvec3 = OpTypeVector %bool 3\n" - "%fvec4 = OpTypeVector %f32 4\n" - "%fmat33 = OpTypeMatrix %fvec3 3\n" - "%const100 = OpConstant %u32 100\n" - "%uarr100 = OpTypeArray %i32 %const100\n" - "%struct = OpTypeStruct %f32 %i32 %u32\n" - "%pointer = OpTypePointer Function %i32\n" - + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + + "${TYPE}\n" "%null = OpConstantNull ${TYPE}\n" "%id = OpVariable %uvec3ptr Input\n" @@ -2390,7 +2355,7 @@ tcu::TestCaseGroup* createOpConstantCompositeGroup (tcu::TestContext& testCtx) vector positiveFloats (numElements, 0); vector negativeFloats (numElements, 0); const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -2398,7 +2363,7 @@ tcu::TestCaseGroup* createOpConstantCompositeGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -2552,7 +2517,7 @@ tcu::TestCaseGroup* createOpQuantizeToF16Group (tcu::TestContext& testCtx) de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opquantize", "Tests the OpQuantizeToF16 instruction")); const std::string shader ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -2560,7 +2525,7 @@ tcu::TestCaseGroup* createOpQuantizeToF16Group (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -2738,22 +2703,12 @@ tcu::TestCaseGroup* createOpQuantizeToF16Group (tcu::TestContext& testCtx) return group.release(); } -// Performs a bitwise copy of source to the destination type Dest. -template -Dest bitwiseCast(Src source) -{ - Dest dest; - DE_STATIC_ASSERT(sizeof(source) == sizeof(dest)); - deMemcpy(&dest, &source, sizeof(dest)); - return dest; -} - tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& testCtx) { de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opspecconstantop_opquantize", "Tests the OpQuantizeToF16 opcode for the OpSpecConstantOp instruction")); const std::string shader ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpName %main \"main\"\n" "OpName %id \"gl_GlobalInvocationID\"\n" @@ -2767,7 +2722,7 @@ tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& te "OpDecorate %sc_4 SpecId 4\n" "OpDecorate %sc_5 SpecId 5\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -2983,14 +2938,14 @@ tcu::TestCaseGroup* createOpConstantUsageGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + "%fmat = OpTypeMatrix %fvec3 3\n" "%ten = OpConstant %u32 10\n" "%f32arr10 = OpTypeArray %f32 %ten\n" "%fst = OpTypeStruct %f32 %f32\n" - + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -3070,7 +3025,7 @@ tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx) vector inputFloats (numElements, 0); vector outputFloats (numElements, 0); const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -3078,7 +3033,7 @@ tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%u32ptr = OpTypePointer Function %u32\n" @@ -3172,7 +3127,7 @@ tcu::TestCaseGroup* createSelectionControlGroup (tcu::TestContext& testCtx) vector inputFloats (numElements, 0); vector outputFloats (numElements, 0); const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -3180,7 +3135,7 @@ tcu::TestCaseGroup* createSelectionControlGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -3266,7 +3221,7 @@ tcu::TestCaseGroup* createFunctionControlGroup (tcu::TestContext& testCtx) vector inputFloats (numElements, 0); vector outputFloats (numElements, 0); const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -3275,7 +3230,7 @@ tcu::TestCaseGroup* createFunctionControlGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%f32f = OpTypeFunction %f32\n" "%id = OpVariable %uvec3ptr Input\n" @@ -3344,7 +3299,7 @@ tcu::TestCaseGroup* createMemoryAccessGroup (tcu::TestContext& testCtx) vector inputFloats (numElements, 0); vector outputFloats (numElements, 0); const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -3352,7 +3307,7 @@ tcu::TestCaseGroup* createMemoryAccessGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + "%f32ptr_f = OpTypePointer Function %f32\n" @@ -3415,7 +3370,7 @@ tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx) vector positiveFloats (numElements, 0); vector negativeFloats (numElements, 0); const StringTemplate shaderTemplate ( - string(s_ShaderPreamble) + + string(getComputeAsmShaderPreamble()) + "OpSource GLSL 430\n" "OpName %main \"main\"\n" @@ -3423,18 +3378,10 @@ tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx) "OpDecorate %id BuiltIn GlobalInvocationId\n" - + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + - "%uvec2 = OpTypeVector %u32 2\n" - "%fvec4 = OpTypeVector %f32 4\n" - "%fmat33 = OpTypeMatrix %fvec3 3\n" - "%image = OpTypeImage %f32 2D 0 0 0 1 Unknown\n" - "%sampler = OpTypeSampler\n" - "%simage = OpTypeSampledImage %image\n" - "%const100 = OpConstant %u32 100\n" - "%uarr100 = OpTypeArray %i32 %const100\n" - "%struct = OpTypeStruct %f32 %i32 %u32\n" - "%pointer = OpTypePointer Function %i32\n" - + string(s_InputOutputBuffer) + + + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) + + + "${TYPE}\n" + "%id = OpVariable %uvec3ptr Input\n" "%zero = OpConstant %i32 0\n" @@ -3490,2168 +3437,6 @@ tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx) return group.release(); } -typedef std::pair EntryToStage; -typedef map > ModuleMap; -typedef map > StageToSpecConstantMap; - -// Context for a specific test instantiation. For example, an instantiation -// may test colors yellow/magenta/cyan/mauve in a tesselation shader -// with an entry point named 'main_to_the_main' -struct InstanceContext -{ - // Map of modules to what entry_points we care to use from those modules. - ModuleMap moduleMap; - RGBA inputColors[4]; - RGBA outputColors[4]; - // Concrete SPIR-V code to test via boilerplate specialization. - map testCodeFragments; - StageToSpecConstantMap specConstants; - bool hasTessellation; - VkShaderStageFlagBits requiredStages; - - InstanceContext (const RGBA (&inputs)[4], const RGBA (&outputs)[4], const map& testCodeFragments_, const StageToSpecConstantMap& specConstants_) - : testCodeFragments (testCodeFragments_) - , specConstants (specConstants_) - , hasTessellation (false) - , requiredStages (static_cast(0)) - { - inputColors[0] = inputs[0]; - inputColors[1] = inputs[1]; - inputColors[2] = inputs[2]; - inputColors[3] = inputs[3]; - - outputColors[0] = outputs[0]; - outputColors[1] = outputs[1]; - outputColors[2] = outputs[2]; - outputColors[3] = outputs[3]; - } - - InstanceContext (const InstanceContext& other) - : moduleMap (other.moduleMap) - , testCodeFragments (other.testCodeFragments) - , specConstants (other.specConstants) - , hasTessellation (other.hasTessellation) - , requiredStages (other.requiredStages) - { - inputColors[0] = other.inputColors[0]; - inputColors[1] = other.inputColors[1]; - inputColors[2] = other.inputColors[2]; - inputColors[3] = other.inputColors[3]; - - outputColors[0] = other.outputColors[0]; - outputColors[1] = other.outputColors[1]; - outputColors[2] = other.outputColors[2]; - outputColors[3] = other.outputColors[3]; - } -}; - -// A description of a shader to be used for a single stage of the graphics pipeline. -struct ShaderElement -{ - // The module that contains this shader entrypoint. - string moduleName; - - // The name of the entrypoint. - string entryName; - - // Which shader stage this entry point represents. - VkShaderStageFlagBits stage; - - ShaderElement (const string& moduleName_, const string& entryPoint_, VkShaderStageFlagBits shaderStage_) - : moduleName(moduleName_) - , entryName(entryPoint_) - , stage(shaderStage_) - { - } -}; - -void getDefaultColors (RGBA (&colors)[4]) -{ - colors[0] = RGBA::white(); - colors[1] = RGBA::red(); - colors[2] = RGBA::green(); - colors[3] = RGBA::blue(); -} - -void getHalfColorsFullAlpha (RGBA (&colors)[4]) -{ - colors[0] = RGBA(127, 127, 127, 255); - colors[1] = RGBA(127, 0, 0, 255); - colors[2] = RGBA(0, 127, 0, 255); - colors[3] = RGBA(0, 0, 127, 255); -} - -void getInvertedDefaultColors (RGBA (&colors)[4]) -{ - colors[0] = RGBA(0, 0, 0, 255); - colors[1] = RGBA(0, 255, 255, 255); - colors[2] = RGBA(255, 0, 255, 255); - colors[3] = RGBA(255, 255, 0, 255); -} - -// Turns a statically sized array of ShaderElements into an instance-context -// by setting up the mapping of modules to their contained shaders and stages. -// The inputs and expected outputs are given by inputColors and outputColors -template -InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map& testCodeFragments, const StageToSpecConstantMap& specConstants) -{ - InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants); - for (size_t i = 0; i < N; ++i) - { - ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage)); - ctx.requiredStages = static_cast(ctx.requiredStages | elements[i].stage); - } - return ctx; -} - -template -inline InstanceContext createInstanceContext (const ShaderElement (&elements)[N], RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map& testCodeFragments) -{ - return createInstanceContext(elements, inputColors, outputColors, testCodeFragments, StageToSpecConstantMap()); -} - -// The same as createInstanceContext above, but with default colors. -template -InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const map& testCodeFragments) -{ - RGBA defaultColors[4]; - getDefaultColors(defaultColors); - return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments); -} - -// For the current InstanceContext, constructs the required modules and shader stage create infos. -void createPipelineShaderStages (const DeviceInterface& vk, const VkDevice vkDevice, InstanceContext& instance, Context& context, vector& modules, vector& createInfos) -{ - for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx) - { - const ModuleHandleSp mod(new Unique(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0))); - modules.push_back(ModuleHandleSp(mod)); - for (vector::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx) - { - const EntryToStage& stage = *shaderNdx; - const VkPipelineShaderStageCreateInfo shaderParam = - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineShaderStageCreateFlags)0, - stage.second, // VkShaderStageFlagBits stage; - **modules.back(), // VkShaderModule module; - stage.first.c_str(), // const char* pName; - (const VkSpecializationInfo*)DE_NULL, - }; - createInfos.push_back(shaderParam); - } - } -} - -#define SPIRV_ASSEMBLY_TYPES \ - "%void = OpTypeVoid\n" \ - "%bool = OpTypeBool\n" \ - \ - "%i32 = OpTypeInt 32 1\n" \ - "%u32 = OpTypeInt 32 0\n" \ - \ - "%f32 = OpTypeFloat 32\n" \ - "%v3f32 = OpTypeVector %f32 3\n" \ - "%v4f32 = OpTypeVector %f32 4\n" \ - "%v4bool = OpTypeVector %bool 4\n" \ - \ - "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \ - "%fun = OpTypeFunction %void\n" \ - \ - "%ip_f32 = OpTypePointer Input %f32\n" \ - "%ip_i32 = OpTypePointer Input %i32\n" \ - "%ip_v3f32 = OpTypePointer Input %v3f32\n" \ - "%ip_v4f32 = OpTypePointer Input %v4f32\n" \ - \ - "%op_f32 = OpTypePointer Output %f32\n" \ - "%op_v4f32 = OpTypePointer Output %v4f32\n" \ - \ - "%fp_f32 = OpTypePointer Function %f32\n" \ - "%fp_i32 = OpTypePointer Function %i32\n" \ - "%fp_v4f32 = OpTypePointer Function %v4f32\n" - -#define SPIRV_ASSEMBLY_CONSTANTS \ - "%c_f32_1 = OpConstant %f32 1.0\n" \ - "%c_f32_0 = OpConstant %f32 0.0\n" \ - "%c_f32_0_5 = OpConstant %f32 0.5\n" \ - "%c_f32_n1 = OpConstant %f32 -1.\n" \ - "%c_f32_7 = OpConstant %f32 7.0\n" \ - "%c_f32_8 = OpConstant %f32 8.0\n" \ - "%c_i32_0 = OpConstant %i32 0\n" \ - "%c_i32_1 = OpConstant %i32 1\n" \ - "%c_i32_2 = OpConstant %i32 2\n" \ - "%c_i32_3 = OpConstant %i32 3\n" \ - "%c_i32_4 = OpConstant %i32 4\n" \ - "%c_u32_0 = OpConstant %u32 0\n" \ - "%c_u32_1 = OpConstant %u32 1\n" \ - "%c_u32_2 = OpConstant %u32 2\n" \ - "%c_u32_3 = OpConstant %u32 3\n" \ - "%c_u32_32 = OpConstant %u32 32\n" \ - "%c_u32_4 = OpConstant %u32 4\n" \ - "%c_u32_31_bits = OpConstant %u32 0x7FFFFFFF\n" \ - "%c_v4f32_1_1_1_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" \ - "%c_v4f32_1_0_0_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_1\n" \ - "%c_v4f32_0_5_0_5_0_5_0_5 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5\n" - -#define SPIRV_ASSEMBLY_ARRAYS \ - "%a1f32 = OpTypeArray %f32 %c_u32_1\n" \ - "%a2f32 = OpTypeArray %f32 %c_u32_2\n" \ - "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n" \ - "%a4f32 = OpTypeArray %f32 %c_u32_4\n" \ - "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n" \ - "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n" \ - "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n" \ - "%op_a2f32 = OpTypePointer Output %a2f32\n" \ - "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n" \ - "%op_a4f32 = OpTypePointer Output %a4f32\n" - -// Creates vertex-shader assembly by specializing a boilerplate StringTemplate -// on fragments, which must (at least) map "testfun" to an OpFunction definition -// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed -// with "BP_" to avoid collisions with fragments. -// -// It corresponds roughly to this GLSL: -//; -// layout(location = 0) in vec4 position; -// layout(location = 1) in vec4 color; -// layout(location = 1) out highp vec4 vtxColor; -// void main (void) { gl_Position = position; vtxColor = test_func(color); } -string makeVertexShaderAssembly(const map& fragments) -{ -// \todo [2015-11-23 awoloszyn] Remove OpName once these have stabalized - static const char vertexShaderBoilerplate[] = - "OpCapability Shader\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Vertex %main \"main\" %BP_stream %BP_position %BP_vtx_color %BP_color %BP_gl_VertexIndex %BP_gl_InstanceIndex\n" - "${debug:opt}\n" - "OpName %main \"main\"\n" - "OpName %BP_gl_PerVertex \"gl_PerVertex\"\n" - "OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n" - "OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n" - "OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n" - "OpName %test_code \"testfun(vf4;\"\n" - "OpName %BP_stream \"\"\n" - "OpName %BP_position \"position\"\n" - "OpName %BP_vtx_color \"vtxColor\"\n" - "OpName %BP_color \"color\"\n" - "OpName %BP_gl_VertexIndex \"gl_VertexIndex\"\n" - "OpName %BP_gl_InstanceIndex \"gl_InstanceIndex\"\n" - "OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n" - "OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n" - "OpDecorate %BP_gl_PerVertex Block\n" - "OpDecorate %BP_position Location 0\n" - "OpDecorate %BP_vtx_color Location 1\n" - "OpDecorate %BP_color Location 1\n" - "OpDecorate %BP_gl_VertexIndex BuiltIn VertexIndex\n" - "OpDecorate %BP_gl_InstanceIndex BuiltIn InstanceIndex\n" - "${decoration:opt}\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_op_gl_PerVertex = OpTypePointer Output %BP_gl_PerVertex\n" - "%BP_stream = OpVariable %BP_op_gl_PerVertex Output\n" - "%BP_position = OpVariable %ip_v4f32 Input\n" - "%BP_vtx_color = OpVariable %op_v4f32 Output\n" - "%BP_color = OpVariable %ip_v4f32 Input\n" - "%BP_gl_VertexIndex = OpVariable %ip_i32 Input\n" - "%BP_gl_InstanceIndex = OpVariable %ip_i32 Input\n" - "${pre_main:opt}\n" - "%main = OpFunction %void None %fun\n" - "%BP_label = OpLabel\n" - "%BP_pos = OpLoad %v4f32 %BP_position\n" - "%BP_gl_pos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n" - "OpStore %BP_gl_pos %BP_pos\n" - "%BP_col = OpLoad %v4f32 %BP_color\n" - "%BP_col_transformed = OpFunctionCall %v4f32 %test_code %BP_col\n" - "OpStore %BP_vtx_color %BP_col_transformed\n" - "OpReturn\n" - "OpFunctionEnd\n" - "${testfun}\n"; - return tcu::StringTemplate(vertexShaderBoilerplate).specialize(fragments); -} - -// Creates tess-control-shader assembly by specializing a boilerplate -// StringTemplate on fragments, which must (at least) map "testfun" to an -// OpFunction definition for %test_code that takes and returns a %v4f32. -// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments. -// -// It roughly corresponds to the following GLSL. -// -// #version 450 -// layout(vertices = 3) out; -// layout(location = 1) in vec4 in_color[]; -// layout(location = 1) out vec4 out_color[]; -// -// void main() { -// out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]); -// gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; -// if (gl_InvocationID == 0) { -// gl_TessLevelOuter[0] = 1.0; -// gl_TessLevelOuter[1] = 1.0; -// gl_TessLevelOuter[2] = 1.0; -// gl_TessLevelInner[0] = 1.0; -// } -// } -string makeTessControlShaderAssembly (const map& fragments) -{ - static const char tessControlShaderBoilerplate[] = - "OpCapability Tessellation\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint TessellationControl %BP_main \"main\" %BP_out_color %BP_gl_InvocationID %BP_in_color %BP_gl_out %BP_gl_in %BP_gl_TessLevelOuter %BP_gl_TessLevelInner\n" - "OpExecutionMode %BP_main OutputVertices 3\n" - "${debug:opt}\n" - "OpName %BP_main \"main\"\n" - "OpName %test_code \"testfun(vf4;\"\n" - "OpName %BP_out_color \"out_color\"\n" - "OpName %BP_gl_InvocationID \"gl_InvocationID\"\n" - "OpName %BP_in_color \"in_color\"\n" - "OpName %BP_gl_PerVertex \"gl_PerVertex\"\n" - "OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n" - "OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n" - "OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n" - "OpName %BP_gl_out \"gl_out\"\n" - "OpName %BP_gl_PVOut \"gl_PerVertex\"\n" - "OpMemberName %BP_gl_PVOut 0 \"gl_Position\"\n" - "OpMemberName %BP_gl_PVOut 1 \"gl_PointSize\"\n" - "OpMemberName %BP_gl_PVOut 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_gl_PVOut 3 \"gl_CullDistance\"\n" - "OpName %BP_gl_in \"gl_in\"\n" - "OpName %BP_gl_TessLevelOuter \"gl_TessLevelOuter\"\n" - "OpName %BP_gl_TessLevelInner \"gl_TessLevelInner\"\n" - "OpDecorate %BP_out_color Location 1\n" - "OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n" - "OpDecorate %BP_in_color Location 1\n" - "OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n" - "OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n" - "OpDecorate %BP_gl_PerVertex Block\n" - "OpMemberDecorate %BP_gl_PVOut 0 BuiltIn Position\n" - "OpMemberDecorate %BP_gl_PVOut 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_gl_PVOut 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_gl_PVOut 3 BuiltIn CullDistance\n" - "OpDecorate %BP_gl_PVOut Block\n" - "OpDecorate %BP_gl_TessLevelOuter Patch\n" - "OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n" - "OpDecorate %BP_gl_TessLevelInner Patch\n" - "OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n" - "${decoration:opt}\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%BP_out_color = OpVariable %op_a3v4f32 Output\n" - "%BP_gl_InvocationID = OpVariable %ip_i32 Input\n" - "%BP_in_color = OpVariable %ip_a32v4f32 Input\n" - "%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_a3_gl_PerVertex = OpTypeArray %BP_gl_PerVertex %c_u32_3\n" - "%BP_op_a3_gl_PerVertex = OpTypePointer Output %BP_a3_gl_PerVertex\n" - "%BP_gl_out = OpVariable %BP_op_a3_gl_PerVertex Output\n" - "%BP_gl_PVOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_a32_gl_PVOut = OpTypeArray %BP_gl_PVOut %c_u32_32\n" - "%BP_ip_a32_gl_PVOut = OpTypePointer Input %BP_a32_gl_PVOut\n" - "%BP_gl_in = OpVariable %BP_ip_a32_gl_PVOut Input\n" - "%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" - "%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n" - "${pre_main:opt}\n" - - "%BP_main = OpFunction %void None %fun\n" - "%BP_label = OpLabel\n" - - "%BP_gl_Invoc = OpLoad %i32 %BP_gl_InvocationID\n" - - "%BP_in_col_loc = OpAccessChain %ip_v4f32 %BP_in_color %BP_gl_Invoc\n" - "%BP_out_col_loc = OpAccessChain %op_v4f32 %BP_out_color %BP_gl_Invoc\n" - "%BP_in_col_val = OpLoad %v4f32 %BP_in_col_loc\n" - "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_col_val\n" - "OpStore %BP_out_col_loc %BP_clr_transformed\n" - - "%BP_in_pos_loc = OpAccessChain %ip_v4f32 %BP_gl_in %BP_gl_Invoc %c_i32_0\n" - "%BP_out_pos_loc = OpAccessChain %op_v4f32 %BP_gl_out %BP_gl_Invoc %c_i32_0\n" - "%BP_in_pos_val = OpLoad %v4f32 %BP_in_pos_loc\n" - "OpStore %BP_out_pos_loc %BP_in_pos_val\n" - - "%BP_cmp = OpIEqual %bool %BP_gl_Invoc %c_i32_0\n" - "OpSelectionMerge %BP_merge_label None\n" - "OpBranchConditional %BP_cmp %BP_if_label %BP_merge_label\n" - "%BP_if_label = OpLabel\n" - "%BP_gl_TessLevelOuterPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n" - "%BP_gl_TessLevelOuterPos_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n" - "%BP_gl_TessLevelOuterPos_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n" - "%BP_gl_TessLevelInnerPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n" - "OpStore %BP_gl_TessLevelOuterPos_0 %c_f32_1\n" - "OpStore %BP_gl_TessLevelOuterPos_1 %c_f32_1\n" - "OpStore %BP_gl_TessLevelOuterPos_2 %c_f32_1\n" - "OpStore %BP_gl_TessLevelInnerPos_0 %c_f32_1\n" - "OpBranch %BP_merge_label\n" - "%BP_merge_label = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n" - "${testfun}\n"; - return tcu::StringTemplate(tessControlShaderBoilerplate).specialize(fragments); -} - -// Creates tess-evaluation-shader assembly by specializing a boilerplate -// StringTemplate on fragments, which must (at least) map "testfun" to an -// OpFunction definition for %test_code that takes and returns a %v4f32. -// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments. -// -// It roughly corresponds to the following glsl. -// -// #version 450 -// -// layout(triangles, equal_spacing, ccw) in; -// layout(location = 1) in vec4 in_color[]; -// layout(location = 1) out vec4 out_color; -// -// #define interpolate(val) -// vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] + -// vec4(gl_TessCoord.z) * val[2] -// -// void main() { -// gl_Position = vec4(gl_TessCoord.x) * gl_in[0].gl_Position + -// vec4(gl_TessCoord.y) * gl_in[1].gl_Position + -// vec4(gl_TessCoord.z) * gl_in[2].gl_Position; -// out_color = testfun(interpolate(in_color)); -// } -string makeTessEvalShaderAssembly(const map& fragments) -{ - static const char tessEvalBoilerplate[] = - "OpCapability Tessellation\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint TessellationEvaluation %BP_main \"main\" %BP_stream %BP_gl_TessCoord %BP_gl_in %BP_out_color %BP_in_color\n" - "OpExecutionMode %BP_main Triangles\n" - "OpExecutionMode %BP_main SpacingEqual\n" - "OpExecutionMode %BP_main VertexOrderCcw\n" - "${debug:opt}\n" - "OpName %BP_main \"main\"\n" - "OpName %test_code \"testfun(vf4;\"\n" - "OpName %BP_gl_PerVertexOut \"gl_PerVertex\"\n" - "OpMemberName %BP_gl_PerVertexOut 0 \"gl_Position\"\n" - "OpMemberName %BP_gl_PerVertexOut 1 \"gl_PointSize\"\n" - "OpMemberName %BP_gl_PerVertexOut 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_gl_PerVertexOut 3 \"gl_CullDistance\"\n" - "OpName %BP_stream \"\"\n" - "OpName %BP_gl_TessCoord \"gl_TessCoord\"\n" - "OpName %BP_gl_PerVertexIn \"gl_PerVertex\"\n" - "OpMemberName %BP_gl_PerVertexIn 0 \"gl_Position\"\n" - "OpMemberName %BP_gl_PerVertexIn 1 \"gl_PointSize\"\n" - "OpMemberName %BP_gl_PerVertexIn 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_gl_PerVertexIn 3 \"gl_CullDistance\"\n" - "OpName %BP_gl_in \"gl_in\"\n" - "OpName %BP_out_color \"out_color\"\n" - "OpName %BP_in_color \"in_color\"\n" - "OpMemberDecorate %BP_gl_PerVertexOut 0 BuiltIn Position\n" - "OpMemberDecorate %BP_gl_PerVertexOut 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_gl_PerVertexOut 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_gl_PerVertexOut 3 BuiltIn CullDistance\n" - "OpDecorate %BP_gl_PerVertexOut Block\n" - "OpDecorate %BP_gl_TessCoord BuiltIn TessCoord\n" - "OpMemberDecorate %BP_gl_PerVertexIn 0 BuiltIn Position\n" - "OpMemberDecorate %BP_gl_PerVertexIn 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_gl_PerVertexIn 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_gl_PerVertexIn 3 BuiltIn CullDistance\n" - "OpDecorate %BP_gl_PerVertexIn Block\n" - "OpDecorate %BP_out_color Location 1\n" - "OpDecorate %BP_in_color Location 1\n" - "${decoration:opt}\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%BP_gl_PerVertexOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_op_gl_PerVertexOut = OpTypePointer Output %BP_gl_PerVertexOut\n" - "%BP_stream = OpVariable %BP_op_gl_PerVertexOut Output\n" - "%BP_gl_TessCoord = OpVariable %ip_v3f32 Input\n" - "%BP_gl_PerVertexIn = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_a32_gl_PerVertexIn = OpTypeArray %BP_gl_PerVertexIn %c_u32_32\n" - "%BP_ip_a32_gl_PerVertexIn = OpTypePointer Input %BP_a32_gl_PerVertexIn\n" - "%BP_gl_in = OpVariable %BP_ip_a32_gl_PerVertexIn Input\n" - "%BP_out_color = OpVariable %op_v4f32 Output\n" - "%BP_in_color = OpVariable %ip_a32v4f32 Input\n" - "${pre_main:opt}\n" - "%BP_main = OpFunction %void None %fun\n" - "%BP_label = OpLabel\n" - "%BP_gl_TC_0 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n" - "%BP_gl_TC_1 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n" - "%BP_gl_TC_2 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n" - "%BP_gl_in_gl_Pos_0 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n" - "%BP_gl_in_gl_Pos_1 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n" - "%BP_gl_in_gl_Pos_2 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n" - - "%BP_gl_OPos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n" - "%BP_in_color_0 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n" - "%BP_in_color_1 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n" - "%BP_in_color_2 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n" - - "%BP_TC_W_0 = OpLoad %f32 %BP_gl_TC_0\n" - "%BP_TC_W_1 = OpLoad %f32 %BP_gl_TC_1\n" - "%BP_TC_W_2 = OpLoad %f32 %BP_gl_TC_2\n" - "%BP_v4f32_TC_0 = OpCompositeConstruct %v4f32 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0\n" - "%BP_v4f32_TC_1 = OpCompositeConstruct %v4f32 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1\n" - "%BP_v4f32_TC_2 = OpCompositeConstruct %v4f32 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2\n" - - "%BP_gl_IP_0 = OpLoad %v4f32 %BP_gl_in_gl_Pos_0\n" - "%BP_gl_IP_1 = OpLoad %v4f32 %BP_gl_in_gl_Pos_1\n" - "%BP_gl_IP_2 = OpLoad %v4f32 %BP_gl_in_gl_Pos_2\n" - - "%BP_IP_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_gl_IP_0\n" - "%BP_IP_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_gl_IP_1\n" - "%BP_IP_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_gl_IP_2\n" - - "%BP_pos_sum_0 = OpFAdd %v4f32 %BP_IP_W_0 %BP_IP_W_1\n" - "%BP_pos_sum_1 = OpFAdd %v4f32 %BP_pos_sum_0 %BP_IP_W_2\n" - - "OpStore %BP_gl_OPos %BP_pos_sum_1\n" - - "%BP_IC_0 = OpLoad %v4f32 %BP_in_color_0\n" - "%BP_IC_1 = OpLoad %v4f32 %BP_in_color_1\n" - "%BP_IC_2 = OpLoad %v4f32 %BP_in_color_2\n" - - "%BP_IC_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_IC_0\n" - "%BP_IC_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_IC_1\n" - "%BP_IC_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_IC_2\n" - - "%BP_col_sum_0 = OpFAdd %v4f32 %BP_IC_W_0 %BP_IC_W_1\n" - "%BP_col_sum_1 = OpFAdd %v4f32 %BP_col_sum_0 %BP_IC_W_2\n" - - "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_col_sum_1\n" - - "OpStore %BP_out_color %BP_clr_transformed\n" - "OpReturn\n" - "OpFunctionEnd\n" - "${testfun}\n"; - return tcu::StringTemplate(tessEvalBoilerplate).specialize(fragments); -} - -// Creates geometry-shader assembly by specializing a boilerplate StringTemplate -// on fragments, which must (at least) map "testfun" to an OpFunction definition -// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed -// with "BP_" to avoid collisions with fragments. -// -// Derived from this GLSL: -// -// #version 450 -// layout(triangles) in; -// layout(triangle_strip, max_vertices = 3) out; -// -// layout(location = 1) in vec4 in_color[]; -// layout(location = 1) out vec4 out_color; -// -// void main() { -// gl_Position = gl_in[0].gl_Position; -// out_color = test_fun(in_color[0]); -// EmitVertex(); -// gl_Position = gl_in[1].gl_Position; -// out_color = test_fun(in_color[1]); -// EmitVertex(); -// gl_Position = gl_in[2].gl_Position; -// out_color = test_fun(in_color[2]); -// EmitVertex(); -// EndPrimitive(); -// } -string makeGeometryShaderAssembly(const map& fragments) -{ - static const char geometryShaderBoilerplate[] = - "OpCapability Geometry\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Geometry %BP_main \"main\" %BP_out_gl_position %BP_gl_in %BP_out_color %BP_in_color\n" - "OpExecutionMode %BP_main Triangles\n" - "OpExecutionMode %BP_main OutputTriangleStrip\n" - "OpExecutionMode %BP_main OutputVertices 3\n" - "${debug:opt}\n" - "OpName %BP_main \"main\"\n" - "OpName %BP_per_vertex_in \"gl_PerVertex\"\n" - "OpMemberName %BP_per_vertex_in 0 \"gl_Position\"\n" - "OpMemberName %BP_per_vertex_in 1 \"gl_PointSize\"\n" - "OpMemberName %BP_per_vertex_in 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_per_vertex_in 3 \"gl_CullDistance\"\n" - "OpName %BP_gl_in \"gl_in\"\n" - "OpName %BP_out_color \"out_color\"\n" - "OpName %BP_in_color \"in_color\"\n" - "OpName %test_code \"testfun(vf4;\"\n" - "OpDecorate %BP_out_gl_position BuiltIn Position\n" - "OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n" - "OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n" - "OpDecorate %BP_per_vertex_in Block\n" - "OpDecorate %BP_out_color Location 1\n" - "OpDecorate %BP_in_color Location 1\n" - "${decoration:opt}\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n" - "%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n" - - "%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n" - "%BP_out_color = OpVariable %op_v4f32 Output\n" - "%BP_in_color = OpVariable %ip_a3v4f32 Input\n" - "%BP_out_gl_position = OpVariable %op_v4f32 Output\n" - "${pre_main:opt}\n" - - "%BP_main = OpFunction %void None %fun\n" - "%BP_label = OpLabel\n" - "%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n" - "%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n" - "%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n" - - "%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n" - "%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n" - "%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n" - - "%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n" - "%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n" - "%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n" - - "%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n" - "%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n" - "%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n" - - "%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n" - "%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n" - "%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n" - - - "OpStore %BP_out_gl_position %BP_in_position_0\n" - "OpStore %BP_out_color %BP_transformed_in_color_0\n" - "OpEmitVertex\n" - - "OpStore %BP_out_gl_position %BP_in_position_1\n" - "OpStore %BP_out_color %BP_transformed_in_color_1\n" - "OpEmitVertex\n" - - "OpStore %BP_out_gl_position %BP_in_position_2\n" - "OpStore %BP_out_color %BP_transformed_in_color_2\n" - "OpEmitVertex\n" - - "OpEndPrimitive\n" - "OpReturn\n" - "OpFunctionEnd\n" - "${testfun}\n"; - return tcu::StringTemplate(geometryShaderBoilerplate).specialize(fragments); -} - -// Creates fragment-shader assembly by specializing a boilerplate StringTemplate -// on fragments, which must (at least) map "testfun" to an OpFunction definition -// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed -// with "BP_" to avoid collisions with fragments. -// -// Derived from this GLSL: -// -// layout(location = 1) in highp vec4 vtxColor; -// layout(location = 0) out highp vec4 fragColor; -// highp vec4 testfun(highp vec4 x) { return x; } -// void main(void) { fragColor = testfun(vtxColor); } -// -// with modifications including passing vtxColor by value and ripping out -// testfun() definition. -string makeFragmentShaderAssembly(const map& fragments) -{ - static const char fragmentShaderBoilerplate[] = - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor\n" - "OpExecutionMode %BP_main OriginUpperLeft\n" - "${debug:opt}\n" - "OpName %BP_main \"main\"\n" - "OpName %BP_fragColor \"fragColor\"\n" - "OpName %BP_vtxColor \"vtxColor\"\n" - "OpName %test_code \"testfun(vf4;\"\n" - "OpDecorate %BP_fragColor Location 0\n" - "OpDecorate %BP_vtxColor Location 1\n" - "${decoration:opt}\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%BP_fragColor = OpVariable %op_v4f32 Output\n" - "%BP_vtxColor = OpVariable %ip_v4f32 Input\n" - "${pre_main:opt}\n" - "%BP_main = OpFunction %void None %fun\n" - "%BP_label_main = OpLabel\n" - "%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n" - "%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n" - "OpStore %BP_fragColor %BP_tmp2\n" - "OpReturn\n" - "OpFunctionEnd\n" - "${testfun}\n"; - return tcu::StringTemplate(fragmentShaderBoilerplate).specialize(fragments); -} - -// Creates fragments that specialize into a simple pass-through shader (of any kind). -map passthruFragments(void) -{ - map fragments; - fragments["testfun"] = - // A %test_code function that returns its argument unchanged. - "%test_code = OpFunction %v4f32 None %v4f32_function\n" - "%param1 = OpFunctionParameter %v4f32\n" - "%label_testfun = OpLabel\n" - "OpReturnValue %param1\n" - "OpFunctionEnd\n"; - return fragments; -} - -// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. -// Vertex shader gets custom code from context, the rest are pass-through. -void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context) -{ - map passthru = passthruFragments(); - dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(context.testCodeFragments); - dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); -} - -// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. -// Tessellation control shader gets custom code from context, the rest are -// pass-through. -void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context) -{ - map passthru = passthruFragments(); - dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); - dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(context.testCodeFragments); - dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru); - dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); -} - -// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. -// Tessellation evaluation shader gets custom code from context, the rest are -// pass-through. -void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context) -{ - map passthru = passthruFragments(); - dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); - dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru); - dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(context.testCodeFragments); - dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); -} - -// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. -// Geometry shader gets custom code from context, the rest are pass-through. -void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context) -{ - map passthru = passthruFragments(); - dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); - dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(context.testCodeFragments); - dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); -} - -// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. -// Fragment shader gets custom code from context, the rest are pass-through. -void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context) -{ - map passthru = passthruFragments(); - dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); - dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(context.testCodeFragments); -} - -void createCombinedModule(vk::SourceCollections& dst, InstanceContext) -{ - // \todo [2015-12-07 awoloszyn] Make tessellation / geometry conditional - // \todo [2015-12-07 awoloszyn] Remove OpName and OpMemberName at some point - dst.spirvAsmSources.add("module") << - "OpCapability Shader\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpCapability Geometry\n" - "OpCapability Tessellation\n" - "OpMemoryModel Logical GLSL450\n" - - "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\n" - "OpEntryPoint Geometry %geom_main \"main\" %geom_out_gl_position %geom_gl_in %geom_out_color %geom_in_color\n" - "OpEntryPoint TessellationControl %tessc_main \"main\" %tessc_out_color %tessc_gl_InvocationID %tessc_in_color %tessc_out_position %tessc_in_position %tessc_gl_TessLevelOuter %tessc_gl_TessLevelInner\n" - "OpEntryPoint TessellationEvaluation %tesse_main \"main\" %tesse_stream %tesse_gl_tessCoord %tesse_in_position %tesse_out_color %tesse_in_color \n" - "OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n" - - "OpExecutionMode %geom_main Triangles\n" - "OpExecutionMode %geom_main OutputTriangleStrip\n" - "OpExecutionMode %geom_main OutputVertices 3\n" - - "OpExecutionMode %tessc_main OutputVertices 3\n" - - "OpExecutionMode %tesse_main Triangles\n" - "OpExecutionMode %tesse_main SpacingEqual\n" - "OpExecutionMode %tesse_main VertexOrderCcw\n" - - "OpExecutionMode %frag_main OriginUpperLeft\n" - - "OpName %vert_main \"main\"\n" - "OpName %vert_vtxPosition \"vtxPosition\"\n" - "OpName %vert_Position \"position\"\n" - "OpName %vert_vtxColor \"vtxColor\"\n" - "OpName %vert_color \"color\"\n" - "OpName %vert_vertex_id \"gl_VertexIndex\"\n" - "OpName %vert_instance_id \"gl_InstanceIndex\"\n" - "OpName %geom_main \"main\"\n" - "OpName %geom_per_vertex_in \"gl_PerVertex\"\n" - "OpMemberName %geom_per_vertex_in 0 \"gl_Position\"\n" - "OpMemberName %geom_per_vertex_in 1 \"gl_PointSize\"\n" - "OpMemberName %geom_per_vertex_in 2 \"gl_ClipDistance\"\n" - "OpMemberName %geom_per_vertex_in 3 \"gl_CullDistance\"\n" - "OpName %geom_gl_in \"gl_in\"\n" - "OpName %geom_out_color \"out_color\"\n" - "OpName %geom_in_color \"in_color\"\n" - "OpName %tessc_main \"main\"\n" - "OpName %tessc_out_color \"out_color\"\n" - "OpName %tessc_gl_InvocationID \"gl_InvocationID\"\n" - "OpName %tessc_in_color \"in_color\"\n" - "OpName %tessc_out_position \"out_position\"\n" - "OpName %tessc_in_position \"in_position\"\n" - "OpName %tessc_gl_TessLevelOuter \"gl_TessLevelOuter\"\n" - "OpName %tessc_gl_TessLevelInner \"gl_TessLevelInner\"\n" - "OpName %tesse_main \"main\"\n" - "OpName %tesse_per_vertex_out \"gl_PerVertex\"\n" - "OpMemberName %tesse_per_vertex_out 0 \"gl_Position\"\n" - "OpMemberName %tesse_per_vertex_out 1 \"gl_PointSize\"\n" - "OpMemberName %tesse_per_vertex_out 2 \"gl_ClipDistance\"\n" - "OpMemberName %tesse_per_vertex_out 3 \"gl_CullDistance\"\n" - "OpName %tesse_stream \"\"\n" - "OpName %tesse_gl_tessCoord \"gl_TessCoord\"\n" - "OpName %tesse_in_position \"in_position\"\n" - "OpName %tesse_out_color \"out_color\"\n" - "OpName %tesse_in_color \"in_color\"\n" - "OpName %frag_main \"main\"\n" - "OpName %frag_fragColor \"fragColor\"\n" - "OpName %frag_vtxColor \"vtxColor\"\n" - - "; Vertex decorations\n" - "OpDecorate %vert_vtxPosition Location 2\n" - "OpDecorate %vert_Position Location 0\n" - "OpDecorate %vert_vtxColor Location 1\n" - "OpDecorate %vert_color Location 1\n" - "OpDecorate %vert_vertex_id BuiltIn VertexIndex\n" - "OpDecorate %vert_instance_id BuiltIn InstanceIndex\n" - - "; Geometry decorations\n" - "OpDecorate %geom_out_gl_position BuiltIn Position\n" - "OpMemberDecorate %geom_per_vertex_in 0 BuiltIn Position\n" - "OpMemberDecorate %geom_per_vertex_in 1 BuiltIn PointSize\n" - "OpMemberDecorate %geom_per_vertex_in 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %geom_per_vertex_in 3 BuiltIn CullDistance\n" - "OpDecorate %geom_per_vertex_in Block\n" - "OpDecorate %geom_out_color Location 1\n" - "OpDecorate %geom_in_color Location 1\n" - - "; Tessellation Control decorations\n" - "OpDecorate %tessc_out_color Location 1\n" - "OpDecorate %tessc_gl_InvocationID BuiltIn InvocationId\n" - "OpDecorate %tessc_in_color Location 1\n" - "OpDecorate %tessc_out_position Location 2\n" - "OpDecorate %tessc_in_position Location 2\n" - "OpDecorate %tessc_gl_TessLevelOuter Patch\n" - "OpDecorate %tessc_gl_TessLevelOuter BuiltIn TessLevelOuter\n" - "OpDecorate %tessc_gl_TessLevelInner Patch\n" - "OpDecorate %tessc_gl_TessLevelInner BuiltIn TessLevelInner\n" - - "; Tessellation Evaluation decorations\n" - "OpMemberDecorate %tesse_per_vertex_out 0 BuiltIn Position\n" - "OpMemberDecorate %tesse_per_vertex_out 1 BuiltIn PointSize\n" - "OpMemberDecorate %tesse_per_vertex_out 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %tesse_per_vertex_out 3 BuiltIn CullDistance\n" - "OpDecorate %tesse_per_vertex_out Block\n" - "OpDecorate %tesse_gl_tessCoord BuiltIn TessCoord\n" - "OpDecorate %tesse_in_position Location 2\n" - "OpDecorate %tesse_out_color Location 1\n" - "OpDecorate %tesse_in_color Location 1\n" - - "; Fragment decorations\n" - "OpDecorate %frag_fragColor Location 0\n" - "OpDecorate %frag_vtxColor Location 1\n" - - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - - "; Vertex Variables\n" - "%vert_vtxPosition = OpVariable %op_v4f32 Output\n" - "%vert_Position = OpVariable %ip_v4f32 Input\n" - "%vert_vtxColor = OpVariable %op_v4f32 Output\n" - "%vert_color = OpVariable %ip_v4f32 Input\n" - "%vert_vertex_id = OpVariable %ip_i32 Input\n" - "%vert_instance_id = OpVariable %ip_i32 Input\n" - - "; Geometry Variables\n" - "%geom_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%geom_a3_per_vertex_in = OpTypeArray %geom_per_vertex_in %c_u32_3\n" - "%geom_ip_a3_per_vertex_in = OpTypePointer Input %geom_a3_per_vertex_in\n" - "%geom_gl_in = OpVariable %geom_ip_a3_per_vertex_in Input\n" - "%geom_out_color = OpVariable %op_v4f32 Output\n" - "%geom_in_color = OpVariable %ip_a3v4f32 Input\n" - "%geom_out_gl_position = OpVariable %op_v4f32 Output\n" - - "; Tessellation Control Variables\n" - "%tessc_out_color = OpVariable %op_a3v4f32 Output\n" - "%tessc_gl_InvocationID = OpVariable %ip_i32 Input\n" - "%tessc_in_color = OpVariable %ip_a32v4f32 Input\n" - "%tessc_out_position = OpVariable %op_a3v4f32 Output\n" - "%tessc_in_position = OpVariable %ip_a32v4f32 Input\n" - "%tessc_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" - "%tessc_gl_TessLevelInner = OpVariable %op_a2f32 Output\n" - - "; Tessellation Evaluation Decorations\n" - "%tesse_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%tesse_op_per_vertex_out = OpTypePointer Output %tesse_per_vertex_out\n" - "%tesse_stream = OpVariable %tesse_op_per_vertex_out Output\n" - "%tesse_gl_tessCoord = OpVariable %ip_v3f32 Input\n" - "%tesse_in_position = OpVariable %ip_a32v4f32 Input\n" - "%tesse_out_color = OpVariable %op_v4f32 Output\n" - "%tesse_in_color = OpVariable %ip_a32v4f32 Input\n" - - "; Fragment Variables\n" - "%frag_fragColor = OpVariable %op_v4f32 Output\n" - "%frag_vtxColor = OpVariable %ip_v4f32 Input\n" - - "; Vertex Entry\n" - "%vert_main = OpFunction %void None %fun\n" - "%vert_label = OpLabel\n" - "%vert_tmp_position = OpLoad %v4f32 %vert_Position\n" - "OpStore %vert_vtxPosition %vert_tmp_position\n" - "%vert_tmp_color = OpLoad %v4f32 %vert_color\n" - "OpStore %vert_vtxColor %vert_tmp_color\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "; Geometry Entry\n" - "%geom_main = OpFunction %void None %fun\n" - "%geom_label = OpLabel\n" - "%geom_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_0 %c_i32_0\n" - "%geom_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_1 %c_i32_0\n" - "%geom_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_2 %c_i32_0\n" - "%geom_in_position_0 = OpLoad %v4f32 %geom_gl_in_0_gl_position\n" - "%geom_in_position_1 = OpLoad %v4f32 %geom_gl_in_1_gl_position\n" - "%geom_in_position_2 = OpLoad %v4f32 %geom_gl_in_2_gl_position \n" - "%geom_in_color_0_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_0\n" - "%geom_in_color_1_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_1\n" - "%geom_in_color_2_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_2\n" - "%geom_in_color_0 = OpLoad %v4f32 %geom_in_color_0_ptr\n" - "%geom_in_color_1 = OpLoad %v4f32 %geom_in_color_1_ptr\n" - "%geom_in_color_2 = OpLoad %v4f32 %geom_in_color_2_ptr\n" - "OpStore %geom_out_gl_position %geom_in_position_0\n" - "OpStore %geom_out_color %geom_in_color_0\n" - "OpEmitVertex\n" - "OpStore %geom_out_gl_position %geom_in_position_1\n" - "OpStore %geom_out_color %geom_in_color_1\n" - "OpEmitVertex\n" - "OpStore %geom_out_gl_position %geom_in_position_2\n" - "OpStore %geom_out_color %geom_in_color_2\n" - "OpEmitVertex\n" - "OpEndPrimitive\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "; Tessellation Control Entry\n" - "%tessc_main = OpFunction %void None %fun\n" - "%tessc_label = OpLabel\n" - "%tessc_invocation_id = OpLoad %i32 %tessc_gl_InvocationID\n" - "%tessc_in_color_ptr = OpAccessChain %ip_v4f32 %tessc_in_color %tessc_invocation_id\n" - "%tessc_in_position_ptr = OpAccessChain %ip_v4f32 %tessc_in_position %tessc_invocation_id\n" - "%tessc_in_color_val = OpLoad %v4f32 %tessc_in_color_ptr\n" - "%tessc_in_position_val = OpLoad %v4f32 %tessc_in_position_ptr\n" - "%tessc_out_color_ptr = OpAccessChain %op_v4f32 %tessc_out_color %tessc_invocation_id\n" - "%tessc_out_position_ptr = OpAccessChain %op_v4f32 %tessc_out_position %tessc_invocation_id\n" - "OpStore %tessc_out_color_ptr %tessc_in_color_val\n" - "OpStore %tessc_out_position_ptr %tessc_in_position_val\n" - "%tessc_is_first_invocation = OpIEqual %bool %tessc_invocation_id %c_i32_0\n" - "OpSelectionMerge %tessc_merge_label None\n" - "OpBranchConditional %tessc_is_first_invocation %tessc_first_invocation %tessc_merge_label\n" - "%tessc_first_invocation = OpLabel\n" - "%tessc_tess_outer_0 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_0\n" - "%tessc_tess_outer_1 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_1\n" - "%tessc_tess_outer_2 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_2\n" - "%tessc_tess_inner = OpAccessChain %op_f32 %tessc_gl_TessLevelInner %c_i32_0\n" - "OpStore %tessc_tess_outer_0 %c_f32_1\n" - "OpStore %tessc_tess_outer_1 %c_f32_1\n" - "OpStore %tessc_tess_outer_2 %c_f32_1\n" - "OpStore %tessc_tess_inner %c_f32_1\n" - "OpBranch %tessc_merge_label\n" - "%tessc_merge_label = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "; Tessellation Evaluation Entry\n" - "%tesse_main = OpFunction %void None %fun\n" - "%tesse_label = OpLabel\n" - "%tesse_tc_0_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_0\n" - "%tesse_tc_1_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_1\n" - "%tesse_tc_2_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_2\n" - "%tesse_tc_0 = OpLoad %f32 %tesse_tc_0_ptr\n" - "%tesse_tc_1 = OpLoad %f32 %tesse_tc_1_ptr\n" - "%tesse_tc_2 = OpLoad %f32 %tesse_tc_2_ptr\n" - "%tesse_in_pos_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_0\n" - "%tesse_in_pos_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_1\n" - "%tesse_in_pos_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_2\n" - "%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n" - "%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n" - "%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n" - "%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_0 %tesse_tc_0\n" - "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_1 %tesse_tc_1\n" - "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_2 %tesse_tc_2\n" - "%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n" - "%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n" - "%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n" - "OpStore %tesse_out_pos_ptr %tesse_computed_out\n" - "%tesse_in_clr_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_0\n" - "%tesse_in_clr_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_1\n" - "%tesse_in_clr_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_2\n" - "%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n" - "%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n" - "%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n" - "%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_0 %tesse_tc_0\n" - "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_1 %tesse_tc_1\n" - "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_2 %tesse_tc_2\n" - "%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n" - "%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n" - "OpStore %tesse_out_color %tesse_computed_clr\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "; Fragment Entry\n" - "%frag_main = OpFunction %void None %fun\n" - "%frag_label_main = OpLabel\n" - "%frag_tmp1 = OpLoad %v4f32 %frag_vtxColor\n" - "OpStore %frag_fragColor %frag_tmp1\n" - "OpReturn\n" - "OpFunctionEnd\n"; -} - -// This has two shaders of each stage. The first -// is a passthrough, the second inverts the color. -void createMultipleEntries(vk::SourceCollections& dst, InstanceContext) -{ - dst.spirvAsmSources.add("vert") << - // This module contains 2 vertex shaders. One that is a passthrough - // and a second that inverts the color of the output (1.0 - color). - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n" - "OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n" - - "OpName %main \"vert1\"\n" - "OpName %main2 \"vert2\"\n" - "OpName %vtxPosition \"vtxPosition\"\n" - "OpName %Position \"position\"\n" - "OpName %vtxColor \"vtxColor\"\n" - "OpName %color \"color\"\n" - "OpName %vertex_id \"gl_VertexIndex\"\n" - "OpName %instance_id \"gl_InstanceIndex\"\n" - - "OpDecorate %vtxPosition Location 2\n" - "OpDecorate %Position Location 0\n" - "OpDecorate %vtxColor Location 1\n" - "OpDecorate %color Location 1\n" - "OpDecorate %vertex_id BuiltIn VertexIndex\n" - "OpDecorate %instance_id BuiltIn InstanceIndex\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" - "%vtxPosition = OpVariable %op_v4f32 Output\n" - "%Position = OpVariable %ip_v4f32 Input\n" - "%vtxColor = OpVariable %op_v4f32 Output\n" - "%color = OpVariable %ip_v4f32 Input\n" - "%vertex_id = OpVariable %ip_i32 Input\n" - "%instance_id = OpVariable %ip_i32 Input\n" - - "%main = OpFunction %void None %fun\n" - "%label = OpLabel\n" - "%tmp_position = OpLoad %v4f32 %Position\n" - "OpStore %vtxPosition %tmp_position\n" - "%tmp_color = OpLoad %v4f32 %color\n" - "OpStore %vtxColor %tmp_color\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "%main2 = OpFunction %void None %fun\n" - "%label2 = OpLabel\n" - "%tmp_position2 = OpLoad %v4f32 %Position\n" - "OpStore %vtxPosition %tmp_position2\n" - "%tmp_color2 = OpLoad %v4f32 %color\n" - "%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n" - "%tmp_color4 = OpVectorInsertDynamic %v4f32 %tmp_color3 %c_f32_1 %c_i32_3\n" - "OpStore %vtxColor %tmp_color4\n" - "OpReturn\n" - "OpFunctionEnd\n"; - - dst.spirvAsmSources.add("frag") << - // This is a single module that contains 2 fragment shaders. - // One that passes color through and the other that inverts the output - // color (1.0 - color). - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n" - "OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n" - "OpExecutionMode %main OriginUpperLeft\n" - "OpExecutionMode %main2 OriginUpperLeft\n" - - "OpName %main \"frag1\"\n" - "OpName %main2 \"frag2\"\n" - "OpName %fragColor \"fragColor\"\n" - "OpName %vtxColor \"vtxColor\"\n" - "OpDecorate %fragColor Location 0\n" - "OpDecorate %vtxColor Location 1\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" - "%fragColor = OpVariable %op_v4f32 Output\n" - "%vtxColor = OpVariable %ip_v4f32 Input\n" - - "%main = OpFunction %void None %fun\n" - "%label_main = OpLabel\n" - "%tmp1 = OpLoad %v4f32 %vtxColor\n" - "OpStore %fragColor %tmp1\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "%main2 = OpFunction %void None %fun\n" - "%label_main2 = OpLabel\n" - "%tmp2 = OpLoad %v4f32 %vtxColor\n" - "%tmp3 = OpFSub %v4f32 %cval %tmp2\n" - "%tmp4 = OpVectorInsertDynamic %v4f32 %tmp3 %c_f32_1 %c_i32_3\n" - "OpStore %fragColor %tmp4\n" - "OpReturn\n" - "OpFunctionEnd\n"; - - dst.spirvAsmSources.add("geom") << - "OpCapability Geometry\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n" - "OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n" - "OpExecutionMode %geom1_main Triangles\n" - "OpExecutionMode %geom2_main Triangles\n" - "OpExecutionMode %geom1_main OutputTriangleStrip\n" - "OpExecutionMode %geom2_main OutputTriangleStrip\n" - "OpExecutionMode %geom1_main OutputVertices 3\n" - "OpExecutionMode %geom2_main OutputVertices 3\n" - "OpName %geom1_main \"geom1\"\n" - "OpName %geom2_main \"geom2\"\n" - "OpName %per_vertex_in \"gl_PerVertex\"\n" - "OpMemberName %per_vertex_in 0 \"gl_Position\"\n" - "OpMemberName %per_vertex_in 1 \"gl_PointSize\"\n" - "OpMemberName %per_vertex_in 2 \"gl_ClipDistance\"\n" - "OpMemberName %per_vertex_in 3 \"gl_CullDistance\"\n" - "OpName %gl_in \"gl_in\"\n" - "OpName %out_color \"out_color\"\n" - "OpName %in_color \"in_color\"\n" - "OpDecorate %out_gl_position BuiltIn Position\n" - "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n" - "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n" - "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n" - "OpDecorate %per_vertex_in Block\n" - "OpDecorate %out_color Location 1\n" - "OpDecorate %in_color Location 1\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" - "%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n" - "%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n" - "%gl_in = OpVariable %ip_a3_per_vertex_in Input\n" - "%out_color = OpVariable %op_v4f32 Output\n" - "%in_color = OpVariable %ip_a3v4f32 Input\n" - "%out_gl_position = OpVariable %op_v4f32 Output\n" - - "%geom1_main = OpFunction %void None %fun\n" - "%geom1_label = OpLabel\n" - "%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n" - "%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n" - "%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n" - "%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n" - "%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n" - "%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n" - "%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" - "%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" - "%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" - "%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n" - "%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n" - "%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n" - "OpStore %out_gl_position %geom1_in_position_0\n" - "OpStore %out_color %geom1_in_color_0\n" - "OpEmitVertex\n" - "OpStore %out_gl_position %geom1_in_position_1\n" - "OpStore %out_color %geom1_in_color_1\n" - "OpEmitVertex\n" - "OpStore %out_gl_position %geom1_in_position_2\n" - "OpStore %out_color %geom1_in_color_2\n" - "OpEmitVertex\n" - "OpEndPrimitive\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "%geom2_main = OpFunction %void None %fun\n" - "%geom2_label = OpLabel\n" - "%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n" - "%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n" - "%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n" - "%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n" - "%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n" - "%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n" - "%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" - "%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" - "%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" - "%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n" - "%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n" - "%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n" - "%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n" - "%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n" - "%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n" - "%geom2_transformed_in_color_0_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_0 %c_f32_1 %c_i32_3\n" - "%geom2_transformed_in_color_1_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_1 %c_f32_1 %c_i32_3\n" - "%geom2_transformed_in_color_2_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_2 %c_f32_1 %c_i32_3\n" - "OpStore %out_gl_position %geom2_in_position_0\n" - "OpStore %out_color %geom2_transformed_in_color_0_a\n" - "OpEmitVertex\n" - "OpStore %out_gl_position %geom2_in_position_1\n" - "OpStore %out_color %geom2_transformed_in_color_1_a\n" - "OpEmitVertex\n" - "OpStore %out_gl_position %geom2_in_position_2\n" - "OpStore %out_color %geom2_transformed_in_color_2_a\n" - "OpEmitVertex\n" - "OpEndPrimitive\n" - "OpReturn\n" - "OpFunctionEnd\n"; - - dst.spirvAsmSources.add("tessc") << - "OpCapability Tessellation\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n" - "OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n" - "OpExecutionMode %tessc1_main OutputVertices 3\n" - "OpExecutionMode %tessc2_main OutputVertices 3\n" - "OpName %tessc1_main \"tessc1\"\n" - "OpName %tessc2_main \"tessc2\"\n" - "OpName %out_color \"out_color\"\n" - "OpName %gl_InvocationID \"gl_InvocationID\"\n" - "OpName %in_color \"in_color\"\n" - "OpName %out_position \"out_position\"\n" - "OpName %in_position \"in_position\"\n" - "OpName %gl_TessLevelOuter \"gl_TessLevelOuter\"\n" - "OpName %gl_TessLevelInner \"gl_TessLevelInner\"\n" - "OpDecorate %out_color Location 1\n" - "OpDecorate %gl_InvocationID BuiltIn InvocationId\n" - "OpDecorate %in_color Location 1\n" - "OpDecorate %out_position Location 2\n" - "OpDecorate %in_position Location 2\n" - "OpDecorate %gl_TessLevelOuter Patch\n" - "OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n" - "OpDecorate %gl_TessLevelInner Patch\n" - "OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" - "%out_color = OpVariable %op_a3v4f32 Output\n" - "%gl_InvocationID = OpVariable %ip_i32 Input\n" - "%in_color = OpVariable %ip_a32v4f32 Input\n" - "%out_position = OpVariable %op_a3v4f32 Output\n" - "%in_position = OpVariable %ip_a32v4f32 Input\n" - "%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" - "%gl_TessLevelInner = OpVariable %op_a2f32 Output\n" - - "%tessc1_main = OpFunction %void None %fun\n" - "%tessc1_label = OpLabel\n" - "%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n" - "%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n" - "%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n" - "%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n" - "%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n" - "%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n" - "%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n" - "OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n" - "OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n" - "%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n" - "OpSelectionMerge %tessc1_merge_label None\n" - "OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n" - "%tessc1_first_invocation = OpLabel\n" - "%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n" - "%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n" - "%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n" - "%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n" - "OpStore %tessc1_tess_outer_0 %c_f32_1\n" - "OpStore %tessc1_tess_outer_1 %c_f32_1\n" - "OpStore %tessc1_tess_outer_2 %c_f32_1\n" - "OpStore %tessc1_tess_inner %c_f32_1\n" - "OpBranch %tessc1_merge_label\n" - "%tessc1_merge_label = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "%tessc2_main = OpFunction %void None %fun\n" - "%tessc2_label = OpLabel\n" - "%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n" - "%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n" - "%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n" - "%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n" - "%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n" - "%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n" - "%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n" - "%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n" - "%tessc2_transformed_color_a = OpVectorInsertDynamic %v4f32 %tessc2_transformed_color %c_f32_1 %c_i32_3\n" - "OpStore %tessc2_out_color_ptr %tessc2_transformed_color_a\n" - "OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n" - "%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n" - "OpSelectionMerge %tessc2_merge_label None\n" - "OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n" - "%tessc2_first_invocation = OpLabel\n" - "%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n" - "%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n" - "%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n" - "%tessc2_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n" - "OpStore %tessc2_tess_outer_0 %c_f32_1\n" - "OpStore %tessc2_tess_outer_1 %c_f32_1\n" - "OpStore %tessc2_tess_outer_2 %c_f32_1\n" - "OpStore %tessc2_tess_inner %c_f32_1\n" - "OpBranch %tessc2_merge_label\n" - "%tessc2_merge_label = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n"; - - dst.spirvAsmSources.add("tesse") << - "OpCapability Tessellation\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n" - "OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n" - "OpExecutionMode %tesse1_main Triangles\n" - "OpExecutionMode %tesse1_main SpacingEqual\n" - "OpExecutionMode %tesse1_main VertexOrderCcw\n" - "OpExecutionMode %tesse2_main Triangles\n" - "OpExecutionMode %tesse2_main SpacingEqual\n" - "OpExecutionMode %tesse2_main VertexOrderCcw\n" - "OpName %tesse1_main \"tesse1\"\n" - "OpName %tesse2_main \"tesse2\"\n" - "OpName %per_vertex_out \"gl_PerVertex\"\n" - "OpMemberName %per_vertex_out 0 \"gl_Position\"\n" - "OpMemberName %per_vertex_out 1 \"gl_PointSize\"\n" - "OpMemberName %per_vertex_out 2 \"gl_ClipDistance\"\n" - "OpMemberName %per_vertex_out 3 \"gl_CullDistance\"\n" - "OpName %stream \"\"\n" - "OpName %gl_tessCoord \"gl_TessCoord\"\n" - "OpName %in_position \"in_position\"\n" - "OpName %out_color \"out_color\"\n" - "OpName %in_color \"in_color\"\n" - "OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n" - "OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n" - "OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n" - "OpDecorate %per_vertex_out Block\n" - "OpDecorate %gl_tessCoord BuiltIn TessCoord\n" - "OpDecorate %in_position Location 2\n" - "OpDecorate %out_color Location 1\n" - "OpDecorate %in_color Location 1\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" - "%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n" - "%stream = OpVariable %op_per_vertex_out Output\n" - "%gl_tessCoord = OpVariable %ip_v3f32 Input\n" - "%in_position = OpVariable %ip_a32v4f32 Input\n" - "%out_color = OpVariable %op_v4f32 Output\n" - "%in_color = OpVariable %ip_a32v4f32 Input\n" - - "%tesse1_main = OpFunction %void None %fun\n" - "%tesse1_label = OpLabel\n" - "%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n" - "%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n" - "%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n" - "%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n" - "%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n" - "%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n" - "%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n" - "%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n" - "%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n" - "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n" - "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n" - "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n" - "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n" - "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n" - "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n" - "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n" - "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n" - "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n" - "OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n" - "%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" - "%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" - "%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" - "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n" - "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n" - "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n" - "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n" - "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n" - "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n" - "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n" - "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n" - "OpStore %out_color %tesse1_computed_clr\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "%tesse2_main = OpFunction %void None %fun\n" - "%tesse2_label = OpLabel\n" - "%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n" - "%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n" - "%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n" - "%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n" - "%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n" - "%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n" - "%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n" - "%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n" - "%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n" - "%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n" - "%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n" - "%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n" - "%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_0 %tesse2_tc_0\n" - "%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_1 %tesse2_tc_1\n" - "%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_2 %tesse2_tc_2\n" - "%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n" - "%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n" - "%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n" - "OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n" - "%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" - "%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" - "%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" - "%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n" - "%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n" - "%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n" - "%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_0 %tesse2_tc_0\n" - "%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_1 %tesse2_tc_1\n" - "%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_2 %tesse2_tc_2\n" - "%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n" - "%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n" - "%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n" - "%tesse2_clr_transformed_a = OpVectorInsertDynamic %v4f32 %tesse2_clr_transformed %c_f32_1 %c_i32_3\n" - "OpStore %out_color %tesse2_clr_transformed_a\n" - "OpReturn\n" - "OpFunctionEnd\n"; -} - -// Sets up and runs a Vulkan pipeline, then spot-checks the resulting image. -// Feeds the pipeline a set of colored triangles, which then must occur in the -// rendered image. The surface is cleared before executing the pipeline, so -// whatever the shaders draw can be directly spot-checked. -TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance) -{ - const VkDevice vkDevice = context.getDevice(); - const DeviceInterface& vk = context.getDeviceInterface(); - const VkQueue queue = context.getUniversalQueue(); - const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); - const tcu::UVec2 renderSize (256, 256); - vector modules; - map moduleByStage; - const int testSpecificSeed = 31354125; - const int seed = context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed; - bool supportsGeometry = false; - bool supportsTessellation = false; - bool hasTessellation = false; - - const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures(); - supportsGeometry = features.geometryShader == VK_TRUE; - supportsTessellation = features.tessellationShader == VK_TRUE; - hasTessellation = (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) || - (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); - - if (hasTessellation && !supportsTessellation) - { - throw tcu::NotSupportedError(std::string("Tessellation not supported")); - } - - if ((instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT) && - !supportsGeometry) - { - throw tcu::NotSupportedError(std::string("Geometry not supported")); - } - - de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4); - de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4); - const Vec4 vertexData[] = - { - // Upper left corner: - Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), - Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), - Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(), - - // Upper right corner: - Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), - Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), - Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(), - - // Lower left corner: - Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(), - Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), - Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), - - // Lower right corner: - Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(), - Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(), - Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec() - }; - const size_t singleVertexDataSize = 2 * sizeof(Vec4); - const size_t vertexCount = sizeof(vertexData) / singleVertexDataSize; - - const VkBufferCreateInfo vertexBufferParams = - { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkBufferCreateFlags flags; - (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // deUint32 queueFamilyCount; - &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; - }; - const Unique vertexBuffer (createBuffer(vk, vkDevice, &vertexBufferParams)); - const UniquePtr vertexBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible)); - - VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset())); - - const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y()); - const VkBufferCreateInfo readImageBufferParams = - { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkBufferCreateFlags flags; - imageSizeBytes, // VkDeviceSize size; - VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // deUint32 queueFamilyCount; - &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; - }; - const Unique readImageBuffer (createBuffer(vk, vkDevice, &readImageBufferParams)); - const UniquePtr readImageBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible)); - - VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset())); - - const VkImageCreateInfo imageParams = - { - VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkImageCreateFlags flags; - VK_IMAGE_TYPE_2D, // VkImageType imageType; - VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; - { renderSize.x(), renderSize.y(), 1 }, // VkExtent3D extent; - 1u, // deUint32 mipLevels; - 1u, // deUint32 arraySize; - VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; - VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // deUint32 queueFamilyCount; - &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; - }; - - const Unique image (createImage(vk, vkDevice, &imageParams)); - const UniquePtr imageMemory (context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any)); - - VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset())); - - const VkAttachmentDescription colorAttDesc = - { - 0u, // VkAttachmentDescriptionFlags flags; - VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; - VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; - }; - const VkAttachmentReference colorAttRef = - { - 0u, // deUint32 attachment; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; - }; - const VkSubpassDescription subpassDesc = - { - 0u, // VkSubpassDescriptionFlags flags; - VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; - 0u, // deUint32 inputCount; - DE_NULL, // const VkAttachmentReference* pInputAttachments; - 1u, // deUint32 colorCount; - &colorAttRef, // const VkAttachmentReference* pColorAttachments; - DE_NULL, // const VkAttachmentReference* pResolveAttachments; - DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; - 0u, // deUint32 preserveCount; - DE_NULL, // const VkAttachmentReference* pPreserveAttachments; - - }; - const VkRenderPassCreateInfo renderPassParams = - { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkRenderPassCreateFlags)0, - 1u, // deUint32 attachmentCount; - &colorAttDesc, // const VkAttachmentDescription* pAttachments; - 1u, // deUint32 subpassCount; - &subpassDesc, // const VkSubpassDescription* pSubpasses; - 0u, // deUint32 dependencyCount; - DE_NULL, // const VkSubpassDependency* pDependencies; - }; - const Unique renderPass (createRenderPass(vk, vkDevice, &renderPassParams)); - - const VkImageViewCreateInfo colorAttViewParams = - { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkImageViewCreateFlags flags; - *image, // VkImage image; - VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; - VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; - { - VK_COMPONENT_SWIZZLE_R, - VK_COMPONENT_SWIZZLE_G, - VK_COMPONENT_SWIZZLE_B, - VK_COMPONENT_SWIZZLE_A - }, // VkChannelMapping channels; - { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; - 0u, // deUint32 baseMipLevel; - 1u, // deUint32 mipLevels; - 0u, // deUint32 baseArrayLayer; - 1u, // deUint32 arraySize; - }, // VkImageSubresourceRange subresourceRange; - }; - const Unique colorAttView (createImageView(vk, vkDevice, &colorAttViewParams)); - - - // Pipeline layout - const VkPipelineLayoutCreateInfo pipelineLayoutParams = - { - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineLayoutCreateFlags)0, - 0u, // deUint32 descriptorSetCount; - DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; - 0u, // deUint32 pushConstantRangeCount; - DE_NULL, // const VkPushConstantRange* pPushConstantRanges; - }; - const Unique pipelineLayout (createPipelineLayout(vk, vkDevice, &pipelineLayoutParams)); - - // Pipeline - vector shaderStageParams; - // We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline(). - vector > specConstantEntries; - vector specializationInfos; - createPipelineShaderStages(vk, vkDevice, instance, context, modules, shaderStageParams); - - // And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents. - specConstantEntries.reserve(shaderStageParams.size()); - specializationInfos.reserve(shaderStageParams.size()); - - // Patch the specialization info field in PipelineShaderStageCreateInfos. - for (vector::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo) - { - const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage); - - if (stageIt != instance.specConstants.end()) - { - const size_t numSpecConstants = stageIt->second.size(); - vector entries; - VkSpecializationInfo specInfo; - - entries.resize(numSpecConstants); - - // Only support 32-bit integers as spec constants now. And their constant IDs are numbered sequentially starting from 0. - for (size_t ndx = 0; ndx < numSpecConstants; ++ndx) - { - entries[ndx].constantID = (deUint32)ndx; - entries[ndx].offset = deUint32(ndx * sizeof(deInt32)); - entries[ndx].size = sizeof(deInt32); - } - - specConstantEntries.push_back(entries); - - specInfo.mapEntryCount = (deUint32)numSpecConstants; - specInfo.pMapEntries = specConstantEntries.back().data(); - specInfo.dataSize = numSpecConstants * sizeof(deInt32); - specInfo.pData = stageIt->second.data(); - specializationInfos.push_back(specInfo); - - stageInfo->pSpecializationInfo = &specializationInfos.back(); - } - } - const VkPipelineDepthStencilStateCreateInfo depthStencilParams = - { - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineDepthStencilStateCreateFlags)0, - DE_FALSE, // deUint32 depthTestEnable; - DE_FALSE, // deUint32 depthWriteEnable; - VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp; - DE_FALSE, // deUint32 depthBoundsTestEnable; - DE_FALSE, // deUint32 stencilTestEnable; - { - VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp; - VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp; - VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp; - VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp; - 0u, // deUint32 stencilCompareMask; - 0u, // deUint32 stencilWriteMask; - 0u, // deUint32 stencilReference; - }, // VkStencilOpState front; - { - VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp; - VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp; - VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp; - VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp; - 0u, // deUint32 stencilCompareMask; - 0u, // deUint32 stencilWriteMask; - 0u, // deUint32 stencilReference; - }, // VkStencilOpState back; - -1.0f, // float minDepthBounds; - +1.0f, // float maxDepthBounds; - }; - const VkViewport viewport0 = - { - 0.0f, // float originX; - 0.0f, // float originY; - (float)renderSize.x(), // float width; - (float)renderSize.y(), // float height; - 0.0f, // float minDepth; - 1.0f, // float maxDepth; - }; - const VkRect2D scissor0 = - { - { - 0u, // deInt32 x; - 0u, // deInt32 y; - }, // VkOffset2D offset; - { - renderSize.x(), // deInt32 width; - renderSize.y(), // deInt32 height; - }, // VkExtent2D extent; - }; - const VkPipelineViewportStateCreateInfo viewportParams = - { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineViewportStateCreateFlags)0, - 1u, // deUint32 viewportCount; - &viewport0, - 1u, - &scissor0 - }; - const VkSampleMask sampleMask = ~0u; - const VkPipelineMultisampleStateCreateInfo multisampleParams = - { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineMultisampleStateCreateFlags)0, - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterSamples; - DE_FALSE, // deUint32 sampleShadingEnable; - 0.0f, // float minSampleShading; - &sampleMask, // const VkSampleMask* pSampleMask; - DE_FALSE, // VkBool32 alphaToCoverageEnable; - DE_FALSE, // VkBool32 alphaToOneEnable; - }; - const VkPipelineRasterizationStateCreateInfo rasterParams = - { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineRasterizationStateCreateFlags)0, - DE_TRUE, // deUint32 depthClipEnable; - DE_FALSE, // deUint32 rasterizerDiscardEnable; - VK_POLYGON_MODE_FILL, // VkFillMode fillMode; - VK_CULL_MODE_NONE, // VkCullMode cullMode; - VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; - VK_FALSE, // VkBool32 depthBiasEnable; - 0.0f, // float depthBias; - 0.0f, // float depthBiasClamp; - 0.0f, // float slopeScaledDepthBias; - 1.0f, // float lineWidth; - }; - const VkPrimitiveTopology topology = hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams = - { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineInputAssemblyStateCreateFlags)0, - topology, // VkPrimitiveTopology topology; - DE_FALSE, // deUint32 primitiveRestartEnable; - }; - const VkVertexInputBindingDescription vertexBinding0 = - { - 0u, // deUint32 binding; - deUint32(singleVertexDataSize), // deUint32 strideInBytes; - VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate; - }; - const VkVertexInputAttributeDescription vertexAttrib0[2] = - { - { - 0u, // deUint32 location; - 0u, // deUint32 binding; - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; - 0u // deUint32 offsetInBytes; - }, - { - 1u, // deUint32 location; - 0u, // deUint32 binding; - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; - sizeof(Vec4), // deUint32 offsetInBytes; - } - }; - - const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = - { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineVertexInputStateCreateFlags)0, - 1u, // deUint32 bindingCount; - &vertexBinding0, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; - 2u, // deUint32 attributeCount; - vertexAttrib0, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; - }; - const VkPipelineColorBlendAttachmentState attBlendParams = - { - DE_FALSE, // deUint32 blendEnable; - VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor; - VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor; - VK_BLEND_OP_ADD, // VkBlendOp blendOpColor; - VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha; - VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha; - VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha; - (VK_COLOR_COMPONENT_R_BIT| - VK_COLOR_COMPONENT_G_BIT| - VK_COLOR_COMPONENT_B_BIT| - VK_COLOR_COMPONENT_A_BIT), // VkChannelFlags channelWriteMask; - }; - const VkPipelineColorBlendStateCreateInfo blendParams = - { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineColorBlendStateCreateFlags)0, - DE_FALSE, // VkBool32 logicOpEnable; - VK_LOGIC_OP_COPY, // VkLogicOp logicOp; - 1u, // deUint32 attachmentCount; - &attBlendParams, // const VkPipelineColorBlendAttachmentState* pAttachments; - { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4]; - }; - const VkPipelineTessellationStateCreateInfo tessellationState = - { - VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, - DE_NULL, - (VkPipelineTessellationStateCreateFlags)0, - 3u - }; - - const VkPipelineTessellationStateCreateInfo* tessellationInfo = hasTessellation ? &tessellationState: DE_NULL; - const VkGraphicsPipelineCreateInfo pipelineParams = - { - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkPipelineCreateFlags flags; - (deUint32)shaderStageParams.size(), // deUint32 stageCount; - &shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages; - &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; - &inputAssemblyParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; - tessellationInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState; - &viewportParams, // const VkPipelineViewportStateCreateInfo* pViewportState; - &rasterParams, // const VkPipelineRasterStateCreateInfo* pRasterState; - &multisampleParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; - &depthStencilParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; - &blendParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; - (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; - *pipelineLayout, // VkPipelineLayout layout; - *renderPass, // VkRenderPass renderPass; - 0u, // deUint32 subpass; - DE_NULL, // VkPipeline basePipelineHandle; - 0u, // deInt32 basePipelineIndex; - }; - - const Unique pipeline (createGraphicsPipeline(vk, vkDevice, DE_NULL, &pipelineParams)); - - // Framebuffer - const VkFramebufferCreateInfo framebufferParams = - { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkFramebufferCreateFlags)0, - *renderPass, // VkRenderPass renderPass; - 1u, // deUint32 attachmentCount; - &*colorAttView, // const VkImageView* pAttachments; - (deUint32)renderSize.x(), // deUint32 width; - (deUint32)renderSize.y(), // deUint32 height; - 1u, // deUint32 layers; - }; - const Unique framebuffer (createFramebuffer(vk, vkDevice, &framebufferParams)); - - const Unique cmdPool (createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); - - // Command buffer - const Unique cmdBuf (allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); - - const VkCommandBufferBeginInfo cmdBufBeginParams = - { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkCommandBufferUsageFlags)0, - (const VkCommandBufferInheritanceInfo*)DE_NULL, - }; - - // Record commands - VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams)); - - { - const VkMemoryBarrier vertFlushBarrier = - { - VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType; - DE_NULL, // const void* pNext; - VK_ACCESS_HOST_WRITE_BIT, // VkMemoryOutputFlags outputMask; - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkMemoryInputFlags inputMask; - }; - const VkImageMemoryBarrier colorAttBarrier = - { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkMemoryOutputFlags outputMask; - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryInputFlags inputMask; - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; - queueFamilyIndex, // deUint32 srcQueueFamilyIndex; - queueFamilyIndex, // deUint32 destQueueFamilyIndex; - *image, // VkImage image; - { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; - 0u, // deUint32 baseMipLevel; - 1u, // deUint32 mipLevels; - 0u, // deUint32 baseArraySlice; - 1u, // deUint32 arraySize; - } // VkImageSubresourceRange subresourceRange; - }; - vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &colorAttBarrier); - } - - { - const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f); - const VkRenderPassBeginInfo passBeginParams = - { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - *renderPass, // VkRenderPass renderPass; - *framebuffer, // VkFramebuffer framebuffer; - { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea; - 1u, // deUint32 clearValueCount; - &clearValue, // const VkClearValue* pClearValues; - }; - vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE); - } - - vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); - { - const VkDeviceSize bindingOffset = 0; - vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset); - } - vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/); - vk.cmdEndRenderPass(*cmdBuf); - - { - const VkImageMemoryBarrier renderFinishBarrier = - { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; - DE_NULL, // const void* pNext; - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryOutputFlags outputMask; - VK_ACCESS_TRANSFER_READ_BIT, // VkMemoryInputFlags inputMask; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; - queueFamilyIndex, // deUint32 srcQueueFamilyIndex; - queueFamilyIndex, // deUint32 destQueueFamilyIndex; - *image, // VkImage image; - { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; - 0u, // deUint32 baseMipLevel; - 1u, // deUint32 mipLevels; - 0u, // deUint32 baseArraySlice; - 1u, // deUint32 arraySize; - } // VkImageSubresourceRange subresourceRange; - }; - vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &renderFinishBarrier); - } - - { - const VkBufferImageCopy copyParams = - { - (VkDeviceSize)0u, // VkDeviceSize bufferOffset; - (deUint32)renderSize.x(), // deUint32 bufferRowLength; - (deUint32)renderSize.y(), // deUint32 bufferImageHeight; - { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; - 0u, // deUint32 mipLevel; - 0u, // deUint32 arrayLayer; - 1u, // deUint32 arraySize; - }, // VkImageSubresourceCopy imageSubresource; - { 0u, 0u, 0u }, // VkOffset3D imageOffset; - { renderSize.x(), renderSize.y(), 1u } // VkExtent3D imageExtent; - }; - vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params); - } - - { - const VkBufferMemoryBarrier copyFinishBarrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; - DE_NULL, // const void* pNext; - VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask; - VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask; - queueFamilyIndex, // deUint32 srcQueueFamilyIndex; - queueFamilyIndex, // deUint32 destQueueFamilyIndex; - *readImageBuffer, // VkBuffer buffer; - 0u, // VkDeviceSize offset; - imageSizeBytes // VkDeviceSize size; - }; - vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©FinishBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); - } - - VK_CHECK(vk.endCommandBuffer(*cmdBuf)); - - // Upload vertex data - { - const VkMappedMemoryRange range = - { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; - DE_NULL, // const void* pNext; - vertexBufferMemory->getMemory(), // VkDeviceMemory mem; - 0, // VkDeviceSize offset; - (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; - }; - void* vertexBufPtr = vertexBufferMemory->getHostPtr(); - - deMemcpy(vertexBufPtr, &vertexData[0], sizeof(vertexData)); - VK_CHECK(vk.flushMappedMemoryRanges(vkDevice, 1u, &range)); - } - - // Submit & wait for completion - { - const Unique fence (createFence(vk, vkDevice)); - const VkSubmitInfo submitInfo = - { - VK_STRUCTURE_TYPE_SUBMIT_INFO, - DE_NULL, - 0u, - (const VkSemaphore*)DE_NULL, - (const VkPipelineStageFlags*)DE_NULL, - 1u, - &cmdBuf.get(), - 0u, - (const VkSemaphore*)DE_NULL, - }; - - VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); - VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull)); - } - - const void* imagePtr = readImageBufferMemory->getHostPtr(); - const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), - renderSize.x(), renderSize.y(), 1, imagePtr); - // Log image - { - const VkMappedMemoryRange range = - { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; - DE_NULL, // const void* pNext; - readImageBufferMemory->getMemory(), // VkDeviceMemory mem; - 0, // VkDeviceSize offset; - imageSizeBytes, // VkDeviceSize size; - }; - - VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range)); - context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer); - } - - const RGBA threshold(1, 1, 1, 1); - const RGBA upperLeft(pixelBuffer.getPixel(1, 1)); - if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold)) - return TestStatus::fail("Upper left corner mismatch"); - - const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1)); - if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold)) - return TestStatus::fail("Upper right corner mismatch"); - - const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1)); - if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold)) - return TestStatus::fail("Lower left corner mismatch"); - - const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1)); - if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold)) - return TestStatus::fail("Lower right corner mismatch"); - - return TestStatus::pass("Rendered output matches input"); -} - -void createTestsForAllStages (const std::string& name, const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map& testCodeFragments, const vector& specConstants, tcu::TestCaseGroup* tests) -{ - const ShaderElement vertFragPipelineStages[] = - { - ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), - ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), - }; - - const ShaderElement tessPipelineStages[] = - { - ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), - ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), - ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), - ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), - }; - - const ShaderElement geomPipelineStages[] = - { - ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), - ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT), - ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), - }; - - StageToSpecConstantMap specConstantMap; - - specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = specConstants; - addFunctionCaseWithPrograms(tests, name + "_vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline, - createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap)); - - specConstantMap.clear(); - specConstantMap[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] = specConstants; - addFunctionCaseWithPrograms(tests, name + "_tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline, - createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap)); - - specConstantMap.clear(); - specConstantMap[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = specConstants; - addFunctionCaseWithPrograms(tests, name + "_tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline, - createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap)); - - specConstantMap.clear(); - specConstantMap[VK_SHADER_STAGE_GEOMETRY_BIT] = specConstants; - addFunctionCaseWithPrograms(tests, name + "_geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline, - createInstanceContext(geomPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap)); - - specConstantMap.clear(); - specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = specConstants; - addFunctionCaseWithPrograms(tests, name + "_frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline, - createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap)); -} - -inline void createTestsForAllStages (const std::string& name, const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map& testCodeFragments, tcu::TestCaseGroup* tests) -{ - vector noSpecConstants; - createTestsForAllStages(name, inputColors, outputColors, testCodeFragments, noSpecConstants, tests); -} } // anonymous @@ -7047,7 +4832,6 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx) createTestsForAllStages("vec4float32", defaultColors, defaultColors, fragments, opUndefTests.get()); fragments["pre_main"] = - "%v2f32 = OpTypeVector %f32 2\n" "%m2x2f32 = OpTypeMatrix %v2f32 2\n"; fragments["testfun"] = "%test_code = OpFunction %v4f32 None %v4f32_function\n" @@ -7431,7 +5215,9 @@ tcu::TestCaseGroup* createModuleTests(tcu::TestContext& testCtx) getDefaultColors(defaultColors); getInvertedDefaultColors(invertedColors); - addFunctionCaseWithPrograms(moduleTests.get(), "same_module", "", createCombinedModule, runAndVerifyDefaultPipeline, createInstanceContext(combinedPipeline, map())); + addFunctionCaseWithPrograms( + moduleTests.get(), "same_module", "", createCombinedModule, runAndVerifyDefaultPipeline, + createInstanceContext(combinedPipeline, map())); const char* numbers[] = { @@ -7455,11 +5241,15 @@ tcu::TestCaseGroup* createModuleTests(tcu::TestContext& testCtx) // If there are an odd number, the color should be flipped. if ((permutation.vertexPermutation + permutation.geometryPermutation + permutation.tesscPermutation + permutation.tessePermutation + permutation.fragmentPermutation) % 2 == 0) { - addFunctionCaseWithPrograms(moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline, createInstanceContext(pipeline, defaultColors, defaultColors, map())); + addFunctionCaseWithPrograms( + moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline, + createInstanceContext(pipeline, defaultColors, defaultColors, map())); } else { - addFunctionCaseWithPrograms(moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline, createInstanceContext(pipeline, defaultColors, invertedColors, map())); + addFunctionCaseWithPrograms( + moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline, + createInstanceContext(pipeline, defaultColors, invertedColors, map())); } } return moduleTests.release(); @@ -7696,26 +5486,6 @@ tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx) return testGroup.release(); } -// Adds a new test to group using custom fragments for the tessellation-control -// stage and passthrough fragments for all other stages. Uses default colors -// for input and expected output. -void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const map& fragments) -{ - RGBA defaultColors[4]; - getDefaultColors(defaultColors); - const ShaderElement pipelineStages[] = - { - ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), - ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), - ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), - ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), - }; - - addFunctionCaseWithPrograms(group, name, "", addShaderCodeCustomTessControl, - runAndVerifyDefaultPipeline, createInstanceContext( - pipelineStages, defaultColors, defaultColors, fragments, StageToSpecConstantMap())); -} - // A collection of tests putting OpControlBarrier in places GLSL forbids but SPIR-V allows. tcu::TestCaseGroup* createBarrierTests(tcu::TestContext& testCtx) { @@ -8011,22 +5781,22 @@ bool usesInt64 (IntegerType from, IntegerType to) || to == INTEGER_TYPE_SIGNED_64 || to == INTEGER_TYPE_UNSIGNED_64); } -ConvertTestFeatures getUsedFeatures (IntegerType from, IntegerType to) +ComputeTestFeatures getConversionUsedFeatures (IntegerType from, IntegerType to) { if (usesInt16(from, to)) { if (usesInt64(from, to)) { - return CONVERT_TEST_USES_INT16_INT64; + return COMPUTE_TEST_USES_INT16_INT64; } else { - return CONVERT_TEST_USES_INT16; + return COMPUTE_TEST_USES_INT16; } } else { - return CONVERT_TEST_USES_INT64; + return COMPUTE_TEST_USES_INT64; } } @@ -8035,7 +5805,7 @@ struct ConvertCase ConvertCase (IntegerType from, IntegerType to, deInt64 number) : m_fromType (from) , m_toType (to) - , m_features (getUsedFeatures(from, to)) + , m_features (getConversionUsedFeatures(from, to)) , m_name (getTestName(from, to)) , m_inputBuffer (getBuffer(from, number)) , m_outputBuffer (getBuffer(to, number)) @@ -8043,15 +5813,15 @@ struct ConvertCase m_asmTypes["inputType"] = getAsmTypeDeclaration(from); m_asmTypes["outputType"] = getAsmTypeDeclaration(to); - if (m_features == CONVERT_TEST_USES_INT16) + if (m_features == COMPUTE_TEST_USES_INT16) { m_asmTypes["int_capabilities"] = "OpCapability Int16\n"; } - else if (m_features == CONVERT_TEST_USES_INT64) + else if (m_features == COMPUTE_TEST_USES_INT64) { m_asmTypes["int_capabilities"] = "OpCapability Int64\n"; } - else if (m_features == CONVERT_TEST_USES_INT16_INT64) + else if (m_features == COMPUTE_TEST_USES_INT16_INT64) { m_asmTypes["int_capabilities"] = string("OpCapability Int16\n") + "OpCapability Int64\n"; @@ -8064,7 +5834,7 @@ struct ConvertCase IntegerType m_fromType; IntegerType m_toType; - ConvertTestFeatures m_features; + ComputeTestFeatures m_features; string m_name; map m_asmTypes; BufferSp m_inputBuffer; @@ -8175,7 +5945,7 @@ tcu::TestCaseGroup* createSConvertTests (tcu::TestContext& testCtx) spec.outputs.push_back(test->m_outputBuffer); spec.numWorkGroups = IVec3(1, 1, 1); - group->addChild(new ConvertTestCase(testCtx, test->m_name.c_str(), "Convert integers with OpSConvert.", spec, test->m_features)); + group->addChild(new SpvAsmComputeShaderCase(testCtx, test->m_name.c_str(), "Convert integers with OpSConvert.", spec, test->m_features)); } return group.release(); @@ -8213,30 +5983,22 @@ tcu::TestCaseGroup* createUConvertTests (tcu::TestContext& testCtx) spec.outputs.push_back(test->m_outputBuffer); spec.numWorkGroups = IVec3(1, 1, 1); - group->addChild(new ConvertTestCase(testCtx, test->m_name.c_str(), "Convert integers with OpUConvert.", spec, test->m_features)); + group->addChild(new SpvAsmComputeShaderCase(testCtx, test->m_name.c_str(), "Convert integers with OpUConvert.", spec, test->m_features)); } return group.release(); } -enum NumberType -{ - TYPE_INT, - TYPE_UINT, - TYPE_FLOAT, - TYPE_END, -}; - const string getNumberTypeName (const NumberType type) { - if (type == TYPE_INT) + if (type == NUMBERTYPE_INT32) { return "int"; } - else if (type == TYPE_UINT) + else if (type == NUMBERTYPE_UINT32) { return "uint"; } - else if (type == TYPE_FLOAT) + else if (type == NUMBERTYPE_FLOAT32) { return "float"; } @@ -8252,14 +6014,6 @@ deInt32 getInt(de::Random& rnd) return rnd.getInt(std::numeric_limits::min(), std::numeric_limits::max()); } -template -const string numberToString (T number) -{ - std::stringstream ss; - ss << number; - return ss.str(); -} - const string repeatString (const string& str, int times) { string filler; @@ -8272,15 +6026,15 @@ const string repeatString (const string& str, int times) const string getRandomConstantString (const NumberType type, de::Random& rnd) { - if (type == TYPE_INT) + if (type == NUMBERTYPE_INT32) { return numberToString(getInt(rnd)); } - else if (type == TYPE_UINT) + else if (type == NUMBERTYPE_UINT32) { return numberToString(rnd.getUint32()); } - else if (type == TYPE_FLOAT) + else if (type == NUMBERTYPE_FLOAT32) { return numberToString(rnd.getFloat()); } @@ -8391,7 +6145,7 @@ void createCompositeCases (vector >& testCases, de::Random& createArrayCompositeCases(testCases, rnd, type); createStructCompositeCases(testCases, rnd, type); // Matrix only supports float types - if (type == TYPE_FLOAT) + if (type == NUMBERTYPE_FLOAT32) { createMatrixCompositeCases(testCases, rnd, type); } @@ -8401,9 +6155,9 @@ const string getAssemblyTypeDeclaration (const NumberType type) { switch (type) { - case TYPE_INT: return "OpTypeInt 32 1"; - case TYPE_UINT: return "OpTypeInt 32 0"; - case TYPE_FLOAT: return "OpTypeFloat 32"; + case NUMBERTYPE_INT32: return "OpTypeInt 32 1"; + case NUMBERTYPE_UINT32: return "OpTypeInt 32 0"; + case NUMBERTYPE_FLOAT32: return "OpTypeFloat 32"; default: DE_ASSERT(false); return ""; } } @@ -8498,7 +6252,7 @@ tcu::TestCaseGroup* createOpCompositeInsertGroup (tcu::TestContext& testCtx) de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opcompositeinsert", "Test the OpCompositeInsert instruction")); de::Random rnd (deStringHash(group->getName())); - for (int type = TYPE_INT; type != TYPE_END; ++type) + for (int type = NUMBERTYPE_INT32; type != NUMBERTYPE_END32; ++type) { NumberType numberType = NumberType(type); const string typeName = getNumberTypeName(numberType); @@ -8516,21 +6270,21 @@ tcu::TestCaseGroup* createOpCompositeInsertGroup (tcu::TestContext& testCtx) switch (numberType) { - case TYPE_INT: + case NUMBERTYPE_INT32: { deInt32 number = getInt(rnd); spec.inputs.push_back(createCompositeBuffer(number)); spec.outputs.push_back(createCompositeBuffer(number)); break; } - case TYPE_UINT: + case NUMBERTYPE_UINT32: { deUint32 number = rnd.getUint32(); spec.inputs.push_back(createCompositeBuffer(number)); spec.outputs.push_back(createCompositeBuffer(number)); break; } - case TYPE_FLOAT: + case NUMBERTYPE_FLOAT32: { float number = rnd.getFloat(); spec.inputs.push_back(createCompositeBuffer(number)); @@ -8676,7 +6430,7 @@ tcu::TestCaseGroup* createOpInBoundsAccessChainGroup (tcu::TestContext& testCtx) de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opinboundsaccesschain", "Test the OpInBoundsAccessChain instruction")); de::Random rnd (deStringHash(group->getName())); - for (int type = TYPE_INT; type != TYPE_END; ++type) + for (int type = NUMBERTYPE_INT32; type != NUMBERTYPE_END32; ++type) { NumberType numberType = NumberType(type); const string typeName = getNumberTypeName(numberType); @@ -8700,21 +6454,21 @@ tcu::TestCaseGroup* createOpInBoundsAccessChainGroup (tcu::TestContext& testCtx) switch (numberType) { - case TYPE_INT: + case NUMBERTYPE_INT32: { deInt32 number = getInt(rnd); spec.inputs.push_back(createCompositeBuffer(number)); spec.outputs.push_back(createCompositeBuffer(number)); break; } - case TYPE_UINT: + case NUMBERTYPE_UINT32: { deUint32 number = rnd.getUint32(); spec.inputs.push_back(createCompositeBuffer(number)); spec.outputs.push_back(createCompositeBuffer(number)); break; } - case TYPE_FLOAT: + case NUMBERTYPE_FLOAT32: { float number = rnd.getFloat(); spec.inputs.push_back(createCompositeBuffer(number)); @@ -8856,7 +6610,7 @@ tcu::TestCaseGroup* createShaderDefaultOutputGroup (tcu::TestContext& testCtx) de::MovePtr group (new tcu::TestCaseGroup(testCtx, "shader_default_output", "Test shader default output.")); de::Random rnd (deStringHash(group->getName())); - for (int type = TYPE_INT; type != TYPE_END; ++type) + for (int type = NUMBERTYPE_INT32; type != NUMBERTYPE_END32; ++type) { NumberType numberType = NumberType(type); const string typeName = getNumberTypeName(numberType); @@ -8873,7 +6627,7 @@ tcu::TestCaseGroup* createShaderDefaultOutputGroup (tcu::TestContext& testCtx) switch (numberType) { - case TYPE_INT: + case NUMBERTYPE_INT32: { deInt32 number = getInt(rnd); spec.inputs.push_back(createCompositeBuffer(number)); @@ -8881,7 +6635,7 @@ tcu::TestCaseGroup* createShaderDefaultOutputGroup (tcu::TestContext& testCtx) params["constValue"] = numberToString(number); break; } - case TYPE_UINT: + case NUMBERTYPE_UINT32: { deUint32 number = rnd.getUint32(); spec.inputs.push_back(createCompositeBuffer(number)); @@ -8889,7 +6643,7 @@ tcu::TestCaseGroup* createShaderDefaultOutputGroup (tcu::TestContext& testCtx) params["constValue"] = numberToString(number); break; } - case TYPE_FLOAT: + case NUMBERTYPE_FLOAT32: { float number = rnd.getFloat(); spec.inputs.push_back(createCompositeBuffer(number)); @@ -8921,6 +6675,41 @@ tcu::TestCaseGroup* createShaderDefaultOutputGroup (tcu::TestContext& testCtx) return group.release(); } +tcu::TestCaseGroup* createOpNopTests (tcu::TestContext& testCtx) +{ + de::MovePtr testGroup (new tcu::TestCaseGroup(testCtx, "opnop", "Test OpNop")); + RGBA defaultColors[4]; + map opNopFragments; + + getDefaultColors(defaultColors); + + opNopFragments["testfun"] = + "%test_code = OpFunction %v4f32 None %v4f32_function\n" + "%param1 = OpFunctionParameter %v4f32\n" + "%label_testfun = OpLabel\n" + "OpNop\n" + "OpNop\n" + "OpNop\n" + "OpNop\n" + "OpNop\n" + "OpNop\n" + "OpNop\n" + "OpNop\n" + "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" + "%b = OpFAdd %f32 %a %a\n" + "OpNop\n" + "%c = OpFSub %f32 %b %a\n" + "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n" + "OpNop\n" + "OpNop\n" + "OpReturnValue %ret\n" + "OpFunctionEnd\n"; + + createTestsForAllStages("opnop", defaultColors, defaultColors, opNopFragments, testGroup.get()); + + return testGroup.release(); +} + tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx) { de::MovePtr instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands")); @@ -8959,37 +6748,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx) computeTests->addChild(createOpInBoundsAccessChainGroup(testCtx)); computeTests->addChild(createShaderDefaultOutputGroup(testCtx)); - RGBA defaultColors[4]; - getDefaultColors(defaultColors); - - de::MovePtr opnopTests (new tcu::TestCaseGroup(testCtx, "opnop", "Test OpNop")); - map opNopFragments; - opNopFragments["testfun"] = - "%test_code = OpFunction %v4f32 None %v4f32_function\n" - "%param1 = OpFunctionParameter %v4f32\n" - "%label_testfun = OpLabel\n" - "OpNop\n" - "OpNop\n" - "OpNop\n" - "OpNop\n" - "OpNop\n" - "OpNop\n" - "OpNop\n" - "OpNop\n" - "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" - "%b = OpFAdd %f32 %a %a\n" - "OpNop\n" - "%c = OpFSub %f32 %b %a\n" - "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n" - "OpNop\n" - "OpNop\n" - "OpReturnValue %ret\n" - "OpFunctionEnd\n" - ; - createTestsForAllStages("opnop", defaultColors, defaultColors, opNopFragments, opnopTests.get()); - - - graphicsTests->addChild(opnopTests.release()); + graphicsTests->addChild(createOpNopTests(testCtx)); graphicsTests->addChild(createOpSourceTests(testCtx)); graphicsTests->addChild(createOpSourceContinuedTests(testCtx)); graphicsTests->addChild(createOpLineTests(testCtx)); diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.cpp new file mode 100644 index 0000000..c4e225a --- /dev/null +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.cpp @@ -0,0 +1,151 @@ +/*------------------------------------------------------------------------- + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2017 Google 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 Utilities for Vulkan SPIR-V assembly tests + *//*--------------------------------------------------------------------*/ + +#include "vktSpvAsmUtils.hpp" + +#include "deMemory.h" +#include "deSTLUtil.hpp" +#include "vkQueryUtil.hpp" +#include "vkRefUtil.hpp" + +namespace vkt +{ +namespace SpirVAssembly +{ + +using namespace vk; + +namespace +{ + +VkPhysicalDeviceFeatures filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures) +{ + VkPhysicalDeviceFeatures enabledDeviceFeatures = deviceFeatures; + + // Disable robustness by default, as it has an impact on performance on some HW. + enabledDeviceFeatures.robustBufferAccess = false; + + return enabledDeviceFeatures; +} + +} // anonymous + +bool is16BitStorageFeaturesSupported (const InstanceInterface& vki, VkPhysicalDevice device, const std::vector& instanceExtensions, Extension16BitStorageFeatures toCheck) +{ + VkPhysicalDevice16BitStorageFeaturesKHR extensionFeatures = + { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR, // sType + DE_NULL, // pNext + false, // storageUniformBufferBlock16 + false, // storageUniform16 + false, // storagePushConstant16 + false, // storageInputOutput16 + }; + VkPhysicalDeviceFeatures2KHR features; + + deMemset(&features, 0, sizeof(features)); + features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; + features.pNext = &extensionFeatures; + + // Call the getter only if supported. Otherwise above "zero" defaults are used + if (de::contains(instanceExtensions.begin(), instanceExtensions.end(), "VK_KHR_get_physical_device_properties2")) + { + vki.getPhysicalDeviceFeatures2KHR(device, &features); + } + + if ((toCheck & EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK) != 0 && extensionFeatures.storageUniformBufferBlock16 == VK_FALSE) + return false; + + if ((toCheck & EXT16BITSTORAGEFEATURES_UNIFORM) != 0 && extensionFeatures.storageUniform16 == VK_FALSE) + return false; + + if ((toCheck & EXT16BITSTORAGEFEATURES_PUSH_CONSTANT) != 0 && extensionFeatures.storagePushConstant16 == VK_FALSE) + return false; + + if ((toCheck & EXT16BITSTORAGEFEATURES_INPUT_OUTPUT) != 0 && extensionFeatures.storageInputOutput16 == VK_FALSE) + return false; + + return true; +} + +Move createDeviceWithExtensions (const InstanceInterface& vki, + VkPhysicalDevice physicalDevice, + const deUint32 queueFamilyIndex, + const std::vector& supportedExtensions, + const std::vector& requiredExtensions) +{ + std::vector extensions (requiredExtensions.size()); + + for (deUint32 extNdx = 0; extNdx < requiredExtensions.size(); ++extNdx) + { + const std::string& ext = requiredExtensions[extNdx]; + + // Check that all required extensions are supported first. + if (!de::contains(supportedExtensions.begin(), supportedExtensions.end(), ext)) + { + TCU_THROW(NotSupportedError, (std::string("Device extension not supported: ") + ext).c_str()); + } + + extensions[extNdx] = ext.c_str(); + } + + const float queuePriorities[] = { 1.0f }; + const VkDeviceQueueCreateInfo queueInfos[] = + { + { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, + DE_NULL, + (VkDeviceQueueCreateFlags)0, + queueFamilyIndex, + DE_LENGTH_OF_ARRAY(queuePriorities), + &queuePriorities[0] + } + }; + const VkPhysicalDeviceFeatures features = filterDefaultDeviceFeatures(getPhysicalDeviceFeatures(vki, physicalDevice)); + const VkDeviceCreateInfo deviceParams = + { + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, + DE_NULL, + (VkDeviceCreateFlags)0, + DE_LENGTH_OF_ARRAY(queueInfos), + &queueInfos[0], + 0u, + DE_NULL, + (deUint32)extensions.size(), + extensions.empty() ? DE_NULL : &extensions[0], + &features + }; + + return vk::createDevice(vki, physicalDevice, &deviceParams); +} + +Allocator* createAllocator (const InstanceInterface& instanceInterface, const VkPhysicalDevice physicalDevice, const DeviceInterface& deviceInterface, const VkDevice device) +{ + const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(instanceInterface, physicalDevice); + + // \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time) + return new SimpleAllocator(deviceInterface, device, memoryProperties); +} + +} // SpirVAssembly +} // vkt diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.hpp new file mode 100644 index 0000000..78c363f --- /dev/null +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.hpp @@ -0,0 +1,84 @@ +#ifndef _VKTSPVASMUTILS_HPP +#define _VKTSPVASMUTILS_HPP +/*------------------------------------------------------------------------- + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2017 Google 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 Utilities for Vulkan SPIR-V assembly tests + *//*--------------------------------------------------------------------*/ + +#include "vkDefs.hpp" +#include "vkMemUtil.hpp" +#include "vkRef.hpp" +#include "vkTypeUtil.hpp" + +#include +#include + +namespace vkt +{ +namespace SpirVAssembly +{ + +enum Extension16BitStorageFeatureBits +{ + EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK = (1u << 1), + EXT16BITSTORAGEFEATURES_UNIFORM = (1u << 2), + EXT16BITSTORAGEFEATURES_PUSH_CONSTANT = (1u << 3), + EXT16BITSTORAGEFEATURES_INPUT_OUTPUT = (1u << 4), +}; +typedef deUint32 Extension16BitStorageFeatures; + +struct ExtensionFeatures +{ + Extension16BitStorageFeatures ext16BitStorage; + + ExtensionFeatures (void) + : ext16BitStorage (0) + {} + explicit ExtensionFeatures (Extension16BitStorageFeatures ext16BitStorage_) + : ext16BitStorage (ext16BitStorage_) + {} +}; + +// Returns true if the given 16bit storage extension features in `toCheck` are all supported. +bool is16BitStorageFeaturesSupported (const vk::InstanceInterface& vkInstance, + vk::VkPhysicalDevice device, + const std::vector& instanceExtensions, + Extension16BitStorageFeatures toCheck); + +// Creates a Vulkan logical device with the requiredExtensions enabled and all other extensions disabled. +// The logical device will be created from the given instance and physical device. A single queue will +// be created from the given queue family. +vk::Move createDeviceWithExtensions (const vk::InstanceInterface& vki, + vk::VkPhysicalDevice physicalDevice, + deUint32 queueFamilyIndex, + const std::vector& supportedExtensions, + const std::vector& requiredExtensions); + +// Creates a SimpleAllocator on the given device. +vk::Allocator* createAllocator (const vk::InstanceInterface& instanceInterface, + const vk::VkPhysicalDevice physicalDevice, + const vk::DeviceInterface& deviceInterface, + const vk::VkDevice device); + +} // SpirVAssembly +} // vkt + +#endif // _VKTSPVASMUTILS_HPP diff --git a/external/vulkancts/scripts/src/vulkan.h.in b/external/vulkancts/scripts/src/vulkan.h.in index 11238cb..8f18a78 100644 --- a/external/vulkancts/scripts/src/vulkan.h.in +++ b/external/vulkancts/scripts/src/vulkan.h.in @@ -224,6 +224,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = 1000083000, VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000, VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000, VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000, @@ -3953,6 +3954,19 @@ VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR( const VkWriteDescriptorSet* pDescriptorWrites); #endif +#define VK_KHR_16bit_storage 1 +#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1 +#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage" + +typedef struct VkPhysicalDevice16BitStorageFeaturesKHR { + VkStructureType sType; + const void* pNext; + VkBool32 storageUniformBufferBlock16; + VkBool32 storageUniform16; + VkBool32 storagePushConstant16; + VkBool32 storageInputOutput16; +} VkPhysicalDevice16BitStorageFeaturesKHR; + #define VK_KHR_incremental_present 1 #define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1 #define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present" -- 2.7.4