[spirv] Execution modes for GS primitive types. (#734)
This commit is contained in:
Родитель
0d9cfd2b3a
Коммит
96c5c0ad17
|
@ -1843,6 +1843,28 @@ and is translated to SPIR-V execution mode as follows:
|
|||
|``maxvertexcount`` | ``n`` | ``OutputVertices n`` |
|
||||
+-------------------------+---------------------+--------------------------+
|
||||
|
||||
Translation for Primitive Types
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Geometry shader vertex inputs may be qualified with primitive types. Only one primitive type
|
||||
is allowed to be used in a given geometry shader. The following table shows the SPIR-V execution
|
||||
mode that is used in order to represent the given primitive type.
|
||||
|
||||
.. table:: Mapping from geometry shader primitive type to SPIR-V execution mode
|
||||
|
||||
+---------------------+-----------------------------+
|
||||
| HLSL Primitive Type | SPIR-V Execution Mode |
|
||||
+=====================+=============================+
|
||||
|``point`` | ``InputPoints`` |
|
||||
+---------------------+-----------------------------+
|
||||
|``line`` | ``InputLines`` |
|
||||
+---------------------+-----------------------------+
|
||||
|``triangle`` | ``Triangles`` |
|
||||
+---------------------+-----------------------------+
|
||||
|``lineadj`` | ``InputLinesAdjacency`` |
|
||||
+---------------------+-----------------------------+
|
||||
|``triangleadj`` | ``InputTrianglesAdjacency`` |
|
||||
+---------------------+-----------------------------+
|
||||
|
||||
TODO: Describe more details about how geometry shaders are translated. e.g. OutputStreams, etc.
|
||||
|
||||
Vulkan Command-line Options
|
||||
|
|
|
@ -54,6 +54,15 @@ ResourceVar::Category getResourceCategory(QualType type) {
|
|||
return ResourceVar::Category::Other;
|
||||
}
|
||||
|
||||
/// \brief Returns true if the given declaration has a primitive type qualifier.
|
||||
/// Returns false otherwise.
|
||||
bool hasGSPrimitiveTypeQualifier(const Decl *decl) {
|
||||
return (decl->hasAttr<HLSLTriangleAttr>() ||
|
||||
decl->hasAttr<HLSLTriangleAdjAttr>() ||
|
||||
decl->hasAttr<HLSLPointAttr>() || decl->hasAttr<HLSLLineAdjAttr>() ||
|
||||
decl->hasAttr<HLSLLineAttr>());
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool DeclResultIdMapper::createStageOutputVar(const DeclaratorDecl *decl,
|
||||
|
@ -684,8 +693,14 @@ bool DeclResultIdMapper::createStageVars(const DeclaratorDecl *decl,
|
|||
// Found semantic attached directly to this Decl. This means we need to
|
||||
// map this decl to a single stage variable.
|
||||
|
||||
const hlsl::DxilParamInputQual qual =
|
||||
hlsl::DxilParamInputQual qual =
|
||||
asInput ? hlsl::DxilParamInputQual::In : hlsl::DxilParamInputQual::Out;
|
||||
|
||||
// The inputs to the geometry shader that have a primitive type qualifier
|
||||
// must use 'InputPrimitive'.
|
||||
if (asInput && shaderModel.IsGS() && hasGSPrimitiveTypeQualifier(decl))
|
||||
qual = hlsl::DxilParamInputQual::InputPrimitive;
|
||||
|
||||
const hlsl::SigPoint *sigPoint =
|
||||
hlsl::SigPoint::GetSigPoint(hlsl::SigPointFromInputQual(
|
||||
qual, shaderModel.GetKind(), isPatchConstant));
|
||||
|
|
|
@ -5142,6 +5142,38 @@ bool SPIRVEmitter::processGeometryShaderAttributes(const FunctionDecl *decl) {
|
|||
spv::ExecutionMode::OutputVertices,
|
||||
{static_cast<uint32_t>(vcAttr->getCount())});
|
||||
}
|
||||
|
||||
// Only one primitive type is permitted for the geometry shader.
|
||||
uint32_t primitiveTypes = 0;
|
||||
for (const auto *param : decl->params()) {
|
||||
if (param->hasAttr<HLSLTriangleAttr>()) {
|
||||
++primitiveTypes;
|
||||
theBuilder.addExecutionMode(entryFunctionId,
|
||||
spv::ExecutionMode::Triangles, {});
|
||||
} else if (param->hasAttr<HLSLTriangleAdjAttr>()) {
|
||||
++primitiveTypes;
|
||||
theBuilder.addExecutionMode(
|
||||
entryFunctionId, spv::ExecutionMode::InputTrianglesAdjacency, {});
|
||||
} else if (param->hasAttr<HLSLPointAttr>()) {
|
||||
++primitiveTypes;
|
||||
theBuilder.addExecutionMode(entryFunctionId,
|
||||
spv::ExecutionMode::InputPoints, {});
|
||||
} else if (param->hasAttr<HLSLLineAdjAttr>()) {
|
||||
++primitiveTypes;
|
||||
theBuilder.addExecutionMode(entryFunctionId,
|
||||
spv::ExecutionMode::InputLinesAdjacency, {});
|
||||
} else if (param->hasAttr<HLSLLineAttr>()) {
|
||||
++primitiveTypes;
|
||||
theBuilder.addExecutionMode(entryFunctionId,
|
||||
spv::ExecutionMode::InputLines, {});
|
||||
}
|
||||
}
|
||||
if (primitiveTypes > 1) {
|
||||
emitError(
|
||||
"only one primitive type can be specified in the geometry shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// Run: %dxc -T gs_6_0 -E main
|
||||
|
||||
[maxvertexcount(3)]
|
||||
void main(triangle in uint i[3] : TriangleVertexID, line in uint j[2] : LineVertexID) {}
|
||||
|
||||
// CHECK: error: only one primitive type can be specified in the geometry shader
|
|
@ -0,0 +1,6 @@
|
|||
// Run: %dxc -T gs_6_0 -E main
|
||||
|
||||
// CHECK: OpExecutionMode %main InputLines
|
||||
|
||||
[maxvertexcount(3)]
|
||||
void main(line in uint id[2] : VertexID) {}
|
|
@ -0,0 +1,6 @@
|
|||
// Run: %dxc -T gs_6_0 -E main
|
||||
|
||||
// CHECK: OpExecutionMode %main InputLinesAdjacency
|
||||
|
||||
[maxvertexcount(3)]
|
||||
void main(lineadj in uint id[4] : VertexID) {}
|
|
@ -0,0 +1,6 @@
|
|||
// Run: %dxc -T gs_6_0 -E main
|
||||
|
||||
// CHECK: OpExecutionMode %main InputPoints
|
||||
|
||||
[maxvertexcount(3)]
|
||||
void main(point in uint id[1] : VertexID) {}
|
|
@ -0,0 +1,6 @@
|
|||
// Run: %dxc -T gs_6_0 -E main
|
||||
|
||||
// CHECK: OpExecutionMode %main Triangles
|
||||
|
||||
[maxvertexcount(3)]
|
||||
void main(triangle in uint i[3] : VertexID) {}
|
|
@ -0,0 +1,6 @@
|
|||
// Run: %dxc -T gs_6_0 -E main
|
||||
|
||||
// CHECK: OpExecutionMode %main InputTrianglesAdjacency
|
||||
|
||||
[maxvertexcount(3)]
|
||||
void main(triangleadj in uint id[6] : VertexID) {}
|
|
@ -683,6 +683,22 @@ TEST_F(FileTest, AttributeMaxVertexCount) {
|
|||
runFileTest("attribute.max-vertex-count.hlsl");
|
||||
}
|
||||
|
||||
// For geometry shader primitive types
|
||||
TEST_F(FileTest, PrimitivePointGS) { runFileTest("primitive.point.gs.hlsl"); }
|
||||
TEST_F(FileTest, PrimitiveLineGS) { runFileTest("primitive.line.gs.hlsl"); }
|
||||
TEST_F(FileTest, PrimitiveTriangleGS) {
|
||||
runFileTest("primitive.triangle.gs.hlsl");
|
||||
}
|
||||
TEST_F(FileTest, PrimitiveLineAdjGS) {
|
||||
runFileTest("primitive.lineadj.gs.hlsl");
|
||||
}
|
||||
TEST_F(FileTest, PrimitiveTriangleAdjGS) {
|
||||
runFileTest("primitive.triangleadj.gs.hlsl");
|
||||
}
|
||||
TEST_F(FileTest, PrimitiveErrorGS) {
|
||||
runFileTest("primitive.error.gs.hlsl", /*expectSuccess*/ false);
|
||||
}
|
||||
|
||||
// Vulkan/SPIR-V specific
|
||||
TEST_F(FileTest, SpirvStorageClass) { runFileTest("spirv.storage-class.hlsl"); }
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче