diff options
| author | ArielG-NV <159081215+ArielG-NV@users.noreply.github.com> | 2024-06-28 04:07:12 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-28 04:07:12 -0400 |
| commit | e49419b0637a357d2e713a0435f0c5ad0c102487 (patch) | |
| tree | 61f815078f7b3b6187abd28101cea76f611462a2 | |
| parent | fd32b1879c8a4de7e97a99be7e0e8093ade8b340 (diff) | |
Implement HLSL resource bindings and default type `float4` to `SubpassInput<T>` (#4462)
* Add case to `emitVectorReshape` for `vector<>` type, `scalar` value
1. Add new case
2. Add test
* fix warning
* fix warning
* Implement HLSL resource bindings and default type `float4` to `SubpassInput<T>`
fixes: #4440
1. Removed GLSLInputAttachmentIndexLayout modifier and the somewhat 'hacky' binding model 'Input Attachment' previously relied upon. This was changed to work with the slang-type-layout rules system. This change allows Slang automatic bindings, HLSL bindings, GLSL bindings, and translation of GLSL to and from HLSL bindings to work.
2. Added default argument `float4` to SubpassInput<T>.
3. Merged glsl.meta and hlsl.meta SubpassInput logic.
* fix InputAttachment attribute checks
fix InputAttachment attribute checks for HLSL and GLSL syntax
* remove unused var
* validate attribute correctly
Attributes do not have type information. We must check the type expression to validate attribute usage.
* remove hacky validation
type based validation before types are fully resolved is quite hacky and unstable to changes and wrapped types
* fix warning
* remove redundant `!= nullptr`
* remove extra `!= nullptr`
* fix some warnings/errors
* subpass capability to limit to dxc & remove default values in some functions
* revert logic to previous logic
revert logic to return if we have a binding regardless of if a VarDecl is given the binding
24 files changed, 243 insertions, 175 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 6b396a621..631c09d19 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -2475,6 +2475,9 @@ attribute_syntax [vk_index(index : int)] : GLSLIndexAttribute; __attributeTarget(FuncDecl) attribute_syntax [vk_spirv_instruction(op : int, set : String = "")] : SPIRVInstructionOpAttribute; +__attributeTarget(VarDeclBase) +attribute_syntax [vk_input_attachment_index(location : int)] : GLSLInputAttachmentIndexLayoutAttribute; + __attributeTarget(FuncDecl) attribute_syntax [spv_target_env_1_3] : SPIRVTargetEnv13Attribute; diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang index f18e07fbd..85d39493b 100644 --- a/source/slang/glsl.meta.slang +++ b/source/slang/glsl.meta.slang @@ -9556,20 +9556,7 @@ ${{{{ [require(glsl_hlsl_spirv, subpass)] public T subpassLoad(__SubpassImpl<T,0> subpass) { - __target_switch - { - case hlsl: return subpass.SubpassLoad(); - case glsl: __intrinsic_asm "subpassLoad($0)"; - case spirv: - { - let zeroVec = ivec2(0); - return spirv_asm - { - OpCapability StorageImageReadWithoutFormat; - result:$$T = OpImageRead $subpass $zeroVec - }; - } - } + return subpass.SubpassLoad(); } __generic<T> [__NoSideEffect] @@ -9577,20 +9564,7 @@ ${{{{ [require(glsl_hlsl_spirv, subpass)] public T subpassLoad(__SubpassImpl<T,1> subpass, int sample) { - __target_switch - { - case hlsl: return subpass.SubpassLoad(sample); - case glsl: __intrinsic_asm "subpassLoad($0, $1)"; - case spirv: - { - let zeroVec = ivec2(0); - return spirv_asm - { - OpCapability StorageImageReadWithoutFormat; - result:$$T = OpImageRead $subpass $zeroVec Sample $sample - }; - } - } + return subpass.SubpassLoad(sample); } /// Section 8.19. Shader Invocation Group Functions diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 0a440f986..8509b4005 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -17304,19 +17304,20 @@ struct __SubpassImpl<T, let isMS:int> { } -__generic<T, let isMS:int=0> +__generic<T = float4, let isMS:int=0> typealias SubpassInput = __SubpassImpl<T, isMS>; __generic<T> extension __SubpassImpl<T, 0> { [ForceInline] - [require(hlsl_spirv, subpass)] + [require(glsl_hlsl_spirv, subpass)] T SubpassLoad() { __target_switch { case hlsl: __intrinsic_asm "$0.SubpassLoad()"; + case glsl: __intrinsic_asm "subpassLoad($0)"; case spirv: { let zeroVec = int2(0); @@ -17330,19 +17331,20 @@ extension __SubpassImpl<T, 0> } } -__generic<T, let isMS:int=1> +__generic<T = float4, let isMS:int=1> typealias SubpassInputMS = __SubpassImpl<T, isMS>; __generic<T> extension __SubpassImpl<T, 1> { [ForceInline] - [require(hlsl_spirv, subpass)] + [require(glsl_hlsl_spirv, subpass)] T SubpassLoad(int sample) { __target_switch { case hlsl: __intrinsic_asm "$0.SubpassLoad($1)"; + case glsl: __intrinsic_asm "subpassLoad($0, $1)"; case spirv: { let zeroVec = int2(0); diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index 39e167ab8..a4e01477c 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -242,11 +242,6 @@ class GLSLLocationLayoutModifier : public GLSLParsedLayoutModifier SLANG_AST_CLASS(GLSLLocationLayoutModifier) }; -class GLSLInputAttachmentIndexLayoutModifier : public GLSLParsedLayoutModifier -{ - SLANG_AST_CLASS(GLSLInputAttachmentIndexLayoutModifier) -}; - class GLSLBufferDataLayoutModifier : public GLSLParsedLayoutModifier { SLANG_AST_CLASS(GLSLBufferDataLayoutModifier) @@ -775,6 +770,14 @@ class GLSLSimpleIntegerLayoutAttribute : public Attribute int32_t value = 0; }; +/// [[vk_input_attachment_index]] +class GLSLInputAttachmentIndexLayoutAttribute : public Attribute +{ + SLANG_AST_CLASS(GLSLInputAttachmentIndexLayoutAttribute) + + IntegerLiteralValue location; +}; + // [[vk_location]] class GLSLLocationAttribute : public GLSLSimpleIntegerLayoutAttribute { diff --git a/source/slang/slang-capabilities.capdef b/source/slang/slang-capabilities.capdef index b011021bc..1511c3a08 100644 --- a/source/slang/slang-capabilities.capdef +++ b/source/slang/slang-capabilities.capdef @@ -410,7 +410,7 @@ alias atomicfloat2 = GL_EXT_shader_atomic_float2 | _sm_6_6 + hlsl_nvapi | cpp | alias fragmentshaderbarycentric = GL_EXT_fragment_shader_barycentric | _sm_6_1; alias shadermemorycontrol = glsl | _spirv_1_0 | _sm_5_0; alias shadermemorycontrol_compute = raytracingstages_compute + shadermemorycontrol; -alias subpass = fragment + any_gfx_target; +alias subpass = fragment + _sm_6_0 | fragment + any_gfx_target; alias waveprefix = _sm_6_5 | _cuda_sm_7_0 | GL_KHR_shader_subgroup_arithmetic; alias bufferreference = GL_EXT_buffer_reference; alias bufferreference_int64 = bufferreference + GL_EXT_shader_explicit_arithmetic_types_int64; diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp index aa30f66ca..7721fedbf 100644 --- a/source/slang/slang-check-modifier.cpp +++ b/source/slang/slang-check-modifier.cpp @@ -474,6 +474,17 @@ namespace Slang } overloadRankAttr->rank = int32_t(rank->getValue()); } + else if (auto inputAttachmentIndexLayoutAttribute = as<GLSLInputAttachmentIndexLayoutAttribute>(attr)) + { + if (attr->args.getCount() != 1) + return false; + + auto location = checkConstantIntVal(attr->args[0]); + if(!location) + return false; + + inputAttachmentIndexLayoutAttribute->location = location->getValue(); + } else if (auto bindingAttr = as<GLSLBindingAttribute>(attr)) { // This must be vk::binding or gl::binding (as specified in core.meta.slang under vk_binding/gl_binding) @@ -1105,7 +1116,7 @@ namespace Slang case ASTNodeType::GLSLParsedLayoutModifier: case ASTNodeType::GLSLConstantIDLayoutModifier: case ASTNodeType::GLSLLocationLayoutModifier: - case ASTNodeType::GLSLInputAttachmentIndexLayoutModifier: + case ASTNodeType::GLSLInputAttachmentIndexLayoutAttribute: case ASTNodeType::GLSLOffsetLayoutAttribute: case ASTNodeType::GLSLUnparsedLayoutModifier: case ASTNodeType::GLSLLayoutModifierGroupMarker: @@ -1185,7 +1196,7 @@ namespace Slang case ASTNodeType::GLSLParsedLayoutModifier: case ASTNodeType::GLSLConstantIDLayoutModifier: case ASTNodeType::GLSLLocationLayoutModifier: - case ASTNodeType::GLSLInputAttachmentIndexLayoutModifier: + case ASTNodeType::GLSLInputAttachmentIndexLayoutAttribute: case ASTNodeType::GLSLOffsetLayoutAttribute: case ASTNodeType::GLSLUnparsedLayoutModifier: case ASTNodeType::GLSLLayoutModifierGroupMarker: diff --git a/source/slang/slang-check-shader.cpp b/source/slang/slang-check-shader.cpp index 67abb56b7..14495dd6e 100644 --- a/source/slang/slang-check-shader.cpp +++ b/source/slang/slang-check-shader.cpp @@ -312,6 +312,8 @@ namespace Slang { if (as<ResourceType>(type)) return true; + if (as<SubpassInputType>(type)) + return true; if (as<HLSLStructuredBufferTypeBase>(type)) return true; if (as<UntypedBufferResourceType>(type)) diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 5b9c3e65a..cb994b904 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -453,7 +453,6 @@ DIAGNOSTIC(31203, Error, cannotExportIncompleteType, "cannot export incomplete t DIAGNOSTIC(31204, Error, incompleteTypeCannotBeUsedInBuffer, "incomplete type '$0' cannot be used in a buffer") DIAGNOSTIC(31205, Error, incompleteTypeCannotBeUsedInUniformParameter, "incomplete type '$0' cannot be used in a uniform parameter") DIAGNOSTIC(31206, Error, memoryQualifierNotAllowedOnANonImageTypeParameter, "modifier $0 is not allowed on a non image type parameter.") -DIAGNOSTIC(31207, Error, InputAttachmentIndexOnlyAllowedOnSubpass, "input_attachment_index is only allowed on subpass images.") DIAGNOSTIC(31208, Error, requireInputDecoratedVarForParameter, "$0 expects for argument $1 a type which is a shader input (`in`) variable.") DIAGNOSTIC(31210, Error, derivativeGroupQuadMustBeMultiple2ForXYThreads, "compute derivative group quad requires thread dispatch count of X and Y to each be at a multiple of 2") DIAGNOSTIC(31211, Error, derivativeGroupLinearMustBeMultiple4ForTotalThreadCount, "compute derivative group linear requires total thread dispatch count to be at a multiple of 4") diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index 6062875b3..66ee12ca6 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -3160,9 +3160,14 @@ void CLikeSourceEmitter::emitSemantics(IRInst* inst, bool allowOffsetLayout) emitSemanticsImpl(inst, allowOffsetLayout); } +void CLikeSourceEmitter::emitDecorationLayoutSemantics(IRInst* inst, char const* uniformSemanticSpelling) +{ + emitLayoutSemanticsImpl(inst, uniformSemanticSpelling, EmitLayoutSemanticOption::kPreType); +} + void CLikeSourceEmitter::emitLayoutSemantics(IRInst* inst, char const* uniformSemanticSpelling) { - emitLayoutSemanticsImpl(inst, uniformSemanticSpelling); + emitLayoutSemanticsImpl(inst, uniformSemanticSpelling, EmitLayoutSemanticOption::kPostType); } void CLikeSourceEmitter::emitRegion(Region* inRegion) @@ -3959,7 +3964,7 @@ void CLikeSourceEmitter::emitVar(IRVar* varDecl) emitType(varType, getName(varDecl)); emitSemantics(varDecl); - emitLayoutSemantics(varDecl); + emitLayoutSemantics(varDecl, "register"); emitPostDeclarationAttributesForType(varType); // TODO: ideally this logic should scan ahead to see if it can find a `store` @@ -4092,7 +4097,7 @@ void CLikeSourceEmitter::emitGlobalVar(IRGlobalVar* varDecl) // global variables. // emitSemantics(varDecl); - emitLayoutSemantics(varDecl); + emitLayoutSemantics(varDecl, "register"); if (varDecl->getFirstBlock()) { @@ -4155,13 +4160,15 @@ void CLikeSourceEmitter::emitGlobalParam(IRGlobalParam* varDecl) SLANG_ASSERT(layout); emitVarModifiers(layout, varDecl, varType); + + emitDecorationLayoutSemantics(varDecl, "register"); emitRateQualifiersAndAddressSpace(varDecl); emitType(varType, getName(varDecl)); emitSemantics(varDecl); - emitLayoutSemantics(varDecl); + emitLayoutSemantics(varDecl, "register"); // A shader parameter cannot have an initializer, // so we do need to consider emitting one here. diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h index ecff57296..07cb4a0bc 100644 --- a/source/slang/slang-emit-c-like.h +++ b/source/slang/slang-emit-c-like.h @@ -20,6 +20,13 @@ namespace Slang class CLikeSourceEmitter: public SourceEmitterBase { public: + + enum class EmitLayoutSemanticOption + { + kPreType, + kPostType + }; + struct Desc { CodeGenContext* codeGenContext = nullptr; @@ -344,7 +351,8 @@ public: void emitSemantics(IRInst* inst, bool allowOffsets = false); void emitSemanticsUsingVarLayout(IRVarLayout* varLayout); - void emitLayoutSemantics(IRInst* inst, char const* uniformSemanticSpelling = "register"); + void emitDecorationLayoutSemantics(IRInst* inst, char const* uniformSemanticSpelling); + void emitLayoutSemantics(IRInst* inst, char const* uniformSemanticSpelling); /// Emit high-level language statements from a structured region. void emitRegion(Region* inRegion); @@ -463,7 +471,7 @@ public: virtual void emitPostDeclarationAttributesForType(IRInst* type) { SLANG_UNUSED(type); } virtual bool doesTargetSupportPtrTypes() { return false; } - virtual void emitLayoutSemanticsImpl(IRInst* inst, char const* uniformSemanticSpelling = "register") { SLANG_UNUSED(inst); SLANG_UNUSED(uniformSemanticSpelling); } + virtual void emitLayoutSemanticsImpl(IRInst* inst, char const* uniformSemanticSpelling, EmitLayoutSemanticOption layoutSemanticOption) { SLANG_UNUSED(inst); SLANG_UNUSED(uniformSemanticSpelling); SLANG_UNUSED(layoutSemanticOption); } virtual void emitParameterGroupImpl(IRGlobalParam* varDecl, IRUniformParameterGroupType* type) = 0; virtual void emitEntryPointAttributesImpl(IRFunc* irFunc, IREntryPointDecoration* entryPointDecor) = 0; diff --git a/source/slang/slang-emit-cuda.cpp b/source/slang/slang-emit-cuda.cpp index 2417a64ec..f4b45b7aa 100644 --- a/source/slang/slang-emit-cuda.cpp +++ b/source/slang/slang-emit-cuda.cpp @@ -212,9 +212,9 @@ SlangResult CUDASourceEmitter::calcTypeName(IRType* type, CodeGenTarget target, return Super::calcTypeName(type, target, out); } -void CUDASourceEmitter::emitLayoutSemanticsImpl(IRInst* inst, char const* uniformSemanticSpelling) +void CUDASourceEmitter::emitLayoutSemanticsImpl(IRInst* inst, char const* uniformSemanticSpelling, EmitLayoutSemanticOption layoutSemanticOption) { - Super::emitLayoutSemanticsImpl(inst, uniformSemanticSpelling); + Super::emitLayoutSemanticsImpl(inst, uniformSemanticSpelling, layoutSemanticOption); } void CUDASourceEmitter::emitParameterGroupImpl(IRGlobalParam* varDecl, IRUniformParameterGroupType* type) diff --git a/source/slang/slang-emit-cuda.h b/source/slang/slang-emit-cuda.h index 13a497343..5d76c4ef3 100644 --- a/source/slang/slang-emit-cuda.h +++ b/source/slang/slang-emit-cuda.h @@ -63,7 +63,7 @@ public: protected: - virtual void emitLayoutSemanticsImpl(IRInst* inst, char const* uniformSemanticSpelling) SLANG_OVERRIDE; + virtual void emitLayoutSemanticsImpl(IRInst* inst, char const* uniformSemanticSpelling, EmitLayoutSemanticOption layoutSemanticOption) SLANG_OVERRIDE; virtual void emitParameterGroupImpl(IRGlobalParam* varDecl, IRUniformParameterGroupType* type) SLANG_OVERRIDE; virtual void emitEntryPointAttributesImpl(IRFunc* irFunc, IREntryPointDecoration* entryPointDecor) SLANG_OVERRIDE; diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index b6c3c0d67..7cf478c36 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -751,6 +751,11 @@ bool GLSLSourceEmitter::_emitGLSLLayoutQualifierWithBindingKinds(LayoutResourceK m_writer->emit("layout(shaderRecordEXT)\n"); break; + case LayoutResourceKind::InputAttachmentIndex: + m_writer->emit("layout(input_attachment_index = "); + m_writer->emit(index); + m_writer->emit(")\n"); + break; } return true; } @@ -1338,7 +1343,7 @@ void GLSLSourceEmitter::_emitGLSLPerVertexVaryingFragmentInput(IRGlobalParam* pa emitSemantics(param, false); - emitLayoutSemantics(param); + emitLayoutSemantics(param, "register"); m_writer->emit(";\n\n"); } @@ -2825,16 +2830,6 @@ void GLSLSourceEmitter::emitVarDecorationsImpl(IRInst* varDecl) break; } - // non raytracing decorations - for (auto decoration : varDecl->getDecorations()) - { - if (auto glslInputAttachment = as<IRGLSLInputAttachmentIndexDecoration>(decoration)) - { - m_writer->emit(toSlice("layout(input_attachment_index = ")); - m_writer->emit(glslInputAttachment->getIndex()->getValue()); - m_writer->emit(toSlice(")\n")); - } - } } void GLSLSourceEmitter::emitMatrixLayoutModifiersImpl(IRVarLayout* layout) diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp index 04f5bd643..4d3830969 100644 --- a/source/slang/slang-emit-hlsl.cpp +++ b/source/slang/slang-emit-hlsl.cpp @@ -93,6 +93,13 @@ void HLSLSourceEmitter::_emitHLSLRegisterSemantic(LayoutResourceKind kind, EmitV break; case LayoutResourceKind::InputAttachmentIndex: + { + m_writer->emit("[[vk::input_attachment_index("); + m_writer->emit(index); + m_writer->emit(")]]"); + } + break; + case LayoutResourceKind::RegisterSpace: case LayoutResourceKind::GenericResource: case LayoutResourceKind::ExistentialTypeParam: @@ -141,7 +148,7 @@ void HLSLSourceEmitter::_emitHLSLRegisterSemantic(LayoutResourceKind kind, EmitV } } -void HLSLSourceEmitter::_emitHLSLRegisterSemantics(EmitVarChain* chain, IRInst* inst, char const* uniformSemanticSpelling) +void HLSLSourceEmitter::_emitHLSLRegisterSemantics(EmitVarChain* chain, IRInst* inst, char const* uniformSemanticSpelling, EmitLayoutSemanticOption layoutSemanticOption) { if (!chain) return; @@ -158,17 +165,20 @@ void HLSLSourceEmitter::_emitHLSLRegisterSemantics(EmitVarChain* chain, IRInst* for (auto rr : layout->getOffsetAttrs()) { + if (layoutSemanticOption == EmitLayoutSemanticOption::kPreType + && rr->getResourceKind() != LayoutResourceKind::InputAttachmentIndex) + continue; _emitHLSLRegisterSemantic(rr->getResourceKind(), chain, inst, uniformSemanticSpelling); } } -void HLSLSourceEmitter::_emitHLSLRegisterSemantics(IRVarLayout* varLayout, IRInst* inst, char const* uniformSemanticSpelling) +void HLSLSourceEmitter::_emitHLSLRegisterSemantics(IRVarLayout* varLayout, IRInst* inst, char const* uniformSemanticSpelling, EmitLayoutSemanticOption layoutSemanticOption) { if (!varLayout) return; EmitVarChain chain(varLayout); - _emitHLSLRegisterSemantics(&chain, inst, uniformSemanticSpelling); + _emitHLSLRegisterSemantics(&chain, inst, uniformSemanticSpelling, layoutSemanticOption); } void HLSLSourceEmitter::_emitHLSLParameterGroupFieldLayoutSemantics(EmitVarChain* chain) @@ -220,7 +230,7 @@ void HLSLSourceEmitter::_emitHLSLParameterGroup(IRGlobalParam* varDecl, IRUnifor typeLayout = parameterGroupTypeLayout->getElementVarLayout()->getTypeLayout(); } - _emitHLSLRegisterSemantic(layoutResourceKind, &containerChain, varDecl); + _emitHLSLRegisterSemantic(layoutResourceKind, &containerChain, varDecl, "register"); auto elementType = type->getElementType(); if (shouldForceUnpackConstantBufferElements(type) || hasExplicitConstantBufferOffset(type)) @@ -320,12 +330,12 @@ void HLSLSourceEmitter::_emitHLSLSubpassInputType(IRSubpassInputType* subpassTyp m_writer->emit(">"); } -void HLSLSourceEmitter::emitLayoutSemanticsImpl(IRInst* inst, char const* uniformSemanticSpelling) +void HLSLSourceEmitter::emitLayoutSemanticsImpl(IRInst* inst, char const* uniformSemanticSpelling, EmitLayoutSemanticOption layoutSemanticOption) { auto layout = getVarLayout(inst); if (layout) { - _emitHLSLRegisterSemantics(layout, inst, uniformSemanticSpelling); + _emitHLSLRegisterSemantics(layout, inst, uniformSemanticSpelling, layoutSemanticOption); } } @@ -1281,13 +1291,6 @@ void HLSLSourceEmitter::emitVarDecorationsImpl(IRInst* varDecl) { for(auto decoration : varDecl->getDecorations()) { - if(auto glslInputAttachmentIndex = as<IRGLSLInputAttachmentIndexDecoration>(decoration)) - { - m_writer->emit("[[vk::input_attachment_index("); - m_writer->emit(glslInputAttachmentIndex->getIndex()->getValue()); - m_writer->emit(")]]\n"); - continue; - } if (auto collection = as<IRMemoryQualifierSetDecoration>(decoration)) { auto flags = collection->getMemoryQualifierBit(); diff --git a/source/slang/slang-emit-hlsl.h b/source/slang/slang-emit-hlsl.h index 30f38b415..abc673a3d 100644 --- a/source/slang/slang-emit-hlsl.h +++ b/source/slang/slang-emit-hlsl.h @@ -29,7 +29,7 @@ public: protected: RefPtr<HLSLExtensionTracker> m_extensionTracker; - virtual void emitLayoutSemanticsImpl(IRInst* inst, char const* uniformSemanticSpelling) SLANG_OVERRIDE; + virtual void emitLayoutSemanticsImpl(IRInst* inst, char const* uniformSemanticSpelling, EmitLayoutSemanticOption layoutSemanticOption) SLANG_OVERRIDE; virtual void emitParameterGroupImpl(IRGlobalParam* varDecl, IRUniformParameterGroupType* type) SLANG_OVERRIDE; virtual void emitEntryPointAttributesImpl(IRFunc* irFunc, IREntryPointDecoration* entryPointDecor) SLANG_OVERRIDE; @@ -66,11 +66,11 @@ protected: // 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, IRInst* inst, char const* uniformSemanticSpelling = "register"); + void _emitHLSLRegisterSemantic(LayoutResourceKind kind, EmitVarChain* chain, IRInst* inst, char const* uniformSemanticSpelling); // Emit all the `register` semantics that are appropriate for a particular variable layout - void _emitHLSLRegisterSemantics(EmitVarChain* chain, IRInst* inst, char const* uniformSemanticSpelling = "register"); - void _emitHLSLRegisterSemantics(IRVarLayout* varLayout, IRInst* inst, char const* uniformSemanticSpelling = "register"); + void _emitHLSLRegisterSemantics(EmitVarChain* chain, IRInst* inst, char const* uniformSemanticSpelling, EmitLayoutSemanticOption layoutSemanticOption); + void _emitHLSLRegisterSemantics(IRVarLayout* varLayout, IRInst* inst, char const* uniformSemanticSpelling, EmitLayoutSemanticOption layoutSemanticOption); void _emitHLSLParameterGroupFieldLayoutSemantics(EmitVarChain* chain); void _emitHLSLParameterGroupFieldLayoutSemantics(IRVarLayout* fieldLayout, EmitVarChain* inChain); diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 51a71d65c..1a4d80ae1 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -2230,6 +2230,16 @@ struct SPIRVEmitContext isDescirptorSetDecorated = true; } break; + case LayoutResourceKind::InputAttachmentIndex: + { + emitOpDecorateInputAttachmentIndex( + getSection(SpvLogicalSectionID::Annotations), + nullptr, + varInst, + SpvLiteralInteger::from32((int32_t)index) + ); + } + break; default: break; } @@ -3576,17 +3586,6 @@ struct SPIRVEmitContext ); } break; - case kIROp_GLSLInputAttachmentIndexDecoration: - { - const auto c = cast<IRGLSLInputAttachmentIndexDecoration>(decoration); - emitOpDecorateInputAttachmentIndex( - getSection(SpvLogicalSectionID::Annotations), - decoration, - dstID, - SpvLiteralInteger::from32(int32_t(c->getIndex()->getValue())) - ); - } - break; case kIROp_VulkanHitAttributesDecoration: case kIROp_VulkanCallablePayloadDecoration: diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 19117c00e..3132536e3 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -893,7 +893,6 @@ INST_RANGE(BindingQuery, GetRegisterIndex, GetRegisterSpace) INST(GlobalOutputDecoration, output, 0, 0) INST(GlobalInputDecoration, output, 0, 0) INST(GLSLLocationDecoration, glslLocation, 1, 0) - INST(GLSLInputAttachmentIndexDecoration, glslInputAttachmentIndex, 1, 0) INST(GLSLOffsetDecoration, glslOffset, 1, 0) INST(PayloadDecoration, payload, 0, 0) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index a63cc5c22..fb9a9613a 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -437,11 +437,6 @@ struct IRGLSLLocationDecoration : IRDecoration IRIntLit* getLocation() { return cast<IRIntLit>(getOperand(0)); } }; -struct IRGLSLInputAttachmentIndexDecoration : IRDecoration -{ - IR_LEAF_ISA(GLSLInputAttachmentIndexDecoration) - IRIntLit* getIndex() { return cast<IRIntLit>(getOperand(0)); } -}; struct IRGLSLOffsetDecoration : IRDecoration { diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index cc4704fe9..c946072f9 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -2212,16 +2212,6 @@ void addVarDecorations( builder->addDecoration(inst, kIROp_GLSLLocationDecoration, builder->getIntValue(builder->getIntType(), stringToInt(glslLocationMod->valToken.getContent()))); } - else if (auto glslInputAttachmentMod = as<GLSLInputAttachmentIndexLayoutModifier>(mod)) - { - auto subpassType = as<IRSubpassInputType>(inst->getDataType()); - - if (!subpassType) - context->getSink()->diagnose(inst, Diagnostics::InputAttachmentIndexOnlyAllowedOnSubpass); - - builder->addDecoration(inst, kIROp_GLSLInputAttachmentIndexDecoration, - builder->getIntValue(builder->getIntType(), stringToInt(glslInputAttachmentMod->valToken.getContent()))); - } else if (auto glslOffsetMod = as<GLSLOffsetLayoutAttribute>(mod)) { builder->addDecoration(inst, kIROp_GLSLOffsetDecoration, diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index d76dda4e1..6a1080b0e 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -996,6 +996,16 @@ static void addExplicitParameterBindings_HLSL( // If the declaration has explicit binding modifiers, then // here is where we want to extract and apply them... + if (auto inputAttachmentIndexLayoutAttribute = varDecl.getDecl()->findModifier<GLSLInputAttachmentIndexLayoutAttribute>()) + { + LayoutSemanticInfo semanticInfo; + semanticInfo.index = (UInt)inputAttachmentIndexLayoutAttribute->location; + semanticInfo.space = 0; + semanticInfo.kind = LayoutResourceKind::InputAttachmentIndex; + + if (auto varDeclBase = varDecl.as<VarDeclBase>()) + addExplicitParameterBinding(context, parameterInfo, varDeclBase.getDecl(), semanticInfo, 1); + } // Look for HLSL `register` or `packoffset` semantics. for (auto semantic : varDecl.getDecl()->getModifiersOfType<HLSLLayoutSemantic>()) @@ -1065,82 +1075,96 @@ static void addExplicitParameterBindings_GLSL( // the index/offset/etc. // - TypeLayout::ResourceInfo* resInfo = nullptr; - TypeLayout::ResourceInfo* foundResInfo = nullptr; - - LayoutSemanticInfo semanticInfo; - semanticInfo.index = 0; - semanticInfo.space = 0; + enum + { + kResInfo = 0, + kSubpassResInfo, + kMaxResCount, + }; - LayoutSemanticInfo subpassSemanticInfo; - bool foundBinding = false; - bool foundSubpass = false; + TypeLayout::ResourceInfo* foundResInfo = nullptr; + struct ResAndSemanticInfo + { + TypeLayout::ResourceInfo* resInfo = nullptr; + LayoutSemanticInfo semanticInfo; + ResAndSemanticInfo() + { + semanticInfo.index = 0; + semanticInfo.space = 0; + } + }; + ResAndSemanticInfo info[kMaxResCount] = {}; + + if (auto foundInputAttachmentIndex = typeLayout->FindResourceInfo(LayoutResourceKind::InputAttachmentIndex)) + { + foundResInfo = foundInputAttachmentIndex; + // Try to find `input_attachment_index` + if (auto glslAttachmentIndexAttr = varDecl.getDecl()->findModifier<GLSLInputAttachmentIndexLayoutAttribute>()) + { + info[kSubpassResInfo].resInfo = foundResInfo; + // Subpass fills semantic info of a descriptor and subpass + info[kSubpassResInfo].semanticInfo.index = (UInt)glslAttachmentIndexAttr->location; + info[kSubpassResInfo].semanticInfo.space = 0; + } + } - if( (foundResInfo = typeLayout->FindResourceInfo(LayoutResourceKind::DescriptorTableSlot)) != nullptr ) + if(auto foundDescriptorTableSlot = typeLayout->FindResourceInfo(LayoutResourceKind::DescriptorTableSlot)) { - for (auto dec : varDecl.getDecl()->modifiers) + foundResInfo = foundDescriptorTableSlot; + // Try to find `binding` and `set` + if (auto glslBindingAttr = varDecl.getDecl()->findModifier<GLSLBindingAttribute>()) { - // Try to find `binding` and `set` - if (auto glslBindingAttr = as<GLSLBindingAttribute>(dec)) - { - resInfo = foundResInfo; - semanticInfo.index = glslBindingAttr->binding; - semanticInfo.space = glslBindingAttr->set; - foundBinding = true; - if (foundSubpass) - break; - } - // Try to find `input_attachment_index` - else if (auto glslAttachmentIndexAttr = as<GLSLInputAttachmentIndexLayoutModifier>(dec)) - { - // Subpass fills semantic info of a descriptor & subpass - subpassSemanticInfo.index = stringToInt(glslAttachmentIndexAttr->valToken.getContent()); - subpassSemanticInfo.space = 0; - subpassSemanticInfo.kind = LayoutResourceKind::InputAttachmentIndex; - foundSubpass = true; - if (foundBinding) - break; - } + info[kResInfo].resInfo = foundResInfo; + info[kResInfo].semanticInfo.index = glslBindingAttr->binding; + info[kResInfo].semanticInfo.space = glslBindingAttr->set; } } - else if( (foundResInfo = typeLayout->FindResourceInfo(LayoutResourceKind::SubElementRegisterSpace)) != nullptr ) + else if(auto foundSubElementRegisterSpace = typeLayout->FindResourceInfo(LayoutResourceKind::SubElementRegisterSpace)) { + foundResInfo = foundSubElementRegisterSpace; // Try to find `set` if (auto attr = varDecl.getDecl()->findModifier<GLSLBindingAttribute>()) { - resInfo = foundResInfo; + info[kResInfo].resInfo = foundResInfo; if (attr->binding != 0) { getSink(context)->diagnose(attr, Diagnostics::wholeSpaceParameterRequiresZeroBinding, varDecl.getName(), attr->binding); } - semanticInfo.index = attr->set; - semanticInfo.space = 0; + info[kResInfo].semanticInfo.index = attr->set; + info[kResInfo].semanticInfo.space = 0; } } - else if( (resInfo = typeLayout->FindResourceInfo(LayoutResourceKind::SpecializationConstant)) != nullptr ) + else if(auto foundSpecializationConstant = typeLayout->FindResourceInfo(LayoutResourceKind::SpecializationConstant)) { + info[kResInfo].resInfo = foundSpecializationConstant; DeclRef<Decl> varDecl2(varDecl); // Try to find `constant_id` binding - if(!findLayoutArg<GLSLConstantIDLayoutModifier>(varDecl2, &semanticInfo.index)) + if(!findLayoutArg<GLSLConstantIDLayoutModifier>(varDecl2, &info[kResInfo].semanticInfo.index)) return; } - // if we found resInfo, we add the explicit binding - if (resInfo) + + auto varDeclBase = as<VarDeclBase>(varDecl); + bool hasABinding = false; + for (int i = 0; i < kMaxResCount; i++) { - auto kind = resInfo->kind; - auto count = resInfo->count; + auto* resInfoItem = info[i].resInfo; + auto& semanticInfo = info[i].semanticInfo; + if (!resInfoItem) + continue; + + auto kind = resInfoItem->kind; + auto count = resInfoItem->count; semanticInfo.kind = kind; + hasABinding = true; + if(!varDeclBase) + break; - if (auto varDeclBase = varDecl.as<VarDeclBase>()) - { - addExplicitParameterBinding(context, parameterInfo, varDeclBase.getDecl(), semanticInfo, count); - if (foundSubpass) - addExplicitParameterBinding(context, parameterInfo, varDeclBase.getDecl(), subpassSemanticInfo, count); - } - return; + addExplicitParameterBinding(context, parameterInfo, varDeclBase.getDecl(), semanticInfo, count); } + if(hasABinding) + return; auto hlslToVulkanLayoutOptions = context->getTargetProgram()->getHLSLToVulkanLayoutOptions(); bool warnedMissingVulkanLayoutModifier = false; @@ -1196,7 +1220,7 @@ static void addExplicitParameterBindings_GLSL( // We use the HLSL binding directly (even though this notionally for GLSL/Vulkan) // We'll do the shifting at later later point in _maybeApplyHLSLToVulkanShifts - resInfo = typeLayout->findOrAddResourceInfo(hlslInfo.kind); + info[kResInfo].resInfo = typeLayout->findOrAddResourceInfo(hlslInfo.kind); if (warnedMissingVulkanLayoutModifier) { @@ -1205,8 +1229,8 @@ static void addExplicitParameterBindings_GLSL( if(!hlslToVulkanLayoutOptions || hlslToVulkanLayoutOptions->getKindShiftEnabledFlags() == HLSLToVulkanLayoutOptions::KindFlag::None) { - resInfo->kind = LayoutResourceKind::DescriptorTableSlot; - resInfo->count = 1; + info[kResInfo].resInfo->kind = LayoutResourceKind::DescriptorTableSlot; + info[kResInfo].resInfo->count = 1; } else { @@ -1214,12 +1238,12 @@ static void addExplicitParameterBindings_GLSL( } } - semanticInfo.kind = resInfo->kind; - semanticInfo.index = UInt(hlslInfo.index); - semanticInfo.space = UInt(hlslInfo.space); - const LayoutSize count = resInfo->count; + info[kResInfo].semanticInfo.kind = info[kResInfo].resInfo->kind; + info[kResInfo].semanticInfo.index = UInt(hlslInfo.index); + info[kResInfo].semanticInfo.space = UInt(hlslInfo.space); + const LayoutSize count = info[kResInfo].resInfo->count; - addExplicitParameterBinding(context, parameterInfo, as<VarDeclBase>(varDecl.getDecl()), semanticInfo, count); + addExplicitParameterBinding(context, parameterInfo, as<VarDeclBase>(varDecl.getDecl()), info[kResInfo].semanticInfo, count); } // Given a single parameter, collect whatever information we have on diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index 3d9f1c199..e6913c6c0 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -8061,7 +8061,7 @@ namespace Slang GLSLLayoutLocalSizeAttribute* numThreadsAttrib = nullptr; GLSLLayoutDerivativeGroupQuadAttribute* derivativeGroupQuadAttrib = nullptr; GLSLLayoutDerivativeGroupLinearAttribute* derivativeGroupLinearAttrib = nullptr; - + GLSLInputAttachmentIndexLayoutAttribute* inputAttachmentIndexLayoutAttribute = nullptr; ImageFormat format; listBuilder.add(parser->astBuilder->create<GLSLLayoutModifierGroupBegin>()); @@ -8115,6 +8115,17 @@ namespace Slang { derivativeGroupLinearAttrib = parser->astBuilder->create<GLSLLayoutDerivativeGroupLinearAttribute>(); } + else if (nameText == "input_attachment_index") + { + inputAttachmentIndexLayoutAttribute = parser->astBuilder->create<GLSLInputAttachmentIndexLayoutAttribute>(); + if (AdvanceIf(parser, TokenType::OpAssign)) + { + auto token = parser->ReadToken(TokenType::IntegerLiteral); + auto intVal = getIntegerLiteralValue(token); + inputAttachmentIndexLayoutAttribute->location = intVal; + } + + } else if (nameText == "binding" || nameText == "set") { @@ -8165,7 +8176,6 @@ namespace Slang CASE(scalar, GLSLScalarModifier) CASE(offset, GLSLOffsetLayoutAttribute) CASE(location, GLSLLocationLayoutModifier) - CASE(input_attachment_index, GLSLInputAttachmentIndexLayoutModifier) { modifier = parser->astBuilder->create<GLSLUnparsedLayoutModifier>(); } @@ -8227,6 +8237,8 @@ namespace Slang listBuilder.add(derivativeGroupQuadAttrib); if(derivativeGroupLinearAttrib) listBuilder.add(derivativeGroupLinearAttrib); + if(inputAttachmentIndexLayoutAttribute) + listBuilder.add(inputAttachmentIndexLayoutAttribute); listBuilder.add(parser->astBuilder->create<GLSLLayoutModifierGroupEnd>()); diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp index 22aa3f304..293dce7c6 100644 --- a/source/slang/slang-type-layout.cpp +++ b/source/slang/slang-type-layout.cpp @@ -722,6 +722,9 @@ static LayoutResourceKind _getHLSLLayoutResourceKind(ShaderParameterKind kind) { switch (kind) { + case ShaderParameterKind::SubpassInput: + return LayoutResourceKind::InputAttachmentIndex; + case ShaderParameterKind::ConstantBuffer: return LayoutResourceKind::ConstantBuffer; @@ -778,6 +781,13 @@ struct GLSLObjectLayoutRulesImpl : ObjectLayoutRulesImpl } } + switch (kind) + { + case ShaderParameterKind::SubpassInput: + return SimpleLayoutInfo(LayoutResourceKind::InputAttachmentIndex, slotCount); + default: + break; + } return SimpleLayoutInfo(LayoutResourceKind::DescriptorTableSlot, slotCount); } }; @@ -4089,6 +4099,17 @@ static TypeLayoutResult _createTypeLayout( type, rules); } + else if (as<SubpassInputType>(type)) + { + // SubpassInputType fills 2 slots, 'shader resource' and 'input_attachment_index' + auto objLayout1 = rules->GetObjectLayout(ShaderParameterKind::Texture, context.objectLayoutOptions); + auto objLayout2 = rules->GetObjectLayout(ShaderParameterKind::SubpassInput, context.objectLayoutOptions); + objLayout1.layoutInfos.add(objLayout2.layoutInfos.getFirst()); + return createSimpleTypeLayout( + objLayout1, + type, + rules); + } else if (auto textureType = as<TextureType>(type)) { // TODO: the logic here should really be defined by the rules, diff --git a/tests/glsl-intrinsic/subpass-input/input-attachment-index-use-error.slang b/tests/glsl-intrinsic/subpass-input/input-attachment-index-use-error.slang deleted file mode 100644 index 889a4e205..000000000 --- a/tests/glsl-intrinsic/subpass-input/input-attachment-index-use-error.slang +++ /dev/null @@ -1,11 +0,0 @@ -//TEST:SIMPLE(filecheck=CHECK): -target glsl -stage fragment -entry main -allow-glsl -#version 450 - -// CHECK: error 31207 -layout (input_attachment_index = 1, set = 0, binding = 1) uniform vec3 image; - -layout (location = 0) out vec4 outColor; - -void main() { - outColor = vec4(0); -}
\ No newline at end of file diff --git a/tests/glsl-intrinsic/subpass-input/subpass-input-hlsl.slang b/tests/glsl-intrinsic/subpass-input/subpass-input-hlsl.slang new file mode 100644 index 000000000..0b8e4896f --- /dev/null +++ b/tests/glsl-intrinsic/subpass-input/subpass-input-hlsl.slang @@ -0,0 +1,32 @@ +//TEST:SIMPLE(filecheck=CHECK_GLSL): -target glsl -stage fragment -entry main -allow-glsl +//TEST:SIMPLE(filecheck=CHECK_SPV): -target spirv -emit-spirv-directly -stage fragment -entry main -allow-glsl +//TEST:SIMPLE(filecheck=CHECK_HLSL): -target hlsl -stage fragment -entry main -allow-glsl + +// CHECK_SPV-DAG: OpEntryPoint +// CHECK_SPV-DAG: InputAttachmentIndex 3 +// CHECK_SPV-DAG: InputAttachmentIndex + +// CHECK_GLSL-DAG: void main() +// CHECK_GLSL-DAG: input_attachment_index = 3 +// CHECK_GLSL-DAG: input_attachment_index + +// CHECK_HLSL-DAG: main() +// CHECK_HLSL-DAG: [vk::input_attachment_index(3)] +// CHECK_HLSL-DAG: vk::input_attachment_index +[[vk::input_attachment_index(3)]] SubpassInput subpassHLSL1; +SubpassInput subpassHLSL2; + +RWTexture2D<float4> t; + +layout (location = 0) out vec4 outColor; + +void main() { +// CHECK_SPV-COUNT-2: OpImageRead +// CHECK_GLSL-COUNT-2: subpassLoad +// CHECK_HLSL-COUNT-2: SubpassLoad + outColor = vec4(true + && subpassHLSL1.SubpassLoad() == vec4(1) + && subpassHLSL2.SubpassLoad() == vec4(1) + && t.Load(int2(0,0)) != float4(0,0,0,0) + ); +}
\ No newline at end of file |
