From 8e912bc830c0ad3b349d3fa0b734b7c8c420376d Mon Sep 17 00:00:00 2001 From: Graeme Leese Date: Thu, 30 Jan 2020 10:35:17 +0000 Subject: [PATCH] Use common code for SG arithmetic-like tests Factor out the parts of arithmetic, clustered, and partitioned subgroup tests so that common code can be written where possible. Components: Vulkan Affects: dEQP-VK.subgroups.arithmetic.* dEQP-VK.subgroups.clustered.* dEQP-VK.subgroups.partitioned.* Change-Id: I8b580c6b4f90229f2cb5a6324dc0c338709c3921 --- AndroidGen.mk | 1 + .../modules/vulkan/subgroups/CMakeLists.txt | 2 + .../subgroups/vktSubgroupsArithmeticTests.cpp | 691 ++++---------------- .../subgroups/vktSubgroupsClusteredTests.cpp | 412 ++---------- .../subgroups/vktSubgroupsPartitionedTests.cpp | 709 +++++---------------- .../vulkan/subgroups/vktSubgroupsScanHelpers.cpp | 325 ++++++++++ .../vulkan/subgroups/vktSubgroupsScanHelpers.hpp | 56 ++ .../vulkan/subgroups/vktSubgroupsTestsUtils.cpp | 14 + .../vulkan/subgroups/vktSubgroupsTestsUtils.hpp | 1 + 9 files changed, 738 insertions(+), 1473 deletions(-) create mode 100644 external/vulkancts/modules/vulkan/subgroups/vktSubgroupsScanHelpers.cpp create mode 100644 external/vulkancts/modules/vulkan/subgroups/vktSubgroupsScanHelpers.hpp diff --git a/AndroidGen.mk b/AndroidGen.mk index 816e5d6..38c4457 100644 --- a/AndroidGen.mk +++ b/AndroidGen.mk @@ -361,6 +361,7 @@ LOCAL_SRC_FILES := \ external/vulkancts/modules/vulkan/subgroups/vktSubgroupsClusteredTests.cpp \ external/vulkancts/modules/vulkan/subgroups/vktSubgroupsPartitionedTests.cpp \ external/vulkancts/modules/vulkan/subgroups/vktSubgroupsQuadTests.cpp \ + external/vulkancts/modules/vulkan/subgroups/vktSubgroupsScanHelpers.cpp \ external/vulkancts/modules/vulkan/subgroups/vktSubgroupsShapeTests.cpp \ external/vulkancts/modules/vulkan/subgroups/vktSubgroupsShuffleTests.cpp \ external/vulkancts/modules/vulkan/subgroups/vktSubgroupsSizeControlTests.cpp \ diff --git a/external/vulkancts/modules/vulkan/subgroups/CMakeLists.txt b/external/vulkancts/modules/vulkan/subgroups/CMakeLists.txt index eb1e225..68acef5 100644 --- a/external/vulkancts/modules/vulkan/subgroups/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/subgroups/CMakeLists.txt @@ -27,6 +27,8 @@ set(DEQP_VK_SUBGROUPS_SRCS vktSubgroupsShuffleTests.hpp vktSubgroupsQuadTests.cpp vktSubgroupsQuadTests.hpp + vktSubgroupsScanHelpers.cpp + vktSubgroupsScanHelpers.hpp vktSubgroupsShapeTests.cpp vktSubgroupsShapeTests.hpp vktSubgroupsTestsUtils.cpp diff --git a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsArithmeticTests.cpp b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsArithmeticTests.cpp index 833c71f..a705015 100755 --- a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsArithmeticTests.cpp +++ b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsArithmeticTests.cpp @@ -24,6 +24,7 @@ */ /*--------------------------------------------------------------------*/ #include "vktSubgroupsArithmeticTests.hpp" +#include "vktSubgroupsScanHelpers.hpp" #include "vktSubgroupsTestsUtils.hpp" #include @@ -62,405 +63,102 @@ enum OpType OPTYPE_LAST }; -static bool checkVertexPipelineStages(const void* internalData, std::vector datas, - deUint32 width, deUint32) +static Operator getOperator(OpType t) { - DE_UNREF(internalData); - return vkt::subgroups::check(datas, width, 0x3); -} - -static bool checkCompute(const void* internalData, std::vector datas, - const deUint32 numWorkgroups[3], const deUint32 localSize[3], - deUint32) -{ - DE_UNREF(internalData); - return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, 0x3); -} - -std::string getOpTypeName(int opType) -{ - switch (opType) + switch (t) { - default: - DE_FATAL("Unsupported op type"); - return ""; - case OPTYPE_ADD: - return "subgroupAdd"; - case OPTYPE_MUL: - return "subgroupMul"; - case OPTYPE_MIN: - return "subgroupMin"; - case OPTYPE_MAX: - return "subgroupMax"; - case OPTYPE_AND: - return "subgroupAnd"; - case OPTYPE_OR: - return "subgroupOr"; - case OPTYPE_XOR: - return "subgroupXor"; - case OPTYPE_INCLUSIVE_ADD: - return "subgroupInclusiveAdd"; - case OPTYPE_INCLUSIVE_MUL: - return "subgroupInclusiveMul"; - case OPTYPE_INCLUSIVE_MIN: - return "subgroupInclusiveMin"; - case OPTYPE_INCLUSIVE_MAX: - return "subgroupInclusiveMax"; - case OPTYPE_INCLUSIVE_AND: - return "subgroupInclusiveAnd"; - case OPTYPE_INCLUSIVE_OR: - return "subgroupInclusiveOr"; - case OPTYPE_INCLUSIVE_XOR: - return "subgroupInclusiveXor"; - case OPTYPE_EXCLUSIVE_ADD: - return "subgroupExclusiveAdd"; - case OPTYPE_EXCLUSIVE_MUL: - return "subgroupExclusiveMul"; - case OPTYPE_EXCLUSIVE_MIN: - return "subgroupExclusiveMin"; - case OPTYPE_EXCLUSIVE_MAX: - return "subgroupExclusiveMax"; - case OPTYPE_EXCLUSIVE_AND: - return "subgroupExclusiveAnd"; - case OPTYPE_EXCLUSIVE_OR: - return "subgroupExclusiveOr"; - case OPTYPE_EXCLUSIVE_XOR: - return "subgroupExclusiveXor"; - } -} - -std::string getOpTypeOperation(int opType, vk::VkFormat format, std::string lhs, std::string rhs) -{ - switch (opType) - { - default: - DE_FATAL("Unsupported op type"); - return ""; case OPTYPE_ADD: case OPTYPE_INCLUSIVE_ADD: case OPTYPE_EXCLUSIVE_ADD: - return lhs + " + " + rhs; + return OPERATOR_ADD; case OPTYPE_MUL: case OPTYPE_INCLUSIVE_MUL: case OPTYPE_EXCLUSIVE_MUL: - return lhs + " * " + rhs; + return OPERATOR_MUL; case OPTYPE_MIN: case OPTYPE_INCLUSIVE_MIN: case OPTYPE_EXCLUSIVE_MIN: - switch (format) - { - default: - return "min(" + lhs + ", " + rhs + ")"; - case VK_FORMAT_R16_SFLOAT: - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R64_SFLOAT: - return "(isnan(" + lhs + ") ? " + rhs + " : (isnan(" + rhs + ") ? " + lhs + " : min(" + lhs + ", " + rhs + ")))"; - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R64G64_SFLOAT: - case VK_FORMAT_R64G64B64_SFLOAT: - case VK_FORMAT_R64G64B64A64_SFLOAT: - return "mix(mix(min(" + lhs + ", " + rhs + "), " + lhs + ", isnan(" + rhs + ")), " + rhs + ", isnan(" + lhs + "))"; - } + return OPERATOR_MIN; case OPTYPE_MAX: case OPTYPE_INCLUSIVE_MAX: case OPTYPE_EXCLUSIVE_MAX: - switch (format) - { - default: - return "max(" + lhs + ", " + rhs + ")"; - case VK_FORMAT_R16_SFLOAT: - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R64_SFLOAT: - return "(isnan(" + lhs + ") ? " + rhs + " : (isnan(" + rhs + ") ? " + lhs + " : max(" + lhs + ", " + rhs + ")))"; - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R64G64_SFLOAT: - case VK_FORMAT_R64G64B64_SFLOAT: - case VK_FORMAT_R64G64B64A64_SFLOAT: - return "mix(mix(max(" + lhs + ", " + rhs + "), " + lhs + ", isnan(" + rhs + ")), " + rhs + ", isnan(" + lhs + "))"; - } + return OPERATOR_MAX; case OPTYPE_AND: case OPTYPE_INCLUSIVE_AND: case OPTYPE_EXCLUSIVE_AND: - switch (format) - { - default: - return lhs + " & " + rhs; - case VK_FORMAT_R8_USCALED: - return lhs + " && " + rhs; - case VK_FORMAT_R8G8_USCALED: - return "bvec2(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y)"; - case VK_FORMAT_R8G8B8_USCALED: - return "bvec3(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y, " + lhs + ".z && " + rhs + ".z)"; - case VK_FORMAT_R8G8B8A8_USCALED: - return "bvec4(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y, " + lhs + ".z && " + rhs + ".z, " + lhs + ".w && " + rhs + ".w)"; - } + return OPERATOR_AND; case OPTYPE_OR: case OPTYPE_INCLUSIVE_OR: case OPTYPE_EXCLUSIVE_OR: - switch (format) - { - default: - return lhs + " | " + rhs; - case VK_FORMAT_R8_USCALED: - return lhs + " || " + rhs; - case VK_FORMAT_R8G8_USCALED: - return "bvec2(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y)"; - case VK_FORMAT_R8G8B8_USCALED: - return "bvec3(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y, " + lhs + ".z || " + rhs + ".z)"; - case VK_FORMAT_R8G8B8A8_USCALED: - return "bvec4(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y, " + lhs + ".z || " + rhs + ".z, " + lhs + ".w || " + rhs + ".w)"; - } + return OPERATOR_OR; case OPTYPE_XOR: case OPTYPE_INCLUSIVE_XOR: case OPTYPE_EXCLUSIVE_XOR: - switch (format) - { - default: - return lhs + " ^ " + rhs; - case VK_FORMAT_R8_USCALED: - return lhs + " ^^ " + rhs; - case VK_FORMAT_R8G8_USCALED: - return "bvec2(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y)"; - case VK_FORMAT_R8G8B8_USCALED: - return "bvec3(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y, " + lhs + ".z ^^ " + rhs + ".z)"; - case VK_FORMAT_R8G8B8A8_USCALED: - return "bvec4(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y, " + lhs + ".z ^^ " + rhs + ".z, " + lhs + ".w ^^ " + rhs + ".w)"; - } + return OPERATOR_XOR; + default: + DE_FATAL("Unsupported op type"); + return OPERATOR_ADD; } } -std::string getIdentity(int opType, vk::VkFormat format) +static ScanType getScanType(OpType t) { - const bool isFloat = subgroups::isFormatFloat(format); - const bool isInt = subgroups::isFormatSigned(format); - const bool isUnsigned = subgroups::isFormatUnsigned(format); - - switch (opType) + switch (t) { - default: - DE_FATAL("Unsupported op type"); - return ""; case OPTYPE_ADD: - case OPTYPE_INCLUSIVE_ADD: - case OPTYPE_EXCLUSIVE_ADD: - return subgroups::getFormatNameForGLSL(format) + "(0)"; case OPTYPE_MUL: - case OPTYPE_INCLUSIVE_MUL: - case OPTYPE_EXCLUSIVE_MUL: - return subgroups::getFormatNameForGLSL(format) + "(1)"; case OPTYPE_MIN: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MIN: - if (isFloat) - { - return subgroups::getFormatNameForGLSL(format) + "(intBitsToFloat(0x7f800000))"; - } - else if (isInt) - { - switch (format) - { - default: - return subgroups::getFormatNameForGLSL(format) + "(0x7fffffff)"; - case VK_FORMAT_R8_SINT: - case VK_FORMAT_R8G8_SINT: - case VK_FORMAT_R8G8B8_SINT: - case VK_FORMAT_R8G8B8A8_SINT: - case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8G8_UINT: - case VK_FORMAT_R8G8B8_UINT: - case VK_FORMAT_R8G8B8A8_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x7f)"; - case VK_FORMAT_R16_SINT: - case VK_FORMAT_R16G16_SINT: - case VK_FORMAT_R16G16B16_SINT: - case VK_FORMAT_R16G16B16A16_SINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16G16_UINT: - case VK_FORMAT_R16G16B16_UINT: - case VK_FORMAT_R16G16B16A16_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x7fff)"; - case VK_FORMAT_R64_SINT: - case VK_FORMAT_R64G64_SINT: - case VK_FORMAT_R64G64B64_SINT: - case VK_FORMAT_R64G64B64A64_SINT: - case VK_FORMAT_R64_UINT: - case VK_FORMAT_R64G64_UINT: - case VK_FORMAT_R64G64B64_UINT: - case VK_FORMAT_R64G64B64A64_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x7fffffffffffffffUL)"; - } - } - else if (isUnsigned) - { - return subgroups::getFormatNameForGLSL(format) + "(-1)"; - } - else - { - DE_FATAL("Unhandled case"); - return ""; - } case OPTYPE_MAX: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_MAX: - if (isFloat) - { - return subgroups::getFormatNameForGLSL(format) + "(intBitsToFloat(0xff800000))"; - } - else if (isInt) - { - switch (format) - { - default: - return subgroups::getFormatNameForGLSL(format) + "(0x80000000)"; - case VK_FORMAT_R8_SINT: - case VK_FORMAT_R8G8_SINT: - case VK_FORMAT_R8G8B8_SINT: - case VK_FORMAT_R8G8B8A8_SINT: - case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8G8_UINT: - case VK_FORMAT_R8G8B8_UINT: - case VK_FORMAT_R8G8B8A8_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x80)"; - case VK_FORMAT_R16_SINT: - case VK_FORMAT_R16G16_SINT: - case VK_FORMAT_R16G16B16_SINT: - case VK_FORMAT_R16G16B16A16_SINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16G16_UINT: - case VK_FORMAT_R16G16B16_UINT: - case VK_FORMAT_R16G16B16A16_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x8000)"; - case VK_FORMAT_R64_SINT: - case VK_FORMAT_R64G64_SINT: - case VK_FORMAT_R64G64B64_SINT: - case VK_FORMAT_R64G64B64A64_SINT: - case VK_FORMAT_R64_UINT: - case VK_FORMAT_R64G64_UINT: - case VK_FORMAT_R64G64B64_UINT: - case VK_FORMAT_R64G64B64A64_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x8000000000000000UL)"; - } - } - else if (isUnsigned) - { - return subgroups::getFormatNameForGLSL(format) + "(0)"; - } - else - { - DE_FATAL("Unhandled case"); - return ""; - } case OPTYPE_AND: - case OPTYPE_INCLUSIVE_AND: - case OPTYPE_EXCLUSIVE_AND: - return subgroups::getFormatNameForGLSL(format) + "(~0)"; case OPTYPE_OR: - case OPTYPE_INCLUSIVE_OR: - case OPTYPE_EXCLUSIVE_OR: - return subgroups::getFormatNameForGLSL(format) + "(0)"; case OPTYPE_XOR: + return SCAN_REDUCE; + case OPTYPE_INCLUSIVE_ADD: + case OPTYPE_INCLUSIVE_MUL: + case OPTYPE_INCLUSIVE_MIN: + case OPTYPE_INCLUSIVE_MAX: + case OPTYPE_INCLUSIVE_AND: + case OPTYPE_INCLUSIVE_OR: case OPTYPE_INCLUSIVE_XOR: + return SCAN_INCLUSIVE; + case OPTYPE_EXCLUSIVE_ADD: + case OPTYPE_EXCLUSIVE_MUL: + case OPTYPE_EXCLUSIVE_MIN: + case OPTYPE_EXCLUSIVE_MAX: + case OPTYPE_EXCLUSIVE_AND: + case OPTYPE_EXCLUSIVE_OR: case OPTYPE_EXCLUSIVE_XOR: - return subgroups::getFormatNameForGLSL(format) + "(0)"; + return SCAN_EXCLUSIVE; + default: + DE_FATAL("Unsupported op type"); + return SCAN_REDUCE; } } -std::string getCompare(int opType, vk::VkFormat format, std::string lhs, std::string rhs) +static bool checkVertexPipelineStages(const void* internalData, std::vector datas, + deUint32 width, deUint32) { - std::string formatName = subgroups::getFormatNameForGLSL(format); - switch (format) - { - default: - return "all(equal(" + lhs + ", " + rhs + "))"; - case VK_FORMAT_R8_USCALED: - case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8_SINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16_SINT: - case VK_FORMAT_R32_UINT: - case VK_FORMAT_R32_SINT: - case VK_FORMAT_R64_UINT: - case VK_FORMAT_R64_SINT: - return "(" + lhs + " == " + rhs + ")"; - case VK_FORMAT_R16_SFLOAT: - switch (opType) - { - default: - return "(abs(" + lhs + " - " + rhs + ") < " + formatName + "(0.1))"; - case OPTYPE_MIN: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MIN: - case OPTYPE_MAX: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_MAX: - return "(" + lhs + " == " + rhs + ")"; - } - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R64_SFLOAT: - switch (opType) - { - default: - return "(abs(" + lhs + " - " + rhs + ") < 0.00001)"; - case OPTYPE_MIN: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MIN: - case OPTYPE_MAX: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_MAX: - return "(" + lhs + " == " + rhs + ")"; - } - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - switch (opType) - { - default: - return "all(lessThan(abs(" + lhs + " - " + rhs + "), " + formatName + "(0.1)))"; - case OPTYPE_MIN: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MIN: - case OPTYPE_MAX: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_MAX: - return "all(equal(" + lhs + ", " + rhs + "))"; - } - break; - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R64G64_SFLOAT: - case VK_FORMAT_R64G64B64_SFLOAT: - case VK_FORMAT_R64G64B64A64_SFLOAT: - switch (opType) - { - default: - return "all(lessThan(abs(" + lhs + " - " + rhs + "), " + formatName + "(0.00001)))"; - case OPTYPE_MIN: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MIN: - case OPTYPE_MAX: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_MAX: - return "all(equal(" + lhs + ", " + rhs + "))"; - } - } - DE_FATAL("Unhandled case"); - return ""; + DE_UNREF(internalData); + return vkt::subgroups::check(datas, width, 0x3); +} + +static bool checkCompute(const void* internalData, std::vector datas, + const deUint32 numWorkgroups[3], const deUint32 localSize[3], + deUint32) +{ + DE_UNREF(internalData); + return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, 0x3); +} + +std::string getOpTypeName(Operator op, ScanType scanType) +{ + return getScanOpName("subgroup", "", op, scanType); } struct CaseDefinition { - int opType; + Operator op; + ScanType scanType; VkShaderStageFlags shaderStage; VkFormat format; de::SharedPtr geometryPointSizeSupported; @@ -474,138 +172,75 @@ std::string getExtHeader(CaseDefinition caseDef) subgroups::getAdditionalExtensionForFormat(caseDef.format); } +std::string getIndexVars(CaseDefinition caseDef) +{ + switch (caseDef.scanType) + { + case SCAN_REDUCE: + return " uint start = 0, end = gl_SubgroupSize;\n"; + case SCAN_INCLUSIVE: + return " uint start = 0, end = gl_SubgroupInvocationID + 1;\n"; + case SCAN_EXCLUSIVE: + return " uint start = 0, end = gl_SubgroupInvocationID;\n"; + } + DE_FATAL("Unreachable"); + return ""; +} + +std::string getTestSrc(CaseDefinition caseDef) +{ + std::string indexVars = getIndexVars(caseDef); + + return " uvec4 mask = subgroupBallot(true);\n" + + indexVars + + " " + subgroups::getFormatNameForGLSL(caseDef.format) + " ref = " + + getIdentity(caseDef.op, caseDef.format) + ";\n" + " tempRes = 0;\n" + " for (uint index = start; index < end; index++)\n" + " {\n" + " if (subgroupBallotBitExtract(mask, index))\n" + " {\n" + " ref = " + getOpOperation(caseDef.op, caseDef.format, "ref", "data[index]") + ";\n" + " }\n" + " }\n" + " tempRes = " + getCompare(caseDef.op, caseDef.format, "ref", getOpTypeName(caseDef.op, caseDef.scanType) + "(data[gl_SubgroupInvocationID])") + " ? 0x1 : 0;\n" + " if (1 == (gl_SubgroupInvocationID % 2))\n" + " {\n" + " mask = subgroupBallot(true);\n" + " ref = " + getIdentity(caseDef.op, caseDef.format) + ";\n" + " for (uint index = start; index < end; index++)\n" + " {\n" + " if (subgroupBallotBitExtract(mask, index))\n" + " {\n" + " ref = " + getOpOperation(caseDef.op, caseDef.format, "ref", "data[index]") + ";\n" + " }\n" + " }\n" + " tempRes |= " + getCompare(caseDef.op, caseDef.format, "ref", getOpTypeName(caseDef.op, caseDef.scanType) + "(data[gl_SubgroupInvocationID])") + " ? 0x2 : 0;\n" + " }\n" + " else\n" + " {\n" + " tempRes |= 0x2;\n" + " }\n"; +} + void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef) { const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); - std::string indexVars; - std::ostringstream bdy; - switch (caseDef.opType) - { - default: - indexVars = " uint start = 0, end = gl_SubgroupSize;\n"; - break; - case OPTYPE_INCLUSIVE_ADD: - case OPTYPE_INCLUSIVE_MUL: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_INCLUSIVE_AND: - case OPTYPE_INCLUSIVE_OR: - case OPTYPE_INCLUSIVE_XOR: - indexVars = " uint start = 0, end = gl_SubgroupInvocationID + 1;\n"; - break; - case OPTYPE_EXCLUSIVE_ADD: - case OPTYPE_EXCLUSIVE_MUL: - case OPTYPE_EXCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_AND: - case OPTYPE_EXCLUSIVE_OR: - case OPTYPE_EXCLUSIVE_XOR: - indexVars = " uint start = 0, end = gl_SubgroupInvocationID;\n"; - break; - } + std::string extHeader = getExtHeader(caseDef); + std::string testSrc = getTestSrc(caseDef); - bdy << " uvec4 mask = subgroupBallot(true);\n" - << indexVars - << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " ref = " - << getIdentity(caseDef.opType, caseDef.format) << ";\n" - << " tempRes = 0;\n" - << " for (uint index = start; index < end; index++)\n" - << " {\n" - << " if (subgroupBallotBitExtract(mask, index))\n" - << " {\n" - << " ref = " << getOpTypeOperation(caseDef.opType, caseDef.format, "ref", "data[index]") << ";\n" - << " }\n" - << " }\n" - << " tempRes = " << getCompare(caseDef.opType, caseDef.format, "ref", - getOpTypeName(caseDef.opType) + "(data[gl_SubgroupInvocationID])") << " ? 0x1 : 0;\n" - << " if (1 == (gl_SubgroupInvocationID % 2))\n" - << " {\n" - << " mask = subgroupBallot(true);\n" - << " ref = " << getIdentity(caseDef.opType, caseDef.format) << ";\n" - << " for (uint index = start; index < end; index++)\n" - << " {\n" - << " if (subgroupBallotBitExtract(mask, index))\n" - << " {\n" - << " ref = " << getOpTypeOperation(caseDef.opType, caseDef.format, "ref", "data[index]") << ";\n" - << " }\n" - << " }\n" - << " tempRes |= " << getCompare(caseDef.opType, caseDef.format, "ref", - getOpTypeName(caseDef.opType) + "(data[gl_SubgroupInvocationID])") << " ? 0x2 : 0;\n" - << " }\n" - << " else\n" - << " {\n" - << " tempRes |= 0x2;\n" - << " }\n"; - - subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, *caseDef.geometryPointSizeSupported, getExtHeader(caseDef), bdy.str(), ""); + subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, *caseDef.geometryPointSizeSupported, extHeader, testSrc, ""); } void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef) { const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); - std::string indexVars; - switch (caseDef.opType) - { - default: - indexVars = " uint start = 0, end = gl_SubgroupSize;\n"; - break; - case OPTYPE_INCLUSIVE_ADD: - case OPTYPE_INCLUSIVE_MUL: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_INCLUSIVE_AND: - case OPTYPE_INCLUSIVE_OR: - case OPTYPE_INCLUSIVE_XOR: - indexVars = " uint start = 0, end = gl_SubgroupInvocationID + 1;\n"; - break; - case OPTYPE_EXCLUSIVE_ADD: - case OPTYPE_EXCLUSIVE_MUL: - case OPTYPE_EXCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_AND: - case OPTYPE_EXCLUSIVE_OR: - case OPTYPE_EXCLUSIVE_XOR: - indexVars = " uint start = 0, end = gl_SubgroupInvocationID;\n"; - break; - } + std::string extHeader = getExtHeader(caseDef); + std::string testSrc = getTestSrc(caseDef); - const string testSrc = - " uvec4 mask = subgroupBallot(true);\n" - + indexVars + - " " + subgroups::getFormatNameForGLSL(caseDef.format) + " ref = " - + getIdentity(caseDef.opType, caseDef.format) + ";\n" - " tempRes = 0;\n" - " for (uint index = start; index < end; index++)\n" - " {\n" - " if (subgroupBallotBitExtract(mask, index))\n" - " {\n" - " ref = " + getOpTypeOperation(caseDef.opType, caseDef.format, "ref", "data[index]") + ";\n" - " }\n" - " }\n" - " tempRes = " + getCompare(caseDef.opType, caseDef.format, "ref", getOpTypeName(caseDef.opType) + "(data[gl_SubgroupInvocationID])") + " ? 0x1 : 0;\n" - " if (1 == (gl_SubgroupInvocationID % 2))\n" - " {\n" - " mask = subgroupBallot(true);\n" - " ref = " + getIdentity(caseDef.opType, caseDef.format) + ";\n" - " for (uint index = start; index < end; index++)\n" - " {\n" - " if (subgroupBallotBitExtract(mask, index))\n" - " {\n" - " ref = " + getOpTypeOperation(caseDef.opType, caseDef.format, "ref", "data[index]") + ";\n" - " }\n" - " }\n" - " tempRes |= " + getCompare(caseDef.opType, caseDef.format, "ref", getOpTypeName(caseDef.opType) + "(data[gl_SubgroupInvocationID])") + " ? 0x2 : 0;\n" - " }\n" - " else\n" - " {\n" - " tempRes |= 0x2;\n" - " }\n"; - - std::string extHeader = getExtHeader(caseDef); - - subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, extHeader, testSrc, ""); + subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, extHeader, testSrc, ""); } void supportedCheck (Context& context, CaseDefinition caseDef) @@ -645,11 +280,9 @@ void supportedCheck (Context& context, CaseDefinition caseDef) tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef) { - if (!subgroups::areSubgroupOperationsSupportedForStage( - context, caseDef.shaderStage)) + if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage)) { - if (subgroups::areSubgroupOperationsRequiredForStage( - caseDef.shaderStage)) + if (subgroups::areSubgroupOperationsRequiredForStage(caseDef.shaderStage)) { return tcu::TestStatus::fail( "Shader stage " + @@ -680,29 +313,12 @@ tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef) TCU_THROW(InternalError, "Unhandled shader stage"); } -bool checkShaderStages (Context& context, const CaseDefinition& caseDef) -{ - if (!subgroups::areSubgroupOperationsSupportedForStage( - context, caseDef.shaderStage)) - { - if (subgroups::areSubgroupOperationsRequiredForStage( - caseDef.shaderStage)) - { - return false; - } - else - { - TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage"); - } - } - return true; -} tcu::TestStatus test(Context& context, const CaseDefinition caseDef) { if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage) { - if (!checkShaderStages(context,caseDef)) + if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage)) { return tcu::TestStatus::fail( "Shader stage " + @@ -813,92 +429,44 @@ tcu::TestCaseGroup* createSubgroupsArithmeticTests(tcu::TestContext& testCtx) for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex) { - bool isBool = false; - bool isFloat = false; - - switch (format) - { - default: - break; - case VK_FORMAT_R16_SFLOAT: - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R64_SFLOAT: - case VK_FORMAT_R64G64_SFLOAT: - case VK_FORMAT_R64G64B64_SFLOAT: - case VK_FORMAT_R64G64B64A64_SFLOAT: - isFloat = true; - break; - case VK_FORMAT_R8_USCALED: - case VK_FORMAT_R8G8_USCALED: - case VK_FORMAT_R8G8B8_USCALED: - case VK_FORMAT_R8G8B8A8_USCALED: - isBool = true; - break; - } + bool isBool = subgroups::isFormatBool(format); + bool isFloat = subgroups::isFormatFloat(format); - bool isBitwiseOp = false; + OpType opType = static_cast(opTypeIndex); + Operator op = getOperator(opType); + ScanType st = getScanType(opType); - switch (opTypeIndex) - { - default: - break; - case OPTYPE_AND: - case OPTYPE_INCLUSIVE_AND: - case OPTYPE_EXCLUSIVE_AND: - case OPTYPE_OR: - case OPTYPE_INCLUSIVE_OR: - case OPTYPE_EXCLUSIVE_OR: - case OPTYPE_XOR: - case OPTYPE_INCLUSIVE_XOR: - case OPTYPE_EXCLUSIVE_XOR: - isBitwiseOp = true; - break; - } + bool isBitwiseOp = (op == OPERATOR_AND || op == OPERATOR_OR || op == OPERATOR_XOR); + // Skip float with bitwise category. if (isFloat && isBitwiseOp) - { - // Skip float with bitwise category. continue; - } + // Skip bool when its not the bitwise category. if (isBool && !isBitwiseOp) - { - // Skip bool when its not the bitwise category. continue; - } - std::string op = getOpTypeName(opTypeIndex); + + const std::string name = de::toLower(getOpTypeName(op, st)) + "_" + subgroups::getFormatNameForGLSL(format); { - CaseDefinition caseDef = {opTypeIndex, VK_SHADER_STAGE_COMPUTE_BIT, format, de::SharedPtr(new bool), DE_FALSE}; - addFunctionCaseWithPrograms(computeGroup.get(), - de::toLower(op) + "_" + - subgroups::getFormatNameForGLSL(format), + CaseDefinition caseDef = {op, st, VK_SHADER_STAGE_COMPUTE_BIT, format, de::SharedPtr(new bool), DE_FALSE}; + addFunctionCaseWithPrograms(computeGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef); caseDef.requiredSubgroupSize = DE_TRUE; - addFunctionCaseWithPrograms(computeGroup.get(), - de::toLower(op) + "_" + - subgroups::getFormatNameForGLSL(format) + "_requiredsubgroupsize", + addFunctionCaseWithPrograms(computeGroup.get(), name + "_requiredsubgroupsize", "", supportedCheck, initPrograms, test, caseDef); } { - const CaseDefinition caseDef = {opTypeIndex, VK_SHADER_STAGE_ALL_GRAPHICS, format, de::SharedPtr(new bool), DE_FALSE}; - addFunctionCaseWithPrograms(graphicGroup.get(), - de::toLower(op) + "_" + - subgroups::getFormatNameForGLSL(format), + const CaseDefinition caseDef = {op, st, VK_SHADER_STAGE_ALL_GRAPHICS, format, de::SharedPtr(new bool), DE_FALSE}; + addFunctionCaseWithPrograms(graphicGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef); } for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex) { - const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format, de::SharedPtr(new bool), DE_FALSE}; - addFunctionCaseWithPrograms(framebufferGroup.get(), de::toLower(op) + "_" + subgroups::getFormatNameForGLSL(format) + + const CaseDefinition caseDef = {op, st, stages[stageIndex], format, de::SharedPtr(new bool), DE_FALSE}; + addFunctionCaseWithPrograms(framebufferGroup.get(), name + "_" + getShaderStageName(caseDef.shaderStage), "", supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef); } @@ -914,6 +482,5 @@ tcu::TestCaseGroup* createSubgroupsArithmeticTests(tcu::TestContext& testCtx) return group.release(); } - } // subgroups } // vkt diff --git a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsClusteredTests.cpp b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsClusteredTests.cpp index b7d4f9d..a1c2967 100755 --- a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsClusteredTests.cpp +++ b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsClusteredTests.cpp @@ -24,6 +24,7 @@ */ /*--------------------------------------------------------------------*/ #include "vktSubgroupsClusteredTests.hpp" +#include "vktSubgroupsScanHelpers.hpp" #include "vktSubgroupsTestsUtils.hpp" #include @@ -48,6 +49,23 @@ enum OpType OPTYPE_CLUSTERED_LAST }; +static Operator getOperator(OpType t) +{ + switch (t) + { + case OPTYPE_CLUSTERED_ADD: return OPERATOR_ADD; + case OPTYPE_CLUSTERED_MUL: return OPERATOR_MUL; + case OPTYPE_CLUSTERED_MIN: return OPERATOR_MIN; + case OPTYPE_CLUSTERED_MAX: return OPERATOR_MAX; + case OPTYPE_CLUSTERED_AND: return OPERATOR_AND; + case OPTYPE_CLUSTERED_OR: return OPERATOR_OR; + case OPTYPE_CLUSTERED_XOR: return OPERATOR_XOR; + default: + DE_FATAL("Unsupported op type"); + return OPERATOR_ADD; + } +} + static bool checkVertexPipelineStages(const void* internalData, std::vector datas, deUint32 width, deUint32) { @@ -63,315 +81,14 @@ static bool checkCompute(const void* internalData, std::vector data return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, 1); } -std::string getOpTypeName(int opType) -{ - switch (opType) - { - default: - DE_FATAL("Unsupported op type"); - return ""; - case OPTYPE_CLUSTERED_ADD: - return "subgroupClusteredAdd"; - case OPTYPE_CLUSTERED_MUL: - return "subgroupClusteredMul"; - case OPTYPE_CLUSTERED_MIN: - return "subgroupClusteredMin"; - case OPTYPE_CLUSTERED_MAX: - return "subgroupClusteredMax"; - case OPTYPE_CLUSTERED_AND: - return "subgroupClusteredAnd"; - case OPTYPE_CLUSTERED_OR: - return "subgroupClusteredOr"; - case OPTYPE_CLUSTERED_XOR: - return "subgroupClusteredXor"; - } -} - -std::string getOpTypeOperation(int opType, vk::VkFormat format, std::string lhs, std::string rhs) -{ - switch (opType) - { - default: - DE_FATAL("Unsupported op type"); - return ""; - case OPTYPE_CLUSTERED_ADD: - return lhs + " + " + rhs; - case OPTYPE_CLUSTERED_MUL: - return lhs + " * " + rhs; - case OPTYPE_CLUSTERED_MIN: - switch (format) - { - default: - return "min(" + lhs + ", " + rhs + ")"; - case VK_FORMAT_R16_SFLOAT: - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R64_SFLOAT: - return "(isnan(" + lhs + ") ? " + rhs + " : (isnan(" + rhs + ") ? " + lhs + " : min(" + lhs + ", " + rhs + ")))"; - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R64G64_SFLOAT: - case VK_FORMAT_R64G64B64_SFLOAT: - case VK_FORMAT_R64G64B64A64_SFLOAT: - return "mix(mix(min(" + lhs + ", " + rhs + "), " + lhs + ", isnan(" + rhs + ")), " + rhs + ", isnan(" + lhs + "))"; - } - case OPTYPE_CLUSTERED_MAX: - switch (format) - { - default: - return "max(" + lhs + ", " + rhs + ")"; - case VK_FORMAT_R16_SFLOAT: - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R64_SFLOAT: - return "(isnan(" + lhs + ") ? " + rhs + " : (isnan(" + rhs + ") ? " + lhs + " : max(" + lhs + ", " + rhs + ")))"; - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R64G64_SFLOAT: - case VK_FORMAT_R64G64B64_SFLOAT: - case VK_FORMAT_R64G64B64A64_SFLOAT: - return "mix(mix(max(" + lhs + ", " + rhs + "), " + lhs + ", isnan(" + rhs + ")), " + rhs + ", isnan(" + lhs + "))"; - } - case OPTYPE_CLUSTERED_AND: - switch (format) - { - default: - return lhs + " & " + rhs; - case VK_FORMAT_R8_USCALED: - return lhs + " && " + rhs; - case VK_FORMAT_R8G8_USCALED: - return "bvec2(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y)"; - case VK_FORMAT_R8G8B8_USCALED: - return "bvec3(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y, " + lhs + ".z && " + rhs + ".z)"; - case VK_FORMAT_R8G8B8A8_USCALED: - return "bvec4(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y, " + lhs + ".z && " + rhs + ".z, " + lhs + ".w && " + rhs + ".w)"; - } - case OPTYPE_CLUSTERED_OR: - switch (format) - { - default: - return lhs + " | " + rhs; - case VK_FORMAT_R8_USCALED: - return lhs + " || " + rhs; - case VK_FORMAT_R8G8_USCALED: - return "bvec2(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y)"; - case VK_FORMAT_R8G8B8_USCALED: - return "bvec3(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y, " + lhs + ".z || " + rhs + ".z)"; - case VK_FORMAT_R8G8B8A8_USCALED: - return "bvec4(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y, " + lhs + ".z || " + rhs + ".z, " + lhs + ".w || " + rhs + ".w)"; - } - case OPTYPE_CLUSTERED_XOR: - switch (format) - { - default: - return lhs + " ^ " + rhs; - case VK_FORMAT_R8_USCALED: - return lhs + " ^^ " + rhs; - case VK_FORMAT_R8G8_USCALED: - return "bvec2(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y)"; - case VK_FORMAT_R8G8B8_USCALED: - return "bvec3(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y, " + lhs + ".z ^^ " + rhs + ".z)"; - case VK_FORMAT_R8G8B8A8_USCALED: - return "bvec4(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y, " + lhs + ".z ^^ " + rhs + ".z, " + lhs + ".w ^^ " + rhs + ".w)"; - } - } -} - -std::string getIdentity(int opType, vk::VkFormat format) -{ - const bool isFloat = subgroups::isFormatFloat(format); - const bool isInt = subgroups::isFormatSigned(format); - const bool isUnsigned = subgroups::isFormatUnsigned(format); - - switch (opType) - { - default: - DE_FATAL("Unsupported op type"); - return ""; - case OPTYPE_CLUSTERED_ADD: - return subgroups::getFormatNameForGLSL(format) + "(0)"; - case OPTYPE_CLUSTERED_MUL: - return subgroups::getFormatNameForGLSL(format) + "(1)"; - case OPTYPE_CLUSTERED_MIN: - if (isFloat) - { - return subgroups::getFormatNameForGLSL(format) + "(intBitsToFloat(0x7f800000))"; - } - else if (isInt) - { - switch (format) - { - default: - return subgroups::getFormatNameForGLSL(format) + "(0x7fffffff)"; - case VK_FORMAT_R8_SINT: - case VK_FORMAT_R8G8_SINT: - case VK_FORMAT_R8G8B8_SINT: - case VK_FORMAT_R8G8B8A8_SINT: - case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8G8_UINT: - case VK_FORMAT_R8G8B8_UINT: - case VK_FORMAT_R8G8B8A8_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x7f)"; - case VK_FORMAT_R16_SINT: - case VK_FORMAT_R16G16_SINT: - case VK_FORMAT_R16G16B16_SINT: - case VK_FORMAT_R16G16B16A16_SINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16G16_UINT: - case VK_FORMAT_R16G16B16_UINT: - case VK_FORMAT_R16G16B16A16_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x7fff)"; - case VK_FORMAT_R64_SINT: - case VK_FORMAT_R64G64_SINT: - case VK_FORMAT_R64G64B64_SINT: - case VK_FORMAT_R64G64B64A64_SINT: - case VK_FORMAT_R64_UINT: - case VK_FORMAT_R64G64_UINT: - case VK_FORMAT_R64G64B64_UINT: - case VK_FORMAT_R64G64B64A64_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x7fffffffffffffffUL)"; - } - } - else if (isUnsigned) - { - return subgroups::getFormatNameForGLSL(format) + "(-1)"; - } - else - { - DE_FATAL("Unhandled case"); - return ""; - } - case OPTYPE_CLUSTERED_MAX: - if (isFloat) - { - return subgroups::getFormatNameForGLSL(format) + "(intBitsToFloat(0xff800000))"; - } - else if (isInt) - { - switch (format) - { - default: - return subgroups::getFormatNameForGLSL(format) + "(0x80000000)"; - case VK_FORMAT_R8_SINT: - case VK_FORMAT_R8G8_SINT: - case VK_FORMAT_R8G8B8_SINT: - case VK_FORMAT_R8G8B8A8_SINT: - case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8G8_UINT: - case VK_FORMAT_R8G8B8_UINT: - case VK_FORMAT_R8G8B8A8_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x80)"; - case VK_FORMAT_R16_SINT: - case VK_FORMAT_R16G16_SINT: - case VK_FORMAT_R16G16B16_SINT: - case VK_FORMAT_R16G16B16A16_SINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16G16_UINT: - case VK_FORMAT_R16G16B16_UINT: - case VK_FORMAT_R16G16B16A16_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x8000)"; - case VK_FORMAT_R64_SINT: - case VK_FORMAT_R64G64_SINT: - case VK_FORMAT_R64G64B64_SINT: - case VK_FORMAT_R64G64B64A64_SINT: - case VK_FORMAT_R64_UINT: - case VK_FORMAT_R64G64_UINT: - case VK_FORMAT_R64G64B64_UINT: - case VK_FORMAT_R64G64B64A64_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x8000000000000000UL)"; - } - } - else if (isUnsigned) - { - return subgroups::getFormatNameForGLSL(format) + "(0)"; - } - else - { - DE_FATAL("Unhandled case"); - return ""; - } - case OPTYPE_CLUSTERED_AND: - return subgroups::getFormatNameForGLSL(format) + "(~0)"; - case OPTYPE_CLUSTERED_OR: - return subgroups::getFormatNameForGLSL(format) + "(0)"; - case OPTYPE_CLUSTERED_XOR: - return subgroups::getFormatNameForGLSL(format) + "(0)"; - } -} - -std::string getCompare(int opType, vk::VkFormat format, std::string lhs, std::string rhs) +std::string getOpTypeName(Operator op) { - std::string formatName = subgroups::getFormatNameForGLSL(format); - switch (format) - { - default: - return "all(equal(" + lhs + ", " + rhs + "))"; - case VK_FORMAT_R8_USCALED: - case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8_SINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16_SINT: - case VK_FORMAT_R32_UINT: - case VK_FORMAT_R32_SINT: - case VK_FORMAT_R64_UINT: - case VK_FORMAT_R64_SINT: - return "(" + lhs + " == " + rhs + ")"; - case VK_FORMAT_R16_SFLOAT: - switch (opType) - { - default: - return "(abs(" + lhs + " - " + rhs + ") < 0.1)"; - case OPTYPE_CLUSTERED_MIN: - case OPTYPE_CLUSTERED_MAX: - return "(" + lhs + " == " + rhs + ")"; - } - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R64_SFLOAT: - switch (opType) - { - default: - return "(abs(" + lhs + " - " + rhs + ") < 0.00001)"; - case OPTYPE_CLUSTERED_MIN: - case OPTYPE_CLUSTERED_MAX: - return "(" + lhs + " == " + rhs + ")"; - } - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - switch (opType) - { - default: - return "all(lessThan(abs(" + lhs + " - " + rhs + "), " + formatName + "(0.1)))"; - case OPTYPE_CLUSTERED_MIN: - case OPTYPE_CLUSTERED_MAX: - return "all(equal(" + lhs + ", " + rhs + "))"; - } - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R64G64_SFLOAT: - case VK_FORMAT_R64G64B64_SFLOAT: - case VK_FORMAT_R64G64B64A64_SFLOAT: - switch (opType) - { - default: - return "all(lessThan(abs(" + lhs + " - " + rhs + "), " + formatName + "(0.00001)))"; - case OPTYPE_CLUSTERED_MIN: - case OPTYPE_CLUSTERED_MAX: - return "all(equal(" + lhs + ", " + rhs + "))"; - } - } + return getScanOpName("subgroupClustered", "", op, SCAN_REDUCE); } struct CaseDefinition { - int opType; + Operator op; VkShaderStageFlags shaderStage; VkFormat format; de::SharedPtr geometryPointSizeSupported; @@ -381,11 +98,11 @@ struct CaseDefinition std::string getExtHeader(CaseDefinition caseDef) { return "#extension GL_KHR_shader_subgroup_clustered: enable\n" - "#extension GL_KHR_shader_subgroup_ballot: enable\n" - + subgroups::getAdditionalExtensionForFormat(caseDef.format); + "#extension GL_KHR_shader_subgroup_ballot: enable\n" + + subgroups::getAdditionalExtensionForFormat(caseDef.format); } -std::string getBodySource(CaseDefinition caseDef) +std::string getTestSrc(CaseDefinition caseDef) { std::ostringstream bdy; bdy << " bool tempResult = true;\n" @@ -398,21 +115,21 @@ std::string getBodySource(CaseDefinition caseDef) << " if (clusterSize <= gl_SubgroupSize)\n" << " {\n" << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " op = " - << getOpTypeName(caseDef.opType) + "(data[gl_SubgroupInvocationID], clusterSize);\n" + << getOpTypeName(caseDef.op) + "(data[gl_SubgroupInvocationID], clusterSize);\n" << " for (uint clusterOffset = 0; clusterOffset < gl_SubgroupSize; clusterOffset += clusterSize)\n" << " {\n" << " " << subgroups::getFormatNameForGLSL(caseDef.format) << " ref = " - << getIdentity(caseDef.opType, caseDef.format) << ";\n" + << getIdentity(caseDef.op, caseDef.format) << ";\n" << " for (uint index = clusterOffset; index < (clusterOffset + clusterSize); index++)\n" << " {\n" << " if (subgroupBallotBitExtract(mask, index))\n" << " {\n" - << " ref = " << getOpTypeOperation(caseDef.opType, caseDef.format, "ref", "data[index]") << ";\n" + << " ref = " << getOpOperation(caseDef.op, caseDef.format, "ref", "data[index]") << ";\n" << " }\n" << " }\n" << " if ((clusterOffset <= gl_SubgroupInvocationID) && (gl_SubgroupInvocationID < (clusterOffset + clusterSize)))\n" << " {\n" - << " if (!" << getCompare(caseDef.opType, caseDef.format, "ref", "op") << ")\n" + << " if (!" << getCompare(caseDef.op, caseDef.format, "ref", "op") << ")\n" << " {\n" << " tempResult = false;\n" << " }\n" @@ -429,17 +146,20 @@ void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinitio { const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); - subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, *caseDef.geometryPointSizeSupported, getExtHeader(caseDef), getBodySource(caseDef), ""); + std::string extHeader = getExtHeader(caseDef); + std::string testSrc = getTestSrc(caseDef); + + subgroups::initStdFrameBufferPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, *caseDef.geometryPointSizeSupported, extHeader, testSrc, ""); } void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef) { const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); - std::string extHeader = getExtHeader(caseDef); - std::string testSrc = getBodySource(caseDef); + std::string extHeader = getExtHeader(caseDef); + std::string testSrc = getTestSrc(caseDef); - subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, extHeader, testSrc, ""); + subgroups::initStdPrograms(programCollection, buildOptions, caseDef.shaderStage, caseDef.format, extHeader, testSrc, ""); } void supportedCheck (Context& context, CaseDefinition caseDef) @@ -627,79 +347,41 @@ tcu::TestCaseGroup* createSubgroupsClusteredTests(tcu::TestContext& testCtx) for (int opTypeIndex = 0; opTypeIndex < OPTYPE_CLUSTERED_LAST; ++opTypeIndex) { - bool isBool = false; - bool isFloat = false; + bool isBool = subgroups::isFormatBool(format); + bool isFloat = subgroups::isFormatFloat(format); - switch (format) - { - default: - break; - case VK_FORMAT_R16_SFLOAT: - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R64_SFLOAT: - case VK_FORMAT_R64G64_SFLOAT: - case VK_FORMAT_R64G64B64_SFLOAT: - case VK_FORMAT_R64G64B64A64_SFLOAT: - isFloat = true; - break; - case VK_FORMAT_R8_USCALED: - case VK_FORMAT_R8G8_USCALED: - case VK_FORMAT_R8G8B8_USCALED: - case VK_FORMAT_R8G8B8A8_USCALED: - isBool = true; - break; - } - - bool isBitwiseOp = false; + OpType opType = static_cast(opTypeIndex); + Operator op = getOperator(opType); - switch (opTypeIndex) - { - default: - break; - case OPTYPE_CLUSTERED_AND: - case OPTYPE_CLUSTERED_OR: - case OPTYPE_CLUSTERED_XOR: - isBitwiseOp = true; - break; - } + bool isBitwiseOp = (op == OPERATOR_AND || op == OPERATOR_OR || op == OPERATOR_XOR); + // Skip float with bitwise category. if (isFloat && isBitwiseOp) - { - // Skip float with bitwise category. continue; - } + // Skip bool when its not the bitwise category. if (isBool && !isBitwiseOp) - { - // Skip bool when its not the bitwise category. continue; - } - const std::string name = de::toLower(getOpTypeName(opTypeIndex)) + const std::string name = de::toLower(getOpTypeName(op)) +"_" + subgroups::getFormatNameForGLSL(format); { - CaseDefinition caseDef = {opTypeIndex, VK_SHADER_STAGE_COMPUTE_BIT, format, de::SharedPtr(new bool), DE_FALSE}; + CaseDefinition caseDef = {op, VK_SHADER_STAGE_COMPUTE_BIT, format, de::SharedPtr(new bool), DE_FALSE}; addFunctionCaseWithPrograms(computeGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef); caseDef.requiredSubgroupSize = DE_TRUE; addFunctionCaseWithPrograms(computeGroup.get(), name + "_requiredsubgroupsize", "", supportedCheck, initPrograms, test, caseDef); } { - const CaseDefinition caseDef = {opTypeIndex, VK_SHADER_STAGE_ALL_GRAPHICS, format, de::SharedPtr(new bool), DE_FALSE}; + const CaseDefinition caseDef = {op, VK_SHADER_STAGE_ALL_GRAPHICS, format, de::SharedPtr(new bool), DE_FALSE}; addFunctionCaseWithPrograms(graphicGroup.get(), name, - "", supportedCheck, initPrograms, test, caseDef); + "", supportedCheck, initPrograms, test, caseDef); } for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex) { - const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format, de::SharedPtr(new bool), DE_FALSE}; + const CaseDefinition caseDef = {op, stages[stageIndex], format, de::SharedPtr(new bool), DE_FALSE}; addFunctionCaseWithPrograms(framebufferGroup.get(), name +"_" + getShaderStageName(caseDef.shaderStage), "", supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef); } diff --git a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsPartitionedTests.cpp b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsPartitionedTests.cpp index 3c73bae..967b4db 100755 --- a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsPartitionedTests.cpp +++ b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsPartitionedTests.cpp @@ -25,6 +25,7 @@ */ /*--------------------------------------------------------------------*/ #include "vktSubgroupsPartitionedTests.hpp" +#include "vktSubgroupsScanHelpers.hpp" #include "vktSubgroupsTestsUtils.hpp" #include @@ -63,410 +64,126 @@ enum OpType OPTYPE_LAST }; -static bool checkVertexPipelineStages(const void* internalData, std::vector datas, - deUint32 width, deUint32) +static Operator getOperator(OpType t) { - DE_UNREF(internalData); - const deUint32* data = - reinterpret_cast(datas[0]); - for (deUint32 x = 0; x < width; ++x) + switch (t) { - deUint32 val = data[x]; - - if (0xFFFFFF != val) - { - return false; - } - } - - return true; -} - -static bool checkCompute(const void* internalData, std::vector datas, - const deUint32 numWorkgroups[3], const deUint32 localSize[3], - deUint32) -{ - DE_UNREF(internalData); - const deUint32* data = - reinterpret_cast(datas[0]); - - for (deUint32 nX = 0; nX < numWorkgroups[0]; ++nX) - { - for (deUint32 nY = 0; nY < numWorkgroups[1]; ++nY) - { - for (deUint32 nZ = 0; nZ < numWorkgroups[2]; ++nZ) - { - for (deUint32 lX = 0; lX < localSize[0]; ++lX) - { - for (deUint32 lY = 0; lY < localSize[1]; ++lY) - { - for (deUint32 lZ = 0; lZ < localSize[2]; - ++lZ) - { - const deUint32 globalInvocationX = - nX * localSize[0] + lX; - const deUint32 globalInvocationY = - nY * localSize[1] + lY; - const deUint32 globalInvocationZ = - nZ * localSize[2] + lZ; - - const deUint32 globalSizeX = - numWorkgroups[0] * localSize[0]; - const deUint32 globalSizeY = - numWorkgroups[1] * localSize[1]; - - const deUint32 offset = - globalSizeX * - ((globalSizeY * - globalInvocationZ) + - globalInvocationY) + - globalInvocationX; - - if (0xFFFFFF != data[offset]) - { - return false; - } - } - } - } - } - } - } - - return true; -} - -std::string getOpTypeName(int opType) -{ - switch (opType) - { - default: - DE_FATAL("Unsupported op type"); - return ""; case OPTYPE_ADD: - return "subgroupAdd"; - case OPTYPE_MUL: - return "subgroupMul"; - case OPTYPE_MIN: - return "subgroupMin"; - case OPTYPE_MAX: - return "subgroupMax"; - case OPTYPE_AND: - return "subgroupAnd"; - case OPTYPE_OR: - return "subgroupOr"; - case OPTYPE_XOR: - return "subgroupXor"; case OPTYPE_INCLUSIVE_ADD: - return "subgroupInclusiveAdd"; - case OPTYPE_INCLUSIVE_MUL: - return "subgroupInclusiveMul"; - case OPTYPE_INCLUSIVE_MIN: - return "subgroupInclusiveMin"; - case OPTYPE_INCLUSIVE_MAX: - return "subgroupInclusiveMax"; - case OPTYPE_INCLUSIVE_AND: - return "subgroupInclusiveAnd"; - case OPTYPE_INCLUSIVE_OR: - return "subgroupInclusiveOr"; - case OPTYPE_INCLUSIVE_XOR: - return "subgroupInclusiveXor"; case OPTYPE_EXCLUSIVE_ADD: - return "subgroupExclusiveAdd"; + return OPERATOR_ADD; + case OPTYPE_MUL: + case OPTYPE_INCLUSIVE_MUL: case OPTYPE_EXCLUSIVE_MUL: - return "subgroupExclusiveMul"; + return OPERATOR_MUL; + case OPTYPE_MIN: + case OPTYPE_INCLUSIVE_MIN: case OPTYPE_EXCLUSIVE_MIN: - return "subgroupExclusiveMin"; + return OPERATOR_MIN; + case OPTYPE_MAX: + case OPTYPE_INCLUSIVE_MAX: case OPTYPE_EXCLUSIVE_MAX: - return "subgroupExclusiveMax"; + return OPERATOR_MAX; + case OPTYPE_AND: + case OPTYPE_INCLUSIVE_AND: case OPTYPE_EXCLUSIVE_AND: - return "subgroupExclusiveAnd"; + return OPERATOR_AND; + case OPTYPE_OR: + case OPTYPE_INCLUSIVE_OR: case OPTYPE_EXCLUSIVE_OR: - return "subgroupExclusiveOr"; + return OPERATOR_OR; + case OPTYPE_XOR: + case OPTYPE_INCLUSIVE_XOR: case OPTYPE_EXCLUSIVE_XOR: - return "subgroupExclusiveXor"; + return OPERATOR_XOR; + default: + DE_FATAL("Unsupported op type"); + return OPERATOR_ADD; } } -std::string getOpTypeNamePartitioned(int opType) +static ScanType getScanType(OpType t) { - switch (opType) + switch (t) { - default: - DE_FATAL("Unsupported op type"); - return ""; case OPTYPE_ADD: - return "subgroupPartitionedAddNV"; case OPTYPE_MUL: - return "subgroupPartitionedMulNV"; case OPTYPE_MIN: - return "subgroupPartitionedMinNV"; case OPTYPE_MAX: - return "subgroupPartitionedMaxNV"; case OPTYPE_AND: - return "subgroupPartitionedAndNV"; case OPTYPE_OR: - return "subgroupPartitionedOrNV"; case OPTYPE_XOR: - return "subgroupPartitionedXorNV"; + return SCAN_REDUCE; case OPTYPE_INCLUSIVE_ADD: - return "subgroupPartitionedInclusiveAddNV"; case OPTYPE_INCLUSIVE_MUL: - return "subgroupPartitionedInclusiveMulNV"; case OPTYPE_INCLUSIVE_MIN: - return "subgroupPartitionedInclusiveMinNV"; case OPTYPE_INCLUSIVE_MAX: - return "subgroupPartitionedInclusiveMaxNV"; case OPTYPE_INCLUSIVE_AND: - return "subgroupPartitionedInclusiveAndNV"; case OPTYPE_INCLUSIVE_OR: - return "subgroupPartitionedInclusiveOrNV"; case OPTYPE_INCLUSIVE_XOR: - return "subgroupPartitionedInclusiveXorNV"; + return SCAN_INCLUSIVE; case OPTYPE_EXCLUSIVE_ADD: - return "subgroupPartitionedExclusiveAddNV"; case OPTYPE_EXCLUSIVE_MUL: - return "subgroupPartitionedExclusiveMulNV"; case OPTYPE_EXCLUSIVE_MIN: - return "subgroupPartitionedExclusiveMinNV"; case OPTYPE_EXCLUSIVE_MAX: - return "subgroupPartitionedExclusiveMaxNV"; case OPTYPE_EXCLUSIVE_AND: - return "subgroupPartitionedExclusiveAndNV"; case OPTYPE_EXCLUSIVE_OR: - return "subgroupPartitionedExclusiveOrNV"; case OPTYPE_EXCLUSIVE_XOR: - return "subgroupPartitionedExclusiveXorNV"; + return SCAN_EXCLUSIVE; + default: + DE_FATAL("Unsupported op type"); + return SCAN_REDUCE; } } -std::string getIdentity(int opType, vk::VkFormat format) +static bool checkVertexPipelineStages(const void* internalData, std::vector datas, + deUint32 width, deUint32) { - const bool isFloat = subgroups::isFormatFloat(format); - const bool isInt = subgroups::isFormatSigned(format); - const bool isUnsigned = subgroups::isFormatUnsigned(format); + DE_UNREF(internalData); + return vkt::subgroups::check(datas, width, 0xFFFFFF); +} - switch (opType) - { - default: - DE_FATAL("Unsupported op type"); - return ""; - case OPTYPE_ADD: - case OPTYPE_INCLUSIVE_ADD: - case OPTYPE_EXCLUSIVE_ADD: - return subgroups::getFormatNameForGLSL(format) + "(0)"; - case OPTYPE_MUL: - case OPTYPE_INCLUSIVE_MUL: - case OPTYPE_EXCLUSIVE_MUL: - return subgroups::getFormatNameForGLSL(format) + "(1)"; - case OPTYPE_MIN: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MIN: - if (isFloat) - { - return subgroups::getFormatNameForGLSL(format) + "(intBitsToFloat(0x7f800000))"; - } - else if (isInt) - { - switch (format) - { - default: - return subgroups::getFormatNameForGLSL(format) + "(0x7fffffff)"; - case VK_FORMAT_R8_SINT: - case VK_FORMAT_R8G8_SINT: - case VK_FORMAT_R8G8B8_SINT: - case VK_FORMAT_R8G8B8A8_SINT: - case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8G8_UINT: - case VK_FORMAT_R8G8B8_UINT: - case VK_FORMAT_R8G8B8A8_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x7f)"; - case VK_FORMAT_R16_SINT: - case VK_FORMAT_R16G16_SINT: - case VK_FORMAT_R16G16B16_SINT: - case VK_FORMAT_R16G16B16A16_SINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16G16_UINT: - case VK_FORMAT_R16G16B16_UINT: - case VK_FORMAT_R16G16B16A16_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x7fff)"; - case VK_FORMAT_R64_SINT: - case VK_FORMAT_R64G64_SINT: - case VK_FORMAT_R64G64B64_SINT: - case VK_FORMAT_R64G64B64A64_SINT: - case VK_FORMAT_R64_UINT: - case VK_FORMAT_R64G64_UINT: - case VK_FORMAT_R64G64B64_UINT: - case VK_FORMAT_R64G64B64A64_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x7fffffffffffffffUL)"; - } - } - else if (isUnsigned) - { - return subgroups::getFormatNameForGLSL(format) + "(-1)"; - } - else - { - DE_FATAL("Unhandled case"); - return ""; - } - case OPTYPE_MAX: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_MAX: - if (isFloat) - { - return subgroups::getFormatNameForGLSL(format) + "(intBitsToFloat(0xff800000))"; - } - else if (isInt) - { - switch (format) - { - default: - return subgroups::getFormatNameForGLSL(format) + "(0x80000000)"; - case VK_FORMAT_R8_SINT: - case VK_FORMAT_R8G8_SINT: - case VK_FORMAT_R8G8B8_SINT: - case VK_FORMAT_R8G8B8A8_SINT: - case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8G8_UINT: - case VK_FORMAT_R8G8B8_UINT: - case VK_FORMAT_R8G8B8A8_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x80)"; - case VK_FORMAT_R16_SINT: - case VK_FORMAT_R16G16_SINT: - case VK_FORMAT_R16G16B16_SINT: - case VK_FORMAT_R16G16B16A16_SINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16G16_UINT: - case VK_FORMAT_R16G16B16_UINT: - case VK_FORMAT_R16G16B16A16_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x8000)"; - case VK_FORMAT_R64_SINT: - case VK_FORMAT_R64G64_SINT: - case VK_FORMAT_R64G64B64_SINT: - case VK_FORMAT_R64G64B64A64_SINT: - case VK_FORMAT_R64_UINT: - case VK_FORMAT_R64G64_UINT: - case VK_FORMAT_R64G64B64_UINT: - case VK_FORMAT_R64G64B64A64_UINT: - return subgroups::getFormatNameForGLSL(format) + "(0x8000000000000000UL)"; - } - } - else if (isUnsigned) - { - return subgroups::getFormatNameForGLSL(format) + "(0)"; - } - else - { - DE_FATAL("Unhandled case"); - return ""; - } - case OPTYPE_AND: - case OPTYPE_INCLUSIVE_AND: - case OPTYPE_EXCLUSIVE_AND: - return subgroups::getFormatNameForGLSL(format) + "(~0)"; - case OPTYPE_OR: - case OPTYPE_INCLUSIVE_OR: - case OPTYPE_EXCLUSIVE_OR: - return subgroups::getFormatNameForGLSL(format) + "(0)"; - case OPTYPE_XOR: - case OPTYPE_INCLUSIVE_XOR: - case OPTYPE_EXCLUSIVE_XOR: - return subgroups::getFormatNameForGLSL(format) + "(0)"; - } +static bool checkCompute(const void* internalData, std::vector datas, + const deUint32 numWorkgroups[3], const deUint32 localSize[3], + deUint32) +{ + DE_UNREF(internalData); + return vkt::subgroups::checkCompute(datas, numWorkgroups, localSize, 0xFFFFFF); } -std::string getCompare(int opType, vk::VkFormat format, std::string lhs, std::string rhs) +std::string getOpTypeName(Operator op, ScanType scanType) { - std::string formatName = subgroups::getFormatNameForGLSL(format); - switch (format) - { - default: - return "all(equal(" + lhs + ", " + rhs + "))"; - case VK_FORMAT_R8_USCALED: - case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8_SINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16_SINT: - case VK_FORMAT_R32_UINT: - case VK_FORMAT_R32_SINT: - case VK_FORMAT_R64_UINT: - case VK_FORMAT_R64_SINT: - return "(" + lhs + " == " + rhs + ")"; - case VK_FORMAT_R16_SFLOAT: - switch (opType) - { - default: - return "(abs(" + lhs + " - " + rhs + ") < 0.1)"; - case OPTYPE_MIN: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MIN: - case OPTYPE_MAX: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_MAX: - return "(" + lhs + " == " + rhs + ")"; - } - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R64_SFLOAT: - switch (opType) - { - default: - return "(abs(" + lhs + " - " + rhs + ") < 0.00001)"; - case OPTYPE_MIN: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MIN: - case OPTYPE_MAX: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_MAX: - return "(" + lhs + " == " + rhs + ")"; - } - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - switch (opType) - { - default: - return "all(lessThan(abs(" + lhs + " - " + rhs + "), " + formatName + "(0.1)))"; - case OPTYPE_MIN: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MIN: - case OPTYPE_MAX: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_MAX: - return "all(equal(" + lhs + ", " + rhs + "))"; - } - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R64G64_SFLOAT: - case VK_FORMAT_R64G64B64_SFLOAT: - case VK_FORMAT_R64G64B64A64_SFLOAT: - switch (opType) - { - default: - return "all(lessThan(abs(" + lhs + " - " + rhs + "), " + formatName + "(0.00001)))"; - case OPTYPE_MIN: - case OPTYPE_INCLUSIVE_MIN: - case OPTYPE_EXCLUSIVE_MIN: - case OPTYPE_MAX: - case OPTYPE_INCLUSIVE_MAX: - case OPTYPE_EXCLUSIVE_MAX: - return "all(equal(" + lhs + ", " + rhs + "))"; - } - } + return getScanOpName("subgroup", "", op, scanType); +} + +std::string getOpTypeNamePartitioned(Operator op, ScanType scanType) +{ + return getScanOpName("subgroupPartitioned", "NV", op, scanType); } struct CaseDefinition { - int opType; + Operator op; + ScanType scanType; VkShaderStageFlags shaderStage; VkFormat format; de::SharedPtr geometryPointSizeSupported; deBool requiredSubgroupSize; }; +std::string getExtHeader(CaseDefinition caseDef) +{ + return "#extension GL_NV_shader_subgroup_partitioned: enable\n" + "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" + "#extension GL_KHR_shader_subgroup_ballot: enable\n" + + subgroups::getAdditionalExtensionForFormat(caseDef.format); +} + string getTestString(const CaseDefinition &caseDef) { + Operator op = caseDef.op; + ScanType st = caseDef.scanType; + // NOTE: tempResult can't have anything in bits 31:24 to avoid int->float // conversion overflow in framebuffer tests. string fmt = subgroups::getFormatNameForGLSL(caseDef.format); @@ -478,85 +195,85 @@ string getTestString(const CaseDefinition &caseDef) // This should generate the same result as the non-partitioned function. bdy += " uvec4 allBallot = mask;\n" - " " + fmt + " allResult = " + getOpTypeNamePartitioned(caseDef.opType) + "(data[gl_SubgroupInvocationID], allBallot);\n" - " " + fmt + " refResult = " + getOpTypeName(caseDef.opType) + "(data[gl_SubgroupInvocationID]);\n" - " if (" + getCompare(caseDef.opType, caseDef.format, "allResult", "refResult") + ") {\n" + " " + fmt + " allResult = " + getOpTypeNamePartitioned(op, st) + "(data[gl_SubgroupInvocationID], allBallot);\n" + " " + fmt + " refResult = " + getOpTypeName(op, st) + "(data[gl_SubgroupInvocationID]);\n" + " if (" + getCompare(op, caseDef.format, "allResult", "refResult") + ") {\n" " tempResult |= 0x1;\n" " }\n"; - // The definition of a partition doesn't forbid bits corresponding to inactive - // invocations being in the subset with active invocations. In other words, test that - // bits corresponding to inactive invocations are ignored. - bdy += - " if (0 == (gl_SubgroupInvocationID % 2)) {\n" - " " + fmt + " allResult = " + getOpTypeNamePartitioned(caseDef.opType) + "(data[gl_SubgroupInvocationID], allBallot);\n" - " " + fmt + " refResult = " + getOpTypeName(caseDef.opType) + "(data[gl_SubgroupInvocationID]);\n" - " if (" + getCompare(caseDef.opType, caseDef.format, "allResult", "refResult") + ") {\n" - " tempResult |= 0x2;\n" - " }\n" - " } else {\n" - " tempResult |= 0x2;\n" - " }\n"; - - // Test the case where the partition has each invocation in a unique subset. For - // exclusive ops, the result is identity. For reduce/inclusive, it's the original value. - string expectedSelfResult = "data[gl_SubgroupInvocationID]"; - if (caseDef.opType >= OPTYPE_EXCLUSIVE_ADD && - caseDef.opType <= OPTYPE_EXCLUSIVE_XOR) { - expectedSelfResult = getIdentity(caseDef.opType, caseDef.format); - } - - bdy += - " uvec4 selfBallot = subgroupPartitionNV(gl_SubgroupInvocationID);\n" - " " + fmt + " selfResult = " + getOpTypeNamePartitioned(caseDef.opType) + "(data[gl_SubgroupInvocationID], selfBallot);\n" - " if (" + getCompare(caseDef.opType, caseDef.format, "selfResult", expectedSelfResult) + ") {\n" - " tempResult |= 0x4;\n" - " }\n"; - - // Test "random" partitions based on a hash of the invocation id. - // This "hash" function produces interesting/randomish partitions. - static const char *idhash = "((id%N)+(id%(N+1))-(id%2)+(id/2))%((N+1)/2)"; - - bdy += + // The definition of a partition doesn't forbid bits corresponding to inactive + // invocations being in the subset with active invocations. In other words, test that + // bits corresponding to inactive invocations are ignored. + bdy += + " if (0 == (gl_SubgroupInvocationID % 2)) {\n" + " " + fmt + " allResult = " + getOpTypeNamePartitioned(op, st) + "(data[gl_SubgroupInvocationID], allBallot);\n" + " " + fmt + " refResult = " + getOpTypeName(op, st) + "(data[gl_SubgroupInvocationID]);\n" + " if (" + getCompare(op, caseDef.format, "allResult", "refResult") + ") {\n" + " tempResult |= 0x2;\n" + " }\n" + " } else {\n" + " tempResult |= 0x2;\n" + " }\n"; + + // Test the case where the partition has each invocation in a unique subset. For + // exclusive ops, the result is identity. For reduce/inclusive, it's the original value. + string expectedSelfResult = "data[gl_SubgroupInvocationID]"; + if (st == SCAN_EXCLUSIVE) + expectedSelfResult = getIdentity(op, caseDef.format); + + bdy += + " uvec4 selfBallot = subgroupPartitionNV(gl_SubgroupInvocationID);\n" + " " + fmt + " selfResult = " + getOpTypeNamePartitioned(op, st) + "(data[gl_SubgroupInvocationID], selfBallot);\n" + " if (" + getCompare(op, caseDef.format, "selfResult", expectedSelfResult) + ") {\n" + " tempResult |= 0x4;\n" + " }\n"; + + // Test "random" partitions based on a hash of the invocation id. + // This "hash" function produces interesting/randomish partitions. + static const char *idhash = "((id%N)+(id%(N+1))-(id%2)+(id/2))%((N+1)/2)"; + + bdy += " for (uint N = 1; N < 16; ++N) {\n" " " + fmt + " idhashFmt = " + fmt + "(" + idhash + ");\n" " uvec4 partitionBallot = subgroupPartitionNV(idhashFmt) & mask;\n" - " " + fmt + " partitionedResult = " + getOpTypeNamePartitioned(caseDef.opType) + "(data[gl_SubgroupInvocationID], partitionBallot);\n" + " " + fmt + " partitionedResult = " + getOpTypeNamePartitioned(op, st) + "(data[gl_SubgroupInvocationID], partitionBallot);\n" " for (uint i = 0; i < N; ++i) {\n" " " + fmt + " iFmt = " + fmt + "(i);\n" - " if (" + getCompare(caseDef.opType, caseDef.format, "idhashFmt", "iFmt") + ") {\n" - " " + fmt + " subsetResult = " + getOpTypeName(caseDef.opType) + "(data[gl_SubgroupInvocationID]);\n" - " tempResult |= " + getCompare(caseDef.opType, caseDef.format, "partitionedResult", "subsetResult") + " ? (0x4 << N) : 0;\n" - " }\n" - " }\n" - " }\n" - // tests in flow control: + " if (" + getCompare(op, caseDef.format, "idhashFmt", "iFmt") + ") {\n" + " " + fmt + " subsetResult = " + getOpTypeName(op, st) + "(data[gl_SubgroupInvocationID]);\n" + " tempResult |= " + getCompare(op, caseDef.format, "partitionedResult", "subsetResult") + " ? (0x4 << N) : 0;\n" + " }\n" + " }\n" + " }\n" + // tests in flow control: " if (1 == (gl_SubgroupInvocationID % 2)) {\n" - " for (uint N = 1; N < 7; ++N) {\n" + " for (uint N = 1; N < 7; ++N) {\n" " " + fmt + " idhashFmt = " + fmt + "(" + idhash + ");\n" " uvec4 partitionBallot = subgroupPartitionNV(idhashFmt) & mask;\n" - " " + fmt + " partitionedResult = " + getOpTypeNamePartitioned(caseDef.opType) + "(data[gl_SubgroupInvocationID], partitionBallot);\n" - " for (uint i = 0; i < N; ++i) {\n" + " " + fmt + " partitionedResult = " + getOpTypeNamePartitioned(op, st) + "(data[gl_SubgroupInvocationID], partitionBallot);\n" + " for (uint i = 0; i < N; ++i) {\n" " " + fmt + " iFmt = " + fmt + "(i);\n" - " if (" + getCompare(caseDef.opType, caseDef.format, "idhashFmt", "iFmt") + ") {\n" - " " + fmt + " subsetResult = " + getOpTypeName(caseDef.opType) + "(data[gl_SubgroupInvocationID]);\n" - " tempResult |= " + getCompare(caseDef.opType, caseDef.format, "partitionedResult", "subsetResult") + " ? (0x20000 << N) : 0;\n" - " }\n" - " }\n" - " }\n" - " } else {\n" - " tempResult |= 0xFC0000;\n" - " }\n" - ; - - return bdy; + " if (" + getCompare(op, caseDef.format, "idhashFmt", "iFmt") + ") {\n" + " " + fmt + " subsetResult = " + getOpTypeName(op, st) + "(data[gl_SubgroupInvocationID]);\n" + " tempResult |= " + getCompare(op, caseDef.format, "partitionedResult", "subsetResult") + " ? (0x20000 << N) : 0;\n" + " }\n" + " }\n" + " }\n" + " } else {\n" + " tempResult |= 0xFC0000;\n" + " }\n" + ; + + return bdy; } -void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefinition caseDef) +void initFrameBufferPrograms(SourceCollections& programCollection, CaseDefinition caseDef) { const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); std::ostringstream bdy; + std::string extHeader = getExtHeader(caseDef); + subgroups::setFragmentShaderFrameBuffer(programCollection); if (VK_SHADER_STAGE_VERTEX_BIT != caseDef.shaderStage) @@ -568,10 +285,7 @@ void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefiniti { std::ostringstream vertexSrc; vertexSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n" - << "#extension GL_NV_shader_subgroup_partitioned: enable\n" - << "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" - << "#extension GL_KHR_shader_subgroup_ballot: enable\n" - << subgroups::getAdditionalExtensionForFormat(caseDef.format) + << extHeader.c_str() << "layout(location = 0) in highp vec4 in_position;\n" << "layout(location = 0) out float out_color;\n" << "layout(set = 0, binding = 0) uniform Buffer1\n" @@ -595,10 +309,7 @@ void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefiniti std::ostringstream geometry; geometry << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n" - << "#extension GL_NV_shader_subgroup_partitioned: enable\n" - << "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" - << "#extension GL_KHR_shader_subgroup_ballot: enable\n" - << subgroups::getAdditionalExtensionForFormat(caseDef.format) + << extHeader.c_str() << "layout(points) in;\n" << "layout(points, max_vertices = 1) out;\n" << "layout(location = 0) out float out_color;\n" @@ -625,10 +336,7 @@ void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefiniti { std::ostringstream controlSource; controlSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n" - << "#extension GL_NV_shader_subgroup_partitioned: enable\n" - << "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" - << "#extension GL_KHR_shader_subgroup_ballot: enable\n" - << subgroups::getAdditionalExtensionForFormat(caseDef.format) + << extHeader.c_str() << "layout(vertices = 2) out;\n" << "layout(location = 0) out float out_color[];\n" << "layout(set = 0, binding = 0) uniform Buffer1\n" @@ -659,10 +367,7 @@ void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefiniti std::ostringstream evaluationSource; evaluationSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n" - << "#extension GL_NV_shader_subgroup_partitioned: enable\n" - << "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" - << "#extension GL_KHR_shader_subgroup_ballot: enable\n" - << subgroups::getAdditionalExtensionForFormat(caseDef.format) + << extHeader.c_str() << "layout(isolines, equal_spacing, ccw ) in;\n" << "layout(location = 0) out float out_color;\n" << "layout(set = 0, binding = 0) uniform Buffer1\n" @@ -689,17 +394,15 @@ void initFrameBufferPrograms (SourceCollections& programCollection, CaseDefiniti void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef) { - const string bdy = getTestString(caseDef); + const string extHeader = getExtHeader(caseDef); + const string bdy = getTestString(caseDef); if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage) { std::ostringstream src; src << "#version 450\n" - << "#extension GL_NV_shader_subgroup_partitioned: enable\n" - << "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" - << "#extension GL_KHR_shader_subgroup_ballot: enable\n" - << subgroups::getAdditionalExtensionForFormat(caseDef.format) + << extHeader.c_str() << "layout (local_size_x_id = 0, local_size_y_id = 1, " "local_size_z_id = 2) in;\n" << "layout(set = 0, binding = 0, std430) buffer Buffer1\n" @@ -730,10 +433,7 @@ void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef) { const std::string vertex = "#version 450\n" - "#extension GL_NV_shader_subgroup_partitioned: enable\n" - "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" - "#extension GL_KHR_shader_subgroup_ballot: enable\n" - + subgroups::getAdditionalExtensionForFormat(caseDef.format) + + + extHeader + "layout(set = 0, binding = 0, std430) buffer Buffer1\n" "{\n" " uint result[];\n" @@ -760,10 +460,7 @@ void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef) { const std::string tesc = "#version 450\n" - "#extension GL_NV_shader_subgroup_partitioned: enable\n" - "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" - "#extension GL_KHR_shader_subgroup_ballot: enable\n" - + subgroups::getAdditionalExtensionForFormat(caseDef.format) + + + extHeader + "layout(vertices=1) out;\n" "layout(set = 0, binding = 1, std430) buffer Buffer1\n" "{\n" @@ -793,10 +490,7 @@ void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef) { const std::string tese = "#version 450\n" - "#extension GL_NV_shader_subgroup_partitioned: enable\n" - "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" - "#extension GL_KHR_shader_subgroup_ballot: enable\n" - + subgroups::getAdditionalExtensionForFormat(caseDef.format) + + + extHeader + "layout(isolines) in;\n" "layout(set = 0, binding = 2, std430) buffer Buffer1\n" "{\n" @@ -822,10 +516,7 @@ void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef) { const std::string geometry = "#version 450\n" - "#extension GL_NV_shader_subgroup_partitioned: enable\n" - "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" - "#extension GL_KHR_shader_subgroup_ballot: enable\n" - + subgroups::getAdditionalExtensionForFormat(caseDef.format) + + + extHeader + "layout(${TOPOLOGY}) in;\n" "layout(points, max_vertices = 1) out;\n" "layout(set = 0, binding = 3, std430) buffer Buffer1\n" @@ -853,10 +544,7 @@ void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef) { const std::string fragment = "#version 450\n" - "#extension GL_NV_shader_subgroup_partitioned: enable\n" - "#extension GL_KHR_shader_subgroup_arithmetic: enable\n" - "#extension GL_KHR_shader_subgroup_ballot: enable\n" - + subgroups::getAdditionalExtensionForFormat(caseDef.format) + + + extHeader + "layout(location = 0) out uint result;\n" "layout(set = 0, binding = 4, std430) readonly buffer Buffer2\n" "{\n" @@ -881,9 +569,7 @@ void supportedCheck (Context& context, CaseDefinition caseDef) TCU_THROW(NotSupportedError, "Subgroup operations are not supported"); if (!subgroups::isSubgroupFeatureSupportedForDevice(context, VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV)) - { TCU_THROW(NotSupportedError, "Device does not support subgroup partitioned operations"); - } if (!subgroups::isFormatSupportedForDevice(context, caseDef.format)) TCU_THROW(NotSupportedError, "Device does not support the specified format in subgroup operations"); @@ -914,11 +600,9 @@ void supportedCheck (Context& context, CaseDefinition caseDef) tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef) { - if (!subgroups::areSubgroupOperationsSupportedForStage( - context, caseDef.shaderStage)) + if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage)) { - if (subgroups::areSubgroupOperationsRequiredForStage( - caseDef.shaderStage)) + if (subgroups::areSubgroupOperationsRequiredForStage(caseDef.shaderStage)) { return tcu::TestStatus::fail( "Shader stage " + @@ -944,39 +628,22 @@ tcu::TestStatus noSSBOtest (Context& context, const CaseDefinition caseDef) else if (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT == caseDef.shaderStage) return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); else if (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == caseDef.shaderStage) - return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); + return subgroups::makeTessellationEvaluationFrameBufferTest(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); else TCU_THROW(InternalError, "Unhandled shader stage"); } -bool checkShaderStages (Context& context, const CaseDefinition& caseDef) -{ - if (!subgroups::areSubgroupOperationsSupportedForStage( - context, caseDef.shaderStage)) - { - if (subgroups::areSubgroupOperationsRequiredForStage( - caseDef.shaderStage)) - { - return false; - } - else - { - TCU_THROW(NotSupportedError, "Device does not support subgroup operations for this stage"); - } - } - return true; -} tcu::TestStatus test(Context& context, const CaseDefinition caseDef) { if (VK_SHADER_STAGE_COMPUTE_BIT == caseDef.shaderStage) { - if(!checkShaderStages(context,caseDef)) + if (!subgroups::areSubgroupOperationsSupportedForStage(context, caseDef.shaderStage)) { return tcu::TestStatus::fail( - "Shader stage " + - subgroups::getShaderStageName(caseDef.shaderStage) + - " is required to support subgroup operations!"); + "Shader stage " + + subgroups::getShaderStageName(caseDef.shaderStage) + + " is required to support subgroup operations!"); } subgroups::SSBOData inputData; inputData.format = caseDef.format; @@ -1028,7 +695,7 @@ tcu::TestStatus test(Context& context, const CaseDefinition caseDef) VkShaderStageFlagBits stages = (VkShaderStageFlagBits)(caseDef.shaderStage & subgroupProperties.supportedStages); - if ( VK_SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context)) + if (VK_SHADER_STAGE_FRAGMENT_BIT != stages && !subgroups::isVertexSSBOSupportedForDevice(context)) { if ( (stages & VK_SHADER_STAGE_FRAGMENT_BIT) == 0) TCU_THROW(NotSupportedError, "Device does not support vertex stage SSBO writes"); @@ -1047,8 +714,7 @@ tcu::TestStatus test(Context& context, const CaseDefinition caseDef) inputData.binding = 4u; inputData.stages = stages; - return subgroups::allStages(context, VK_FORMAT_R32_UINT, &inputData, - 1, DE_NULL, checkVertexPipelineStages, stages); + return subgroups::allStages(context, VK_FORMAT_R32_UINT, &inputData, 1, DE_NULL, checkVertexPipelineStages, stages); } } } @@ -1082,92 +748,44 @@ tcu::TestCaseGroup* createSubgroupsPartitionedTests(tcu::TestContext& testCtx) for (int opTypeIndex = 0; opTypeIndex < OPTYPE_LAST; ++opTypeIndex) { - bool isBool = false; - bool isFloat = false; - - switch (format) - { - default: - break; - case VK_FORMAT_R16_SFLOAT: - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R64_SFLOAT: - case VK_FORMAT_R64G64_SFLOAT: - case VK_FORMAT_R64G64B64_SFLOAT: - case VK_FORMAT_R64G64B64A64_SFLOAT: - isFloat = true; - break; - case VK_FORMAT_R8_USCALED: - case VK_FORMAT_R8G8_USCALED: - case VK_FORMAT_R8G8B8_USCALED: - case VK_FORMAT_R8G8B8A8_USCALED: - isBool = true; - break; - } + bool isBool = subgroups::isFormatBool(format); + bool isFloat = subgroups::isFormatFloat(format); - bool isBitwiseOp = false; + OpType opType = static_cast(opTypeIndex); + Operator op = getOperator(opType); + ScanType st = getScanType(opType); - switch (opTypeIndex) - { - default: - break; - case OPTYPE_AND: - case OPTYPE_INCLUSIVE_AND: - case OPTYPE_EXCLUSIVE_AND: - case OPTYPE_OR: - case OPTYPE_INCLUSIVE_OR: - case OPTYPE_EXCLUSIVE_OR: - case OPTYPE_XOR: - case OPTYPE_INCLUSIVE_XOR: - case OPTYPE_EXCLUSIVE_XOR: - isBitwiseOp = true; - break; - } + bool isBitwiseOp = (op == OPERATOR_AND || op == OPERATOR_OR || op == OPERATOR_XOR); + // Skip float with bitwise category. if (isFloat && isBitwiseOp) - { - // Skip float with bitwise category. continue; - } + // Skip bool when its not the bitwise category. if (isBool && !isBitwiseOp) - { - // Skip bool when its not the bitwise category. continue; - } - std::string op = getOpTypeName(opTypeIndex); + + const std::string name = de::toLower(getOpTypeName(op, st)) + "_" + subgroups::getFormatNameForGLSL(format); { - CaseDefinition caseDef = {opTypeIndex, VK_SHADER_STAGE_COMPUTE_BIT, format, de::SharedPtr(new bool), DE_FALSE}; - addFunctionCaseWithPrograms(computeGroup.get(), - de::toLower(op) + "_" + - subgroups::getFormatNameForGLSL(format), + CaseDefinition caseDef = {op, st, VK_SHADER_STAGE_COMPUTE_BIT, format, de::SharedPtr(new bool), DE_FALSE}; + addFunctionCaseWithPrograms(computeGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef); caseDef.requiredSubgroupSize = DE_TRUE; - addFunctionCaseWithPrograms(computeGroup.get(), - de::toLower(op) + "_" + - subgroups::getFormatNameForGLSL(format) + "_requiredsubgroupsize", + addFunctionCaseWithPrograms(computeGroup.get(), name + "_requiredsubgroupsize", "", supportedCheck, initPrograms, test, caseDef); } { - const CaseDefinition caseDef = {opTypeIndex, VK_SHADER_STAGE_ALL_GRAPHICS, format, de::SharedPtr(new bool), DE_FALSE}; - addFunctionCaseWithPrograms(graphicGroup.get(), - de::toLower(op) + "_" + - subgroups::getFormatNameForGLSL(format), + const CaseDefinition caseDef = {op, st, VK_SHADER_STAGE_ALL_GRAPHICS, format, de::SharedPtr(new bool), DE_FALSE}; + addFunctionCaseWithPrograms(graphicGroup.get(), name, "", supportedCheck, initPrograms, test, caseDef); } for (int stageIndex = 0; stageIndex < DE_LENGTH_OF_ARRAY(stages); ++stageIndex) { - const CaseDefinition caseDef = {opTypeIndex, stages[stageIndex], format, de::SharedPtr(new bool), DE_FALSE}; - addFunctionCaseWithPrograms(framebufferGroup.get(), de::toLower(op) + "_" + subgroups::getFormatNameForGLSL(format) + + const CaseDefinition caseDef = {op, st, stages[stageIndex], format, de::SharedPtr(new bool), DE_FALSE}; + addFunctionCaseWithPrograms(framebufferGroup.get(), name + "_" + getShaderStageName(caseDef.shaderStage), "", supportedCheck, initFrameBufferPrograms, noSSBOtest, caseDef); } @@ -1183,6 +801,5 @@ tcu::TestCaseGroup* createSubgroupsPartitionedTests(tcu::TestContext& testCtx) return group.release(); } - } // subgroups } // vkt diff --git a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsScanHelpers.cpp b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsScanHelpers.cpp new file mode 100644 index 0000000..8e3ead2 --- /dev/null +++ b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsScanHelpers.cpp @@ -0,0 +1,325 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2019 The Khronos Group Inc. + * Copyright (c) 2019 Google Inc. + * Copyright (c) 2017 Codeplay Software Ltd. + * + * 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 Subgroups Tests + */ /*--------------------------------------------------------------------*/ + +#include "vktSubgroupsScanHelpers.hpp" +#include "vktSubgroupsTestsUtils.hpp" + +#include +#include + +using namespace tcu; +using namespace std; +using namespace vk; +using namespace vkt; + +string getScanOpName(string prefix, string suffix, Operator op, ScanType scanType) +{ + string n; + switch (scanType) + { + case SCAN_REDUCE: n = ""; break; + case SCAN_INCLUSIVE: n = "Inclusive"; break; + case SCAN_EXCLUSIVE: n = "Exclusive"; break; + } + switch (op) + { + case OPERATOR_ADD: n += "Add"; break; + case OPERATOR_MUL: n += "Mul"; break; + case OPERATOR_MIN: n += "Min"; break; + case OPERATOR_MAX: n += "Max"; break; + case OPERATOR_AND: n += "And"; break; + case OPERATOR_OR: n += "Or"; break; + case OPERATOR_XOR: n += "Xor"; break; + } + return prefix + n + suffix; +} + +string getOpOperation(Operator op, VkFormat format, string lhs, string rhs) +{ + switch (op) + { + default: + DE_FATAL("Unsupported op type"); + return ""; + case OPERATOR_ADD: + return lhs + " + " + rhs; + case OPERATOR_MUL: + return lhs + " * " + rhs; + case OPERATOR_MIN: + switch (format) + { + default: + return "min(" + lhs + ", " + rhs + ")"; + case VK_FORMAT_R16_SFLOAT: + case VK_FORMAT_R32_SFLOAT: + case VK_FORMAT_R64_SFLOAT: + return "(isnan(" + lhs + ") ? " + rhs + " : (isnan(" + rhs + ") ? " + lhs + " : min(" + lhs + ", " + rhs + ")))"; + case VK_FORMAT_R16G16_SFLOAT: + case VK_FORMAT_R16G16B16_SFLOAT: + case VK_FORMAT_R16G16B16A16_SFLOAT: + case VK_FORMAT_R32G32_SFLOAT: + case VK_FORMAT_R32G32B32_SFLOAT: + case VK_FORMAT_R32G32B32A32_SFLOAT: + case VK_FORMAT_R64G64_SFLOAT: + case VK_FORMAT_R64G64B64_SFLOAT: + case VK_FORMAT_R64G64B64A64_SFLOAT: + return "mix(mix(min(" + lhs + ", " + rhs + "), " + lhs + ", isnan(" + rhs + ")), " + rhs + ", isnan(" + lhs + "))"; + } + case OPERATOR_MAX: + switch (format) + { + default: + return "max(" + lhs + ", " + rhs + ")"; + case VK_FORMAT_R16_SFLOAT: + case VK_FORMAT_R32_SFLOAT: + case VK_FORMAT_R64_SFLOAT: + return "(isnan(" + lhs + ") ? " + rhs + " : (isnan(" + rhs + ") ? " + lhs + " : max(" + lhs + ", " + rhs + ")))"; + case VK_FORMAT_R16G16_SFLOAT: + case VK_FORMAT_R16G16B16_SFLOAT: + case VK_FORMAT_R16G16B16A16_SFLOAT: + case VK_FORMAT_R32G32_SFLOAT: + case VK_FORMAT_R32G32B32_SFLOAT: + case VK_FORMAT_R32G32B32A32_SFLOAT: + case VK_FORMAT_R64G64_SFLOAT: + case VK_FORMAT_R64G64B64_SFLOAT: + case VK_FORMAT_R64G64B64A64_SFLOAT: + return "mix(mix(max(" + lhs + ", " + rhs + "), " + lhs + ", isnan(" + rhs + ")), " + rhs + ", isnan(" + lhs + "))"; + } + case OPERATOR_AND: + switch (format) + { + default: + return lhs + " & " + rhs; + case VK_FORMAT_R8_USCALED: + return lhs + " && " + rhs; + case VK_FORMAT_R8G8_USCALED: + return "bvec2(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y)"; + case VK_FORMAT_R8G8B8_USCALED: + return "bvec3(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y, " + lhs + ".z && " + rhs + ".z)"; + case VK_FORMAT_R8G8B8A8_USCALED: + return "bvec4(" + lhs + ".x && " + rhs + ".x, " + lhs + ".y && " + rhs + ".y, " + lhs + ".z && " + rhs + ".z, " + lhs + ".w && " + rhs + ".w)"; + } + case OPERATOR_OR: + switch (format) + { + default: + return lhs + " | " + rhs; + case VK_FORMAT_R8_USCALED: + return lhs + " || " + rhs; + case VK_FORMAT_R8G8_USCALED: + return "bvec2(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y)"; + case VK_FORMAT_R8G8B8_USCALED: + return "bvec3(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y, " + lhs + ".z || " + rhs + ".z)"; + case VK_FORMAT_R8G8B8A8_USCALED: + return "bvec4(" + lhs + ".x || " + rhs + ".x, " + lhs + ".y || " + rhs + ".y, " + lhs + ".z || " + rhs + ".z, " + lhs + ".w || " + rhs + ".w)"; + } + case OPERATOR_XOR: + switch (format) + { + default: + return lhs + " ^ " + rhs; + case VK_FORMAT_R8_USCALED: + return lhs + " ^^ " + rhs; + case VK_FORMAT_R8G8_USCALED: + return "bvec2(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y)"; + case VK_FORMAT_R8G8B8_USCALED: + return "bvec3(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y, " + lhs + ".z ^^ " + rhs + ".z)"; + case VK_FORMAT_R8G8B8A8_USCALED: + return "bvec4(" + lhs + ".x ^^ " + rhs + ".x, " + lhs + ".y ^^ " + rhs + ".y, " + lhs + ".z ^^ " + rhs + ".z, " + lhs + ".w ^^ " + rhs + ".w)"; + } + } +} + +string getIdentity(Operator op, VkFormat format) +{ + const bool isFloat = subgroups::isFormatFloat(format); + const bool isInt = subgroups::isFormatSigned(format); + const bool isUnsigned = subgroups::isFormatUnsigned(format); + + switch (op) + { + default: + DE_FATAL("Unsupported op type"); + return ""; + case OPERATOR_ADD: + return subgroups::getFormatNameForGLSL(format) + "(0)"; + case OPERATOR_MUL: + return subgroups::getFormatNameForGLSL(format) + "(1)"; + case OPERATOR_MIN: + if (isFloat) + { + return subgroups::getFormatNameForGLSL(format) + "(intBitsToFloat(0x7f800000))"; + } + else if (isInt) + { + switch (format) + { + default: + return subgroups::getFormatNameForGLSL(format) + "(0x7fffffff)"; + case VK_FORMAT_R8_SINT: + case VK_FORMAT_R8G8_SINT: + case VK_FORMAT_R8G8B8_SINT: + case VK_FORMAT_R8G8B8A8_SINT: + case VK_FORMAT_R8_UINT: + case VK_FORMAT_R8G8_UINT: + case VK_FORMAT_R8G8B8_UINT: + case VK_FORMAT_R8G8B8A8_UINT: + return subgroups::getFormatNameForGLSL(format) + "(0x7f)"; + case VK_FORMAT_R16_SINT: + case VK_FORMAT_R16G16_SINT: + case VK_FORMAT_R16G16B16_SINT: + case VK_FORMAT_R16G16B16A16_SINT: + case VK_FORMAT_R16_UINT: + case VK_FORMAT_R16G16_UINT: + case VK_FORMAT_R16G16B16_UINT: + case VK_FORMAT_R16G16B16A16_UINT: + return subgroups::getFormatNameForGLSL(format) + "(0x7fff)"; + case VK_FORMAT_R64_SINT: + case VK_FORMAT_R64G64_SINT: + case VK_FORMAT_R64G64B64_SINT: + case VK_FORMAT_R64G64B64A64_SINT: + case VK_FORMAT_R64_UINT: + case VK_FORMAT_R64G64_UINT: + case VK_FORMAT_R64G64B64_UINT: + case VK_FORMAT_R64G64B64A64_UINT: + return subgroups::getFormatNameForGLSL(format) + "(0x7fffffffffffffffUL)"; + } + } + else if (isUnsigned) + { + return subgroups::getFormatNameForGLSL(format) + "(-1)"; + } + else + { + DE_FATAL("Unhandled case"); + return ""; + } + case OPERATOR_MAX: + if (isFloat) + { + return subgroups::getFormatNameForGLSL(format) + "(intBitsToFloat(0xff800000))"; + } + else if (isInt) + { + switch (format) + { + default: + return subgroups::getFormatNameForGLSL(format) + "(0x80000000)"; + case VK_FORMAT_R8_SINT: + case VK_FORMAT_R8G8_SINT: + case VK_FORMAT_R8G8B8_SINT: + case VK_FORMAT_R8G8B8A8_SINT: + case VK_FORMAT_R8_UINT: + case VK_FORMAT_R8G8_UINT: + case VK_FORMAT_R8G8B8_UINT: + case VK_FORMAT_R8G8B8A8_UINT: + return subgroups::getFormatNameForGLSL(format) + "(0x80)"; + case VK_FORMAT_R16_SINT: + case VK_FORMAT_R16G16_SINT: + case VK_FORMAT_R16G16B16_SINT: + case VK_FORMAT_R16G16B16A16_SINT: + case VK_FORMAT_R16_UINT: + case VK_FORMAT_R16G16_UINT: + case VK_FORMAT_R16G16B16_UINT: + case VK_FORMAT_R16G16B16A16_UINT: + return subgroups::getFormatNameForGLSL(format) + "(0x8000)"; + case VK_FORMAT_R64_SINT: + case VK_FORMAT_R64G64_SINT: + case VK_FORMAT_R64G64B64_SINT: + case VK_FORMAT_R64G64B64A64_SINT: + case VK_FORMAT_R64_UINT: + case VK_FORMAT_R64G64_UINT: + case VK_FORMAT_R64G64B64_UINT: + case VK_FORMAT_R64G64B64A64_UINT: + return subgroups::getFormatNameForGLSL(format) + "(0x8000000000000000UL)"; + } + } + else if (isUnsigned) + { + return subgroups::getFormatNameForGLSL(format) + "(0)"; + } + else + { + DE_FATAL("Unhandled case"); + return ""; + } + case OPERATOR_AND: + return subgroups::getFormatNameForGLSL(format) + "(~0)"; + case OPERATOR_OR: + return subgroups::getFormatNameForGLSL(format) + "(0)"; + case OPERATOR_XOR: + return subgroups::getFormatNameForGLSL(format) + "(0)"; + } +} + +string getCompare(Operator op, VkFormat format, string lhs, string rhs) +{ + string formatName = subgroups::getFormatNameForGLSL(format); + bool isMinMax = (op == OPERATOR_MIN || op == OPERATOR_MAX); + + switch (format) + { + default: + return "all(equal(" + lhs + ", " + rhs + "))"; + case VK_FORMAT_R8_USCALED: + case VK_FORMAT_R8_UINT: + case VK_FORMAT_R8_SINT: + case VK_FORMAT_R16_UINT: + case VK_FORMAT_R16_SINT: + case VK_FORMAT_R32_UINT: + case VK_FORMAT_R32_SINT: + case VK_FORMAT_R64_UINT: + case VK_FORMAT_R64_SINT: + return "(" + lhs + " == " + rhs + ")"; + case VK_FORMAT_R16_SFLOAT: + if (isMinMax) + return "(" + lhs + " == " + rhs + ")"; + else + return "(abs(" + lhs + " - " + rhs + ") < " + formatName + "(0.1))"; + case VK_FORMAT_R32_SFLOAT: + case VK_FORMAT_R64_SFLOAT: + if (isMinMax) + return "(" + lhs + " == " + rhs + ")"; + else + return "(abs(" + lhs + " - " + rhs + ") < 0.00001)"; + case VK_FORMAT_R16G16_SFLOAT: + case VK_FORMAT_R16G16B16_SFLOAT: + case VK_FORMAT_R16G16B16A16_SFLOAT: + if (isMinMax) + return "all(equal(" + lhs + ", " + rhs + "))"; + else + return "all(lessThan(abs(" + lhs + " - " + rhs + "), " + formatName + "(0.1)))"; + case VK_FORMAT_R32G32_SFLOAT: + case VK_FORMAT_R32G32B32_SFLOAT: + case VK_FORMAT_R32G32B32A32_SFLOAT: + case VK_FORMAT_R64G64_SFLOAT: + case VK_FORMAT_R64G64B64_SFLOAT: + case VK_FORMAT_R64G64B64A64_SFLOAT: + if (isMinMax) + return "all(equal(" + lhs + ", " + rhs + "))"; + else + return "all(lessThan(abs(" + lhs + " - " + rhs + "), " + formatName + "(0.00001)))"; + } +} diff --git a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsScanHelpers.hpp b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsScanHelpers.hpp new file mode 100644 index 0000000..e446852 --- /dev/null +++ b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsScanHelpers.hpp @@ -0,0 +1,56 @@ +#ifndef _VKTSUBGROUPSSCANHELPERS_HPP +#define _VKTSUBGROUPSSCANHELPERS_HPP + +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2019 The Khronos Group Inc. + * Copyright (c) 2019 Google Inc. + * Copyright (c) 2017 Codeplay Software Ltd. + * + * 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 Subgroups Tests + */ /*--------------------------------------------------------------------*/ + +#include "vktSubgroupsTestsUtils.hpp" + +#include + +enum Operator +{ + OPERATOR_ADD, + OPERATOR_MUL, + OPERATOR_MIN, + OPERATOR_MAX, + OPERATOR_AND, + OPERATOR_OR, + OPERATOR_XOR, +}; + +enum ScanType +{ + SCAN_REDUCE, + SCAN_INCLUSIVE, + SCAN_EXCLUSIVE +}; + +std::string getScanOpName(std::string prefix, std::string suffix, Operator op, ScanType scanType); +std::string getOpOperation(Operator op, vk::VkFormat format, std::string lhs, std::string rhs); +std::string getIdentity(Operator op, vk::VkFormat format); +std::string getCompare(Operator op, vk::VkFormat format, std::string lhs, std::string rhs); + +#endif // _VKTSUBGROUPSSCANHELPERS_HPP diff --git a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsTestsUtils.cpp b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsTestsUtils.cpp index 88820f0..ff12585 100644 --- a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsTestsUtils.cpp +++ b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsTestsUtils.cpp @@ -1961,6 +1961,20 @@ bool vkt::subgroups::isFormatFloat (VkFormat format) } } +bool vkt::subgroups::isFormatBool (VkFormat format) +{ + switch (format) + { + default: + return false; + case VK_FORMAT_R8_USCALED: + case VK_FORMAT_R8G8_USCALED: + case VK_FORMAT_R8G8B8_USCALED: + case VK_FORMAT_R8G8B8A8_USCALED: + return true; + } +} + void vkt::subgroups::setVertexShaderFrameBuffer (SourceCollections& programCollection) { /* diff --git a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsTestsUtils.hpp b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsTestsUtils.hpp index c9b2f45..e7cfa69 100644 --- a/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsTestsUtils.hpp +++ b/external/vulkancts/modules/vulkan/subgroups/vktSubgroupsTestsUtils.hpp @@ -151,6 +151,7 @@ const std::vector getAllFormats (); bool isFormatSigned (vk::VkFormat format); bool isFormatUnsigned (vk::VkFormat format); bool isFormatFloat (vk::VkFormat format); +bool isFormatBool (vk::VkFormat format); void addGeometryShadersFromTemplate (const std::string& glslTemplate, const vk::ShaderBuildOptions& options, vk::GlslSourceCollection& collection); void addGeometryShadersFromTemplate (const std::string& spirvTemplate, const vk::SpirVAsmBuildOptions& options, vk::SpirVAsmCollection& collection); -- 2.7.4