From c9ef8d58a135061262fd321a82061d27dc733cf5 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Wed, 3 May 2023 20:16:58 -0400 Subject: HLSL->Vulkan binding support (#2865) * WIP around VK shift binding. * Refactor around options parsing. * Remove needless passing around of sink. * Some more tidying around OptionsParser. * Handle vulkan shift parsing. * Fix small issue around vk binding and "all". * Fixing some small issues. Missing break. * Split out VulkanLayoutOptions * WIP binding taking into account HLSL->Vulkan options. * First attempt at making binding work with HLSLVulkanOptions. * VulkanLayoutOptions -> HLSLToVulkanLayoutOptions * WIP with HLSL-Vulkan binding. * Some more testing around vk-shift. * Improvements around global binding. More tests. * Improve test coverage. Improve checking for requirements around default space. * Update command line options. * Small fixes. * Small fix in options reporting. * Fix warning issue. * Some fixes for isDefault for HLSLToVulkanLayoutOptions. * Update hlsl-to-vulkan-shift output. The difference was due to default handling if shift isn't specified, and not being specified was not correctly tracked. --- build/visual-studio/slang/slang.vcxproj | 2 + build/visual-studio/slang/slang.vcxproj.filters | 6 + docs/command-line-slangc-reference.md | 37 + source/compiler-core/slang-command-line-args.h | 16 +- source/compiler-core/slang-diagnostic-sink.h | 2 +- source/slang/slang-compiler.h | 13 +- source/slang/slang-diagnostic-defs.h | 1 + .../slang/slang-hlsl-to-vulkan-layout-options.cpp | 132 + source/slang/slang-hlsl-to-vulkan-layout-options.h | 85 + source/slang/slang-options.cpp | 3556 +++++++++++--------- source/slang/slang-parameter-binding.cpp | 359 +- source/slang/slang.cpp | 14 + tests/bindings/hlsl-to-vulkan-combined.hlsl | 9 + .../bindings/hlsl-to-vulkan-combined.hlsl.expected | 54 + tests/bindings/hlsl-to-vulkan-global.hlsl | 12 + tests/bindings/hlsl-to-vulkan-global.hlsl.expected | 77 + tests/bindings/hlsl-to-vulkan-shift.hlsl | 21 + tests/bindings/hlsl-to-vulkan-shift.hlsl.expected | 178 + 18 files changed, 2781 insertions(+), 1793 deletions(-) create mode 100644 source/slang/slang-hlsl-to-vulkan-layout-options.cpp create mode 100644 source/slang/slang-hlsl-to-vulkan-layout-options.h create mode 100644 tests/bindings/hlsl-to-vulkan-combined.hlsl create mode 100644 tests/bindings/hlsl-to-vulkan-combined.hlsl.expected create mode 100644 tests/bindings/hlsl-to-vulkan-global.hlsl create mode 100644 tests/bindings/hlsl-to-vulkan-global.hlsl.expected create mode 100644 tests/bindings/hlsl-to-vulkan-shift.hlsl create mode 100644 tests/bindings/hlsl-to-vulkan-shift.hlsl.expected diff --git a/build/visual-studio/slang/slang.vcxproj b/build/visual-studio/slang/slang.vcxproj index 7e0348d73..fcc125860 100644 --- a/build/visual-studio/slang/slang.vcxproj +++ b/build/visual-studio/slang/slang.vcxproj @@ -344,6 +344,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla + @@ -543,6 +544,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla + diff --git a/build/visual-studio/slang/slang.vcxproj.filters b/build/visual-studio/slang/slang.vcxproj.filters index cae2199b8..3ff574d10 100644 --- a/build/visual-studio/slang/slang.vcxproj.filters +++ b/build/visual-studio/slang/slang.vcxproj.filters @@ -120,6 +120,9 @@ Header Files + + Header Files + Header Files @@ -713,6 +716,9 @@ Source Files + + Source Files + Source Files diff --git a/docs/command-line-slangc-reference.md b/docs/command-line-slangc-reference.md index e61c4245b..8b91096e7 100644 --- a/docs/command-line-slangc-reference.md +++ b/docs/command-line-slangc-reference.md @@ -31,6 +31,7 @@ slangc -help-style markdown -h * [file-system-type](#file-system-type) * [target](#target) * [stage](#stage) +* [vulkan-shift](#vulkan-shift) * [capability](#capability) * [file-extension](#file-extension) @@ -305,6 +306,32 @@ Set the optimization level. Remove all source file information from outputs. + +## -force-glsl-scalar-layout +Force using scalar block layout for uniform and shader storage buffers in GLSL output. + + + +## -fvk-bind-globals + +**-fvk-bind-globals <N> <descriptor-set>** + +Places the $Globals cbuffer at descriptor set <descriptor-set> and binding <N>. See HLSL global variables and Vulkan binding for explanation and examples. + + + +## -enable-effect-annotations +Enables support for legacy effect annotation syntax. + + + +## -fvk-b-shift, -fvk-s-shift, -fvk-t-shift, -fvk-u-shift + +**-vk-<[vulkan-shift](#vulkan-shift)>-shift <N> <space>** + +Shifts by N the inferred binding numbers for all resources in b-type registers of space <space>. Specifically, for a resouce attached with :register(bX, <space>) but not \[vk::binding(...)\], sets its Vulkan descriptor set to <space> and binding number to X + N. If you need to shift the inferred binding numbers for more than one space, provide more than one such option. If more than one such option is provided for the same space, the last one takes effect. If you need to shift the inferred binding numbers for all sets, use 'all' as <space>. + + # Downstream @@ -737,6 +764,16 @@ Stage * `mesh` * `amplification` + +# vulkan-shift + +Vulkan Shift + +* `b` : Vulkan Buffer resource +* `s` : Vulkan Sampler resource +* `t` : Vulkan Texture resource +* `u` : Vulkan Uniform resource + # capability diff --git a/source/compiler-core/slang-command-line-args.h b/source/compiler-core/slang-command-line-args.h index 31807cd48..b2bd48c61 100644 --- a/source/compiler-core/slang-command-line-args.h +++ b/source/compiler-core/slang-command-line-args.h @@ -109,17 +109,15 @@ struct CommandLineReader /// Set the current index void setIndex(Index index) { SLANG_ASSERT(index >= 0 && index <= m_args->getArgCount()); m_index = index; } + void init(CommandLineArgs* args, DiagnosticSink* sink) { m_args = args; m_sink = sink; m_index = 0; } + /// Set up reader with args - CommandLineReader(CommandLineArgs* args, DiagnosticSink* sink): - m_args(args), - m_index(0), - m_sink(sink) - { - } + CommandLineReader(CommandLineArgs* args, DiagnosticSink* sink) { init(args, sink); } + CommandLineReader() = default; - DiagnosticSink* m_sink; - CommandLineArgs* m_args; - Index m_index; + DiagnosticSink* m_sink = nullptr; + CommandLineArgs* m_args = nullptr; + Index m_index = 0; }; struct DownstreamArgs diff --git a/source/compiler-core/slang-diagnostic-sink.h b/source/compiler-core/slang-diagnostic-sink.h index 5131e5194..ebd43b456 100644 --- a/source/compiler-core/slang-diagnostic-sink.h +++ b/source/compiler-core/slang-diagnostic-sink.h @@ -255,7 +255,7 @@ public: /// Default Ctor DiagnosticSink(): m_sourceManager(nullptr), - m_sourceLocationLexer (nullptr) + m_sourceLocationLexer(nullptr) { } diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 117c3f037..42fc3ca1f 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -25,6 +25,8 @@ #include "slang-syntax.h" #include "slang-content-assist-info.h" +#include "slang-hlsl-to-vulkan-layout-options.h" + #include "slang-serialize-ir-types.h" #include "../compiler-core/slang-artifact-representation-impl.h" @@ -1535,6 +1537,7 @@ namespace Slang class TargetRequest : public RefObject { public: + TargetRequest(Linkage* linkage, CodeGenTarget format); void addTargetFlags(SlangTargetFlags flags) @@ -1575,6 +1578,10 @@ namespace Slang return (targetFlags & SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM) != 0; } + void setHLSLToVulkanLayoutOptions(HLSLToVulkanLayoutOptions* opts); + + const HLSLToVulkanLayoutOptions* getHLSLToVulkanLayoutOptions() const { return hlslToVulkanLayoutOptions; } + bool shouldDumpIntermediates() { return dumpIntermediates; } void setTrackLiveness(bool enable) { enableLivenessTracking = enable; } @@ -1611,6 +1618,8 @@ namespace Slang bool dumpIntermediates = false; bool forceGLSLScalarBufferLayout = false; bool enableLivenessTracking = false; + + RefPtr hlslToVulkanLayoutOptions; ///< Optional vulkan layout options }; /// Are we generating code for a D3D API? @@ -1858,7 +1867,7 @@ namespace Slang Type* const* args, DiagnosticSink* sink); - /// Add a mew target and return its index. + /// Add a new target and return its index. UInt addTarget( CodeGenTarget target); @@ -2629,6 +2638,8 @@ namespace Slang virtual SLANG_NO_THROW void SLANG_MCALL setDiagnosticFlags(SlangDiagnosticFlags flags) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setDebugInfoFormat(SlangDebugInfoFormat format) SLANG_OVERRIDE; + void setHLSLToVulkanLayoutOptions(int targetIndex, HLSLToVulkanLayoutOptions* vulkanLayoutOptions); + EndToEndCompileRequest( Session* session); diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index a35c48a6a..e8d521630 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -85,6 +85,7 @@ DIAGNOSTIC( 32, Warning, explicitStageDoesntMatchImpliedStage, "the stage spe DIAGNOSTIC( 33, Error, stageSpecificationIgnoredBecauseNoEntryPoints, "one or more stages were specified, but no entry points were specified with '-entry'") DIAGNOSTIC( 34, Error, stageSpecificationIgnoredBecauseBeforeAllEntryPoints, "when compiling multiple entry points, any '-stage' options must follow the '-entry' option that they apply to") DIAGNOSTIC( 35, Error, noStageSpecifiedInPassThroughMode, "no stage was specified for entry point '$0'; when using the '-pass-through' option, stages must be fully specified on the command line") +DIAGNOSTIC( 36, Error, expectingAnInteger, "expecting an integer value") DIAGNOSTIC( 40, Warning, sameProfileSpecifiedMoreThanOnce, "the '$0' was specified more than once for target '$0'") DIAGNOSTIC( 41, Error, conflictingProfilesSpecifiedForTarget, "conflicting profiles have been specified for target '$0'") diff --git a/source/slang/slang-hlsl-to-vulkan-layout-options.cpp b/source/slang/slang-hlsl-to-vulkan-layout-options.cpp new file mode 100644 index 000000000..e143762a1 --- /dev/null +++ b/source/slang/slang-hlsl-to-vulkan-layout-options.cpp @@ -0,0 +1,132 @@ +// slang-hlsl-to-vulkan-layout-options.cpp + +#include "slang-hlsl-to-vulkan-layout-options.h" + +namespace Slang { + +namespace { // anonymous + +typedef HLSLToVulkanLayoutOptions::Kind ShiftKind; + +/* {b|s|t|u} */ + +static NamesDescriptionValue s_vulkanShiftKinds[] = +{ + { ValueInt(ShiftKind::Buffer), "b", "Vulkan Buffer resource" }, + { ValueInt(ShiftKind::Sampler), "s", "Vulkan Sampler resource" }, + { ValueInt(ShiftKind::Texture), "t", "Vulkan Texture resource" }, + { ValueInt(ShiftKind::Uniform), "u", "Vulkan Uniform resource" }, +}; + +} // anonymous + +/* static */ConstArrayView HLSLToVulkanLayoutOptions::getKindInfos() +{ + return makeConstArrayView(s_vulkanShiftKinds); +} + +HLSLToVulkanLayoutOptions::HLSLToVulkanLayoutOptions() +{ + for (auto& shift : m_allShifts) + { + shift = kInvalidShift; + } +} + + + /// Set the the all option for the kind +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 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); + } + + m_allShifts[Index(kind)] = shift; +} + +void HLSLToVulkanLayoutOptions::setShift(Kind kind, Index set, Index shift) +{ + SLANG_ASSERT(shift != kInvalidShift); + + Key key{ kind, set }; + m_shifts.add(key, shift); +} + +Index HLSLToVulkanLayoutOptions::getShift(Kind kind, Index set) const +{ + if (auto ptr = m_shifts.tryGetValue(Key{ kind, set })) + { + return *ptr; + } + + return m_allShifts[Index(kind)]; +} + +bool HLSLToVulkanLayoutOptions::isDefault() const +{ + // If any all shift is set it's not default + for (auto shift : m_allShifts) + { + if (shift != kInvalidShift) + { + return false; + } + } + + // If any has a non zero shift, it's not default + for (auto& pair : m_shifts) + { + // We need a value that is non zero... + if (pair.value) + { + return false; + } + } + + // If either has been set it's not default + return m_globalsBinding < 0 && m_globalsBindingSet < 0; +} + +/* static */HLSLToVulkanLayoutOptions::Kind HLSLToVulkanLayoutOptions::getKind(slang::ParameterCategory param) +{ + typedef slang::ParameterCategory ParameterCategory; + + switch (param) + { + case ParameterCategory::Mixed: + { + // TODO(JS): + // Hmm, is this TextureSampler? + return Kind::Invalid; + } + case ParameterCategory::Uniform: + case ParameterCategory::ConstantBuffer: + { + return Kind::Uniform; + } + case ParameterCategory::ShaderResource: return Kind::Texture; + case ParameterCategory::UnorderedAccess: return Kind::Buffer; + case ParameterCategory::SamplerState: return Kind::Sampler; + + default: + { + return Kind::Invalid; + } + } +} + +} // namespace Slang diff --git a/source/slang/slang-hlsl-to-vulkan-layout-options.h b/source/slang/slang-hlsl-to-vulkan-layout-options.h new file mode 100644 index 000000000..9260fe91d --- /dev/null +++ b/source/slang/slang-hlsl-to-vulkan-layout-options.h @@ -0,0 +1,85 @@ +// slang-hlsl-to-vulkan-layout-options.h +#ifndef SLANG_HLSL_TO_VULKAN_LAYOUT_OPTIONS_H +#define SLANG_HLSL_TO_VULKAN_LAYOUT_OPTIONS_H + +#include "../core/slang-basic.h" +#include "../core/slang-name-value.h" + +namespace Slang +{ + +/* +For support features similar to described here.. + +https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#descriptors + +Options that allow for infering Vulkan bindings based on HLSL register bindings + */ +struct HLSLToVulkanLayoutOptions : public RefObject +{ +public: + + static const Index kInvalidShift = Index(0x80000000); + + // {b|s|t|u} + enum class Kind + { + Invalid = -1, + + Buffer, ///< Buffer + Sampler, ///< Sampler + Texture, ///< Texture + Uniform, ///< Uniform + + CountOf, + }; + + struct Key + { + typedef Key ThisType; + + bool operator==(const ThisType& rhs) const { return kind == rhs.kind && set == rhs.set; } + bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } + + HashCode getHashCode() const { return combineHash(Slang::getHashCode(kind), Slang::getHashCode(set)); } + + Kind kind; ///< The kind this entry is for + Index set; ///< The set this shift is associated with + }; + + /// Set the the all option for the kind + void setAllShift(Kind kind, Index shift); + + /// Set the shift for kind/set + void setShift(Kind kind, Index set, Index shift); + + /// Get the shift. Returns kInvalidShift if no shift is found + Index getShift(Kind kind, Index set) const; + + /// Returns true if contains default information. If so it can in effect be ignored + bool isDefault() const; + + /// True as global binds set + bool hasGlobalsBinding() const { return m_globalsBinding >= 0 && m_globalsBindingSet >= 0; } + + /// Ctor + HLSLToVulkanLayoutOptions(); + + /// Get information about the different kinds + static ConstArrayView getKindInfos(); + + /// Given a paramCategory get the kind. Returns Kind::Invalid if not an applicable category + static Kind getKind(slang::ParameterCategory param); + + Index m_globalsBinding = -1; + Index m_globalsBindingSet = -1; + + Index m_allShifts[Count(Kind::CountOf)]; + + /// Maps a key to the amount of shift + Dictionary m_shifts; +}; + +} // namespace Slang + +#endif diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index 353c6e57f..0c788a404 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -19,6 +19,7 @@ #include "slang-repro.h" #include "slang-serialize-ir.h" +#include "slang-hlsl-to-vulkan-layout-options.h" #include "../core/slang-castable.h" #include "../core/slang-file-system.h" @@ -81,6 +82,10 @@ enum class OptionKind LineDirectiveMode, Optimization, Obfuscate, + + VulkanBindShift, + VulkanBindGlobals, + GLSLForceScalarLayout, EnableEffectAnnotations, @@ -160,10 +165,25 @@ enum class ValueCategory OptimizationLevel, DebugLevel, FileSystemType, + VulkanShift, CountOf, }; +template +struct GetValueCategory; + +#define SLANG_GET_VALUE_CATEGORY(cat, type) template <> struct GetValueCategory { enum { Value = Index(ValueCategory::cat) }; }; + +SLANG_GET_VALUE_CATEGORY(Compiler, SlangPassThrough) +SLANG_GET_VALUE_CATEGORY(ArchiveType, SlangArchiveType) +SLANG_GET_VALUE_CATEGORY(LineDirectiveMode, SlangLineDirectiveMode) +SLANG_GET_VALUE_CATEGORY(FloatingPointMode, FloatingPointMode) +SLANG_GET_VALUE_CATEGORY(FileSystemType, TypeTextUtil::FileSystemType) +SLANG_GET_VALUE_CATEGORY(HelpStyle, CommandOptionsWriter::Style) +SLANG_GET_VALUE_CATEGORY(OptimizationLevel, SlangOptimizationLevel) +SLANG_GET_VALUE_CATEGORY(VulkanShift, HLSLToVulkanLayoutOptions::Kind) + } // anonymous static void _addOptions(const ConstArrayView