Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions source/slang/core.meta.slang
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ syntax globallycoherent : GloballyCoherentModifier;
///
syntax pervertex : PerVertexModifier;

/// Modifier to disable inteprolation and force per-primitive passing of a varying attribute.
syntax perprimitive : PerPrimitiveModifier;

/// Modifier to indicate a buffer or texture element type is
/// backed by data in an unsigned normalized format.
///
Expand Down
7 changes: 7 additions & 0 deletions source/slang/slang-ast-modifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,13 @@ class PerVertexModifier : public InterpolationModeModifier
FIDDLE(...)
};

/// Slang-defined `perprimitive` modifier
FIDDLE()
class PerPrimitiveModifier : public Modifier
{
FIDDLE(...)
};


// HLSL `precise` modifier
FIDDLE()
Expand Down
2 changes: 2 additions & 0 deletions source/slang/slang-check-modifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1374,6 +1374,7 @@ ASTNodeType getModifierConflictGroupKind(ASTNodeType modifierType)
case ASTNodeType::HLSLSampleModifier:
case ASTNodeType::HLSLCentroidModifier:
case ASTNodeType::PerVertexModifier:
case ASTNodeType::PerPrimitiveModifier:
return ASTNodeType::InterpolationModeModifier;

case ASTNodeType::PrefixModifier:
Expand Down Expand Up @@ -1466,6 +1467,7 @@ bool isModifierAllowedOnDecl(bool isGLSLInput, ASTNodeType modifierType, Decl* d
case ASTNodeType::HLSLSampleModifier:
case ASTNodeType::HLSLCentroidModifier:
case ASTNodeType::PerVertexModifier:
case ASTNodeType::PerPrimitiveModifier:
case ASTNodeType::HLSLUniformModifier:
case ASTNodeType::DynamicUniformModifier:
return (as<VarDeclBase>(decl) &&
Expand Down
7 changes: 7 additions & 0 deletions source/slang/slang-emit-glsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ void GLSLSourceEmitter::_requireFragmentShaderBarycentric()
m_glslExtensionTracker->requireVersion(ProfileVersion::GLSL_450);
}

void GLSLSourceEmitter::_requireMeshShader()
{
m_glslExtensionTracker->requireExtension(
UnownedStringSlice::fromLiteral("GL_EXT_mesh_shader"));
m_glslExtensionTracker->requireVersion(ProfileVersion::GLSL_450);
}

void GLSLSourceEmitter::_requireGLSLExtension(const UnownedStringSlice& name)
{
Expand Down Expand Up @@ -3723,6 +3729,7 @@ void GLSLSourceEmitter::emitMeshShaderModifiersImpl(IRInst* varInst)
{
if (varInst->findDecoration<IRGLSLPrimitivesRateDecoration>())
{
_requireMeshShader();
m_writer->emit("perprimitiveEXT");
m_writer->emit(" ");
}
Expand Down
2 changes: 2 additions & 0 deletions source/slang/slang-emit-glsl.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ class GLSLSourceEmitter : public CLikeSourceEmitter

void _requireFragmentShaderBarycentric();

void _requireMeshShader();

void _emitSpecialFloatImpl(IRType* type, const char* valueExpr);

void emitAtomicImageCoord(IRImageSubscript* operand);
Expand Down
19 changes: 11 additions & 8 deletions source/slang/slang-emit-spirv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2945,6 +2945,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
return false;
}
}

void emitSystemVarDecoration(IRInst* var, SpvInst* varInst)
{
for (auto decor : var->getDecorations())
Expand Down Expand Up @@ -3084,7 +3085,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
SpvLiteralInteger::from32(int32_t(0)));
}

bool anyModifiers = (var->findDecoration<IRInterpolationModeDecoration>() != nullptr);
bool anyModifiers = (var->findDecoration<IRInterpolationModeDecoration>() != nullptr || var->findDecoration<IRGLSLPrimitivesRateDecoration>() != nullptr);

