From f310c4806fa82fc0af44c50d44209db8a598e313 Mon Sep 17 00:00:00 2001 From: Paavo Pessi Date: Mon, 3 Jul 2017 12:34:48 +0300 Subject: [PATCH] Add test for maxVertexInputAttributes Tests were added to verify that implementations can use as many vertex input attributes as they advertise. Existing vertex input tests were modified to never consume more than one vertex input binding per vertex input attribute. New tests: dEQP-VK.pipeline.vertex_input.max_attributes.* Affects: dEQP-VK.pipeline.vertex_input.single_attribute.* dEQP-VK.pipeline.vertex_input.multiple_attributes.* Components: Vulkan VK-GL-CTS issue: 261 Change-Id: I3a481618e700ccda8caa4ea00426be14867a58e5 --- android/cts/master/vk-master.txt | 15 + .../pipeline/vktPipelineVertexInputTests.cpp | 382 +++++++++++++++++---- external/vulkancts/mustpass/1.0.3/vk-default.txt | 15 + 3 files changed, 342 insertions(+), 70 deletions(-) diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index ffee8d1..09ffbe3 100644 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -138302,6 +138302,21 @@ dEQP-VK.pipeline.vertex_input.multiple_attributes.binding_one_to_many.attributes dEQP-VK.pipeline.vertex_input.multiple_attributes.binding_one_to_many.attributes_sequential.vec4.mat2.mat4 dEQP-VK.pipeline.vertex_input.multiple_attributes.binding_one_to_many.attributes_sequential.vec4.mat3.mat4 dEQP-VK.pipeline.vertex_input.multiple_attributes.binding_one_to_many.attributes_sequential.mat2.mat3.mat4 +dEQP-VK.pipeline.vertex_input.max_attributes.16_attributes.binding_one_to_one.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.16_attributes.binding_one_to_many.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.16_attributes.binding_one_to_many.sequential +dEQP-VK.pipeline.vertex_input.max_attributes.32_attributes.binding_one_to_one.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.32_attributes.binding_one_to_many.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.32_attributes.binding_one_to_many.sequential +dEQP-VK.pipeline.vertex_input.max_attributes.64_attributes.binding_one_to_one.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.64_attributes.binding_one_to_many.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.64_attributes.binding_one_to_many.sequential +dEQP-VK.pipeline.vertex_input.max_attributes.128_attributes.binding_one_to_one.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.128_attributes.binding_one_to_many.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.128_attributes.binding_one_to_many.sequential +dEQP-VK.pipeline.vertex_input.max_attributes.query_max_attributes.binding_one_to_one.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.query_max_attributes.binding_one_to_many.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.query_max_attributes.binding_one_to_many.sequential dEQP-VK.pipeline.input_assembly.primitive_topology.point_list dEQP-VK.pipeline.input_assembly.primitive_topology.line_list dEQP-VK.pipeline.input_assembly.primitive_topology.line_strip diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineVertexInputTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineVertexInputTests.cpp index dcef8c5..1b4d8df 100644 --- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineVertexInputTests.cpp +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineVertexInputTests.cpp @@ -176,15 +176,19 @@ public: static bool isCompatibleType (VkFormat format, GlslType glslType); private: + AttributeInfo getAttributeInfo (size_t attributeNdx) const; + size_t getNumAttributes (void) const; std::string getGlslInputDeclarations (void) const; std::string getGlslVertexCheck (void) const; - std::string getGlslAttributeConditions (const AttributeInfo& attributeInfo, deUint32 attributeIndex) const; + std::string getGlslAttributeConditions (const AttributeInfo& attributeInfo, const std::string attributeIndex) const; static tcu::Vec4 getFormatThreshold (VkFormat format); const std::vector m_attributeInfos; const BindingMapping m_bindingMapping; const AttributeLayout m_attributeLayout; + const bool m_queryMaxAttributes; bool m_usesDoubleType; + mutable size_t m_maxAttributes; }; class VertexInputInstance : public vkt::TestInstance @@ -281,6 +285,8 @@ VertexInputTest::VertexInputTest (tcu::TestContext& testContext, , m_attributeInfos (attributeInfos) , m_bindingMapping (bindingMapping) , m_attributeLayout (attributeLayout) + , m_queryMaxAttributes (attributeInfos.size() == 0) + , m_maxAttributes (16) { DE_ASSERT(m_attributeLayout == ATTRIBUTE_LAYOUT_INTERLEAVED || m_bindingMapping == BINDING_MAPPING_ONE_TO_MANY); @@ -296,21 +302,17 @@ VertexInputTest::VertexInputTest (tcu::TestContext& testContext, } } -deUint32 getAttributeBinding (const VertexInputTest::BindingMapping bindingMapping, const VkVertexInputRate inputRate, const deUint32 attributeNdx) +deUint32 getAttributeBinding (const VertexInputTest::BindingMapping bindingMapping, const VkVertexInputRate firstInputRate, const VkVertexInputRate inputRate, const deUint32 attributeNdx) { if (bindingMapping == VertexInputTest::BINDING_MAPPING_ONE_TO_ONE) { - if (inputRate == VK_VERTEX_INPUT_RATE_VERTEX) - return attributeNdx * 2; // Even binding number - else // inputRate == VK_VERTEX_INPUT_STEP_RATE_INSTANCE - return attributeNdx * 2 + 1; // Odd binding number + // Each attribute uses a unique binding + return attributeNdx; } else // bindingMapping == BINDING_MAPPING_ONE_TO_MANY { - if (inputRate == VK_VERTEX_INPUT_RATE_VERTEX) - return 0u; - else // inputRate == VK_VERTEX_INPUT_STEP_RATE_INSTANCE - return 1u; + // Alternate between two bindings + return deUint32(firstInputRate + inputRate) % 2u; } } @@ -328,18 +330,67 @@ deUint32 getConsumedLocations (const VertexInputTest::AttributeInfo& attributeIn return 1u; } +VertexInputTest::AttributeInfo VertexInputTest::getAttributeInfo (size_t attributeNdx) const +{ + if (m_queryMaxAttributes) + { + AttributeInfo attributeInfo = + { + GLSL_TYPE_VEC4, + VK_FORMAT_R8G8B8A8_SNORM, + (attributeNdx % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE + }; + + return attributeInfo; + } + else + { + return m_attributeInfos.at(attributeNdx); + } +} + +size_t VertexInputTest::getNumAttributes (void) const +{ + if (m_queryMaxAttributes) + return m_maxAttributes; + else + return m_attributeInfos.size(); +} + TestInstance* VertexInputTest::createInstance (Context& context) const { typedef VertexInputInstance::VertexInputAttributeDescription VertexInputAttributeDescription; + // Check upfront for maximum number of vertex input attributes + { + const InstanceInterface& vki = context.getInstanceInterface(); + const VkPhysicalDevice physDevice = context.getPhysicalDevice(); + const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits; + + const deUint32 maxAttributes = limits.maxVertexInputAttributes; + + if (m_attributeInfos.size() > maxAttributes) + { + const std::string notSupportedStr = "Unsupported number of vertex input attributes, maxVertexInputAttributes: " + de::toString(maxAttributes); + TCU_THROW(NotSupportedError, notSupportedStr.c_str()); + } + + // Use VkPhysicalDeviceLimits::maxVertexInputAttributes + if (m_queryMaxAttributes) + m_maxAttributes = maxAttributes; + } + // Create enough binding descriptions with random offsets std::vector bindingDescriptions; std::vector bindingOffsets; + const size_t numAttributes = getNumAttributes(); + const size_t numBindings = (m_bindingMapping == BINDING_MAPPING_ONE_TO_ONE) ? numAttributes : ((numAttributes > 1) ? 2 : 1); + const VkVertexInputRate firstInputrate = getAttributeInfo(0).inputRate; - for (size_t bindingNdx = 0; bindingNdx < m_attributeInfos.size() * 2; ++bindingNdx) + for (size_t bindingNdx = 0; bindingNdx < numBindings; ++bindingNdx) { - // Use STEP_RATE_VERTEX in even bindings and STEP_RATE_INSTANCE in odd bindings - const VkVertexInputRate inputRate = (bindingNdx % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; + // Bindings alternate between STEP_RATE_VERTEX and STEP_RATE_INSTANCE + const VkVertexInputRate inputRate = ((firstInputrate + bindingNdx) % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; // Stride will be updated when creating the attribute descriptions const VkVertexInputBindingDescription bindingDescription = @@ -360,22 +411,22 @@ TestInstance* VertexInputTest::createInstance (Context& context) const // To place the attributes sequentially we need to know the largest attribute and use its size in stride and offset calculations. if (m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL) - for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); ++attributeNdx) + for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx) { - const AttributeInfo& attributeInfo = m_attributeInfos[attributeNdx]; - const deUint32 attributeBinding = getAttributeBinding(m_bindingMapping, attributeInfo.inputRate, static_cast(attributeNdx)); + const AttributeInfo& attributeInfo = getAttributeInfo(attributeNdx); + const deUint32 attributeBinding = getAttributeBinding(m_bindingMapping, firstInputrate, attributeInfo.inputRate, static_cast(attributeNdx)); const deUint32 inputSize = getVertexFormatSize(attributeInfo.vkType); attributeMaxSizes[attributeBinding] = de::max(attributeMaxSizes[attributeBinding], inputSize); } // Create attribute descriptions, assign them to bindings and update stride. - for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); ++attributeNdx) + for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx) { - const AttributeInfo& attributeInfo = m_attributeInfos[attributeNdx]; + const AttributeInfo& attributeInfo = getAttributeInfo(attributeNdx); const GlslTypeDescription& glslTypeDescription = s_glslTypeDescriptions[attributeInfo.glslType]; const deUint32 inputSize = getVertexFormatSize(attributeInfo.vkType); - const deUint32 attributeBinding = getAttributeBinding(m_bindingMapping, attributeInfo.inputRate, static_cast(attributeNdx)); + const deUint32 attributeBinding = getAttributeBinding(m_bindingMapping, firstInputrate, attributeInfo.inputRate, static_cast(attributeNdx)); const deUint32 vertexCount = (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? (4 * 2) : 2; VertexInputAttributeDescription attributeDescription = @@ -431,6 +482,21 @@ TestInstance* VertexInputTest::createInstance (Context& context) const bindingDescriptions[bindingNdx].stride += getNextMultipleOffset(attributeMaxSizes[bindingNdx], bindingDescriptions[bindingNdx].stride); } + // Check upfront for maximum number of vertex input bindings + { + const InstanceInterface& vki = context.getInstanceInterface(); + const VkPhysicalDevice physDevice = context.getPhysicalDevice(); + const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits; + + const deUint32 maxBindings = limits.maxVertexInputBindings; + + if (bindingDescriptions.size() > maxBindings) + { + const std::string notSupportedStr = "Unsupported number of vertex input bindings, maxVertexInputBindings: " + de::toString(maxBindings); + TCU_THROW(NotSupportedError, notSupportedStr.c_str()); + } + } + return new VertexInputInstance(context, attributeDescriptions, bindingDescriptions, bindingOffsets); } @@ -439,6 +505,7 @@ void VertexInputTest::initPrograms (SourceCollections& programCollection) const std::ostringstream vertexSrc; vertexSrc << "#version 440\n" + << "layout(constant_id = 0) const int numAttributes = " << m_maxAttributes << ";\n" << getGlslInputDeclarations() << "layout(location = 0) out highp vec4 vtxColor;\n" << "out gl_PerVertex {\n" @@ -471,12 +538,20 @@ std::string VertexInputTest::getGlslInputDeclarations (void) const std::ostringstream glslInputs; deUint32 location = 0; - for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++) + if (m_queryMaxAttributes) { - const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType]; + const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[GLSL_TYPE_VEC4]; + glslInputs << "layout(location = 0) in " << glslTypeDesc.name << " attr[numAttributes];\n"; + } + else + { + for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++) + { + const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType]; - glslInputs << "layout(location = " << location << ") in " << glslTypeDesc.name << " attr" << attributeNdx << ";\n"; - location += glslTypeDesc.vertexInputCount; + glslInputs << "layout(location = " << location << ") in " << glslTypeDesc.name << " attr" << attributeNdx << ";\n"; + location += glslTypeDesc.vertexInputCount; + } } return glslInputs.str(); @@ -487,61 +562,112 @@ std::string VertexInputTest::getGlslVertexCheck (void) const std::ostringstream glslCode; int totalInputComponentCount = 0; - glslCode << " int okCount = 0;\n"; - for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++) + if (m_queryMaxAttributes) { - glslCode << getGlslAttributeConditions(m_attributeInfos[attributeNdx], (deUint32)attributeNdx); - - const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputCount; - totalInputComponentCount += vertexInputCount * VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputComponentCount; + const AttributeInfo attributeInfo = getAttributeInfo(0); + + glslCode << " for (int checkNdx = 0; checkNdx < numAttributes; checkNdx++)\n" + << " {\n" + << " uint index = (checkNdx % 2 == 0) ? gl_VertexIndex : gl_InstanceIndex;\n"; + + glslCode << getGlslAttributeConditions(attributeInfo, "checkNdx") + << " }\n"; + + const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount; + totalInputComponentCount += vertexInputCount * VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount; + + glslCode << + " if (okCount == " << totalInputComponentCount << " * numAttributes)\n" + " {\n" + " if (gl_InstanceIndex == 0)\n" + " vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n" + " else\n" + " vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n" + " }\n" + " else\n" + " {\n" + " vtxColor = vec4(okCount / float(" << totalInputComponentCount << " * numAttributes), 0.0f, 0.0f, 1.0);\n" << + " }\n\n" + " if (gl_InstanceIndex == 0)\n" + " {\n" + " if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n" + " else gl_Position = vec4(0.0);\n" + " }\n" + " else\n" + " {\n" + " if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n" + " else gl_Position = vec4(0.0);\n" + " }\n"; } + else + { + for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++) + { + glslCode << getGlslAttributeConditions(m_attributeInfos[attributeNdx], de::toString(attributeNdx)); - glslCode << - " if (okCount == " << totalInputComponentCount << ")\n" - " {\n" - " if (gl_InstanceIndex == 0)\n" - " vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n" - " else\n" - " vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n" - " }\n" - " else\n" - " {\n" - " vtxColor = vec4(okCount / float(" << totalInputComponentCount << "), 0.0f, 0.0f, 1.0);\n" << - " }\n\n" - " if (gl_InstanceIndex == 0)\n" - " {\n" - " if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" - " else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" - " else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" - " else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n" - " else gl_Position = vec4(0.0);\n" - " }\n" - " else\n" - " {\n" - " if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" - " else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n" - " else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n" - " else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n" - " else gl_Position = vec4(0.0);\n" - " }\n"; + const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputCount; + totalInputComponentCount += vertexInputCount * VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputComponentCount; + } + glslCode << + " if (okCount == " << totalInputComponentCount << ")\n" + " {\n" + " if (gl_InstanceIndex == 0)\n" + " vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n" + " else\n" + " vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n" + " }\n" + " else\n" + " {\n" + " vtxColor = vec4(okCount / float(" << totalInputComponentCount << "), 0.0f, 0.0f, 1.0);\n" << + " }\n\n" + " if (gl_InstanceIndex == 0)\n" + " {\n" + " if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n" + " else gl_Position = vec4(0.0);\n" + " }\n" + " else\n" + " {\n" + " if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n" + " else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n" + " else gl_Position = vec4(0.0);\n" + " }\n"; + } return glslCode.str(); } -std::string VertexInputTest::getGlslAttributeConditions (const AttributeInfo& attributeInfo, deUint32 attributeIndex) const +std::string VertexInputTest::getGlslAttributeConditions (const AttributeInfo& attributeInfo, const std::string attributeIndex) const { std::ostringstream glslCode; std::ostringstream attributeVar; - const std::string indexId = (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? "gl_VertexIndex" : "gl_InstanceIndex"; const int componentCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount; const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount; const deUint32 totalComponentCount = componentCount * vertexInputCount; const tcu::Vec4 threshold = getFormatThreshold(attributeInfo.vkType); deUint32 componentIndex = 0; + const std::string indexStr = m_queryMaxAttributes ? "[" + attributeIndex + "]" : attributeIndex; + const std::string indentStr = m_queryMaxAttributes ? "\t\t" : "\t"; + std::string indexId; + + if (m_queryMaxAttributes) + indexId = "index"; + else + indexId = (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? "gl_VertexIndex" : "gl_InstanceIndex"; - attributeVar << "attr" << attributeIndex; + attributeVar << "attr" << indexStr; glslCode << std::fixed; @@ -570,49 +696,49 @@ std::string VertexInputTest::getGlslAttributeConditions (const AttributeInfo& at if (isVertexFormatSint(attributeInfo.vkType)) { - glslCode << "\tif (" << accessStr << " == -(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n"; + glslCode << indentStr << "if (" << accessStr << " == -(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n"; } else if (isVertexFormatUint(attributeInfo.vkType)) { - glslCode << "\tif (" << accessStr << " == uint(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n"; + glslCode << indentStr << "if (" << accessStr << " == uint(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n"; } else if (isVertexFormatSfloat(attributeInfo.vkType)) { if (VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].basicType == VertexInputTest::GLSL_BASIC_TYPE_DOUBLE) { - glslCode << "\tif (abs(" << accessStr << " + double(0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < double(" << threshold[rowNdx] << "))\n"; + glslCode << indentStr << "if (abs(" << accessStr << " + double(0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < double(" << threshold[rowNdx] << "))\n"; } else { - glslCode << "\tif (abs(" << accessStr << " + (0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n"; + glslCode << indentStr << "if (abs(" << accessStr << " + (0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n"; } } else if (isVertexFormatSscaled(attributeInfo.vkType)) { - glslCode << "\tif (abs(" << accessStr << " + (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n"; + glslCode << indentStr << "if (abs(" << accessStr << " + (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n"; } else if (isVertexFormatUscaled(attributeInfo.vkType)) { - glslCode << "\t if (abs(" << accessStr << " - (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n"; + glslCode << indentStr << "if (abs(" << accessStr << " - (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n"; } else if (isVertexFormatSnorm(attributeInfo.vkType)) { const float representableDiff = getRepresentableDifferenceSnorm(attributeInfo.vkType); - glslCode << "\tif (abs(" << accessStr << " - (-1.0 + " << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n"; + glslCode << indentStr << "if (abs(" << accessStr << " - (-1.0 + " << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n"; } else if (isVertexFormatUnorm(attributeInfo.vkType) || isVertexFormatSRGB(attributeInfo.vkType)) { const float representableDiff = getRepresentableDifferenceUnorm(attributeInfo.vkType); - glslCode << "\tif (abs(" << accessStr << " - " << "(" << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n"; + glslCode << indentStr << "if (abs(" << accessStr << " - " << "(" << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n"; } else { DE_ASSERT(false); } - glslCode << "\t\tokCount++;\n\n"; + glslCode << indentStr << "\tokCount++;\n\n"; componentIndex++; } @@ -811,6 +937,23 @@ VertexInputInstance::VertexInputInstance (Context& context, m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_vert"), 0); m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_frag"), 0); + // Create specialization constant + deUint32 specializationData = static_cast(attributeDescriptions.size()); + + const VkSpecializationMapEntry specializationMapEntry = + { + 0, // uint32_t constantID + 0, // uint32_t offset + sizeof(specializationData), // uint32_t size + }; + + const VkSpecializationInfo specializationInfo = + { + 1, // uint32_t mapEntryCount + &specializationMapEntry, // const void* pMapEntries + sizeof(specializationData), // size_t dataSize + &specializationData // const void* pData + }; // Create pipeline { @@ -823,7 +966,7 @@ VertexInputInstance::VertexInputInstance (Context& context, VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; *m_vertexShaderModule, // VkShaderModule module; "main", // const char* pName; - DE_NULL // const VkSpecializationInfo* pSpecializationInfo; + &specializationInfo // const VkSpecializationInfo* pSpecializationInfo; }, { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; @@ -1700,12 +1843,111 @@ void createMultipleAttributeTests (tcu::TestCaseGroup* multipleAttributeTests) multipleAttributeTests->addChild(bindingOneToManyTests.release()); } +void createMaxAttributeTests (tcu::TestCaseGroup* maxAttributeTests) +{ + // Required vertex formats, unpacked + const VkFormat vertexFormats[] = + { + VK_FORMAT_R8_UNORM, + VK_FORMAT_R8_SNORM, + VK_FORMAT_R8_UINT, + VK_FORMAT_R8_SINT, + VK_FORMAT_R8G8_UNORM, + VK_FORMAT_R8G8_SNORM, + VK_FORMAT_R8G8_UINT, + VK_FORMAT_R8G8_SINT, + VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_R8G8B8A8_SNORM, + VK_FORMAT_R8G8B8A8_UINT, + VK_FORMAT_R8G8B8A8_SINT, + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_R16_UNORM, + VK_FORMAT_R16_SNORM, + VK_FORMAT_R16_UINT, + VK_FORMAT_R16_SINT, + VK_FORMAT_R16_SFLOAT, + VK_FORMAT_R16G16_UNORM, + VK_FORMAT_R16G16_SNORM, + VK_FORMAT_R16G16_UINT, + VK_FORMAT_R16G16_SINT, + VK_FORMAT_R16G16_SFLOAT, + VK_FORMAT_R16G16B16A16_UNORM, + VK_FORMAT_R16G16B16A16_SNORM, + VK_FORMAT_R16G16B16A16_UINT, + VK_FORMAT_R16G16B16A16_SINT, + VK_FORMAT_R16G16B16A16_SFLOAT, + VK_FORMAT_R32_UINT, + VK_FORMAT_R32_SINT, + VK_FORMAT_R32_SFLOAT, + VK_FORMAT_R32G32_UINT, + VK_FORMAT_R32G32_SINT, + VK_FORMAT_R32G32_SFLOAT, + VK_FORMAT_R32G32B32_UINT, + VK_FORMAT_R32G32B32_SINT, + VK_FORMAT_R32G32B32_SFLOAT, + VK_FORMAT_R32G32B32A32_UINT, + VK_FORMAT_R32G32B32A32_SINT, + VK_FORMAT_R32G32B32A32_SFLOAT + }; + + // VkPhysicalDeviceLimits::maxVertexInputAttributes is used when attributeCount is 0 + const deUint32 attributeCount[] = { 16, 32, 64, 128, 0 }; + tcu::TestContext& testCtx (maxAttributeTests->getTestContext()); + de::Random randomFunc (132030); + + // Find compatible VK formats for each GLSL vertex type + CompatibleFormats compatibleFormats[VertexInputTest::GLSL_TYPE_COUNT]; + { + for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++) + { + for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++) + { + if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx)) + compatibleFormats[glslTypeNdx].compatibleVkFormats.push_back(vertexFormats[formatNdx]); + } + } + } + + for (deUint32 attributeCountNdx = 0; attributeCountNdx < DE_LENGTH_OF_ARRAY(attributeCount); attributeCountNdx++) + { + const std::string groupName = (attributeCount[attributeCountNdx] == 0 ? "query_max" : de::toString(attributeCount[attributeCountNdx])) + "_attributes"; + const std::string groupDesc = de::toString(attributeCount[attributeCountNdx]) + " vertex input attributes"; + + de::MovePtr numAttributeTests(new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str())); + de::MovePtr bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding")); + de::MovePtr bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding")); + + std::vector attributeInfos(attributeCount[attributeCountNdx]); + + for (deUint32 attributeNdx = 0; attributeNdx < attributeCount[attributeCountNdx]; attributeNdx++) + { + // Use random glslTypes, each consuming one attribute location + const VertexInputTest::GlslType glslType = (VertexInputTest::GlslType)(randomFunc.getUint32() % VertexInputTest::GLSL_TYPE_MAT2); + const std::vector& formats = compatibleFormats[glslType].compatibleVkFormats; + const VkFormat format = formats[randomFunc.getUint32() % formats.size()]; + + attributeInfos[attributeNdx].glslType = glslType; + attributeInfos[attributeNdx].inputRate = ((attributeCountNdx + attributeNdx) % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; + attributeInfos[attributeNdx].vkType = format; + } + + bindingOneToOneTests->addChild(new VertexInputTest(testCtx, "interleaved", "Interleaved attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_ONE, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED)); + bindingOneToManyTests->addChild(new VertexInputTest(testCtx, "interleaved", "Interleaved attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED)); + bindingOneToManyTests->addChild(new VertexInputTest(testCtx, "sequential", "Sequential attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_SEQUENTIAL)); + + numAttributeTests->addChild(bindingOneToOneTests.release()); + numAttributeTests->addChild(bindingOneToManyTests.release()); + maxAttributeTests->addChild(numAttributeTests.release()); + } +} + } // anonymous void createVertexInputTests (tcu::TestCaseGroup* vertexInputTests) { addTestGroup(vertexInputTests, "single_attribute", "Uses one attribute", createSingleAttributeTests); addTestGroup(vertexInputTests, "multiple_attributes", "Uses more than one attribute", createMultipleAttributeTests); + addTestGroup(vertexInputTests, "max_attributes", "Implementations can use as many vertex input attributes as they advertise", createMaxAttributeTests); } } // pipeline diff --git a/external/vulkancts/mustpass/1.0.3/vk-default.txt b/external/vulkancts/mustpass/1.0.3/vk-default.txt index ba1abdd..310f248 100644 --- a/external/vulkancts/mustpass/1.0.3/vk-default.txt +++ b/external/vulkancts/mustpass/1.0.3/vk-default.txt @@ -138307,6 +138307,21 @@ dEQP-VK.pipeline.vertex_input.multiple_attributes.binding_one_to_many.attributes dEQP-VK.pipeline.vertex_input.multiple_attributes.binding_one_to_many.attributes_sequential.vec4.mat2.mat4 dEQP-VK.pipeline.vertex_input.multiple_attributes.binding_one_to_many.attributes_sequential.vec4.mat3.mat4 dEQP-VK.pipeline.vertex_input.multiple_attributes.binding_one_to_many.attributes_sequential.mat2.mat3.mat4 +dEQP-VK.pipeline.vertex_input.max_attributes.16_attributes.binding_one_to_one.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.16_attributes.binding_one_to_many.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.16_attributes.binding_one_to_many.sequential +dEQP-VK.pipeline.vertex_input.max_attributes.32_attributes.binding_one_to_one.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.32_attributes.binding_one_to_many.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.32_attributes.binding_one_to_many.sequential +dEQP-VK.pipeline.vertex_input.max_attributes.64_attributes.binding_one_to_one.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.64_attributes.binding_one_to_many.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.64_attributes.binding_one_to_many.sequential +dEQP-VK.pipeline.vertex_input.max_attributes.128_attributes.binding_one_to_one.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.128_attributes.binding_one_to_many.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.128_attributes.binding_one_to_many.sequential +dEQP-VK.pipeline.vertex_input.max_attributes.query_max_attributes.binding_one_to_one.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.query_max_attributes.binding_one_to_many.interleaved +dEQP-VK.pipeline.vertex_input.max_attributes.query_max_attributes.binding_one_to_many.sequential dEQP-VK.pipeline.input_assembly.primitive_topology.point_list dEQP-VK.pipeline.input_assembly.primitive_topology.line_list dEQP-VK.pipeline.input_assembly.primitive_topology.line_strip -- 2.7.4