diff options
| -rw-r--r-- | source/slang/core.meta.slang | 3 | ||||
| -rw-r--r-- | source/slang/slang-ast-modifier.h | 27 | ||||
| -rw-r--r-- | source/slang/slang-emit-c-like.cpp | 3 | ||||
| -rw-r--r-- | source/slang/slang-emit-c-like.h | 6 | ||||
| -rw-r--r-- | source/slang/slang-emit-hlsl.cpp | 31 | ||||
| -rw-r--r-- | source/slang/slang-emit-hlsl.h | 6 | ||||
| -rw-r--r-- | source/slang/slang-ir-inst-defs.h | 7 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 24 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 28 | ||||
| -rw-r--r-- | source/slang/slang-parser.cpp | 57 |
10 files changed, 191 insertions, 1 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 887852cbc..970ed1fa8 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -2098,3 +2098,6 @@ attribute_syntax [__requiresNVAPI] : RequiresNVAPIAttribute; __attributeTarget(FunctionDeclBase) attribute_syntax [noinline] : NoInlineAttribute; + +__attributeTarget(StructDecl) +attribute_syntax [payload] : PayloadAttribute; diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index 3d0c3c6c1..10560dc84 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -292,6 +292,24 @@ class HLSLSimpleSemantic : public HLSLSemantic SLANG_AST_CLASS(HLSLSimpleSemantic) }; +// A semantic applied to a field of a ray-payload type, to control access +class RayPayloadAccessSemantic : public HLSLSemantic +{ + SLANG_AST_CLASS(RayPayloadAccessSemantic) + + List<Token> stageNameTokens; +}; + +class RayPayloadReadSemantic : public RayPayloadAccessSemantic +{ + SLANG_AST_CLASS(RayPayloadReadSemantic) +}; + +class RayPayloadWriteSemantic : public RayPayloadAccessSemantic +{ + SLANG_AST_CLASS(RayPayloadWriteSemantic) +}; + // GLSL @@ -948,5 +966,14 @@ class NoInlineAttribute : public Attribute SLANG_AST_CLASS(NoInlineAttribute) }; + /// A `[payload]` attribute indicates that a `struct` type will be used as + /// a ray payload for `TraceRay()` calls, and thus also as input/output + /// for shaders in the ray tracing pipeline that might be invoked for + /// such a ray. + /// +class PayloadAttribute : public Attribute +{ + SLANG_AST_CLASS(PayloadAttribute) +}; } // namespace Slang diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index d916019c7..92947214d 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -2898,6 +2898,9 @@ void CLikeSourceEmitter::emitStruct(IRStructType* structType) } m_writer->emit("struct "); + + emitPostKeywordTypeAttributes(structType); + m_writer->emit(getName(structType)); m_writer->emit("\n{\n"); m_writer->indent(); diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h index 5846d99fd..a969fa334 100644 --- a/source/slang/slang-emit-c-like.h +++ b/source/slang/slang-emit-c-like.h @@ -253,6 +253,9 @@ public: void emitStruct(IRStructType* structType); + /// Emit type attributes that should appear after, e.g., a `struct` keyword + void emitPostKeywordTypeAttributes(IRInst* inst) { emitPostKeywordTypeAttributesImpl(inst); } + void emitInterpolationModifiers(IRInst* varInst, IRType* valueType, IRVarLayout* layout); UInt getRayPayloadLocation(IRInst* inst); @@ -368,6 +371,9 @@ public: void handleRequiredCapabilities(IRInst* inst); virtual void handleRequiredCapabilitiesImpl(IRInst* inst) { SLANG_UNUSED(inst); } + virtual void emitPostKeywordTypeAttributesImpl(IRInst* inst) { SLANG_UNUSED(inst); } + + void _emitArrayType(IRArrayType* arrayType, EDeclarator* declarator); void _emitUnsizedArrayType(IRUnsizedArrayType* arrayType, EDeclarator* declarator); void _emitType(IRType* type, EDeclarator* declarator); diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp index a1da1bbdf..26a841190 100644 --- a/source/slang/slang-emit-hlsl.cpp +++ b/source/slang/slang-emit-hlsl.cpp @@ -915,6 +915,11 @@ void HLSLSourceEmitter::emitSemanticsImpl(IRInst* inst) return; } + if( auto readAccessSemantic = inst->findDecoration<IRStageReadAccessDecoration>()) + _emitStageAccessSemantic(readAccessSemantic, "read"); + if( auto writeAccessSemantic = inst->findDecoration<IRStageWriteAccessDecoration>()) + _emitStageAccessSemantic(writeAccessSemantic, "write"); + if (auto layoutDecoration = inst->findDecoration<IRLayoutDecoration>()) { auto layout = layoutDecoration->getLayout(); @@ -932,6 +937,32 @@ void HLSLSourceEmitter::emitSemanticsImpl(IRInst* inst) } } +void HLSLSourceEmitter::_emitStageAccessSemantic(IRStageAccessDecoration* decoration, const char* name) +{ + Int stageCount = decoration->getStageCount(); + if(stageCount == 0) + return; + + m_writer->emit(" : "); + m_writer->emit(name); + m_writer->emit("("); + for( Int i = 0; i < stageCount; ++i ) + { + if(i != 0) m_writer->emit(", "); + m_writer->emit(decoration->getStageName(i)); + } + m_writer->emit(")"); +} + +void HLSLSourceEmitter::emitPostKeywordTypeAttributesImpl(IRInst* inst) +{ + if( auto payloadDecoration = inst->findDecoration<IRPayloadDecoration>() ) + { + m_writer->emit("[payload] "); + } +} + + void HLSLSourceEmitter::emitSimpleFuncParamImpl(IRParam* param) { if (auto decor = param->findDecoration<IRGeometryInputPrimitiveTypeDecoration>()) diff --git a/source/slang/slang-emit-hlsl.h b/source/slang/slang-emit-hlsl.h index 614ee58bc..59449e519 100644 --- a/source/slang/slang-emit-hlsl.h +++ b/source/slang/slang-emit-hlsl.h @@ -53,6 +53,9 @@ protected: virtual void emitGlobalInstImpl(IRInst* inst) SLANG_OVERRIDE; + virtual void emitPostKeywordTypeAttributesImpl(IRInst* inst) SLANG_OVERRIDE; + + // Emit a single `register` semantic, as appropriate for a given resource-type-specific layout info // Keyword to use in the uniform case (`register` for globals, `packoffset` inside a `cbuffer`) void _emitHLSLRegisterSemantic(LayoutResourceKind kind, EmitVarChain* chain, char const* uniformSemanticSpelling = "register"); @@ -70,7 +73,8 @@ protected: void _emitHLSLDecorationSingleString(const char* name, IRFunc* entryPoint, IRStringLit* val); void _emitHLSLDecorationSingleInt(const char* name, IRFunc* entryPoint, IRIntLit* val); - + + void _emitStageAccessSemantic(IRStageAccessDecoration* decoration, const char* name); }; } diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 082de1c42..f73dbd006 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -605,6 +605,13 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) /// Applie to an IR function and signals that inlining should not be performed unless unavoidable. INST(NoInlineDecoration, noInline, 0, 0) + INST(PayloadDecoration, payload, 0, 0) + + /* StageAccessDecoration */ + INST(StageReadAccessDecoration, stageReadAccess, 0, 0) + INST(StageWriteAccessDecoration, stageWriteAccess, 0, 0) + INST_RANGE(StageAccessDecoration, StageReadAccessDecoration, StageWriteAccessDecoration) + INST(SemanticDecoration, semantic, 2, 0) INST_RANGE(Decoration, HighLevelDeclDecoration, SemanticDecoration) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index bde7be24c..334815d54 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -575,6 +575,30 @@ struct IRSemanticDecoration : public IRDecoration int getSemanticIndex() { return int(getIntVal(getSemanticIndexOperand())); } }; +struct IRStageAccessDecoration : public IRDecoration +{ + IR_PARENT_ISA(StageAccessDecoration) + + Int getStageCount() { return (Int) getOperandCount(); } + IRStringLit* getStageOperand(Int index) { return cast<IRStringLit>(getOperand(index)); } + UnownedStringSlice getStageName(Int index) { return getStageOperand(index)->getStringSlice(); } +}; + +struct IRStageReadAccessDecoration : public IRStageAccessDecoration +{ + IR_LEAF_ISA(StageReadAccessDecoration) +}; + +struct IRStageWriteAccessDecoration : public IRStageAccessDecoration +{ + IR_LEAF_ISA(StageWriteAccessDecoration) +}; + +struct IRPayloadDecoration : public IRDecoration +{ + IR_LEAF_ISA(PayloadDecoration) +}; + /// An attribute that can be attached to another instruction as an operand. /// /// Attributes serve a similar role to decorations, in that both are ways diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 58a5b0ed1..f0066b543 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -6191,6 +6191,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> addNameHint(context, irStruct, decl); addLinkageDecoration(context, irStruct, decl); + if( auto payloadAttribute = decl->findModifier<PayloadAttribute>() ) + { + subBuilder->addDecoration(irStruct, kIROp_PayloadDecoration); + } + subBuilder->setInsertInto(irStruct); // A `struct` that inherits from another `struct` must start @@ -6261,6 +6266,20 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> return LoweredValInfo::simple(finishOuterGenerics(subBuilder, irStruct, outerGeneric)); } + void lowerRayPayloadAccessModifier(IRInst* inst, RayPayloadAccessSemantic* semantic, IROp op) + { + auto builder = getBuilder(); + + List<IRInst*> operands; + for(auto stageNameToken : semantic->stageNameTokens) + { + IRInst* stageName = builder->getStringValue(stageNameToken.getContent()); + operands.add(stageName); + } + + builder->addDecoration(inst, op, operands.getBuffer(), operands.getCount()); + } + LoweredValInfo lowerMemberVarDecl(VarDecl* fieldDecl) { // Each field declaration in the AST translates into @@ -6285,6 +6304,15 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> builder->addSemanticDecoration(irFieldKey, semanticModifier->name.getName()->text.getUnownedSlice()); } + if( auto readModifier = fieldDecl->findModifier<RayPayloadReadSemantic>() ) + { + lowerRayPayloadAccessModifier(irFieldKey, readModifier, kIROp_StageReadAccessDecoration); + } + if( auto writeModifier = fieldDecl->findModifier<RayPayloadWriteSemantic>()) + { + lowerRayPayloadAccessModifier(irFieldKey, writeModifier, kIROp_StageWriteAccessDecoration); + } + // We allow a field to be marked as a target intrinsic, // so that we can override its mangled name in the // output for the chosen target. diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index 8ea51645a..68d06714d 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -2202,6 +2202,40 @@ namespace Slang parser->sink->diagnose(semantic, Diagnostics::packOffsetNotSupported); } + static RayPayloadAccessSemantic* _parseRayPayloadAccessSemantic(Parser* parser, RayPayloadAccessSemantic* semantic) + { + parser->FillPosition(semantic); + + // Read the keyword that introduced the semantic + semantic->name = parser->ReadToken(TokenType::Identifier); + + parser->ReadToken(TokenType::LParent); + + for(;;) + { + if(AdvanceIfMatch(parser, TokenType::RParent)) + break; + + auto stageName = parser->ReadToken(TokenType::Identifier); + semantic->stageNameTokens.add(stageName); + + if(AdvanceIfMatch(parser, TokenType::RParent)) + break; + + expect(parser, TokenType::Comma); + } + + return semantic; + } + + template<typename T> + static T* _parseRayPayloadAccessSemantic(Parser* parser) + { + T* semantic = parser->astBuilder->create<T>(); + _parseRayPayloadAccessSemantic(parser, semantic); + return semantic; + } + // // semantic ::= identifier ( '(' args ')' )? // @@ -2222,6 +2256,14 @@ namespace Slang parseHLSLPackOffsetSemantic(parser, semantic); return semantic; } + else if( parser->LookAheadToken("read") && parser->LookAheadToken(TokenType::LParent, 1) ) + { + return _parseRayPayloadAccessSemantic<RayPayloadReadSemantic>(parser); + } + else if( parser->LookAheadToken("write") && parser->LookAheadToken(TokenType::LParent, 1) ) + { + return _parseRayPayloadAccessSemantic<RayPayloadWriteSemantic>(parser); + } else if (parser->LookAheadToken(TokenType::Identifier)) { HLSLSimpleSemantic* semantic = parser->astBuilder->create<HLSLSimpleSemantic>(); @@ -3414,6 +3456,21 @@ namespace Slang FillPosition(rs); ReadToken("struct"); + // The `struct` keyword may optionally be followed by + // attributes that appertain to the struct declaration + // itself, and not to any variables declared using this + // type specifier. + // + // TODO: We don't yet correctly associate attributes with + // a variable decarlation vs. a struct type when a variable + // is declared with a struct type specified. + // + if(LookAheadToken(TokenType::LBracket)) + { + Modifier** modifierLink = &rs->modifiers.first; + ParseSquareBracketAttributes(this, &modifierLink); + } + // TODO: support `struct` declaration without tag rs->nameAndLoc = expectIdentifier(this); |