// If the user didn't explicitly qualify a varying
// with integer or pointer type, then we need to explicitly
Expand All @@ -3111,13 +3112,6 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
{
switch (decor->getOp())
{
case kIROp_GLSLPrimitivesRateDecoration:
emitOpDecorate(
getSection(SpvLogicalSectionID::Annotations),
decor,
varInst,
SpvDecorationPerPrimitiveEXT);
break;
case kIROp_RequireSPIRVDescriptorIndexingExtensionDecoration:
ensureExtensionDeclarationBeforeSpv15(
UnownedStringSlice("SPV_EXT_descriptor_indexing"));
Expand Down Expand Up @@ -5609,6 +5603,15 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
dstID,
SpvDecorationPerVertexKHR);
break;
case kIROp_GLSLPrimitivesRateDecoration:
ensureExtensionDeclaration(UnownedStringSlice("SPV_EXT_mesh_shader"));
requireSPIRVAnyCapability({SpvCapabilityMeshShadingEXT});
emitOpDecorate(
getSection(SpvLogicalSectionID::Annotations),
decoration,
dstID,
SpvDecorationPerPrimitiveEXT);
break;
case kIROp_OutputControlPointsDecoration:
requireSPIRVExecutionMode(
decoration,
Expand Down
6 changes: 6 additions & 0 deletions source/slang/slang-ir-glsl-legalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,12 @@ void createVarLayoutForLegalizedGlobalParam(
builder->addInterpolationModeDecoration(globalParam, interpolationModeDecor->getMode());
break;
}

if (decorParent->findDecoration<IRGLSLPrimitivesRateDecoration>())
{
builder->addSimpleDecoration<IRGLSLPrimitivesRateDecoration>(globalParam);
break;
}
}

if (declarator && declarator->flavor == GlobalVaryingDeclarator::Flavor::meshOutputPrimitives)
Expand Down
4 changes: 4 additions & 0 deletions source/slang/slang-lower-to-ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2626,6 +2626,10 @@ void addVarDecorations(IRGenContext* context, IRInst* inst, Decl* decl)
if (op != kIROp_Invalid)
builder->addDecoration(inst, op);
}
else if (as<PerPrimitiveModifier>(mod))
{
builder->addSimpleDecoration<IRGLSLPrimitivesRateDecoration>(inst);
}
// TODO: what are other modifiers we need to propagate through?
}
if (auto t = composeGetters<IRMeshOutputType>(
Expand Down
69 changes: 49 additions & 20 deletions tests/spirv/mesh-primitive.slang
Original file line number Diff line number Diff line change
@@ -1,40 +1,62 @@
//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly
// TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly

// CHECK: OpDecorate %primitives_color Location 0
// CHECK: OpDecorate %primitives_color PerPrimitive
// CHECK: OpDecorate %prim_color Location 0
// CHECK: OpDecorate %prim_color Flat
// VUID-CullPrimitiveEXT-CullPrimitiveEXT-07038
// CHECK: OpDecorate %[[CULLPRIMITIVE:[0-9]+]] BuiltIn CullPrimitiveEXT
// CHECK: OpDecorate %[[CULLPRIMITIVE]] PerPrimitive

// CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
// CHECK: OpDecorate %gl_PrimitiveID PerPrimitiveEXT
// CHECK: OpDecorate %out_primitives_color Location 0
// CHECK: OpDecorate %out_primitives_color PerPrimitiveEXT
// CHECK: OpDecorate %out_primitives_values Location 2
// CHECK: OpDecorate %out_primitives_values PerPrimitiveEXT
// CHECK: OpDecorate %entryPointParam_entry_mesh_out_normal Location 1
// CHECK: OpDecorate %entryPointParam_entry_mesh_out_normal PerPrimitiveEXT

// CHECK: OpDecorate %gl_PrimitiveID_0 BuiltIn PrimitiveId
// CHECK: OpDecorate %gl_PrimitiveID_0 PerPrimitiveEXT
// CHECK: OpDecorate %in_normal Location 1
// CHECK: OpDecorate %in_normal PerPrimitiveEXT
// CHECK: OpDecorate %in_color Location 0
// CHECK: OpDecorate %in_color PerPrimitiveEXT
// CHECK: OpDecorate %in_values Location 2
// CHECK: OpDecorate %in_values PerPrimitiveEXT

const static uint MAX_VERTS = 6;
const static uint MAX_PRIMS = 2;

const static float2 positions[MAX_VERTS] = {
float2(0.0, -0.5),
float2(0.5, 0),
float2(-0.5, 0),
float2(0.0, 0.5),
float2(0.5, 0),
float2(-0.5, 0),
float2(0.0, -0.5),
float2(0.5, 0),
float2(-0.5, 0),
float2(0.0, 0.5),
float2(0.5, 0),
float2(-0.5, 0),
};

struct Vertex
{
float4 pos : SV_Position;
float4 pos : SV_Position;
};

struct Primitive
{
[[vk::location(0)]] float3 color;
bool cull : SV_CullPrimitive;
uint primitive_id : SV_PrimitiveID;
[[vk::location(0)]] float3 color;
[[vk::location(2)]] float values[2];
}

[[vk::location(1)]] out perprimitive float3 out_normal[MAX_PRIMS];

[outputtopology("triangle")]
[numthreads(MAX_VERTS, 1, 1)]
[shader("mesh")]
void entry_mesh(
in uint tig : SV_GroupThreadID,
OutputVertices<Vertex, MAX_VERTS> verts,
OutputIndices<uint3, MAX_PRIMS> triangles,
OutputPrimitives<Primitive, MAX_PRIMS> primitives)
OutputPrimitives<Primitive, MAX_PRIMS> out_primitives)
{
const uint numVertices = MAX_VERTS;
const uint numPrimitives = MAX_PRIMS;
Expand All @@ -44,21 +66,28 @@ void entry_mesh(
verts[tig] = {float4(positions[tig], 0, 1)};
}

if(tig < numPrimitives) {
triangles[tig] = uint3(0,1,2) + tig * 3;
primitives[tig] = { float3(1,0,0) };
if (tig < numPrimitives) {
triangles[tig] = uint3(0, 1, 2) + tig * 3;
out_primitives[tig] = { false, tig, float3(1, 0, 0) };
out_normal[tig] = float3(1.0, 0.0, 0.0);
}
}

struct FragmentOut
{
[[vk::location(0)]] float3 color;
[[vk::location(0)]] float3 frag_color;
};

[[vk::location(1)]] in perprimitive float3 in_normal;
[[vk::location(2)]] in perprimitive float in_values[2];
in perprimitive uint in_primitive_id : SV_PrimitiveID;

[shader("fragment")]
FragmentOut entry_fragment(in nointerpolation Primitive prim)
FragmentOut entry_fragment([[vk::location(0)]] in perprimitive float3 in_color, )
{
let n_dot_l = dot(in_normal, float3(0.0, 1.0, 0.0)) + in_values[0] + in_primitive_id;

FragmentOut frag_out;
frag_out.color = prim.color;
frag_out.frag_color = in_color * n_dot_l;
return frag_out;
}