From 840afe4d2bd7bf7f7e7616646c48ff71fd7c35a8 Mon Sep 17 00:00:00 2001 From: Anders Leino Date: Fri, 27 Sep 2024 10:04:51 +0300 Subject: [PATCH 1/5] Use the assembly description as target when disassembling I believe this is a bugfix. It seems to have worked before because up until the WGSL case, the disassembler has been the same executable as the one producing the binary to be disassembled. --- source/slang/slang-artifact-output-util.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/slang/slang-artifact-output-util.cpp b/source/slang/slang-artifact-output-util.cpp index 3cb0e6c939..dcd6eb84e6 100644 --- a/source/slang/slang-artifact-output-util.cpp +++ b/source/slang/slang-artifact-output-util.cpp @@ -33,12 +33,12 @@ namespace Slang } return SLANG_FAIL; } - // Get the downstream compiler that can be used for this target + // Get the downstream disassembler that can be used for this target // TODO(JS): // This could perhaps be performed in some other manner if there was more than one way to produce // disassembly from a binary. - const CodeGenTarget target = (CodeGenTarget)ArtifactDescUtil::getCompileTargetFromDesc(desc); + const CodeGenTarget target = (CodeGenTarget)ArtifactDescUtil::getCompileTargetFromDesc(assemblyDesc); if (target == CodeGenTarget::Unknown) { return SLANG_FAIL; From 5e953f1b6a80b77b13a8b54823ade2214459afbb Mon Sep 17 00:00:00 2001 From: Anders Leino Date: Tue, 18 Jun 2024 08:51:13 +0300 Subject: [PATCH 2/5] Add Tint as a downstream compiler This closes issue #5104. * Add downstream compiler for Tint. * Tint is wrapped in a shared library, 'slang-tint' available from [1]. * The header file for slang-tint.dll is added in external/slang-tint-headers. * Add some boilerplate for WGSL targets. * Add an entry point test for WGSL. [1] https://github.com/shader-slang/dawn/releases/tag/slang-tint-0 --- external/slang-tint-headers/slang-tint.h | 22 +++ include/slang.h | 4 +- .../slang-artifact-desc-util.cpp | 5 + source/compiler-core/slang-artifact.h | 1 + .../slang-downstream-compiler-util.cpp | 2 + source/compiler-core/slang-tint-compiler.cpp | 164 ++++++++++++++++++ source/compiler-core/slang-tint-compiler.h | 17 ++ source/core/slang-type-convert-util.cpp | 1 + source/core/slang-type-text-util.cpp | 3 + source/slang/slang-compiler.cpp | 15 +- source/slang/slang-compiler.h | 3 + source/slang/slang-emit.cpp | 4 + source/slang/slang-options.cpp | 3 +- source/slang/slang-type-layout.cpp | 2 + source/slang/slang.cpp | 3 + tests/wgsl/entry-point.slang | 10 ++ tools/slang-test/slang-test-main.cpp | 5 + tools/slang-test/test-context.h | 2 +- 18 files changed, 262 insertions(+), 4 deletions(-) create mode 100644 external/slang-tint-headers/slang-tint.h create mode 100644 source/compiler-core/slang-tint-compiler.cpp create mode 100644 source/compiler-core/slang-tint-compiler.h create mode 100644 tests/wgsl/entry-point.slang diff --git a/external/slang-tint-headers/slang-tint.h b/external/slang-tint-headers/slang-tint.h new file mode 100644 index 0000000000..ee70b56070 --- /dev/null +++ b/external/slang-tint-headers/slang-tint.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +struct tint_CompileRequest +{ + const char* wgslCode; + size_t wgslCodeLength; +}; + +struct tint_CompileResult +{ + const uint8_t* buffer; + size_t bufferSize; + const char* error; +}; + + +typedef int (*tint_CompileFunc)(tint_CompileRequest* request, tint_CompileResult* result); + +typedef void (*tint_FreeResultFunc)(tint_CompileResult* result); diff --git a/include/slang.h b/include/slang.h index 81b3ac1cbe..5bbe0e50f0 100644 --- a/include/slang.h +++ b/include/slang.h @@ -610,6 +610,8 @@ extern "C" SLANG_METAL_LIB_ASM, ///< Metal library assembly SLANG_HOST_SHARED_LIBRARY, ///< A shared library/Dll for host code (for hosting CPU/OS) SLANG_WGSL, ///< WebGPU shading language + SLANG_WGSL_SPIRV_ASM, ///< SPIR-V assembly via WebGPU shading language + SLANG_WGSL_SPIRV, ///< SPIR-V via WebGPU shading language SLANG_TARGET_COUNT_OF, }; @@ -643,7 +645,7 @@ extern "C" SLANG_PASS_THROUGH_LLVM, ///< LLVM 'compiler' - includes LLVM and Clang SLANG_PASS_THROUGH_SPIRV_OPT, ///< SPIRV-opt SLANG_PASS_THROUGH_METAL, ///< Metal compiler - SLANG_PASS_THROUGH_WGSL, ///< WGSL compiler + SLANG_PASS_THROUGH_TINT, ///< Tint WGSL compiler SLANG_PASS_THROUGH_COUNT_OF, }; diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp index 9794cc90e9..ae7f842272 100644 --- a/source/compiler-core/slang-artifact-desc-util.cpp +++ b/source/compiler-core/slang-artifact-desc-util.cpp @@ -205,6 +205,7 @@ SLANG_HIERARCHICAL_ENUM(ArtifactKind, SLANG_ARTIFACT_KIND, SLANG_ARTIFACT_KIND_E x(PTX, KernelLike) \ x(CuBin, KernelLike) \ x(MetalAIR, KernelLike) \ + x(WGSL_SPIRV, KernelLike) \ x(CPULike, Base) \ x(UnknownCPU, CPULike) \ x(X86, CPULike) \ @@ -290,6 +291,8 @@ SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYL case SLANG_METAL_LIB: return Desc::make(Kind::Executable, Payload::MetalAIR, Style::Kernel, 0); case SLANG_METAL_LIB_ASM: return Desc::make(Kind::Assembly, Payload::MetalAIR, Style::Kernel, 0); case SLANG_WGSL: return Desc::make(Kind::Source, Payload::WGSL, Style::Kernel, 0); + case SLANG_WGSL_SPIRV_ASM: return Desc::make(Kind::Assembly, Payload::WGSL_SPIRV, Style::Kernel, 0); + case SLANG_WGSL_SPIRV: return Desc::make(Kind::Executable, Payload::WGSL_SPIRV, Style::Kernel, 0); default: break; } @@ -346,6 +349,7 @@ SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYL case Payload::DXBC: return SLANG_DXBC_ASM; case Payload::PTX: return SLANG_PTX; case Payload::MetalAIR: return SLANG_METAL_LIB_ASM; + case Payload::WGSL_SPIRV: return SLANG_WGSL_SPIRV_ASM; default: break; } } @@ -374,6 +378,7 @@ SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYL case Payload::DXBC: return SLANG_DXBC; case Payload::PTX: return SLANG_PTX; case Payload::MetalAIR: return SLANG_METAL_LIB_ASM; + case Payload::WGSL_SPIRV: return SLANG_WGSL_SPIRV; default: break; } } diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index 6d65aafba4..d3784ca0a1 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -153,6 +153,7 @@ enum class ArtifactPayload : uint8_t PTX, ///< PTX. NOTE! PTX is a text format, but is handable to CUDA API. MetalAIR, ///< Metal AIR CuBin, ///< CUDA binary + WGSL_SPIRV, ///< SPIR-V derived via WebGPU shading language CPULike, ///< CPU code diff --git a/source/compiler-core/slang-downstream-compiler-util.cpp b/source/compiler-core/slang-downstream-compiler-util.cpp index 70063b772e..bf4c7cc049 100644 --- a/source/compiler-core/slang-downstream-compiler-util.cpp +++ b/source/compiler-core/slang-downstream-compiler-util.cpp @@ -24,6 +24,7 @@ #include "slang-glslang-compiler.h" #include "slang-llvm-compiler.h" #include "slang-metal-compiler.h" +#include "slang-tint-compiler.h" namespace Slang { @@ -332,6 +333,7 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() outFuncs[int(SLANG_PASS_THROUGH_LLVM)] = &LLVMDownstreamCompilerUtil::locateCompilers; outFuncs[int(SLANG_PASS_THROUGH_SPIRV_DIS)] = &SpirvDisDownstreamCompilerUtil::locateCompilers; outFuncs[int(SLANG_PASS_THROUGH_METAL)] = &MetalDownstreamCompilerUtil::locateCompilers; + outFuncs[int(SLANG_PASS_THROUGH_TINT)] = &TintDownstreamCompilerUtil::locateCompilers; } static String _getParentPath(const String& path) diff --git a/source/compiler-core/slang-tint-compiler.cpp b/source/compiler-core/slang-tint-compiler.cpp new file mode 100644 index 0000000000..6319ecf9ff --- /dev/null +++ b/source/compiler-core/slang-tint-compiler.cpp @@ -0,0 +1,164 @@ +#include "slang-tint-compiler.h" + +#include "slang-artifact-associated-impl.h" + +#include "../../external/slang-tint-headers/slang-tint.h" + +namespace Slang +{ + + class TintDownstreamCompiler : public DownstreamCompilerBase + { + + public: + + // IDownstreamCompiler + virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile( + const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW bool SLANG_MCALL canConvert( + const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert( + IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) + SLANG_OVERRIDE; + + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE + { + return false; + } + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString( + slang::IBlob** outVersionString) SLANG_OVERRIDE; + + SlangResult compile(IArtifact *const sourceArtifact, IArtifact** outArtifact); + + SlangResult init(ISlangSharedLibrary* library); + + protected: + + ComPtr m_sharedLibrary; + + private: + + tint_CompileFunc m_compile; + tint_FreeResultFunc m_freeResult; + }; + + SlangResult TintDownstreamCompiler::init(ISlangSharedLibrary* library) + { + tint_CompileFunc compile = + (tint_CompileFunc)library->findFuncByName("tint_compile"); + if (compile == nullptr) + { + return SLANG_FAIL; + } + + tint_FreeResultFunc freeResult = + (tint_FreeResultFunc)library->findFuncByName("tint_free_result"); + if (freeResult == nullptr) + { + return SLANG_FAIL; + } + + m_sharedLibrary = library; + m_desc = Desc(SLANG_PASS_THROUGH_TINT); + m_compile = compile; + m_freeResult = freeResult; + return SLANG_OK; + } + + SlangResult TintDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) + { + ComPtr library; + SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary( + path, loader, nullptr, "slang-tint", library)); + SLANG_ASSERT(library); + + ComPtr compiler = ComPtr( + new TintDownstreamCompiler()); + SLANG_RETURN_ON_FAIL(static_cast( + compiler.get())->init(library)); + + set->addCompiler(compiler); + return SLANG_OK; + } + + SlangResult TintDownstreamCompiler::compile( + const CompileOptions& options, IArtifact** outArtifact) + { + IArtifact * sourceArtifact = options.sourceArtifacts[0]; + return compile(sourceArtifact, outArtifact); + } + + SlangResult TintDownstreamCompiler::compile( + IArtifact *const sourceArtifact, IArtifact** outArtifact) + { + tint_CompileRequest req = {}; + + if (sourceArtifact == nullptr) + return SLANG_FAIL; + + ComPtr sourceBlob; + SLANG_RETURN_FALSE_ON_FAIL(sourceArtifact->loadBlob( + ArtifactKeep::Yes, sourceBlob.writeRef())); + + String wgslCode( + (char*)sourceBlob->getBufferPointer(), + (char*)sourceBlob->getBufferPointer() + sourceBlob->getBufferSize()); + req.wgslCode = wgslCode.begin(); + req.wgslCodeLength = wgslCode.getLength(); + + tint_CompileResult result = {}; + SLANG_DEFER(m_freeResult(&result)); + bool compileSucceeded = m_compile(&req, &result) == 0; + + ComPtr spirvBlob = RawBlob::create(result.buffer, result.bufferSize); + result.buffer = nullptr; + + ComPtr resultArtifact = ArtifactUtil::createArtifactForCompileTarget( + SlangCompileTarget::SLANG_WGSL_SPIRV); + auto diagnostics = ArtifactDiagnostics::create(); + diagnostics->setResult(compileSucceeded ? SLANG_OK : SLANG_FAIL); + ArtifactUtil::addAssociated(resultArtifact, diagnostics); + if (compileSucceeded) + { + resultArtifact->addRepresentationUnknown(spirvBlob); + } + else + { + diagnostics->setRaw(CharSlice(result.error)); + diagnostics->requireErrorDiagnostic(); + } + + *outArtifact = resultArtifact.detach(); + return SLANG_OK; + } + + bool TintDownstreamCompiler::canConvert( + const ArtifactDesc& from, const ArtifactDesc& to) + { + return (from.payload == ArtifactPayload::WGSL) && + (to.payload == ArtifactPayload::SPIRV); + } + + SlangResult TintDownstreamCompiler::convert( + IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) + { + if (!canConvert(from->getDesc(), to)) + return SLANG_FAIL; + return compile(from, outArtifact); + } + + SlangResult TintDownstreamCompiler::getVersionString( + slang::IBlob** /* outVersionString */) + { + // We just use Tint at whatever version is in our Dawn fork, so nobody should + // depend on the particular version at the moment. + return SLANG_FAIL; + } + +} diff --git a/source/compiler-core/slang-tint-compiler.h b/source/compiler-core/slang-tint-compiler.h new file mode 100644 index 0000000000..d5e596d4d2 --- /dev/null +++ b/source/compiler-core/slang-tint-compiler.h @@ -0,0 +1,17 @@ +#pragma once + +#include "slang-downstream-compiler-util.h" +#include "../core/slang-platform.h" + +namespace Slang +{ + + struct TintDownstreamCompilerUtil + { + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); + }; + +} diff --git a/source/core/slang-type-convert-util.cpp b/source/core/slang-type-convert-util.cpp index cb5b4d38b6..12908f2110 100644 --- a/source/core/slang-type-convert-util.cpp +++ b/source/core/slang-type-convert-util.cpp @@ -18,6 +18,7 @@ namespace Slang case SLANG_CPP_PYTORCH_BINDING:return SLANG_SOURCE_LANGUAGE_CPP; case SLANG_HOST_CPP_SOURCE: return SLANG_SOURCE_LANGUAGE_CPP; case SLANG_CUDA_SOURCE: return SLANG_SOURCE_LANGUAGE_CUDA; + case SLANG_WGSL: return SLANG_SOURCE_LANGUAGE_WGSL; default: break; } return SLANG_SOURCE_LANGUAGE_UNKNOWN; diff --git a/source/core/slang-type-text-util.cpp b/source/core/slang-type-text-util.cpp index 9f9deb92c8..f02325792d 100644 --- a/source/core/slang-type-text-util.cpp +++ b/source/core/slang-type-text-util.cpp @@ -64,6 +64,8 @@ static const TypeTextUtil::CompileTargetInfo s_compileTargetInfos[] = { SLANG_METAL_LIB, "metallib", "metallib", "Metal Library Bytecode" }, { SLANG_METAL_LIB_ASM, "metallib-asm" "metallib-asm", "Metal Library Bytecode assembly" }, { SLANG_WGSL, "wgsl", "wgsl", "WebGPU shading language source" }, + { SLANG_WGSL_SPIRV_ASM, "wgsl-spirv-asm", "wgsl-spirv-asm,wgsl-spirv-assembly", "SPIR-V assembly via WebGPU shading language" }, + { SLANG_WGSL_SPIRV, "wgsl-spirv", "wgsl-spirv", "SPIR-V via WebGPU shading language" }, }; static const NamesDescriptionValue s_languageInfos[] = @@ -91,6 +93,7 @@ static const NamesDescriptionValue s_compilerInfos[] = { SLANG_PASS_THROUGH_LLVM, "llvm", "LLVM/Clang `slang-llvm`" }, { SLANG_PASS_THROUGH_SPIRV_OPT, "spirv-opt", "spirv-tools SPIRV optimizer" }, { SLANG_PASS_THROUGH_METAL, "metal", "Metal shader compiler" }, + { SLANG_PASS_THROUGH_TINT, "tint", "Tint compiler" }, }; static const NamesDescriptionValue s_archiveTypeInfos[] = diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 1f962d625f..5bbc92e97d 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -520,6 +520,10 @@ namespace Slang { return SourceLanguage::CUDA; } + case PassThroughMode::Tint: + { + return SourceLanguage::WGSL; + } case PassThroughMode::SpirvDis: { return SourceLanguage::SPIRV; @@ -555,6 +559,7 @@ namespace Slang { return PassThroughMode::None; } + case CodeGenTarget::WGSLSPIRVAssembly: case CodeGenTarget::SPIRVAssembly: case CodeGenTarget::SPIRV: { @@ -588,7 +593,10 @@ namespace Slang { return PassThroughMode::NVRTC; } - + case CodeGenTarget::WGSLSPIRV: + { + return PassThroughMode::Tint; + } default: break; } @@ -1010,6 +1018,7 @@ namespace Slang case CodeGenTarget::DXIL: return CodeGenTarget::HLSL; case CodeGenTarget::SPIRV: return CodeGenTarget::GLSL; case CodeGenTarget::MetalLib: return CodeGenTarget::Metal; + case CodeGenTarget::WGSLSPIRV: return CodeGenTarget::WGSL; default: break; } return CodeGenTarget::Unknown; @@ -1621,6 +1630,7 @@ namespace Slang case CodeGenTarget::DXBytecodeAssembly: return CodeGenTarget::DXBytecode; case CodeGenTarget::DXILAssembly: return CodeGenTarget::DXIL; case CodeGenTarget::SPIRVAssembly: return CodeGenTarget::SPIRV; + case CodeGenTarget::WGSLSPIRVAssembly: return CodeGenTarget::WGSLSPIRV; default: return CodeGenTarget::None; } } @@ -1635,6 +1645,7 @@ namespace Slang case CodeGenTarget::DXBytecodeAssembly: case CodeGenTarget::DXILAssembly: case CodeGenTarget::MetalLibAssembly: + case CodeGenTarget::WGSLSPIRVAssembly: { // First compile to an intermediate target for the corresponding binary format. const CodeGenTarget intermediateTarget = _getIntermediateTarget(target); @@ -1669,6 +1680,7 @@ namespace Slang case CodeGenTarget::HostExecutable: case CodeGenTarget::HostHostCallable: case CodeGenTarget::HostSharedLibrary: + case CodeGenTarget::WGSLSPIRV: SLANG_RETURN_ON_FAIL(emitWithDownstreamForEntryPoints(outArtifact)); return SLANG_OK; @@ -1701,6 +1713,7 @@ namespace Slang case CodeGenTarget::ShaderSharedLibrary: case CodeGenTarget::HostExecutable: case CodeGenTarget::HostSharedLibrary: + case CodeGenTarget::WGSLSPIRVAssembly: { SLANG_RETURN_ON_FAIL(_emitEntryPoints(outArtifact)); diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 17501163f7..ac34668170 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -97,6 +97,8 @@ namespace Slang MetalLib = SLANG_METAL_LIB, MetalLibAssembly = SLANG_METAL_LIB_ASM, WGSL = SLANG_WGSL, + WGSLSPIRVAssembly = SLANG_WGSL_SPIRV_ASM, + WGSLSPIRV = SLANG_WGSL_SPIRV, CountOf = SLANG_TARGET_COUNT_OF, }; @@ -1336,6 +1338,7 @@ namespace Slang LLVM = SLANG_PASS_THROUGH_LLVM, ///< LLVM 'compiler' SpirvOpt = SLANG_PASS_THROUGH_SPIRV_OPT, ///< pass thorugh spirv to spirv-opt MetalC = SLANG_PASS_THROUGH_METAL, + Tint = SLANG_PASS_THROUGH_TINT, ///< pass through spirv to Tint API CountOf = SLANG_PASS_THROUGH_COUNT_OF, }; void printDiagnosticArg(StringBuilder& sb, PassThroughMode val); diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 97ee2a5958..c9319a13bc 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -1317,6 +1317,8 @@ Result linkAndOptimizeIR( break; case CodeGenTarget::WGSL: + case CodeGenTarget::WGSLSPIRV: + case CodeGenTarget::WGSLSPIRVAssembly: { legalizeIRForWGSL(irModule, sink); } @@ -1637,6 +1639,8 @@ SlangResult CodeGenContext::emitEntryPointsSourceFromIR(ComPtr& outAr lineDirectiveMode = LineDirectiveMode::GLSL; break; + case CodeGenTarget::WGSLSPIRVAssembly: + case CodeGenTarget::WGSLSPIRV: case CodeGenTarget::WGSL: // WGSL doesn't support line directives. // See https://github.com/gpuweb/gpuweb/issues/606. diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index b9a12f971e..48c593889b 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -931,8 +931,9 @@ SlangSourceLanguage findSourceLanguageFromPath(const String& path, Stage& outImp { ".c", SLANG_SOURCE_LANGUAGE_C, SLANG_STAGE_NONE }, { ".cpp", SLANG_SOURCE_LANGUAGE_CPP, SLANG_STAGE_NONE }, - { ".cu", SLANG_SOURCE_LANGUAGE_CUDA, SLANG_STAGE_NONE } + { ".cu", SLANG_SOURCE_LANGUAGE_CUDA, SLANG_STAGE_NONE }, + { ".wgsl", SLANG_SOURCE_LANGUAGE_WGSL, SLANG_STAGE_NONE }, }; for (Index i = 0; i < SLANG_COUNT_OF(entries); ++i) diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp index 1fb8b57ab6..2fe16188c9 100644 --- a/source/slang/slang-type-layout.cpp +++ b/source/slang/slang-type-layout.cpp @@ -1950,6 +1950,8 @@ LayoutRulesFamilyImpl* getDefaultLayoutRulesFamilyForTarget(TargetRequest* targe return &kGLSLLayoutRulesFamilyImpl; case CodeGenTarget::WGSL: + case CodeGenTarget::WGSLSPIRV: + case CodeGenTarget::WGSLSPIRVAssembly: return &kWGSLLayoutRulesFamilyImpl; case CodeGenTarget::HostHostCallable: diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index c9717272b0..e59be24828 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -260,8 +260,11 @@ void Session::_initCodeGenTransitionMap() map.addTransition(CodeGenTarget::HLSL, CodeGenTarget::DXIL, PassThroughMode::Dxc); map.addTransition(CodeGenTarget::GLSL, CodeGenTarget::SPIRV, PassThroughMode::Glslang); map.addTransition(CodeGenTarget::Metal, CodeGenTarget::MetalLib, PassThroughMode::MetalC); + map.addTransition(CodeGenTarget::WGSL, CodeGenTarget::WGSLSPIRV, PassThroughMode::Tint); // To assembly map.addTransition(CodeGenTarget::SPIRV, CodeGenTarget::SPIRVAssembly, PassThroughMode::Glslang); + // We use glslang to turn SPIR-V into SPIR-V assembly. + map.addTransition(CodeGenTarget::WGSLSPIRV, CodeGenTarget::WGSLSPIRVAssembly, PassThroughMode::Glslang); map.addTransition(CodeGenTarget::DXIL, CodeGenTarget::DXILAssembly, PassThroughMode::Dxc); map.addTransition(CodeGenTarget::DXBytecode, CodeGenTarget::DXBytecodeAssembly, PassThroughMode::Fxc); map.addTransition(CodeGenTarget::MetalLib, CodeGenTarget::MetalLibAssembly, PassThroughMode::MetalC); diff --git a/tests/wgsl/entry-point.slang b/tests/wgsl/entry-point.slang new file mode 100644 index 0000000000..2e807c1819 --- /dev/null +++ b/tests/wgsl/entry-point.slang @@ -0,0 +1,10 @@ +//TEST:SIMPLE(filecheck=CHECK): -target wgsl-spirv-asm +//CHECK: OpEntryPoint + +RWStructuredBuffer outputBuffer; + +[numthreads(1,1,1)] +void computeMain() +{ + outputBuffer[0] = 42; +} diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp index 47a87ddc21..8c50d2ee21 100644 --- a/tools/slang-test/slang-test-main.cpp +++ b/tools/slang-test/slang-test-main.cpp @@ -972,6 +972,11 @@ static PassThroughFlags _getPassThroughFlagsForTarget(SlangCompileTarget target) { return 0; } + case SLANG_WGSL_SPIRV: + case SLANG_WGSL_SPIRV_ASM: + { + return PassThroughFlag::Tint; + } case SLANG_DXBC: case SLANG_DXBC_ASM: { diff --git a/tools/slang-test/test-context.h b/tools/slang-test/test-context.h index 314ec2803a..c1bd82c8c1 100644 --- a/tools/slang-test/test-context.h +++ b/tools/slang-test/test-context.h @@ -38,7 +38,7 @@ struct PassThroughFlag NVRTC = 1 << int(SLANG_PASS_THROUGH_NVRTC), LLVM = 1 << int(SLANG_PASS_THROUGH_LLVM), Metal = 1 << int(SLANG_PASS_THROUGH_METAL), - WGSL = 1 << int(SLANG_PASS_THROUGH_WGSL) + Tint = 1 << int(SLANG_PASS_THROUGH_TINT), }; }; From d50155b2891171932f28c6c6da6ed01436875d0c Mon Sep 17 00:00:00 2001 From: Anders Leino Date: Fri, 27 Sep 2024 11:30:27 +0300 Subject: [PATCH 3/5] Add WGSL_SPIRV as supported target for Glslang --- source/compiler-core/slang-glslang-compiler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/compiler-core/slang-glslang-compiler.cpp b/source/compiler-core/slang-glslang-compiler.cpp index 9ef8e7fb4c..54635873a4 100644 --- a/source/compiler-core/slang-glslang-compiler.cpp +++ b/source/compiler-core/slang-glslang-compiler.cpp @@ -301,7 +301,9 @@ SlangResult GlslangDownstreamCompiler::validate(const uint32_t* contents, int co bool GlslangDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) { // Can only disassemble blobs that are SPIR-V - return ArtifactDescUtil::isDisassembly(from, to) && from.payload == ArtifactPayload::SPIRV; + return ArtifactDescUtil::isDisassembly(from, to) && ( + (from.payload == ArtifactPayload::SPIRV) || + (from.payload == ArtifactPayload::WGSL_SPIRV)); } SlangResult GlslangDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) From 9202f3852008881470d9c16148bb813f7f240ab5 Mon Sep 17 00:00:00 2001 From: Anders Leino Date: Thu, 5 Sep 2024 15:32:20 +0300 Subject: [PATCH 4/5] Add WebGPU support to slang-test This helps to address issue #5051. --- include/slang-gfx.h | 1 + source/core/slang-render-api-util.cpp | 5 +++++ source/core/slang-render-api-util.h | 2 ++ tools/render-test/options.cpp | 1 + tools/render-test/render-test-main.cpp | 6 ++++++ tools/slang-test/slang-test-main.cpp | 4 ++++ 6 files changed, 19 insertions(+) diff --git a/include/slang-gfx.h b/include/slang-gfx.h index d273ce4276..207b3e1361 100644 --- a/include/slang-gfx.h +++ b/include/slang-gfx.h @@ -92,6 +92,7 @@ enum class DeviceType Metal, CPU, CUDA, + WebGPU, CountOf, }; diff --git a/source/core/slang-render-api-util.cpp b/source/core/slang-render-api-util.cpp index 0a303b6659..797d82cd70 100644 --- a/source/core/slang-render-api-util.cpp +++ b/source/core/slang-render-api-util.cpp @@ -19,6 +19,7 @@ namespace Slang { { RenderApiType::Metal, "mtl,metal", ""}, { RenderApiType::CPU, "cpu", ""}, { RenderApiType::CUDA, "cuda", "cuda,ptx"}, + { RenderApiType::WebGPU, "wgpu,webgpu", "wgsl"}, }; static int _calcAvailableApis() @@ -265,6 +266,10 @@ static bool _canLoadSharedLibrary(const char* libName) { #if SLANG_WINDOWS_FAMILY case RenderApiType::Vulkan: return _canLoadSharedLibrary("vulkan-1") || _canLoadSharedLibrary("vk_swiftshader"); + case RenderApiType::WebGPU: + return _canLoadSharedLibrary("webgpu_dawn") && + _canLoadSharedLibrary("dxcompiler") && + _canLoadSharedLibrary("dxil"); #elif SLANG_APPLE_FAMILY case RenderApiType::Vulkan: return true; case RenderApiType::Metal: return true; diff --git a/source/core/slang-render-api-util.h b/source/core/slang-render-api-util.h index 224fe6996c..f1be930cc0 100644 --- a/source/core/slang-render-api-util.h +++ b/source/core/slang-render-api-util.h @@ -17,6 +17,7 @@ enum class RenderApiType Metal, CPU, CUDA, + WebGPU, CountOf, }; @@ -31,6 +32,7 @@ struct RenderApiFlag Metal = 1 << int(RenderApiType::Metal), CPU = 1 << int(RenderApiType::CPU), CUDA = 1 << int(RenderApiType::CUDA), + WebGPU = 1 << int(RenderApiType::WebGPU), AllOf = (1 << int(RenderApiType::CountOf)) - 1 ///< All bits set }; }; diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp index dc1850d379..07e8b0e2af 100644 --- a/tools/render-test/options.cpp +++ b/tools/render-test/options.cpp @@ -33,6 +33,7 @@ static rhi::DeviceType _toRenderType(Slang::RenderApiType apiType) case RenderApiType::Metal: return rhi::DeviceType::Metal; case RenderApiType::CPU: return rhi::DeviceType::CPU; case RenderApiType::CUDA: return rhi::DeviceType::CUDA; + case RenderApiType::WebGPU: return rhi::DeviceType::WGPU; default: return rhi::DeviceType::Default; } diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 5f0e51da3f..4835c3affd 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -1229,6 +1229,12 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi input.profile = ""; nativeLanguage = SLANG_SOURCE_LANGUAGE_CUDA; slangPassThrough = SLANG_PASS_THROUGH_NVRTC; + break; + case DeviceType::WGPU: + input.target = SLANG_WGSL; + input.profile = ""; + nativeLanguage = SLANG_SOURCE_LANGUAGE_WGSL; + slangPassThrough = SLANG_PASS_THROUGH_NONE; break; default: diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp index 8c50d2ee21..7929857075 100644 --- a/tools/slang-test/slang-test-main.cpp +++ b/tools/slang-test/slang-test-main.cpp @@ -1122,6 +1122,10 @@ static SlangResult _extractRenderTestRequirements(const CommandLine& cmdLine, Te nativeLanguage = SLANG_SOURCE_LANGUAGE_CUDA; passThru = SLANG_PASS_THROUGH_NVRTC; break; + case RenderApiType::WebGPU: + target = SLANG_WGSL; + SLANG_ASSERT(!usePassthru); + break; } SlangSourceLanguage sourceLanguage = nativeLanguage; From 5923957628071df8e4815245cb79fd10006c616f Mon Sep 17 00:00:00 2001 From: Anders Leino Date: Fri, 27 Sep 2024 14:21:03 +0300 Subject: [PATCH 5/5] Disable lots of crashing compute tests for 'wgpu' This closes issue #5051. --- tests/compute/atomics-buffer.slang | 1 + tests/compute/atomics-groupshared.slang | 1 + tests/compute/atomics.slang | 1 + tests/compute/buffer-type-splitting.slang | 1 + tests/compute/byte-address-buffer.slang | 1 + tests/compute/column-major.slang | 1 + .../constant-buffer-memory-packing.slang | 2 ++ tests/compute/func-cbuffer-param.slang | 1 + tests/compute/parameter-block.slang | 1 + tests/compute/texture-get-dimensions.slang | 1 + tests/compute/texture-sampling.slang | 1 + tests/compute/texture-simple.slang | 2 ++ tests/compute/texture-simpler.slang | 1 + tests/compute/transcendental-double.slang | 1 + tests/expected-failure-github.txt | 29 +++++++++++++++++++ 15 files changed, 45 insertions(+) diff --git a/tests/compute/atomics-buffer.slang b/tests/compute/atomics-buffer.slang index 6745d6b581..ca609635e6 100644 --- a/tests/compute/atomics-buffer.slang +++ b/tests/compute/atomics-buffer.slang @@ -12,6 +12,7 @@ // RWBuffer does not work with the GFX backend as expected with Metal //DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -mtl //TEST:SIMPLE(filecheck=METALLIB): -target metallib -stage compute -entry computeMain +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu //METALLIB: @computeMain diff --git a/tests/compute/atomics-groupshared.slang b/tests/compute/atomics-groupshared.slang index a01f7bf6ab..9d153d9e3a 100644 --- a/tests/compute/atomics-groupshared.slang +++ b/tests/compute/atomics-groupshared.slang @@ -5,6 +5,7 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -vk -shaderobj //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -cuda -shaderobj //TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -mtl +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu //TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer diff --git a/tests/compute/atomics.slang b/tests/compute/atomics.slang index ee02c623f6..da08b0cb78 100644 --- a/tests/compute/atomics.slang +++ b/tests/compute/atomics.slang @@ -5,6 +5,7 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -vk -shaderobj //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -cuda -shaderobj //TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -mtl +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu //TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out, name outputBuffer diff --git a/tests/compute/buffer-type-splitting.slang b/tests/compute/buffer-type-splitting.slang index ea9af31465..dbbe9789fe 100644 --- a/tests/compute/buffer-type-splitting.slang +++ b/tests/compute/buffer-type-splitting.slang @@ -1,6 +1,7 @@ //TEST(compute):COMPARE_COMPUTE:-cpu //TEST(compute):COMPARE_COMPUTE: -shaderobj //DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -mtl +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu //TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer //TEST_INPUT:ubuffer(data=[0 2 3 3]):name=s[0].a diff --git a/tests/compute/byte-address-buffer.slang b/tests/compute/byte-address-buffer.slang index 65356ec220..77748eb606 100644 --- a/tests/compute/byte-address-buffer.slang +++ b/tests/compute/byte-address-buffer.slang @@ -4,6 +4,7 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj //TEST(compute):COMPARE_COMPUTE_EX:-d3d12 -compute -shaderobj +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu // Confirm cross-compilation of `(RW)ByteAddressBuffer` // diff --git a/tests/compute/column-major.slang b/tests/compute/column-major.slang index 1cd08434b8..6fc978ba6e 100644 --- a/tests/compute/column-major.slang +++ b/tests/compute/column-major.slang @@ -7,6 +7,7 @@ //TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-vk -compute -emit-spirv-via-glsl -Xslang -matrix-layout-column-major //TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-cuda -compute -shaderobj -Xslang -matrix-layout-column-major //TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-mtl -compute -shaderobj -Xslang -matrix-layout-column-major +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu // This data is in column major layout order.... //TEST_INPUT:cbuffer(data=[1.0 0.0 0.0 10.0 0.0 1.0 0.0 20.0 0.0 0.0 1.0 30.0 0.0 0.0 0.0 1.0]):name matrixBuffer diff --git a/tests/compute/constant-buffer-memory-packing.slang b/tests/compute/constant-buffer-memory-packing.slang index fb7a78fc1d..93d4331fdf 100644 --- a/tests/compute/constant-buffer-memory-packing.slang +++ b/tests/compute/constant-buffer-memory-packing.slang @@ -9,6 +9,8 @@ //TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-vk -compute //TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=BUF):-mtl -compute +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu + // CPP/CUDA due to natural layout rules will recieve the following ROW matrix: // {1,2,3} // {0,4,5} diff --git a/tests/compute/func-cbuffer-param.slang b/tests/compute/func-cbuffer-param.slang index ec95433348..8b3c02e582 100644 --- a/tests/compute/func-cbuffer-param.slang +++ b/tests/compute/func-cbuffer-param.slang @@ -9,6 +9,7 @@ //TEST(compute, vulkan, compatibility-issue):COMPARE_COMPUTE_EX:-dx12 -compute -use-dxil -shaderobj //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-cpu -compute -shaderobj +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu struct Data { diff --git a/tests/compute/parameter-block.slang b/tests/compute/parameter-block.slang index 2922f0813c..baa4206656 100644 --- a/tests/compute/parameter-block.slang +++ b/tests/compute/parameter-block.slang @@ -3,6 +3,7 @@ //TEST(compute):COMPARE_COMPUTE:-vk -shaderobj //TEST(compute):COMPARE_COMPUTE:-shaderobj //TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -mtl -render-features argument-buffer-tier-2 +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu // Ensure that Slang `ParameterBlock` type is lowered // to HLSL in the fashion that we expect. diff --git a/tests/compute/texture-get-dimensions.slang b/tests/compute/texture-get-dimensions.slang index 526e9feb11..55eeb68f5b 100644 --- a/tests/compute/texture-get-dimensions.slang +++ b/tests/compute/texture-get-dimensions.slang @@ -6,6 +6,7 @@ //DISABLE_TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj // TODO(JS): Doesn't work on CUDA as there aren't any CUDA functions to get dimensions. //DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-cuda -compute -shaderobj +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu //TEST_INPUT: Texture1D(size=4, content = one):name t1D Texture1D t1D; diff --git a/tests/compute/texture-sampling.slang b/tests/compute/texture-sampling.slang index 0e319680a3..3e56be5a7b 100644 --- a/tests/compute/texture-sampling.slang +++ b/tests/compute/texture-sampling.slang @@ -12,6 +12,7 @@ //TEST_INPUT: TextureCube(size=4, content = one, arrayLength=2):name=tCubeArray //TEST_INPUT: Sampler:name=samplerState //TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu Texture1D t1D; Texture2D t2D; diff --git a/tests/compute/texture-simple.slang b/tests/compute/texture-simple.slang index efa83edfbe..c319d9d29e 100644 --- a/tests/compute/texture-simple.slang +++ b/tests/compute/texture-simple.slang @@ -9,6 +9,8 @@ //DISABLE_TEST_INPUT: Texture1D(format=R_Float32, size=4, content = one, mipMaps=1):name tLoad1D //Texture1D tLoad1D; +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu + //TEST_INPUT: Texture1D(size=4, content = one):name t1D Texture1D t1D; //TEST_INPUT: Texture2D(size=4, content = one):name t2D diff --git a/tests/compute/texture-simpler.slang b/tests/compute/texture-simpler.slang index 0f9dfcbade..777f13ef61 100644 --- a/tests/compute/texture-simpler.slang +++ b/tests/compute/texture-simpler.slang @@ -5,6 +5,7 @@ //TEST(smoke,compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj -output-using-type -render-feature hardware-device //TEST(smoke,compute):COMPARE_COMPUTE_EX:-cuda -compute -shaderobj -output-using-type //TEST(smoke,compute):COMPARE_COMPUTE:-slang -shaderobj -mtl -output-using-type +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu //TEST_INPUT: Texture2D(size=4, content = one):name t2D Texture2D t2D; diff --git a/tests/compute/transcendental-double.slang b/tests/compute/transcendental-double.slang index 886bdfd4c5..4b71e0babd 100644 --- a/tests/compute/transcendental-double.slang +++ b/tests/compute/transcendental-double.slang @@ -7,6 +7,7 @@ // When using double on vulkan the values are incorrect(!) //DISABLE_TEST(compute,vulkan):COMPARE_COMPUTE:-vk -output-using-type -shaderobj //DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -mtl +//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -wgpu //TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0], stride=4):out,name=outputBuffer RWStructuredBuffer outputBuffer; diff --git a/tests/expected-failure-github.txt b/tests/expected-failure-github.txt index 524930f621..4551a4c691 100644 --- a/tests/expected-failure-github.txt +++ b/tests/expected-failure-github.txt @@ -5,3 +5,32 @@ tests/language-feature/saturated-cooperation/fuse-product.slang (vk) tests/language-feature/saturated-cooperation/fuse.slang (vk) tests/bugs/byte-address-buffer-interlocked-add-f32.slang (vk) tests/serialization/obfuscated-serialized-module-test.slang.2 syn (mtl) +tests/compute/atomics (wgpu) +tests/compute/atomics-buffer (wgpu) +tests/compute/atomics-groupshared (wgpu) +tests/compute/buffer-type-splitting (wgpu) +tests/compute/byte-address-buffer (wgpu) +tests/compute/cbuffer-legalize.slang.2 syn (wgpu) +tests/compute/column-major (wgpu) +tests/compute/compile-time-loop.slang.2 syn (wgpu) +tests/compute/constant-buffer-memory-packing (wgpu) +tests/compute/constexpr.slang.2 syn (wgpu) +tests/compute/discard-stmt.slang.2 syn (wgpu) +tests/compute/func-cbuffer-param (wgpu) +tests/compute/func-param-legalize.slang.1 syn (wgpu) +tests/compute/func-resource-param.slang.4 syn (wgpu) +tests/compute/global-init.slang.2 syn (wgpu) +tests/compute/interface-shader-param-in-struct.slang.4 syn (wgpu) +tests/compute/interface-shader-param.slang.5 syn (wgpu) +tests/compute/kernel-context-threading.slang.6 syn (wgpu) +tests/compute/loop-unroll.slang.7 syn (wgpu) +tests/compute/matrix-layout.hlsl.3 syn (wgpu) +tests/compute/non-square-column-major.slang.6 syn (wgpu) +tests/compute/non-square-row-major.slang.6 syn (wgpu) +tests/compute/parameter-block (wgpu) +tests/compute/row-major.slang.4 syn (wgpu) +tests/compute/texture-get-dimensions (wgpu) +tests/compute/texture-sampling (wgpu) +tests/compute/texture-simple (wgpu) +tests/compute/texture-simpler (wgpu) +tests/compute/transcendental-double (wgpu)