[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:
Lei Zhang 2017-11-22 18:16:48 -05:00 коммит произвёл GitHub
Родитель d1f1665865
Коммит 9745b0d55c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
10 изменённых файлов: 205 добавлений и 4 удалений

Просмотреть файл

@ -854,6 +854,8 @@ some system-value (SV) semantic strings will be translated into SPIR-V
+---------------------------+-------------+--------------------------+-----------------------+-----------------------+
| SV_StencilRef | PSOut | ``FragStencilRefEXT`` | N/A | ``StencilExportEXT`` |
+---------------------------+-------------+--------------------------+-----------------------+-----------------------+
| SV_Barycentrics | PSIn | ``BaryCoord*AMD`` | N/A | ``Shader`` |
+---------------------------+-------------+--------------------------+-----------------------+-----------------------+
| | GSOut | ``Layer`` | N/A | ``Geometry`` |
| SV_RenderTargetArrayIndex +-------------+--------------------------+-----------------------+-----------------------+
| | PSIn | ``Layer`` | N/A | ``Geometry`` |

Просмотреть файл

@ -944,6 +944,9 @@ bool DeclResultIdMapper::createStageVars(
case hlsl::Semantic::Kind::Coverage:
typeId = theBuilder.getArrayType(typeId, theBuilder.getConstantUint32(1));
break;
case hlsl::Semantic::Kind::Barycentrics:
typeId = theBuilder.getVecType(theBuilder.getFloat32Type(), 2);
break;
}
// Handle the extra arrayness
@ -959,7 +962,7 @@ bool DeclResultIdMapper::createStageVars(
const std::string semanticStr = stageVar.getSemanticStr();
llvm::Twine name = namePrefix + "." + semanticStr;
const uint32_t varId =
createSpirvStageVar(&stageVar, name, semanticToUse->loc);
createSpirvStageVar(&stageVar, decl, name, semanticToUse->loc);
if (varId == 0)
return false;
@ -978,7 +981,9 @@ bool DeclResultIdMapper::createStageVars(
theBuilder.decorate(varId, spv::Decoration::Patch);
// 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);
if (asInput) {
@ -1028,6 +1033,21 @@ bool DeclResultIdMapper::createStageVars(
else if (semanticKind == hlsl::Semantic::Kind::Coverage) {
*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 {
if (noWriteBack)
return true;
@ -1275,6 +1295,7 @@ void DeclResultIdMapper::decoratePSInterpolationMode(const DeclaratorDecl *decl,
}
uint32_t DeclResultIdMapper::createSpirvStageVar(StageVar *stageVar,
const DeclaratorDecl *decl,
const llvm::Twine &name,
SourceLocation srcLoc) {
using spv::BuiltIn;
@ -1505,6 +1526,33 @@ uint32_t DeclResultIdMapper::createSpirvStageVar(StageVar *stageVar,
stageVar->setIsSpirvBuiltin();
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
// VSIn, VSOut, HSCPIn, HSCPOut, DSIn, DSOut, GSVIn, GSOut, PSIn.
// 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
/// its storage class accordingly. name will be used as the debug name when
/// creating a stage input/output variable.
uint32_t createSpirvStageVar(StageVar *, const llvm::Twine &name,
SourceLocation);
uint32_t createSpirvStageVar(StageVar *, const DeclaratorDecl *decl,
const llvm::Twine &name, SourceLocation);
/// Creates the associated counter variable for RW/Append/Consume
/// 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) {
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) {
runFileTest("semantic.coverage.ps.hlsl");
}