[spirv] Execution modes for GS primitive types. (#734)

This commit is contained in:
Ehsan 2017-10-25 16:02:23 -04:00 коммит произвёл GitHub
Родитель 0d9cfd2b3a
Коммит 96c5c0ad17
10 изменённых файлов: 122 добавлений и 1 удалений

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

@ -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"); }