diff options
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-hlsl-to-vulkan-layout-options.cpp | 56 | ||||
| -rw-r--r-- | source/slang/slang-hlsl-to-vulkan-layout-options.h | 38 | ||||
| -rw-r--r-- | source/slang/slang-parameter-binding.cpp | 307 | ||||
| -rw-r--r-- | source/slang/slang-type-layout.cpp | 132 | ||||
| -rw-r--r-- | source/slang/slang-type-layout.h | 14 | ||||
| -rw-r--r-- | tests/bindings/hlsl-to-vulkan-array.hlsl | 16 | ||||
| -rw-r--r-- | tests/bindings/hlsl-to-vulkan-array.hlsl.expected | 94 | ||||
| -rw-r--r-- | tests/bindings/hlsl-to-vulkan-combined.hlsl.expected | 8 | ||||
| -rw-r--r-- | tests/bindings/hlsl-to-vulkan-shift-implicit.hlsl | 20 | ||||
| -rw-r--r-- | tests/bindings/hlsl-to-vulkan-shift-implicit.hlsl.expected | 178 | ||||
| -rw-r--r-- | tests/bindings/hlsl-to-vulkan-shift.hlsl | 2 | ||||
| -rw-r--r-- | tests/bindings/hlsl-to-vulkan-shift.hlsl.expected | 26 | ||||
| -rw-r--r-- | tests/diagnostics/hlsl-to-vulkan-shift-diagnostic.hlsl.expected | 11 |
14 files changed, 753 insertions, 151 deletions
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 463c6f525..286551716 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -582,6 +582,8 @@ DIAGNOSTIC(39023, Error, mixingImplicitAndExplicitBindingForVaryingParams, "mixi DIAGNOSTIC(39024, Warning, cannotInferVulkanBindingWithoutRegisterModifier, "shader parameter '$0' doesn't have a 'register' specified, automatic layout will be used") +DIAGNOSTIC(39025, Error, conflictingVulkanInferredBindingForParameter, "conflicting vulkan inferred binding for parameter '$0' overlap is $1 and $2") + // // 4xxxx - IL code generation. diff --git a/source/slang/slang-hlsl-to-vulkan-layout-options.cpp b/source/slang/slang-hlsl-to-vulkan-layout-options.cpp index 1033c0f56..74a3313da 100644 --- a/source/slang/slang-hlsl-to-vulkan-layout-options.cpp +++ b/source/slang/slang-hlsl-to-vulkan-layout-options.cpp @@ -29,7 +29,12 @@ static NamesDescriptionValue s_vulkanShiftKinds[] = HLSLToVulkanLayoutOptions::HLSLToVulkanLayoutOptions() { - reset(); + // Clear the all shifts + for (auto& shift : m_allShifts) + { + shift = kInvalidShift; + } + SLANG_ASSERT(isReset()); } @@ -40,6 +45,8 @@ void HLSLToVulkanLayoutOptions::setGlobalsBinding(const Binding& binding) void HLSLToVulkanLayoutOptions::reset() { + m_kindShiftEnabledFlags = 0; + for (auto& shift : m_allShifts) { shift = kInvalidShift; @@ -50,25 +57,10 @@ void HLSLToVulkanLayoutOptions::reset() void HLSLToVulkanLayoutOptions::setAllShift(Kind kind, Index shift) { - // We try to follow the convention, of the *last* entry set is the one used. - // If there a "all" set, we remove everything for the kind. - - // Find all the entries for the kind - List<Key> keys; - for (auto& pair : m_shifts) - { - if (pair.key.kind == kind) - { - keys.add(pair.key); - } - } - // Remove them all - for (auto& key : keys) - { - m_shifts.remove(key); - } + SLANG_ASSERT(shift != kInvalidShift); m_allShifts[Index(kind)] = shift; + _enableShiftForKind(kind); } void HLSLToVulkanLayoutOptions::setShift(Kind kind, Index set, Index shift) @@ -76,31 +68,25 @@ void HLSLToVulkanLayoutOptions::setShift(Kind kind, Index set, Index shift) SLANG_ASSERT(shift != kInvalidShift); Key key{ kind, set }; - m_shifts.add(key, shift); + m_shifts.set(key, shift); + _enableShiftForKind(kind); } Index HLSLToVulkanLayoutOptions::getShift(Kind kind, Index set) const { - if (auto ptr = m_shifts.tryGetValue(Key{ kind, set })) + if (canInferBindingForKind(kind)) { - return *ptr; - } - - return m_allShifts[Index(kind)]; -} - -bool HLSLToVulkanLayoutOptions::canInferBindings() const -{ - // If any all shift is set it's not default - for (auto shift : m_allShifts) - { - if (shift != kInvalidShift) + // We lookup a shift for a set first as this shift is "more specific" and + // is seen as taken precedent over the "all" scenario + if (auto ptr = m_shifts.tryGetValue(Key{ kind, set })) { - return true; + return *ptr; } - } - return m_shifts.getCount() > 0; + // Must have an `all` shift + return m_allShifts[Index(kind)]; + } + return kInvalidShift; } bool HLSLToVulkanLayoutOptions::hasState() const diff --git a/source/slang/slang-hlsl-to-vulkan-layout-options.h b/source/slang/slang-hlsl-to-vulkan-layout-options.h index b9eb3046d..e16989810 100644 --- a/source/slang/slang-hlsl-to-vulkan-layout-options.h +++ b/source/slang/slang-hlsl-to-vulkan-layout-options.h @@ -44,7 +44,7 @@ public: /// Append/ConsumeStructuredBuffer /// RWBuffer /// RWTextureXD/Array - UnorderedAccess, + UnorderedAccess = 0, /// Sampler (s) /// @@ -66,6 +66,22 @@ public: CountOf, }; + // A flag for each kind + typedef uint32_t KindFlags; + struct KindFlag + { + enum Enum : KindFlags + { + UnorderedAccess = KindFlags(1) << Index(Kind::UnorderedAccess), + Sampler = KindFlags(1) << Index(Kind::Sampler), + ShaderResource = KindFlags(1) << Index(Kind::ShaderResource), + ConstantBuffer = KindFlags(1) << Index(Kind::ConstantBuffer), + }; + }; + + /// Get a kind flag from a kind + SLANG_FORCE_INLINE static KindFlag::Enum getKindFlag(Kind kind) { SLANG_ASSERT(kind != Kind::Invalid); return KindFlag::Enum(KindFlags(1) << Index(kind)); } + struct Key { typedef Key ThisType; @@ -79,7 +95,7 @@ public: Index set; ///< The set this shift is associated with }; - /// Set the the all option for the kind + /// Set the the all option for the kind. void setAllShift(Kind kind, Index shift); /// Set the shift for kind/set @@ -92,12 +108,21 @@ public: bool hasGlobalsBinding() const { return m_globalsBinding.isSet(); } /// True if holds state such that vulkan bindings can be inferred from HLSL bindings - bool canInferBindings() const; + bool canInferBindings() const { return m_kindShiftEnabledFlags != 0; } + + /// True if the kind/set can be inferred + bool canInfer(Kind kind, Index set) const { return getShift(kind, set) != kInvalidShift; } + + /// True if can infer a binding for a kind + bool canInferBindingForKind(Kind kind) const { return (m_kindShiftEnabledFlags & getKindFlag(kind)) != 0; } /// Given an kind and a binding infer the vulkan binding. /// Will return an invalid binding if one is not found Binding inferBinding(Kind kind, const Binding& inBinding) const; + /// Returns flags indicating for each kind if there is shift inference + KindFlags getKindShiftEnabledFlags() const { return m_kindShiftEnabledFlags; } + /// Reset state such that all options are set to their default. The same state as when /// originally constructed void reset(); @@ -125,10 +150,17 @@ public: static Kind getKind(slang::ParameterCategory param); protected: + /// Marks that a shift is enabled for the kind + void _enableShiftForKind(Kind kind) { m_kindShiftEnabledFlags |= getKindFlag(kind); } + Binding m_globalsBinding; + /// The `all` shifts Index m_allShifts[Count(Kind::CountOf)]; + /// Holds a bit for each kind that has a shift enabled + KindFlags m_kindShiftEnabledFlags = 0; + /// Maps a key to the amount of shift Dictionary<Key, Index> m_shifts; }; diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index 1d38bc2f0..51279b605 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -232,22 +232,70 @@ struct UsedRanges return Add(range); } - bool contains(UInt index) + /// Finds the range that contains the index + /// Returns -1 if not found + Index findRangeContaining(UInt index) const { - for (auto rr : ranges) + const auto rangeCount = ranges.getCount(); + for (Index i = 0; i < rangeCount; ++i) { - if (index < rr.begin) - return false; + const auto& rr = ranges[i]; + if (index >= rr.begin && index < rr.end) + { + return index; + } + } + return -1; + } + /// Finds the range index that contains the range passed in. + /// Returns -1 if not found + Index findRangeContaining(UInt index, UInt count) const + { + const auto start = index; + const auto end = index + count; - if (index >= rr.end) - continue; + const auto rangeCount = ranges.getCount(); + for (Index i = 0; i < rangeCount; ++i) + { + const auto& rr = ranges[i]; - return true; + if (!(end <= rr.begin || start >= rr.end)) + { + return i; + } } + return -1; + } - return false; + Index findRangeContaining(UInt index, LayoutSize size) const + { + if (size.isFinite()) + { + const auto count = size.getFiniteValue(); + if (count > 0) + { + return (count == 1) ? + findRangeContaining(index) : + findRangeContaining(index, count); + } + } + else + { + // The size is infinite... + const auto rangeCount = ranges.getCount(); + for (Index i = 0; i < rangeCount; ++i) + { + // If the range end is part start index it's a hit + if (ranges[i].end > index) + { + return i; + } + } + } + return -1; } + bool contains(UInt index) const { return findRangeContaining(index) >= 0; } // Try to find space for `count` entries UInt Allocate(VarLayout* param, UInt count) @@ -285,7 +333,7 @@ struct ParameterBindingInfo { size_t space = 0; size_t index = 0; - LayoutSize count; + LayoutSize count = 0; }; struct ParameterBindingAndKindInfo : ParameterBindingInfo @@ -312,18 +360,6 @@ struct ParameterInfo : RefObject RefPtr<VarLayout> varLayout; ParameterBindingInfo bindingInfo[kLayoutResourceKindCount]; - - // The translation unit this parameter is specific to, if any -// TranslationUnitRequest* translationUnit = nullptr; - - ParameterInfo() - { - // Make sure we aren't claiming any resources yet - for( int ii = 0; ii < kLayoutResourceKindCount; ++ii ) - { - bindingInfo[ii].count = 0; - } - } }; struct EntryPointParameterBindingContext @@ -766,17 +802,31 @@ static void collectGlobalScopeParameter( parameterInfo->varLayout = varLayout; } -static RefPtr<UsedRangeSet> findUsedRangeSetForSpace( +static UsedRangeSet* _getOrCreateUsedRangeSetForSpace( ParameterBindingContext* context, UInt space) { - RefPtr<UsedRangeSet> usedRangeSet; - if (context->shared->globalSpaceUsedRangeSets.tryGetValue(space, usedRangeSet)) - return usedRangeSet; + auto& globalSpaceUsedRangeSets = context->shared->globalSpaceUsedRangeSets; - usedRangeSet = new UsedRangeSet(); - context->shared->globalSpaceUsedRangeSets.add(space, usedRangeSet); - return usedRangeSet; + auto& value = globalSpaceUsedRangeSets.getOrAddValue(space, RefPtr<UsedRangeSet>()); + if (!value) + { + value = new UsedRangeSet(); + } + return value; +} + +static UsedRangeSet* _getUsedRangeSetForSpace( + ParameterBindingContext* context, + UInt space) +{ + auto& globalSpaceUsedRangeSets = context->shared->globalSpaceUsedRangeSets; + + if (auto usedRangeSetPtr = globalSpaceUsedRangeSets.tryGetValue(space)) + { + return *usedRangeSetPtr; + } + return nullptr; } // Record that a particular register space (or set, in the GLSL case) @@ -860,7 +910,7 @@ static void addExplicitParameterBinding( } else { - auto usedRangeSet = findUsedRangeSetForSpace(context, semanticInfo.space); + auto usedRangeSet = _getOrCreateUsedRangeSetForSpace(context, semanticInfo.space); // Record that the particular binding space was // used by an explicit binding, so that we don't @@ -1065,50 +1115,51 @@ static void addExplicitParameterBindings_GLSL( // We need an HLSL register semantic to to infer from auto hlslRegSemantic = varDecl.getDecl()->findModifier<HLSLRegisterSemantic>(); - if (hlslRegSemantic == nullptr) + if (!hlslRegSemantic) { - // We don't have a HLSL binding, so no inferance can occur, issue a warning - // - // TODO(JS): I suppose there is some ambiguity here, because if we did a semantic lookup, and it didn't have a vulkanKind - // or didn't parse correctly we wouldn't issue this message. - getSink(context)->diagnose(varDecl.getDecl(), Diagnostics::cannotInferVulkanBindingWithoutRegisterModifier, varDecl); + // We'll use inference from the HLSL like layout that will happen elsewhere return; } - - // Get the HLSL binding info + + const auto hlslInfo = _extractLayoutSemanticInfo(context, hlslRegSemantic); if (hlslInfo.kind == LayoutResourceKind::None) { - // Is no hlsl resource binding + // Doesn't have an HLSL resource consumption, so we are done return; } - // We need to map to the GLSL binding types - HLSLToVulkanLayoutOptions::Kind vulkanKind = HLSLToVulkanLayoutOptions::getKind(hlslInfo.kind); - if (vulkanKind == HLSLToVulkanLayoutOptions::Kind::Invalid) + // We can't infer TextureSampler from HLSL (it's not an HLSL concept) + // So use default layout + auto varType = varDecl.getDecl()->getType(); + if (as<TextureSamplerType>(varType)) { - // The binding is not "inferable" so we are done return; } - - const auto hlslBinding = HLSLToVulkanLayoutOptions::Binding{ Index(hlslInfo.space), Index(hlslInfo.index) }; - const auto vulkanBinding = hlslToVulkanLayoutOptions->inferBinding(vulkanKind, hlslBinding); - if (vulkanBinding.isInvalid()) + // Can we map to a Vulkan kind in principal? + const HLSLToVulkanLayoutOptions::Kind vulkanKind = HLSLToVulkanLayoutOptions::getKind(hlslInfo.kind); + if (vulkanKind == HLSLToVulkanLayoutOptions::Kind::Invalid) { - // If we made it here, there are shift options, but there isn't one for the space/kind specified - // That could be a problem and unexpected, so issue a warning - getSink(context)->diagnose(varDecl.getDecl(), Diagnostics::hlslToVulkanMappingNotFound, varDecl); + // If we can't use inference, for the kind we'll use other mechanisms so we are done return; } - // Add for descriptor slot - resInfo = typeLayout->findOrAddResourceInfo(LayoutResourceKind::DescriptorTableSlot); + // If inference is not enabled for this kind, we can issue a warning + if (!hlslToVulkanLayoutOptions->canInfer(vulkanKind, hlslInfo.space)) + { + _maybeDiagnoseMissingVulkanLayoutModifier(context, varDecl); + return; + } + // 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); + semanticInfo.kind = resInfo->kind; - semanticInfo.index = UInt(vulkanBinding.index); - semanticInfo.space = UInt(vulkanBinding.set); - + semanticInfo.index = UInt(hlslInfo.index); + semanticInfo.space = UInt(hlslInfo.space); + const LayoutSize count = resInfo->count; addExplicitParameterBinding(context, parameterInfo, varDecl.getDecl(), semanticInfo, count); @@ -1116,7 +1167,7 @@ static void addExplicitParameterBindings_GLSL( // Given a single parameter, collect whatever information we have on // how it has been explicitly bound, which may come from multiple declarations -void generateParameterBindings( +void _generateParameterBindings( ParameterBindingContext* context, RefPtr<ParameterInfo> parameterInfo) { @@ -1330,7 +1381,7 @@ static void completeBindingsForParameterImpl( // space. UInt space = context->shared->defaultSpace; - RefPtr<UsedRangeSet> usedRangeSet = findUsedRangeSetForSpace(context, space); + RefPtr<UsedRangeSet> usedRangeSet = _getOrCreateUsedRangeSetForSpace(context, space); bindingInfo.count = count; bindingInfo.index = usedRangeSet->usedResourceRanges[(int)kind].Allocate(firstVarLayout, count.getFiniteValue()); @@ -1518,7 +1569,7 @@ static RefPtr<TypeLayout> processSimpleEntryPointParameter( // TODO: construct a `ParameterInfo` we can use here so that // overlapped layout errors get reported nicely. // - auto usedResourceSet = findUsedRangeSetForSpace(context, 0); + auto usedResourceSet = _getOrCreateUsedRangeSetForSpace(context, 0); usedResourceSet->usedResourceRanges[int(LayoutResourceKind::UnorderedAccess)].Add(nullptr, semanticIndex, semanticIndex + semanticSlotCount); } } @@ -2528,11 +2579,11 @@ static ParameterBindingAndKindInfo _allocateConstantBufferBinding( ParameterBindingContext* context) { UInt space = context->shared->defaultSpace; - auto usedRangeSet = findUsedRangeSetForSpace(context, space); + auto usedRangeSet = _getOrCreateUsedRangeSetForSpace(context, space); auto layoutInfo = context->getRulesFamily() ->getConstantBufferRules(context->getTargetRequest()) - ->GetObjectLayout(ShaderParameterKind::ConstantBuffer); + ->GetObjectLayout(ShaderParameterKind::ConstantBuffer, context->layoutContext.objectLayoutOptions); ParameterBindingAndKindInfo info; info.kind = layoutInfo.kind; @@ -2548,11 +2599,11 @@ static ParameterBindingAndKindInfo _assignConstantBufferBinding( UInt space, UInt index) { - auto usedRangeSet = findUsedRangeSetForSpace(context, space); + auto usedRangeSet = _getOrCreateUsedRangeSetForSpace(context, space); auto layoutInfo = context->getRulesFamily() ->getConstantBufferRules(context->getTargetRequest()) - ->GetObjectLayout(ShaderParameterKind::ConstantBuffer); + ->GetObjectLayout(ShaderParameterKind::ConstantBuffer, context->layoutContext.objectLayoutOptions); const Index count = Index(layoutInfo.size.getFiniteValue()); @@ -3561,6 +3612,133 @@ static bool _calcNeedsDefaultSpace(SharedParameterBindingContext& sharedContext) return false; } +static void _appendRange(Index start, LayoutSize size, StringBuilder& ioBuf) +{ + if (size == 1) + { + // If it's in effect a single index, just append like that. + ioBuf << start; + } + else + { + ioBuf << "[ " << start << " ... "; + if (size.isFinite()) + { + ioBuf << start + size.getFiniteValue() << ")"; + } + else + { + ioBuf << "inf )"; + } + } +} + +static void _maybeApplyHLSLToVulkanShifts( + ParameterBindingContext* paramContext, + TargetRequest* targetReq, + DiagnosticSink* sink) +{ + SLANG_UNUSED(sink); + + SharedParameterBindingContext& sharedContext = *paramContext->shared; + + // We may need to finally do any shifting if we have HLSLToVulkanLayoutOptions + auto vulkanOptions = targetReq->getHLSLToVulkanLayoutOptions(); + if (!vulkanOptions) + { + return; + } + + // We only need to do this if there is some inferance + if (!vulkanOptions->canInferBindings()) + { + return; + } + + for (ParameterInfo* parameterInfo : sharedContext.parameters) + { + auto varLayout = parameterInfo->varLayout; + SLANG_RELEASE_ASSERT(varLayout); + + // Iterate over all of the resourceInfos + for (auto& resourceInfo : varLayout->resourceInfos) + { + // Get the hlslToVulkanKind, and apply if valid + auto hlslToVulkanKind = HLSLToVulkanLayoutOptions::getKind(resourceInfo.kind); + if (hlslToVulkanKind != HLSLToVulkanLayoutOptions::Kind::Invalid) + { + auto& bindingInfo = parameterInfo->bindingInfo[Index(resourceInfo.kind)]; + + // Lookup the shift for the kind/space + const auto shift = vulkanOptions->getShift(hlslToVulkanKind, resourceInfo.space); + // If the shift is valid.. + if (shift != HLSLToVulkanLayoutOptions::kInvalidShift) + { + // Apply the shift + resourceInfo.index += shift; + + // Fix the parameter binding info + bindingInfo.index += shift; + + // Presumably they should both match + SLANG_ASSERT(bindingInfo.index == resourceInfo.index); + SLANG_ASSERT(bindingInfo.space == resourceInfo.space); + } + + // We should go looking for overlaps. + // In essence we need to look for HLSL kinds which have inferance. + // We assume all map to Descriptor, and look for descriptor overlaps + + // We know there can't be a clash of HLSL layout kinds previously, otherwise that would have already produced an a warning. + // We also know the only change is either *all* of a set is shifted or none. + // That means post a shift there still can't be clash between HLSL types. + + // So clashes can only be between HLSL types and other bindings (regardless) + + + auto usedSpace = _getUsedRangeSetForSpace(paramContext, bindingInfo.space); + + // The space must exist, because we are already consuming resources on it + SLANG_ASSERT(usedSpace); + + const auto& usedRanges = usedSpace->usedResourceRanges; + + // All the HLSL like bindings, we in actuality be DescriptorSlots on Vulkan + const auto& usedRange = usedRanges[Index(LayoutResourceKind::DescriptorTableSlot)]; + + // We need to get the count for the amount of slots consumed for this type + auto typeLayout = varLayout->getTypeLayout(); + + if (auto resInfo = typeLayout->FindResourceInfo(resourceInfo.kind)) + { + const auto rangeIndex = usedRange.findRangeContaining(bindingInfo.index, resInfo->count); + if (rangeIndex >= 0) + { + // We found a clash. + + const auto& clashRange = usedRange.ranges[rangeIndex]; + + // Get the var we are clashing with + auto clashingVarLayout = clashRange.parameter; + + // Get the var that we are currently looking at + auto curVar = parameterInfo->varLayout->getVariable(); + + StringBuilder curRangeBuf; + _appendRange(bindingInfo.index, resInfo->count, curRangeBuf); + + StringBuilder clashRangeBuf; + _appendRange(clashRange.begin, LayoutSize(clashRange.end), clashRangeBuf); + + // Report the clash. + sink->diagnose(curVar, Diagnostics::conflictingVulkanInferredBindingForParameter, getReflectionName(clashingVarLayout->getVariable()), curRangeBuf, clashRangeBuf); + } + } + } + } + } +} + RefPtr<ProgramLayout> generateParameterBindings( TargetProgram* targetProgram, DiagnosticSink* sink) @@ -3644,7 +3822,7 @@ RefPtr<ProgramLayout> generateParameterBindings( // for( auto& parameter : sharedContext.parameters ) { - generateParameterBindings(&context, parameter); + _generateParameterBindings(&context, parameter); } // It is possible that code has specified an explicit location @@ -3714,7 +3892,7 @@ RefPtr<ProgramLayout> generateParameterBindings( // kind of a mess, but also seems to be the best possible // answer given the constraints. // - auto usedRangeSet = findUsedRangeSetForSpace(&context, info.space); + auto usedRangeSet = _getOrCreateUsedRangeSetForSpace(&context, info.space); markSpaceUsed(&context, nullptr, info.space); usedRangeSet->usedResourceRanges[(int)kind].Add( nullptr, @@ -3856,6 +4034,9 @@ RefPtr<ProgramLayout> generateParameterBindings( // _completeBindings(&context, program); + // We may need to finally do any shifting if we have HLSLToVulkanLayoutOptions + _maybeApplyHLSLToVulkanShifts(&context, targetReq, sink); + // Next we need to create a type layout to reflect the information // we have collected, and we will use the `ScopeLayoutBuilder` // to encapsulate the logic that can be shared with the entry-point diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp index c933c5bb5..5cf8d2350 100644 --- a/source/slang/slang-type-layout.cpp +++ b/source/slang/slang-type-layout.cpp @@ -696,12 +696,60 @@ struct GLSLSpecializationConstantLayoutRulesImpl : DefaultLayoutRulesImpl GLSLSpecializationConstantLayoutRulesImpl kGLSLSpecializationConstantLayoutRulesImpl; -// +// Given a ShaderParamKind returns the equivalent LayoutResourceKind/ParameterCategory/SlangParameterCategory +static LayoutResourceKind _getHLSLLayoutResourceKind(ShaderParameterKind kind) +{ + switch (kind) + { + case ShaderParameterKind::ConstantBuffer: + return LayoutResourceKind::ConstantBuffer; + + case ShaderParameterKind::TextureUniformBuffer: + case ShaderParameterKind::StructuredBuffer: + case ShaderParameterKind::RawBuffer: + case ShaderParameterKind::Buffer: + case ShaderParameterKind::Texture: + return LayoutResourceKind::ShaderResource; + + case ShaderParameterKind::MutableStructuredBuffer: + case ShaderParameterKind::MutableRawBuffer: + case ShaderParameterKind::MutableBuffer: + case ShaderParameterKind::MutableTexture: + return LayoutResourceKind::UnorderedAccess; + + case ShaderParameterKind::SamplerState: + return LayoutResourceKind::SamplerState; + default: + return LayoutResourceKind::None; + } +} struct GLSLObjectLayoutRulesImpl : ObjectLayoutRulesImpl { - virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind) override + virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind, const Options& options) override { + if (options.hlslToVulkanKindFlags) + { + // Is this an HLSL kind that might be shifted + + // Get as hlslLayoutKind + const auto hlslLayoutKind = _getHLSLLayoutResourceKind(kind); + + // Get as hlslToVulkanKind + const auto hlslToVulkanKind = HLSLToVulkanLayoutOptions::getKind(hlslLayoutKind); + + if (hlslToVulkanKind != HLSLToVulkanLayoutOptions::Kind::Invalid) + { + // Is this kind enabled for shift? + if (options.hlslToVulkanKindFlags & HLSLToVulkanLayoutOptions::getKindFlag(hlslToVulkanKind)) + { + // We are going to consume a HLSL layout kind + // Later we will do shifting as necessary + return SimpleLayoutInfo(hlslLayoutKind, 1); + } + } + } + // In Vulkan GLSL, pretty much every object is just a descriptor-table slot. // We can refine this method once we support a case where this isn't true. return SimpleLayoutInfo(LayoutResourceKind::DescriptorTableSlot, 1); @@ -711,7 +759,7 @@ GLSLObjectLayoutRulesImpl kGLSLObjectLayoutRulesImpl; struct GLSLPushConstantBufferObjectLayoutRulesImpl : GLSLObjectLayoutRulesImpl { - virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind /*kind*/) override + virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind /*kind*/, const Options& /* options */) override { // Special-case the layout for a constant-buffer, because we don't // want it to allocate a descriptor-table slot @@ -722,7 +770,7 @@ GLSLPushConstantBufferObjectLayoutRulesImpl kGLSLPushConstantBufferObjectLayoutR struct GLSLShaderRecordConstantBufferObjectLayoutRulesImpl : GLSLObjectLayoutRulesImpl { - virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind /*kind*/) override + virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind /*kind*/, const Options& /* options */) override { // Special-case the layout for a constant-buffer, because we don't // want it to allocate a descriptor-table slot @@ -733,7 +781,7 @@ GLSLShaderRecordConstantBufferObjectLayoutRulesImpl kGLSLShaderRecordConstantBuf struct HLSLObjectLayoutRulesImpl : ObjectLayoutRulesImpl { - virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind) override + virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind, const Options& /* options */) override { switch( kind ) { @@ -910,7 +958,7 @@ CUDALayoutRulesFamilyImpl kCUDALayoutRulesFamilyImpl; struct CPUObjectLayoutRulesImpl : ObjectLayoutRulesImpl { - virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind) override + virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind, const Options& /* options */) override { switch (kind) { @@ -962,7 +1010,7 @@ struct CUDAObjectLayoutRulesImpl : CPUObjectLayoutRulesImpl // of opaque handle (as opposed to a pointer) such as CUsurfObject, CUtexObject typedef unsigned long long ObjectHandle; - virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind) override + virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind, const Options & /* options */) override { switch (kind) { @@ -1501,6 +1549,11 @@ TypeLayoutContext getInitialLayoutContextForTarget(TargetRequest* targetReq, Pro context.rules = nullptr; context.matrixLayoutMode = targetReq->getDefaultMatrixLayoutMode(); + if (auto hlslToVulkanLayoutOptions = targetReq->getHLSLToVulkanLayoutOptions()) + { + context.objectLayoutOptions.hlslToVulkanKindFlags = hlslToVulkanLayoutOptions->getKindShiftEnabledFlags(); + } + if( rulesFamily ) { context.rules = rulesFamily->getConstantBufferRules(targetReq); @@ -1586,21 +1639,22 @@ static TypeLayoutResult createSimpleTypeLayout( return TypeLayoutResult(typeLayout, info); } -static SimpleLayoutInfo getParameterGroupLayoutInfo( - ParameterGroupType* type, - LayoutRulesImpl* rules) +static SimpleLayoutInfo _getParameterGroupLayoutInfo( + TypeLayoutContext const& context, + ParameterGroupType* type, + LayoutRulesImpl* rules) { if( as<ConstantBufferType>(type) ) { - return rules->GetObjectLayout(ShaderParameterKind::ConstantBuffer); + return rules->GetObjectLayout(ShaderParameterKind::ConstantBuffer, context.objectLayoutOptions); } else if( as<TextureBufferType>(type) ) { - return rules->GetObjectLayout(ShaderParameterKind::TextureUniformBuffer); + return rules->GetObjectLayout(ShaderParameterKind::TextureUniformBuffer, context.objectLayoutOptions); } else if( as<GLSLShaderStorageBufferType>(type) ) { - return rules->GetObjectLayout(ShaderParameterKind::ShaderStorageBuffer); + return rules->GetObjectLayout(ShaderParameterKind::ShaderStorageBuffer, context.objectLayoutOptions); } else if (as<ParameterBlockType>(type)) { @@ -2270,7 +2324,7 @@ static RefPtr<TypeLayout> _createParameterGroupTypeLayout( // allocate a constant buffer regiser/binding into // the overall layout, to account for it. // - auto cbUsage = parameterGroupRules->GetObjectLayout(ShaderParameterKind::ConstantBuffer); + auto cbUsage = parameterGroupRules->GetObjectLayout(ShaderParameterKind::ConstantBuffer, context.objectLayoutOptions); containerTypeLayout->addResourceUsage(cbUsage.kind, cbUsage.size); } @@ -2730,7 +2784,7 @@ createStructuredBufferTypeLayout( RefPtr<TypeLayout> elementTypeLayout) { auto rules = context.rules; - auto info = rules->GetObjectLayout(kind); + auto info = rules->GetObjectLayout(kind, context.objectLayoutOptions); auto typeLayout = new StructuredBufferTypeLayout(); @@ -3378,6 +3432,26 @@ RefPtr<TypeLayout> createTypeLayoutForGlobalGenericTypeParam( return _createTypeLayoutForGlobalGenericTypeParam(context, type, globalGenericParamDecl).layout; } +static bool _isDescriptorSlotLike( + TypeLayoutContext const& context, + LayoutResourceKind kind) +{ + if (kind == LayoutResourceKind::DescriptorTableSlot) + { + return true; + } + + if (context.objectLayoutOptions.hlslToVulkanKindFlags) + { + const auto hlslToVulkanKind = HLSLToVulkanLayoutOptions::getKind(kind); + // If it maps to a kind and it is enabled it is 'in effect' a Descriptor slot + return hlslToVulkanKind != HLSLToVulkanLayoutOptions::Kind::Invalid && + (context.objectLayoutOptions.hlslToVulkanKindFlags & HLSLToVulkanLayoutOptions::getKindFlag(hlslToVulkanKind)); + } + + return false; +} + static TypeLayoutResult createArrayLikeTypeLayout( TypeLayoutContext const& context, Type* type, @@ -3472,6 +3546,13 @@ static TypeLayoutResult createArrayLikeTypeLayout( LayoutSize arrayResourceCount = 0; + // We copy because if the element is *actually* DescriptorSlot like, + // we'll change the type. + // NOTE! That as it stands this will change the resource type from an HLSL type + // to Descriptor slot. This scenario happens when we have HLSLToVulkanLayoutOptions + // enabled, we layout with some HLSL types. + auto elementResourceKind = elementResourceInfo.kind; + // In almost all cases, the resources consumed by an array // will be its element count times the resources consumed // by its element type. @@ -3480,14 +3561,15 @@ static TypeLayoutResult createArrayLikeTypeLayout( // compiling to GLSL for Vulkan, where an entire array // only consumes a single descriptor-table slot. // - if (elementResourceInfo.kind == LayoutResourceKind::DescriptorTableSlot) + if (_isDescriptorSlotLike(context, elementResourceKind)) { arrayResourceCount = elementResourceInfo.count; + elementResourceKind = LayoutResourceKind::DescriptorTableSlot; } // The second exception to this is arrays of an existential type // where the entire array should be specialized to a single concrete type. // - else if (elementResourceInfo.kind == LayoutResourceKind::ExistentialTypeParam) + else if (elementResourceKind == LayoutResourceKind::ExistentialTypeParam) { arrayResourceCount = elementResourceInfo.count; } @@ -3505,7 +3587,7 @@ static TypeLayoutResult createArrayLikeTypeLayout( else if( elementCount.isInfinite() && adjustedElementTypeLayout != elementTypeLayout - && doesResourceRequireAdjustmentForArrayOfStructs(elementResourceInfo.kind) ) + && doesResourceRequireAdjustmentForArrayOfStructs(elementResourceKind) ) { // We want to ignore resource types consumed by the element type // that need adjustement if the array size is infinite, since @@ -3611,7 +3693,7 @@ static TypeLayoutResult _createTypeLayout( // different from a `Texture2D<U>` in terms of how it // should be handled as a member of a container. // - auto info = getParameterGroupLayoutInfo(parameterGroupType, rules); + auto info = _getParameterGroupLayoutInfo(context, parameterGroupType, rules); // The more interesting case, though, is when the user // is requesting us to actually create a `TypeLayout`, @@ -3633,7 +3715,7 @@ static TypeLayoutResult _createTypeLayout( else if (const auto samplerStateType = as<SamplerStateType>(type)) { return createSimpleTypeLayout( - rules->GetObjectLayout(ShaderParameterKind::SamplerState), + rules->GetObjectLayout(ShaderParameterKind::SamplerState, context.objectLayoutOptions), type, rules); } @@ -3654,7 +3736,7 @@ static TypeLayoutResult _createTypeLayout( } return createSimpleTypeLayout( - rules->GetObjectLayout(kind), + rules->GetObjectLayout(kind, context.objectLayoutOptions), type, rules); } @@ -3675,7 +3757,7 @@ static TypeLayoutResult _createTypeLayout( } return createSimpleTypeLayout( - rules->GetObjectLayout(kind), + rules->GetObjectLayout(kind, context.objectLayoutOptions), type, rules); } @@ -3696,7 +3778,7 @@ static TypeLayoutResult _createTypeLayout( } return createSimpleTypeLayout( - rules->GetObjectLayout(kind), + rules->GetObjectLayout(kind, context.objectLayoutOptions), type, rules); } @@ -3704,7 +3786,7 @@ static TypeLayoutResult _createTypeLayout( // TODO: need a better way to handle this stuff... #define CASE(TYPE, KIND) \ else if(auto type_##TYPE = as<TYPE>(type)) do { \ - auto info = rules->GetObjectLayout(ShaderParameterKind::KIND); \ + auto info = rules->GetObjectLayout(ShaderParameterKind::KIND, context.objectLayoutOptions); \ auto typeLayout = createStructuredBufferTypeLayout( \ context, \ ShaderParameterKind::KIND, \ @@ -3726,7 +3808,7 @@ static TypeLayoutResult _createTypeLayout( #define CASE(TYPE, KIND) \ else if(as<TYPE>(type)) do { \ return createSimpleTypeLayout( \ - rules->GetObjectLayout(ShaderParameterKind::KIND), \ + rules->GetObjectLayout(ShaderParameterKind::KIND, context.objectLayoutOptions), \ type, rules); \ } while(0) diff --git a/source/slang/slang-type-layout.h b/source/slang/slang-type-layout.h index a80f6afdd..dc769d1c7 100644 --- a/source/slang/slang-type-layout.h +++ b/source/slang/slang-type-layout.h @@ -947,8 +947,13 @@ struct SimpleLayoutRulesImpl struct ObjectLayoutRulesImpl { + struct Options + { + HLSLToVulkanLayoutOptions::KindFlags hlslToVulkanKindFlags = 0; + }; + // Compute layout info for an object type - virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind) = 0; + virtual SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind, const Options& options) = 0; }; struct LayoutRulesImpl @@ -999,9 +1004,9 @@ struct LayoutRulesImpl // Forward `ObjectLayoutRulesImpl` interface - SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind) + SimpleLayoutInfo GetObjectLayout(ShaderParameterKind kind, const ObjectLayoutRulesImpl::Options& options) { - return objectRules->GetObjectLayout(kind); + return objectRules->GetObjectLayout(kind, options); } // @@ -1084,6 +1089,9 @@ struct TypeLayoutContext // Map types to their type layout Dictionary<Type*, TypeLayoutResult> layoutMap; + // Options passed to object layout + ObjectLayoutRulesImpl::Options objectLayoutOptions; + LayoutRulesImpl* getRules() { return rules; } LayoutRulesFamilyImpl* getRulesFamily() const { return rules->getLayoutRulesFamily(); } diff --git a/tests/bindings/hlsl-to-vulkan-array.hlsl b/tests/bindings/hlsl-to-vulkan-array.hlsl new file mode 100644 index 000000000..072f99914 --- /dev/null +++ b/tests/bindings/hlsl-to-vulkan-array.hlsl @@ -0,0 +1,16 @@ +//TEST:REFLECTION:-target glsl -profile ps_4_0 -entry main -fvk-t-shift 10 all -fvk-s-shift 100 all -fvk-u-shift 100 all -fvk-b-shift 1000 all + +struct Data +{ + Texture2D tex; + RWStructuredBuffer<float> structuredBuffer; + float a; + int b; +}; + +Data g_data[2]; + +float4 main() : SV_TARGET +{ + return float4(1, 1, 1, 0); +}
\ No newline at end of file diff --git a/tests/bindings/hlsl-to-vulkan-array.hlsl.expected b/tests/bindings/hlsl-to-vulkan-array.hlsl.expected new file mode 100644 index 000000000..ab3e659ec --- /dev/null +++ b/tests/bindings/hlsl-to-vulkan-array.hlsl.expected @@ -0,0 +1,94 @@ +result code = 0 +standard error = { +} +standard output = { +{ + "parameters": [ + { + "name": "g_data", + "bindings": [ + {"kind": "uniform", "offset": 0, "size": 32}, + {"kind": "shaderResource", "index": 10}, + {"kind": "unorderedAccess", "index": 100} + ], + "type": { + "kind": "array", + "elementCount": 2, + "elementType": { + "kind": "struct", + "name": "Data", + "fields": [ + { + "name": "tex", + "type": { + "kind": "resource", + "baseShape": "texture2D" + }, + "binding": {"kind": "shaderResource", "index": 0} + }, + { + "name": "structuredBuffer", + "type": { + "kind": "resource", + "baseShape": "structuredBuffer", + "access": "readWrite", + "resultType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "unorderedAccess", "index": 0} + }, + { + "name": "a", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "b", + "type": { + "kind": "scalar", + "scalarType": "int32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4} + } + ] + }, + "uniformStride": 16 + } + } + ], + "entryPoints": [ + { + "name": "main", + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + }, + "bindings": [ + { + "name": "g_data", + "bindings": [ + {"kind": "uniform", "offset": 0, "size": 32}, + {"kind": "shaderResource", "index": 10, "used": 0}, + {"kind": "unorderedAccess", "index": 100, "used": 0} + ] + } + ] + } + ] +} +} diff --git a/tests/bindings/hlsl-to-vulkan-combined.hlsl.expected b/tests/bindings/hlsl-to-vulkan-combined.hlsl.expected index 127d0fe4c..de67a3592 100644 --- a/tests/bindings/hlsl-to-vulkan-combined.hlsl.expected +++ b/tests/bindings/hlsl-to-vulkan-combined.hlsl.expected @@ -6,7 +6,7 @@ standard output = { "parameters": [ { "name": "t0", - "binding": {"kind": "descriptorTableSlot", "index": 7}, + "binding": {"kind": "descriptorTableSlot", "index": 0}, "type": { "kind": "resource", "baseShape": "texture2D" @@ -14,7 +14,7 @@ standard output = { }, { "name": "t1", - "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 14}, + "binding": {"kind": "descriptorTableSlot", "index": 1}, "type": { "kind": "resource", "baseShape": "texture2D" @@ -41,11 +41,11 @@ standard output = { "bindings": [ { "name": "t0", - "binding": {"kind": "descriptorTableSlot", "index": 7} + "binding": {"kind": "descriptorTableSlot", "index": 0} }, { "name": "t1", - "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 14} + "binding": {"kind": "descriptorTableSlot", "index": 1} } ] } diff --git a/tests/bindings/hlsl-to-vulkan-shift-implicit.hlsl b/tests/bindings/hlsl-to-vulkan-shift-implicit.hlsl new file mode 100644 index 000000000..c7c25f6f1 --- /dev/null +++ b/tests/bindings/hlsl-to-vulkan-shift-implicit.hlsl @@ -0,0 +1,20 @@ +//TEST:REFLECTION:-target glsl -profile ps_4_0 -entry main -fvk-t-shift 10 all -fvk-s-shift 100 all -fvk-b-shift 0 all -fvk-u-shift 1000 all + +struct Data +{ + float a; + int b; +}; + +Texture2D t; +SamplerState s; +ConstantBuffer<Data> c; +Texture2D t2; + +RWStructuredBuffer<Data> u; +RWStructuredBuffer<int> u2; + +float4 main() : SV_TARGET +{ + return float4(1, 1, 1, 0); +}
\ No newline at end of file diff --git a/tests/bindings/hlsl-to-vulkan-shift-implicit.hlsl.expected b/tests/bindings/hlsl-to-vulkan-shift-implicit.hlsl.expected new file mode 100644 index 000000000..2d918deed --- /dev/null +++ b/tests/bindings/hlsl-to-vulkan-shift-implicit.hlsl.expected @@ -0,0 +1,178 @@ +result code = 0 +standard error = { +} +standard output = { +{ + "parameters": [ + { + "name": "t", + "binding": {"kind": "shaderResource", "index": 10}, + "type": { + "kind": "resource", + "baseShape": "texture2D" + } + }, + { + "name": "s", + "binding": {"kind": "samplerState", "index": 100}, + "type": { + "kind": "samplerState" + } + }, + { + "name": "c", + "binding": {"kind": "constantBuffer", "index": 0}, + "type": { + "kind": "constantBuffer", + "elementType": { + "kind": "struct", + "name": "Data", + "fields": [ + { + "name": "a", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "b", + "type": { + "kind": "scalar", + "scalarType": "int32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4} + } + ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "Data", + "fields": [ + { + "name": "a", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "b", + "type": { + "kind": "scalar", + "scalarType": "int32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 16} + } + } + }, + { + "name": "t2", + "binding": {"kind": "shaderResource", "index": 11}, + "type": { + "kind": "resource", + "baseShape": "texture2D" + } + }, + { + "name": "u", + "binding": {"kind": "unorderedAccess", "index": 1000}, + "type": { + "kind": "resource", + "baseShape": "structuredBuffer", + "access": "readWrite", + "resultType": { + "kind": "struct", + "name": "Data", + "fields": [ + { + "name": "a", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "b", + "type": { + "kind": "scalar", + "scalarType": "int32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4} + } + ] + } + } + }, + { + "name": "u2", + "binding": {"kind": "unorderedAccess", "index": 1001}, + "type": { + "kind": "resource", + "baseShape": "structuredBuffer", + "access": "readWrite", + "resultType": { + "kind": "scalar", + "scalarType": "int32" + } + } + } + ], + "entryPoints": [ + { + "name": "main", + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + }, + "bindings": [ + { + "name": "t", + "binding": {"kind": "shaderResource", "index": 10, "used": 0} + }, + { + "name": "s", + "binding": {"kind": "samplerState", "index": 100, "used": 0} + }, + { + "name": "c", + "binding": {"kind": "constantBuffer", "index": 0, "used": 0} + }, + { + "name": "t2", + "binding": {"kind": "shaderResource", "index": 11, "used": 0} + }, + { + "name": "u", + "binding": {"kind": "unorderedAccess", "index": 1000, "used": 0} + }, + { + "name": "u2", + "binding": {"kind": "unorderedAccess", "index": 1001, "used": 0} + } + ] + } + ] +} +} diff --git a/tests/bindings/hlsl-to-vulkan-shift.hlsl b/tests/bindings/hlsl-to-vulkan-shift.hlsl index 13f76297d..3083dd4d7 100644 --- a/tests/bindings/hlsl-to-vulkan-shift.hlsl +++ b/tests/bindings/hlsl-to-vulkan-shift.hlsl @@ -17,5 +17,5 @@ RWStructuredBuffer<int> u2 : register(u3, space2); float4 main() : SV_TARGET { - return float4(1, 1, 1, 0); + return float4(1, 1, 1, 0) * c.a; }
\ No newline at end of file diff --git a/tests/bindings/hlsl-to-vulkan-shift.hlsl.expected b/tests/bindings/hlsl-to-vulkan-shift.hlsl.expected index 939f847ca..b79c76c43 100644 --- a/tests/bindings/hlsl-to-vulkan-shift.hlsl.expected +++ b/tests/bindings/hlsl-to-vulkan-shift.hlsl.expected @@ -6,7 +6,7 @@ standard output = { "parameters": [ { "name": "t", - "binding": {"kind": "descriptorTableSlot", "index": 5}, + "binding": {"kind": "shaderResource", "index": 5}, "type": { "kind": "resource", "baseShape": "texture2D" @@ -14,14 +14,14 @@ standard output = { }, { "name": "s", - "binding": {"kind": "descriptorTableSlot", "index": 1}, + "binding": {"kind": "samplerState", "index": 1}, "type": { "kind": "samplerState" } }, { "name": "c", - "binding": {"kind": "descriptorTableSlot", "index": 3}, + "binding": {"kind": "constantBuffer", "index": 3}, "type": { "kind": "constantBuffer", "elementType": { @@ -47,7 +47,7 @@ standard output = { ] }, "containerVarLayout": { - "binding": {"kind": "descriptorTableSlot", "index": 0} + "binding": {"kind": "constantBuffer", "index": 0} }, "elementVarLayout": { "type": { @@ -78,7 +78,7 @@ standard output = { }, { "name": "t2", - "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 7}, + "binding": {"kind": "shaderResource", "space": 2, "index": 7}, "type": { "kind": "resource", "baseShape": "texture2D" @@ -86,7 +86,7 @@ standard output = { }, { "name": "u", - "binding": {"kind": "descriptorTableSlot", "index": 11}, + "binding": {"kind": "unorderedAccess", "index": 11}, "type": { "kind": "resource", "baseShape": "structuredBuffer", @@ -117,7 +117,7 @@ standard output = { }, { "name": "u2", - "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 4}, + "binding": {"kind": "unorderedAccess", "space": 2, "index": 4}, "type": { "kind": "resource", "baseShape": "structuredBuffer", @@ -149,27 +149,27 @@ standard output = { "bindings": [ { "name": "t", - "binding": {"kind": "descriptorTableSlot", "index": 5} + "binding": {"kind": "shaderResource", "index": 5, "used": 0} }, { "name": "s", - "binding": {"kind": "descriptorTableSlot", "index": 1} + "binding": {"kind": "samplerState", "index": 1, "used": 0} }, { "name": "c", - "binding": {"kind": "descriptorTableSlot", "index": 3} + "binding": {"kind": "constantBuffer", "index": 3, "used": 1} }, { "name": "t2", - "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 7} + "binding": {"kind": "shaderResource", "space": 2, "index": 7, "used": 0} }, { "name": "u", - "binding": {"kind": "descriptorTableSlot", "index": 11} + "binding": {"kind": "unorderedAccess", "index": 11, "used": 0} }, { "name": "u2", - "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 4} + "binding": {"kind": "unorderedAccess", "space": 2, "index": 4, "used": 0} } ] } diff --git a/tests/diagnostics/hlsl-to-vulkan-shift-diagnostic.hlsl.expected b/tests/diagnostics/hlsl-to-vulkan-shift-diagnostic.hlsl.expected index a7e4e27bb..907572f9e 100644 --- a/tests/diagnostics/hlsl-to-vulkan-shift-diagnostic.hlsl.expected +++ b/tests/diagnostics/hlsl-to-vulkan-shift-diagnostic.hlsl.expected @@ -1,9 +1,12 @@ -result code = 0 +result code = -1 standard error = { -tests/diagnostics/hlsl-to-vulkan-shift-diagnostic.hlsl(11): warning 39016: unable to infer Vulkan binding for 'c', automatic layout will be used +tests/diagnostics/hlsl-to-vulkan-shift-diagnostic.hlsl(11): warning 39013: shader parameter 'c' has a 'register' specified for D3D, but no '[[vk::binding(...)]]` specified for Vulkan ConstantBuffer<Data> c : register(b2); - ^ -tests/diagnostics/hlsl-to-vulkan-shift-diagnostic.hlsl(15): warning 39016: unable to infer Vulkan binding for 'u', automatic layout will be used + ^~~~~~~~ +tests/diagnostics/hlsl-to-vulkan-shift-diagnostic.hlsl(15): warning 39013: shader parameter 'u' has a 'register' specified for D3D, but no '[[vk::binding(...)]]` specified for Vulkan +RWStructuredBuffer<Data> u : register(u11); + ^~~~~~~~ +tests/diagnostics/hlsl-to-vulkan-shift-diagnostic.hlsl(15): error 39025: conflicting vulkan inferred binding for parameter 'c' overlap is 0 and 0 RWStructuredBuffer<Data> u : register(u11); ^ } |
