diff options
| -rw-r--r-- | source/slang/slang-emit-cpp.cpp | 4 | ||||
| -rw-r--r-- | source/slang/slang-emit-glsl.cpp | 67 | ||||
| -rw-r--r-- | source/slang/slang-emit-hlsl.cpp | 35 | ||||
| -rw-r--r-- | source/slang/slang-ir-entry-point-uniforms.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.cpp | 44 | ||||
| -rw-r--r-- | source/slang/slang-ir-inst-defs.h | 21 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 36 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 43 | ||||
| -rw-r--r-- | tests/ir/string-literal.slang.expected | 2 |
9 files changed, 183 insertions, 71 deletions
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp index 1f38512b4..3727bf45e 100644 --- a/source/slang/slang-emit-cpp.cpp +++ b/source/slang/slang-emit-cpp.cpp @@ -2343,7 +2343,7 @@ void CPPSourceEmitter::emitOperandImpl(IRInst* inst, EmitOpInfo const& outerPre { String name = getName(inst); - if (inst->findDecorationImpl(kIROp_EntryPointDecoration)) + if (inst->findDecorationImpl(kIROp_EntryPointParamDecoration)) { // It's an entry point parameter // The parameter is held in a struct so always deref @@ -2695,7 +2695,7 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module) { auto inst = action.inst; - if (inst->findDecorationImpl(kIROp_EntryPointDecoration)) + if (inst->findDecorationImpl(kIROp_EntryPointParamDecoration)) { // Should only be one instruction marked this way SLANG_ASSERT(entryPointGlobalParams == nullptr); diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index e43d41d5c..78d34d649 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -654,7 +654,14 @@ void GLSLSourceEmitter::emitParameterGroupImpl(IRGlobalParam* varDecl, IRUniform void GLSLSourceEmitter::emitEntryPointAttributesImpl(IRFunc* irFunc, EntryPointLayout* entryPointLayout) { - auto profile = entryPointLayout->profile; + SLANG_UNUSED(entryPointLayout); + + IREntryPointDecoration* entryPointDecor = irFunc->findDecoration<IREntryPointDecoration>(); + SLANG_ASSERT(entryPointDecor); + + //auto profile = entryPointLayout->profile; + + auto profile = entryPointDecor->getProfile(); auto stage = profile.GetStage(); switch (stage) @@ -695,50 +702,36 @@ void GLSLSourceEmitter::emitEntryPointAttributesImpl(IRFunc* irFunc, EntryPointL m_writer->emit(") in;\n"); } - for (auto pp : entryPointLayout->getFuncDecl()->GetParameters()) + // These decorations were moved from the parameters to the entry point by ir-glsl-legalize. + // The actual parameters have become potentially multiple global parameters. + if (auto decor = irFunc->findDecoration<IRGeometryPrimitiveTypeDecoration>()) { - if (auto inputPrimitiveTypeModifier = pp->FindModifier<HLSLGeometryShaderInputPrimitiveTypeModifier>()) + switch (decor->op) { - if (as<HLSLTriangleModifier>(inputPrimitiveTypeModifier)) - { - m_writer->emit("layout(triangles) in;\n"); - } - else if (as<HLSLLineModifier>(inputPrimitiveTypeModifier)) - { - m_writer->emit("layout(lines) in;\n"); - } - else if (as<HLSLLineAdjModifier>(inputPrimitiveTypeModifier)) - { - m_writer->emit("layout(lines_adjacency) in;\n"); - } - else if (as<HLSLPointModifier>(inputPrimitiveTypeModifier)) + case kIROp_TrianglePrimitiveTypeDecoration: m_writer->emit("layout(triangles) in;\n"); break; + case kIROp_LinePrimitiveTypeDecoration: m_writer->emit("layout(lines) in;\n"); break; + case kIROp_LineAdjPrimitiveTypeDecoration: m_writer->emit("layout(lines_adjacency) in;\n"); break; + case kIROp_PointPrimitiveTypeDecoration: m_writer->emit("layout(points) in;\n"); break; + case kIROp_TriangleAdjPrimitiveTypeDecoration: m_writer->emit("layout(triangles_adjacency) in;\n"); break; + default: { - m_writer->emit("layout(points) in;\n"); - } - else if (as<HLSLTriangleAdjModifier>(inputPrimitiveTypeModifier)) - { - m_writer->emit("layout(triangles_adjacency) in;\n"); - } - } - - if (auto outputStreamType = as<HLSLStreamOutputType>(pp->type)) - { - if (as<HLSLTriangleStreamType>(outputStreamType)) - { - m_writer->emit("layout(triangle_strip) out;\n"); - } - else if (as<HLSLLineStreamType>(outputStreamType)) - { - m_writer->emit("layout(line_strip) out;\n"); - } - else if (as<HLSLPointStreamType>(outputStreamType)) - { - m_writer->emit("layout(points) out;\n"); + SLANG_ASSERT(!"Unknown primitive type"); } } } + if (auto decor = irFunc->findDecoration<IRStreamOutputTypeDecoration>()) + { + IRType* type = decor->getStreamType(); + switch (type->op) + { + case kIROp_HLSLPointStreamType: m_writer->emit("layout(points) out;\n"); break; + case kIROp_HLSLLineStreamType: m_writer->emit("layout(line_strip) out;\n"); break; + case kIROp_HLSLTriangleStreamType: m_writer->emit("layout(triangle_strip) out;\n"); break; + default: SLANG_ASSERT(!"Unknown stream out type"); + } + } } break; case Stage::Pixel: diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp index a5c4ae088..0ce3a682d 100644 --- a/source/slang/slang-emit-hlsl.cpp +++ b/source/slang/slang-emit-hlsl.cpp @@ -222,8 +222,13 @@ void HLSLSourceEmitter::_emitHLSLParameterGroup(IRGlobalParam* varDecl, IRUnifor void HLSLSourceEmitter::_emitHLSLEntryPointAttributes(IRFunc* irFunc, EntryPointLayout* entryPointLayout) { + SLANG_UNUSED(entryPointLayout); + + IREntryPointDecoration* entryPointDecor = irFunc->findDecoration<IREntryPointDecoration>(); + SLANG_ASSERT(entryPointDecor); + auto profile = m_effectiveProfile; - auto stage = entryPointLayout->profile.GetStage(); + auto stage = entryPointDecor->getProfile().GetStage(); if (profile.getFamily() == ProfileFamily::DX) { @@ -668,28 +673,16 @@ void HLSLSourceEmitter::emitSemanticsImpl(IRInst* inst) void HLSLSourceEmitter::emitSimpleFuncParamImpl(IRParam* param) { - if (auto layoutDecor = param->findDecoration<IRLayoutDecoration>()) + if (auto decor = param->findDecoration<IRGeometryPrimitiveTypeDecoration>()) { - Layout* layout = layoutDecor->getLayout(); - VarLayout* varLayout = as<VarLayout>(layout); - - if (varLayout) + switch (decor->op) { - auto var = varLayout->getVariable(); - - if (auto primTypeModifier = var->FindModifier<HLSLGeometryShaderInputPrimitiveTypeModifier>()) - { - if (as<HLSLTriangleModifier>(primTypeModifier)) - m_writer->emit("triangle "); - else if (as<HLSLPointModifier>(primTypeModifier)) - m_writer->emit("point "); - else if (as<HLSLLineModifier>(primTypeModifier)) - m_writer->emit("line "); - else if (as<HLSLLineAdjModifier>(primTypeModifier)) - m_writer->emit("lineadj "); - else if (as<HLSLTriangleAdjModifier>(primTypeModifier)) - m_writer->emit("triangleadj "); - } + case kIROp_TrianglePrimitiveTypeDecoration: m_writer->emit("triangle "); break; + case kIROp_PointPrimitiveTypeDecoration: m_writer->emit("point "); break; + case kIROp_LinePrimitiveTypeDecoration: m_writer->emit("line "); break; + case kIROp_LineAdjPrimitiveTypeDecoration: m_writer->emit("lineadj "); break; + case kIROp_TriangleAdjPrimitiveTypeDecoration: m_writer->emit("triangleadj "); break; + default: SLANG_ASSERT(!"Unknown primitive type"); break; } } diff --git a/source/slang/slang-ir-entry-point-uniforms.cpp b/source/slang/slang-ir-entry-point-uniforms.cpp index 670327446..9e36c0853 100644 --- a/source/slang/slang-ir-entry-point-uniforms.cpp +++ b/source/slang/slang-ir-entry-point-uniforms.cpp @@ -250,7 +250,7 @@ struct MoveEntryPointUniformParametersToGlobalScope globalParam = builder->createGlobalParam(paramStructType); // Mark that this global comes from the entry point - builder->addEntryPointDecoration(globalParam); + builder->addDecoration(globalParam, kIROp_EntryPointParamDecoration); } // No matter what, the global shader parameter should have the layout diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index 11456976e..5f5db5f01 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -1246,6 +1246,48 @@ void legalizeEntryPointParameterForGLSL( auto builder = context->getBuilder(); auto stage = context->getStage(); + // (JS): In the legalization process parameters are moved from the entry point. + // So when we get to emit we have a problem in that we can't use parameters to find important decorations + // And in the future we will not have front end 'Layout' available. To work around this, we take the + // decorations that need special handling from parameters and put them on the IRFunc. + // + // This is only appropriate of course if there is only one of each for all parameters... + // which is what current emit code assumes, but may not be more generally applicable. + if (auto geomDecor = pp->findDecoration<IRGeometryPrimitiveTypeDecoration>()) + { + if (!func->findDecoration<IRGeometryPrimitiveTypeDecoration>()) + { + builder->addDecoration(func, geomDecor->op); + } + else + { + SLANG_UNEXPECTED("Only expected a single parameter to have IRGeometryPrimitiveTypeDecoration decoration"); + } + } + + // There *can* be multiple streamout parameters, to an entry point (points if nothing else) + { + IRType* type = pp->getFullType(); + // Strip out type + if (auto outType = as<IROutTypeBase>(type)) + { + type = outType->getValueType(); + } + + if (auto streamType = as<IRHLSLStreamOutputType>(type)) + { + if (auto decor = func->findDecoration<IRStreamOutputTypeDecoration>()) + { + // If it has the same stream out type, we *may* be ok (might not work for all types of streams) + SLANG_ASSERT(decor->getStreamType()->op == streamType->op); + } + else + { + builder->addDecoration(func, kIROp_StreamOutputTypeDecoration, streamType); + } + } + } + // We need to create a global variable that will replace the parameter. // It seems superficially obvious that the variable should have // the same type as the parameter. @@ -1289,8 +1331,6 @@ void legalizeEntryPointParameterForGLSL( // For now we will just try to deal with `Append` calls // directly in this function. - - for( auto bb = func->getFirstBlock(); bb; bb = bb->getNextBlock() ) { for( auto ii = bb->getFirstInst(); ii; ii = ii->getNextInst() ) diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index b586aa5bc..dee0ef2f8 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -422,9 +422,24 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) INST(InstanceDecoration, instance, 1, 0) INST(NumThreadsDecoration, numThreads, 3, 0) - /// An `[entryPoint]` decoration marks a function that represents a shader entry point. - /// Also used in some scenarios mark parameters that are moved from entry point parameters to global params as coming from the entry point. - INST(EntryPointDecoration, entryPoint, 0, 0) + // Added to IRParam parameters to an entry point + INST(GeometryPrimitiveTypeDecoration, geometryPrimitiveTypeDecoration, 1, 0) + + /* GeometryPrimitiveTypeDecoration */ + INST(PointPrimitiveTypeDecoration, pointPrimitiveType, 0, 0) + INST(LinePrimitiveTypeDecoration, linePrimitiveType, 0, 0) + INST(TrianglePrimitiveTypeDecoration, trianglePrimitiveType, 0, 0) + INST(LineAdjPrimitiveTypeDecoration, lineAdjPrimitiveType, 0, 0) + INST(TriangleAdjPrimitiveTypeDecoration, triangleAdjPrimitiveType, 0, 0) + INST_RANGE(GeometryPrimitiveTypeDecoration, PointPrimitiveTypeDecoration, TriangleAdjPrimitiveTypeDecoration) + + INST(StreamOutputTypeDecoration, streamOutputTypeDecoration, 1, 0) + + /// An `[entryPoint]` decoration marks a function that represents a shader entry point + INST(EntryPointDecoration, entryPoint, 1, 0) + + /// Used to mark parameters that are moved from entry point parameters to global params as coming from the entry point. + INST(EntryPointParamDecoration, entryPointParam, 0, 0) /// A `[dependsOn(x)]` decoration indicates that the parent instruction depends on `x` /// even if it does not otherwise reference it. diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 9dc80beac..8122fb7b6 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -287,13 +287,43 @@ struct IRNumThreadsDecoration : IRDecoration IRIntLit* getZ() { return cast<IRIntLit>(getOperand(2)); } }; +struct IREntryPointDecoration : IRDecoration +{ + enum { kOp = kIROp_EntryPointDecoration }; + IR_LEAF_ISA(EntryPointDecoration) + + IRIntLit* getProfileInst() { return cast<IRIntLit>(getOperand(0)); } + Profile getProfile() { return Profile(Profile::RawVal(GetIntVal(getProfileInst()))); } +}; + +struct IRGeometryPrimitiveTypeDecoration: IRDecoration +{ + enum { kOp = kIROp_GeometryPrimitiveTypeDecoration }; + IR_PARENT_ISA(GeometryPrimitiveTypeDecoration) +}; + +IR_SIMPLE_DECORATION(PointPrimitiveTypeDecoration) +IR_SIMPLE_DECORATION(LinePrimitiveTypeDecoration) +IR_SIMPLE_DECORATION(TrianglePrimitiveTypeDecoration) +IR_SIMPLE_DECORATION(LineAdjPrimitiveTypeDecoration) +IR_SIMPLE_DECORATION(TriangleAdjPrimitiveTypeDecoration) + + /// This is a bit of a hack. The problem is that when GLSL legalization takes place /// A decoration that marks a value as having linkage. /// /// A value with linkage is either exported from its module, /// or will have a definition imported from another module. /// In either case, it requires a mangled name to use when /// matching imports and exports. - /// +struct IRStreamOutputTypeDecoration : IRDecoration +{ + enum { kOp = kIROp_StreamOutputTypeDecoration }; + IR_LEAF_ISA(StreamOutputTypeDecoration) + + IRHLSLStreamOutputType* getStreamType() { return cast<IRHLSLStreamOutputType>(getOperand(0)); } +}; + + struct IRLinkageDecoration : IRDecoration { IR_PARENT_ISA(LinkageDecoration) @@ -1368,9 +1398,9 @@ struct IRBuilder addDecoration(value, kIROp_ExportDecoration, getStringValue(mangledName)); } - void addEntryPointDecoration(IRInst* value) + void addEntryPointDecoration(IRInst* value, Profile profile) { - addDecoration(value, kIROp_EntryPointDecoration); + addDecoration(value, kIROp_EntryPointDecoration, getIntValue(getIntType(), profile.raw)); } void addKeepAliveDecoration(IRInst* value) diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index a622c9802..cec2bd988 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -6338,7 +6338,48 @@ static void lowerFrontEndEntryPointToIR( { instToDecorate = findGenericReturnVal(irGeneric); } - builder->addEntryPointDecoration(instToDecorate); + builder->addEntryPointDecoration(instToDecorate, entryPoint->getProfile()); + + // Go through the entry point parameters creating decorations from layout as appropriate + { + FilteredMemberList<ParamDecl> params = entryPointFuncDecl->GetParameters(); + + IRGlobalValueWithParams* valueWithParams = as<IRGlobalValueWithParams>(instToDecorate); + if (valueWithParams) + { + IRParam* irParam = valueWithParams->getFirstParam(); + + for (auto param : params) + { + if (auto modifier = param->FindModifier<HLSLGeometryShaderInputPrimitiveTypeModifier>()) + { + IROp op = kIROp_Invalid; + + if (as<HLSLTriangleModifier>(modifier)) + op = kIROp_TrianglePrimitiveTypeDecoration; + else if (as<HLSLPointModifier>(modifier)) + op = kIROp_PointPrimitiveTypeDecoration; + else if (as<HLSLLineModifier>(modifier)) + op = kIROp_LinePrimitiveTypeDecoration; + else if (as<HLSLLineAdjModifier>(modifier)) + op = kIROp_LineAdjPrimitiveTypeDecoration; + else if (as<HLSLTriangleAdjModifier>(modifier)) + op = kIROp_TriangleAdjPrimitiveTypeDecoration; + + if (op != kIROp_Invalid) + { + builder->addDecoration(irParam, op); + } + else + { + SLANG_UNEXPECTED("unhandled primitive type"); + } + } + + irParam = irParam->getNextParam(); + } + } + } } static void lowerProgramEntryPointToIR( diff --git a/tests/ir/string-literal.slang.expected b/tests/ir/string-literal.slang.expected index 44bafd86a..72baa8f7e 100644 --- a/tests/ir/string-literal.slang.expected +++ b/tests/ir/string-literal.slang.expected @@ -1,6 +1,6 @@ result code = 0 standard error = { -[entryPoint] +[entryPoint(6)] [numThreads(1, 1, 1)] [export("_S3tu04mainp1puV")] [nameHint("main")] |
