From c66c37cfa10100860fc470d83639f11ac5b1a403 Mon Sep 17 00:00:00 2001 From: Ehsan Date: Fri, 23 Mar 2018 10:40:02 -0400 Subject: [PATCH] [spirv] Add support for DeviceIndex builtin. (#1171) --- docs/SPIR-V.rst | 2 ++ tools/clang/lib/SPIRV/DeclResultIdMapper.cpp | 17 +++++++++++++++++ tools/clang/lib/Sema/SemaHLSL.cpp | 2 +- .../spirv.builtin.device-index.hlsl | 15 +++++++++++++++ .../spirv.builtin.device-index.invalid.hlsl | 9 +++++++++ .../clang/unittests/SPIRV/CodeGenSPIRVTest.cpp | 6 ++++++ 6 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 tools/clang/test/CodeGenSPIRV/spirv.builtin.device-index.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/spirv.builtin.device-index.invalid.hlsl diff --git a/docs/SPIR-V.rst b/docs/SPIR-V.rst index 58e4fe1d1..1b0a12a4c 100644 --- a/docs/SPIR-V.rst +++ b/docs/SPIR-V.rst @@ -241,6 +241,8 @@ Right now the following ```` are supported: Need ``SPV_KHR_shader_draw_parameters`` extension. * ``DrawIndex``: The GLSL equivalent is ``gl_DrawIDARB``. Need ``SPV_KHR_shader_draw_parameters`` extension. +* ``DeviceIndex``: The GLSL equivalent is ``gl_DeviceIndex``. + Need ``SPV_KHR_device_group`` extension. Please see Vulkan spec. `14.6. Built-In Variables `_ for detailed explanation of these builtins. diff --git a/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp b/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp index d04339a03..689740a43 100644 --- a/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp +++ b/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp @@ -1829,6 +1829,7 @@ uint32_t DeclResultIdMapper::createSpirvStageVar(StageVar *stageVar, .Case("BaseVertex", BuiltIn::BaseVertex) .Case("BaseInstance", BuiltIn::BaseInstance) .Case("DrawIndex", BuiltIn::DrawIndex) + .Case("DeviceIndex", BuiltIn::DeviceIndex) .Default(BuiltIn::Max); assert(spvBuiltIn != BuiltIn::Max); // The frontend should guarantee this. @@ -1840,6 +1841,10 @@ uint32_t DeclResultIdMapper::createSpirvStageVar(StageVar *stageVar, theBuilder.addExtension("SPV_KHR_shader_draw_parameters"); theBuilder.requireCapability(spv::Capability::DrawParameters); break; + case BuiltIn::DeviceIndex: + theBuilder.addExtension("SPV_KHR_device_group"); + theBuilder.requireCapability(spv::Capability::DeviceGroup); + break; } return theBuilder.addStageBuiltinVar(type, sc, spvBuiltIn); @@ -2242,6 +2247,18 @@ bool DeclResultIdMapper::validateVKBuiltins(const NamedDecl *decl, << builtin; success = false; } + } else if (builtin == "DeviceIndex") { + if (getStorageClassForSigPoint(sigPoint) != spv::StorageClass::Input) { + emitError("%0 builtin can only be used as shader input", loc) + << builtin; + success = false; + } + if (!declType->isSpecificBuiltinType(BuiltinType::Kind::Int) && + !declType->isSpecificBuiltinType(BuiltinType::Kind::UInt)) { + emitError("%0 builtin must be of 32-bit scalar integer type", loc) + << builtin; + success = false; + } } } diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index feb64f80a..6c61555cf 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -10472,7 +10472,7 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A, { case AttributeList::AT_VKBuiltIn: declAttr = ::new (S.Context) VKBuiltInAttr(A.getRange(), S.Context, - ValidateAttributeStringArg(S, A, "PointSize,HelperInvocation,BaseVertex,BaseInstance,DrawIndex"), + ValidateAttributeStringArg(S, A, "PointSize,HelperInvocation,BaseVertex,BaseInstance,DrawIndex,DeviceIndex"), A.getAttributeSpellingListIndex()); break; case AttributeList::AT_VKLocation: diff --git a/tools/clang/test/CodeGenSPIRV/spirv.builtin.device-index.hlsl b/tools/clang/test/CodeGenSPIRV/spirv.builtin.device-index.hlsl new file mode 100644 index 000000000..ebd2e8ee9 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/spirv.builtin.device-index.hlsl @@ -0,0 +1,15 @@ +// Run: %dxc -T vs_6_0 -E main + +// CHECK: OpCapability DeviceGroup + +// CHECK: OpExtension "SPV_KHR_device_group" + + +// CHECK: OpDecorate [[a:%\d+]] BuiltIn DeviceIndex + +float main( + // CHECK: [[a]] = OpVariable %_ptr_Input_int Input + [[vk::builtin("DeviceIndex")]] int deviceIndex : A +) : OUTPUT{ + return 1.0; +} diff --git a/tools/clang/test/CodeGenSPIRV/spirv.builtin.device-index.invalid.hlsl b/tools/clang/test/CodeGenSPIRV/spirv.builtin.device-index.invalid.hlsl new file mode 100644 index 000000000..77357addd --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/spirv.builtin.device-index.invalid.hlsl @@ -0,0 +1,9 @@ +// Run: %dxc -T ps_6_0 -E main + +[[vk::builtin("DeviceIndex")]] +float4 main(float a : A) : SV_Target { + return a.xxxx; +} + +// CHECK: :3:3: error: DeviceIndex builtin can only be used as shader input +// CHECK: :3:3: error: DeviceIndex builtin must be of 32-bit scalar integer type diff --git a/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp b/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp index efe4a2cce..ff5b56418 100644 --- a/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp +++ b/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp @@ -1142,6 +1142,12 @@ TEST_F(FileTest, SpirvBuiltInShaderDrawParametersInvalidUsage) { runFileTest("spirv.builtin.shader-draw-parameters.invalid.hlsl", Expect::Failure); } +TEST_F(FileTest, SpirvBuiltInDeviceIndex) { + runFileTest("spirv.builtin.device-index.hlsl"); +} +TEST_F(FileTest, SpirvBuiltInDeviceIndexInvalidUsage) { + runFileTest("spirv.builtin.device-index.invalid.hlsl", Expect::Failure); +} // For shader stage input/output interface // For semantic SV_Position, SV_ClipDistance, SV_CullDistance