[spirv] Add support for SV_Barycentrics (#837)
The translation is done using SPIR-V Extension SPV_AMD_shader_explicit_vertex_parameter.
This commit is contained in:
Родитель
d1f1665865
Коммит
9745b0d55c
|
@ -854,6 +854,8 @@ some system-value (SV) semantic strings will be translated into SPIR-V
|
||||||
+---------------------------+-------------+--------------------------+-----------------------+-----------------------+
|
+---------------------------+-------------+--------------------------+-----------------------+-----------------------+
|
||||||
| SV_StencilRef | PSOut | ``FragStencilRefEXT`` | N/A | ``StencilExportEXT`` |
|
| SV_StencilRef | PSOut | ``FragStencilRefEXT`` | N/A | ``StencilExportEXT`` |
|
||||||
+---------------------------+-------------+--------------------------+-----------------------+-----------------------+
|
+---------------------------+-------------+--------------------------+-----------------------+-----------------------+
|
||||||
|
| SV_Barycentrics | PSIn | ``BaryCoord*AMD`` | N/A | ``Shader`` |
|
||||||
|
+---------------------------+-------------+--------------------------+-----------------------+-----------------------+
|
||||||
| | GSOut | ``Layer`` | N/A | ``Geometry`` |
|
| | GSOut | ``Layer`` | N/A | ``Geometry`` |
|
||||||
| SV_RenderTargetArrayIndex +-------------+--------------------------+-----------------------+-----------------------+
|
| SV_RenderTargetArrayIndex +-------------+--------------------------+-----------------------+-----------------------+
|
||||||
| | PSIn | ``Layer`` | N/A | ``Geometry`` |
|
| | PSIn | ``Layer`` | N/A | ``Geometry`` |
|
||||||
|
|
|
@ -944,6 +944,9 @@ bool DeclResultIdMapper::createStageVars(
|
||||||
case hlsl::Semantic::Kind::Coverage:
|
case hlsl::Semantic::Kind::Coverage:
|
||||||
typeId = theBuilder.getArrayType(typeId, theBuilder.getConstantUint32(1));
|
typeId = theBuilder.getArrayType(typeId, theBuilder.getConstantUint32(1));
|
||||||
break;
|
break;
|
||||||
|
case hlsl::Semantic::Kind::Barycentrics:
|
||||||
|
typeId = theBuilder.getVecType(theBuilder.getFloat32Type(), 2);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the extra arrayness
|
// Handle the extra arrayness
|
||||||
|
@ -959,7 +962,7 @@ bool DeclResultIdMapper::createStageVars(
|
||||||
const std::string semanticStr = stageVar.getSemanticStr();
|
const std::string semanticStr = stageVar.getSemanticStr();
|
||||||
llvm::Twine name = namePrefix + "." + semanticStr;
|
llvm::Twine name = namePrefix + "." + semanticStr;
|
||||||
const uint32_t varId =
|
const uint32_t varId =
|
||||||
createSpirvStageVar(&stageVar, name, semanticToUse->loc);
|
createSpirvStageVar(&stageVar, decl, name, semanticToUse->loc);
|
||||||
|
|
||||||
if (varId == 0)
|
if (varId == 0)
|
||||||
return false;
|
return false;
|
||||||
|
@ -978,7 +981,9 @@ bool DeclResultIdMapper::createStageVars(
|
||||||
theBuilder.decorate(varId, spv::Decoration::Patch);
|
theBuilder.decorate(varId, spv::Decoration::Patch);
|
||||||
|
|
||||||
// Decorate with interpolation modes for pixel shader input variables
|
// Decorate with interpolation modes for pixel shader input variables
|
||||||
if (shaderModel.IsPS() && sigPoint->IsInput())
|
if (shaderModel.IsPS() && sigPoint->IsInput() &&
|
||||||
|
// BaryCoord*AMD buitins already encode the interpolation mode.
|
||||||
|
semanticKind != hlsl::Semantic::Kind::Barycentrics)
|
||||||
decoratePSInterpolationMode(decl, type, varId);
|
decoratePSInterpolationMode(decl, type, varId);
|
||||||
|
|
||||||
if (asInput) {
|
if (asInput) {
|
||||||
|
@ -1028,6 +1033,21 @@ bool DeclResultIdMapper::createStageVars(
|
||||||
else if (semanticKind == hlsl::Semantic::Kind::Coverage) {
|
else if (semanticKind == hlsl::Semantic::Kind::Coverage) {
|
||||||
*value = theBuilder.createCompositeExtract(srcTypeId, *value, {0});
|
*value = theBuilder.createCompositeExtract(srcTypeId, *value, {0});
|
||||||
}
|
}
|
||||||
|
// Special handling of SV_Barycentrics, which is a float3, but the
|
||||||
|
// underlying stage input variable is a float2 (only provides the first
|
||||||
|
// two components). Calculate the third element.
|
||||||
|
else if (semanticKind == hlsl::Semantic::Kind::Barycentrics) {
|
||||||
|
const auto f32Type = theBuilder.getFloat32Type();
|
||||||
|
const auto x = theBuilder.createCompositeExtract(f32Type, *value, {0});
|
||||||
|
const auto y = theBuilder.createCompositeExtract(f32Type, *value, {1});
|
||||||
|
const auto xy =
|
||||||
|
theBuilder.createBinaryOp(spv::Op::OpFAdd, f32Type, x, y);
|
||||||
|
const auto z = theBuilder.createBinaryOp(
|
||||||
|
spv::Op::OpFSub, f32Type, theBuilder.getConstantFloat32(1), xy);
|
||||||
|
const auto v3f32Type = theBuilder.getVecType(f32Type, 3);
|
||||||
|
|
||||||
|
*value = theBuilder.createCompositeConstruct(v3f32Type, {x, y, z});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (noWriteBack)
|
if (noWriteBack)
|
||||||
return true;
|
return true;
|
||||||
|
@ -1275,6 +1295,7 @@ void DeclResultIdMapper::decoratePSInterpolationMode(const DeclaratorDecl *decl,
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DeclResultIdMapper::createSpirvStageVar(StageVar *stageVar,
|
uint32_t DeclResultIdMapper::createSpirvStageVar(StageVar *stageVar,
|
||||||
|
const DeclaratorDecl *decl,
|
||||||
const llvm::Twine &name,
|
const llvm::Twine &name,
|
||||||
SourceLocation srcLoc) {
|
SourceLocation srcLoc) {
|
||||||
using spv::BuiltIn;
|
using spv::BuiltIn;
|
||||||
|
@ -1505,6 +1526,33 @@ uint32_t DeclResultIdMapper::createSpirvStageVar(StageVar *stageVar,
|
||||||
stageVar->setIsSpirvBuiltin();
|
stageVar->setIsSpirvBuiltin();
|
||||||
return theBuilder.addStageBuiltinVar(type, sc, BuiltIn::FragStencilRefEXT);
|
return theBuilder.addStageBuiltinVar(type, sc, BuiltIn::FragStencilRefEXT);
|
||||||
}
|
}
|
||||||
|
// According to DXIL spec, the ViewID SV can only be used by PSIn.
|
||||||
|
case hlsl::Semantic::Kind::Barycentrics: {
|
||||||
|
theBuilder.addExtension("SPV_AMD_shader_explicit_vertex_parameter");
|
||||||
|
stageVar->setIsSpirvBuiltin();
|
||||||
|
|
||||||
|
// Selecting the correct builtin according to interpolation mode
|
||||||
|
auto bi = BuiltIn::Max;
|
||||||
|
if (decl->hasAttr<HLSLNoPerspectiveAttr>()) {
|
||||||
|
if (decl->hasAttr<HLSLCentroidAttr>()) {
|
||||||
|
bi = BuiltIn::BaryCoordNoPerspCentroidAMD;
|
||||||
|
} else if (decl->hasAttr<HLSLSampleAttr>()) {
|
||||||
|
bi = BuiltIn::BaryCoordNoPerspSampleAMD;
|
||||||
|
} else {
|
||||||
|
bi = BuiltIn::BaryCoordNoPerspAMD;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (decl->hasAttr<HLSLCentroidAttr>()) {
|
||||||
|
bi = BuiltIn::BaryCoordSmoothCentroidAMD;
|
||||||
|
} else if (decl->hasAttr<HLSLSampleAttr>()) {
|
||||||
|
bi = BuiltIn::BaryCoordSmoothSampleAMD;
|
||||||
|
} else {
|
||||||
|
bi = BuiltIn::BaryCoordSmoothAMD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return theBuilder.addStageBuiltinVar(type, sc, bi);
|
||||||
|
}
|
||||||
// According to DXIL spec, the RenderTargetArrayIndex SV can only be used by
|
// According to DXIL spec, the RenderTargetArrayIndex SV can only be used by
|
||||||
// VSIn, VSOut, HSCPIn, HSCPOut, DSIn, DSOut, GSVIn, GSOut, PSIn.
|
// VSIn, VSOut, HSCPIn, HSCPOut, DSIn, DSOut, GSVIn, GSOut, PSIn.
|
||||||
// According to Vulkan spec, the Layer BuiltIn can only be used in GSOut and
|
// According to Vulkan spec, the Layer BuiltIn can only be used in GSOut and
|
||||||
|
|
|
@ -397,8 +397,8 @@ private:
|
||||||
/// the <result-id>. Also sets whether the StageVar is a SPIR-V builtin and
|
/// the <result-id>. Also sets whether the StageVar is a SPIR-V builtin and
|
||||||
/// its storage class accordingly. name will be used as the debug name when
|
/// its storage class accordingly. name will be used as the debug name when
|
||||||
/// creating a stage input/output variable.
|
/// creating a stage input/output variable.
|
||||||
uint32_t createSpirvStageVar(StageVar *, const llvm::Twine &name,
|
uint32_t createSpirvStageVar(StageVar *, const DeclaratorDecl *decl,
|
||||||
SourceLocation);
|
const llvm::Twine &name, SourceLocation);
|
||||||
|
|
||||||
/// Creates the associated counter variable for RW/Append/Consume
|
/// Creates the associated counter variable for RW/Append/Consume
|
||||||
/// structured buffer.
|
/// structured buffer.
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Run: %dxc -T ps_6_1 -E main
|
||||||
|
|
||||||
|
// CHECK: OpExtension "SPV_AMD_shader_explicit_vertex_parameter"
|
||||||
|
|
||||||
|
// CHECK: OpEntryPoint Fragment
|
||||||
|
// CHECK-SAME: [[bary:%\d+]]
|
||||||
|
|
||||||
|
// CHECK: OpDecorate [[bary]] BuiltIn BaryCoordNoPerspCentroidAMD
|
||||||
|
|
||||||
|
// CHECK: [[bary]] = OpVariable %_ptr_Input_v2float Input
|
||||||
|
|
||||||
|
float4 main(noperspective centroid float3 bary : SV_Barycentrics) : SV_Target {
|
||||||
|
return float4(bary, 1.0);
|
||||||
|
// CHECK: %param_var_bary = OpVariable %_ptr_Function_v3float Function
|
||||||
|
// CHECK-NEXT: [[c2:%\d+]] = OpLoad %v2float [[bary]]
|
||||||
|
// CHECK-NEXT: [[x:%\d+]] = OpCompositeExtract %float [[c2]] 0
|
||||||
|
// CHECK-NEXT: [[y:%\d+]] = OpCompositeExtract %float [[c2]] 1
|
||||||
|
// CHECK-NEXT: [[xy:%\d+]] = OpFAdd %float [[x]] [[y]]
|
||||||
|
// CHECK-NEXT: [[z:%\d+]] = OpFSub %float %float_1 [[xy]]
|
||||||
|
// CHECK-NEXT: [[c3:%\d+]] = OpCompositeConstruct %v3float [[x]] [[y]] [[z]]
|
||||||
|
// CHECK-NEXT: OpStore %param_var_bary [[c3]]
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Run: %dxc -T ps_6_1 -E main
|
||||||
|
|
||||||
|
// CHECK: OpExtension "SPV_AMD_shader_explicit_vertex_parameter"
|
||||||
|
|
||||||
|
// CHECK: OpEntryPoint Fragment
|
||||||
|
// CHECK-SAME: [[bary:%\d+]]
|
||||||
|
|
||||||
|
// CHECK: OpDecorate [[bary]] BuiltIn BaryCoordNoPerspSampleAMD
|
||||||
|
|
||||||
|
// CHECK: [[bary]] = OpVariable %_ptr_Input_v2float Input
|
||||||
|
|
||||||
|
float4 main(noperspective sample float3 bary : SV_Barycentrics) : SV_Target {
|
||||||
|
return float4(bary, 1.0);
|
||||||
|
// CHECK: %param_var_bary = OpVariable %_ptr_Function_v3float Function
|
||||||
|
// CHECK-NEXT: [[c2:%\d+]] = OpLoad %v2float [[bary]]
|
||||||
|
// CHECK-NEXT: [[x:%\d+]] = OpCompositeExtract %float [[c2]] 0
|
||||||
|
// CHECK-NEXT: [[y:%\d+]] = OpCompositeExtract %float [[c2]] 1
|
||||||
|
// CHECK-NEXT: [[xy:%\d+]] = OpFAdd %float [[x]] [[y]]
|
||||||
|
// CHECK-NEXT: [[z:%\d+]] = OpFSub %float %float_1 [[xy]]
|
||||||
|
// CHECK-NEXT: [[c3:%\d+]] = OpCompositeConstruct %v3float [[x]] [[y]] [[z]]
|
||||||
|
// CHECK-NEXT: OpStore %param_var_bary [[c3]]
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Run: %dxc -T ps_6_1 -E main
|
||||||
|
|
||||||
|
// CHECK: OpExtension "SPV_AMD_shader_explicit_vertex_parameter"
|
||||||
|
|
||||||
|
// CHECK: OpEntryPoint Fragment
|
||||||
|
// CHECK-SAME: [[bary:%\d+]]
|
||||||
|
|
||||||
|
// CHECK: OpDecorate [[bary]] BuiltIn BaryCoordNoPerspAMD
|
||||||
|
|
||||||
|
// CHECK: [[bary]] = OpVariable %_ptr_Input_v2float Input
|
||||||
|
|
||||||
|
float4 main(noperspective float3 bary : SV_Barycentrics) : SV_Target {
|
||||||
|
return float4(bary, 1.0);
|
||||||
|
// CHECK: %param_var_bary = OpVariable %_ptr_Function_v3float Function
|
||||||
|
// CHECK-NEXT: [[c2:%\d+]] = OpLoad %v2float [[bary]]
|
||||||
|
// CHECK-NEXT: [[x:%\d+]] = OpCompositeExtract %float [[c2]] 0
|
||||||
|
// CHECK-NEXT: [[y:%\d+]] = OpCompositeExtract %float [[c2]] 1
|
||||||
|
// CHECK-NEXT: [[xy:%\d+]] = OpFAdd %float [[x]] [[y]]
|
||||||
|
// CHECK-NEXT: [[z:%\d+]] = OpFSub %float %float_1 [[xy]]
|
||||||
|
// CHECK-NEXT: [[c3:%\d+]] = OpCompositeConstruct %v3float [[x]] [[y]] [[z]]
|
||||||
|
// CHECK-NEXT: OpStore %param_var_bary [[c3]]
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Run: %dxc -T ps_6_1 -E main
|
||||||
|
|
||||||
|
// CHECK: OpExtension "SPV_AMD_shader_explicit_vertex_parameter"
|
||||||
|
|
||||||
|
// CHECK: OpEntryPoint Fragment
|
||||||
|
// CHECK-SAME: [[bary:%\d+]]
|
||||||
|
|
||||||
|
// CHECK: OpDecorate [[bary]] BuiltIn BaryCoordSmoothCentroidAMD
|
||||||
|
|
||||||
|
// CHECK: [[bary]] = OpVariable %_ptr_Input_v2float Input
|
||||||
|
|
||||||
|
float4 main(centroid float3 bary : SV_Barycentrics) : SV_Target {
|
||||||
|
return float4(bary, 1.0);
|
||||||
|
// CHECK: %param_var_bary = OpVariable %_ptr_Function_v3float Function
|
||||||
|
// CHECK-NEXT: [[c2:%\d+]] = OpLoad %v2float [[bary]]
|
||||||
|
// CHECK-NEXT: [[x:%\d+]] = OpCompositeExtract %float [[c2]] 0
|
||||||
|
// CHECK-NEXT: [[y:%\d+]] = OpCompositeExtract %float [[c2]] 1
|
||||||
|
// CHECK-NEXT: [[xy:%\d+]] = OpFAdd %float [[x]] [[y]]
|
||||||
|
// CHECK-NEXT: [[z:%\d+]] = OpFSub %float %float_1 [[xy]]
|
||||||
|
// CHECK-NEXT: [[c3:%\d+]] = OpCompositeConstruct %v3float [[x]] [[y]] [[z]]
|
||||||
|
// CHECK-NEXT: OpStore %param_var_bary [[c3]]
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Run: %dxc -T ps_6_1 -E main
|
||||||
|
|
||||||
|
// CHECK: OpExtension "SPV_AMD_shader_explicit_vertex_parameter"
|
||||||
|
|
||||||
|
// CHECK: OpEntryPoint Fragment
|
||||||
|
// CHECK-SAME: [[bary:%\d+]]
|
||||||
|
|
||||||
|
// CHECK: OpDecorate [[bary]] BuiltIn BaryCoordSmoothSampleAMD
|
||||||
|
|
||||||
|
// CHECK: [[bary]] = OpVariable %_ptr_Input_v2float Input
|
||||||
|
|
||||||
|
float4 main(sample float3 bary : SV_Barycentrics) : SV_Target {
|
||||||
|
return float4(bary, 1.0);
|
||||||
|
// CHECK: %param_var_bary = OpVariable %_ptr_Function_v3float Function
|
||||||
|
// CHECK-NEXT: [[c2:%\d+]] = OpLoad %v2float [[bary]]
|
||||||
|
// CHECK-NEXT: [[x:%\d+]] = OpCompositeExtract %float [[c2]] 0
|
||||||
|
// CHECK-NEXT: [[y:%\d+]] = OpCompositeExtract %float [[c2]] 1
|
||||||
|
// CHECK-NEXT: [[xy:%\d+]] = OpFAdd %float [[x]] [[y]]
|
||||||
|
// CHECK-NEXT: [[z:%\d+]] = OpFSub %float %float_1 [[xy]]
|
||||||
|
// CHECK-NEXT: [[c3:%\d+]] = OpCompositeConstruct %v3float [[x]] [[y]] [[z]]
|
||||||
|
// CHECK-NEXT: OpStore %param_var_bary [[c3]]
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Run: %dxc -T ps_6_1 -E main
|
||||||
|
|
||||||
|
// CHECK: OpExtension "SPV_AMD_shader_explicit_vertex_parameter"
|
||||||
|
|
||||||
|
// CHECK: OpEntryPoint Fragment
|
||||||
|
// CHECK-SAME: [[bary:%\d+]]
|
||||||
|
|
||||||
|
// CHECK: OpDecorate [[bary]] BuiltIn BaryCoordSmoothAMD
|
||||||
|
|
||||||
|
// CHECK: [[bary]] = OpVariable %_ptr_Input_v2float Input
|
||||||
|
|
||||||
|
float4 main(float3 bary : SV_Barycentrics) : SV_Target {
|
||||||
|
return float4(bary, 1.0);
|
||||||
|
// CHECK: %param_var_bary = OpVariable %_ptr_Function_v3float Function
|
||||||
|
// CHECK-NEXT: [[c2:%\d+]] = OpLoad %v2float [[bary]]
|
||||||
|
// CHECK-NEXT: [[x:%\d+]] = OpCompositeExtract %float [[c2]] 0
|
||||||
|
// CHECK-NEXT: [[y:%\d+]] = OpCompositeExtract %float [[c2]] 1
|
||||||
|
// CHECK-NEXT: [[xy:%\d+]] = OpFAdd %float [[x]] [[y]]
|
||||||
|
// CHECK-NEXT: [[z:%\d+]] = OpFSub %float %float_1 [[xy]]
|
||||||
|
// CHECK-NEXT: [[c3:%\d+]] = OpCompositeConstruct %v3float [[x]] [[y]] [[z]]
|
||||||
|
// CHECK-NEXT: OpStore %param_var_bary [[c3]]
|
||||||
|
}
|
|
@ -487,6 +487,25 @@ TEST_F(FileTest, SemanticViewportArrayIndexGS) {
|
||||||
TEST_F(FileTest, SemanticViewportArrayIndexPS) {
|
TEST_F(FileTest, SemanticViewportArrayIndexPS) {
|
||||||
runFileTest("semantic.viewport-array-index.ps.hlsl");
|
runFileTest("semantic.viewport-array-index.ps.hlsl");
|
||||||
}
|
}
|
||||||
|
TEST_F(FileTest, SemanticBarycentricsSmoothPS) {
|
||||||
|
runFileTest("semantic.barycentrics.ps.s.hlsl");
|
||||||
|
}
|
||||||
|
TEST_F(FileTest, SemanticBarycentricsSmoothCentroidPS) {
|
||||||
|
runFileTest("semantic.barycentrics.ps.s-c.hlsl");
|
||||||
|
}
|
||||||
|
TEST_F(FileTest, SemanticBarycentricsSmoothSamplePS) {
|
||||||
|
runFileTest("semantic.barycentrics.ps.s-s.hlsl");
|
||||||
|
}
|
||||||
|
TEST_F(FileTest, SemanticBarycentricsNoPerspectivePS) {
|
||||||
|
runFileTest("semantic.barycentrics.ps.np.hlsl");
|
||||||
|
}
|
||||||
|
TEST_F(FileTest, SemanticBarycentricsNoPerspectiveCentroidPS) {
|
||||||
|
runFileTest("semantic.barycentrics.ps.np-c.hlsl");
|
||||||
|
}
|
||||||
|
TEST_F(FileTest, SemanticBarycentricsNoPerspectiveSamplePS) {
|
||||||
|
runFileTest("semantic.barycentrics.ps.np-s.hlsl");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(FileTest, SemanticCoveragePS) {
|
TEST_F(FileTest, SemanticCoveragePS) {
|
||||||
runFileTest("semantic.coverage.ps.hlsl");
|
runFileTest("semantic.coverage.ps.hlsl");
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче