diff options
author | Geoff Lang <geofflang@chromium.org> | 2024-04-05 13:25:12 -0400 |
---|---|---|
committer | Angle LUCI CQ <angle-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2024-04-12 19:14:13 +0000 |
commit | 67fc293ab0b33e82cc151286f22d55a0781e9e86 (patch) | |
tree | bb5d3b630d23980ef3d3478d0b48bbc077fca146 | |
parent | 5e790bfb16e8246bdf73e625bd4203ce761b959a (diff) | |
download | angle-67fc293ab0b33e82cc151286f22d55a0781e9e86.tar.gz |
WebGPU: Add shader translation and program linking stubs.
Add a TranslatorWGSL which outputs the same translated shaders every
time.
Implement the compile and link tasks.
Bug: angleproject:8662
Change-Id: I62bbd6c528e1d671d0f4becc38f15f1eceb0336c
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5428807
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Matthew Denton <mpdenton@chromium.org>
-rw-r--r-- | BUILD.gn | 5 | ||||
-rw-r--r-- | include/GLSLANG/ShaderLang.h | 5 | ||||
-rwxr-xr-x | scripts/export_targets.py | 1 | ||||
-rw-r--r-- | src/angle_program_serialize_data_version.gni | 8 | ||||
-rw-r--r-- | src/compiler.gni | 3 | ||||
-rw-r--r-- | src/compiler/translator/CodeGen.cpp | 15 | ||||
-rw-r--r-- | src/compiler/translator/util.cpp | 4 | ||||
-rw-r--r-- | src/compiler/translator/util.h | 1 | ||||
-rw-r--r-- | src/compiler/translator/wgsl/TranslatorWGSL.cpp | 58 | ||||
-rw-r--r-- | src/compiler/translator/wgsl/TranslatorWGSL.h | 29 | ||||
-rw-r--r-- | src/libANGLE/renderer/wgpu/CompilerWgpu.cpp | 2 | ||||
-rw-r--r-- | src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.cpp | 6 | ||||
-rw-r--r-- | src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.h | 12 | ||||
-rw-r--r-- | src/libANGLE/renderer/wgpu/ProgramWgpu.cpp | 127 | ||||
-rw-r--r-- | src/libANGLE/renderer/wgpu/ShaderWgpu.cpp | 24 | ||||
-rw-r--r-- | src/tests/gl_tests/RendererTest.cpp | 26 |
16 files changed, 315 insertions, 11 deletions
@@ -755,6 +755,11 @@ template("translator_lib") { sources += angle_translator_lib_msl_sources defines += [ "ANGLE_ENABLE_METAL" ] } + + if (angle_enable_wgpu) { + sources += angle_translator_lib_wgsl_sources + defines += [ "ANGLE_ENABLE_WGPU" ] + } } if (_needs_glsl_base) { diff --git a/include/GLSLANG/ShaderLang.h b/include/GLSLANG/ShaderLang.h index 5eb4806568..0d2497540e 100644 --- a/include/GLSLANG/ShaderLang.h +++ b/include/GLSLANG/ShaderLang.h @@ -26,7 +26,7 @@ // Version number for shader translation API. // It is incremented every time the API changes. -#define ANGLE_SH_VERSION 349 +#define ANGLE_SH_VERSION 350 enum ShShaderSpec { @@ -74,6 +74,9 @@ enum ShShaderOutput // Output for MSL SH_MSL_METAL_OUTPUT = 0x8B4D, + + // Output for WGSL + SH_WGSL_OUTPUT = 0x8B4E, }; struct ShCompileOptionsMetal diff --git a/scripts/export_targets.py b/scripts/export_targets.py index 11ea9e8aff..5a06940715 100755 --- a/scripts/export_targets.py +++ b/scripts/export_targets.py @@ -189,6 +189,7 @@ IGNORED_INCLUDES = { b'compiler/translator/hlsl/TranslatorHLSL.h', b'compiler/translator/msl/TranslatorMSL.h', b'compiler/translator/spirv/TranslatorSPIRV.h', + b'compiler/translator/wgsl/TranslatorWGSL.h', b'contrib/optimizations/slide_hash_neon.h', b'dirent_on_windows.h', b'dlopen_fuchsia.h', diff --git a/src/angle_program_serialize_data_version.gni b/src/angle_program_serialize_data_version.gni index 9453612459..d247714a97 100644 --- a/src/angle_program_serialize_data_version.gni +++ b/src/angle_program_serialize_data_version.gni @@ -17,6 +17,7 @@ import("libANGLE/renderer/gl/gl_backend.gni") import("libANGLE/renderer/metal/metal_backend.gni") import("libANGLE/renderer/null/null_backend.gni") import("libANGLE/renderer/vulkan/vulkan_backend.gni") +import("libANGLE/renderer/wgpu/wgpu_sources.gni") import("libGLESv2.gni") angle_code_affecting_program_serialize = libangle_common_sources @@ -39,6 +40,7 @@ angle_code_affecting_program_serialize += angle_code_affecting_program_serialize += angle_translator_glsl_symbol_table_sources angle_code_affecting_program_serialize += angle_translator_lib_msl_sources +angle_code_affecting_program_serialize += angle_translator_lib_wgsl_sources angle_code_affecting_program_serialize += angle_preprocessor_sources angle_dependencies_affecting_program_serialize = [] @@ -79,6 +81,12 @@ if (angle_enable_metal) { } } +if (angle_enable_wgpu) { + wgpu_backend_dir = "libANGLE/renderer/wgpu/" + angle_code_affecting_program_serialize += + rebase_path(wgpu_backend_sources, angle_root, wgpu_backend_dir) +} + if (angle_has_frame_capture) { angle_code_affecting_program_serialize += libangle_capture_sources } diff --git a/src/compiler.gni b/src/compiler.gni index 165055273b..c4feb4bbc5 100644 --- a/src/compiler.gni +++ b/src/compiler.gni @@ -449,6 +449,9 @@ angle_translator_lib_msl_sources = [ "src/compiler/translator/tree_ops/msl/WrapMain.h", ] +angle_translator_lib_wgsl_sources = + [ "src/compiler/translator/wgsl/TranslatorWGSL.cpp" ] + angle_preprocessor_sources = [ "src/compiler/preprocessor/DiagnosticsBase.cpp", "src/compiler/preprocessor/DiagnosticsBase.h", diff --git a/src/compiler/translator/CodeGen.cpp b/src/compiler/translator/CodeGen.cpp index 4c5b8b3d77..383bee94ca 100644 --- a/src/compiler/translator/CodeGen.cpp +++ b/src/compiler/translator/CodeGen.cpp @@ -24,6 +24,14 @@ # include "compiler/translator/msl/TranslatorMSL.h" #endif // ANGLE_ENABLE_METAL +#ifdef ANGLE_ENABLE_WEBGPU +# include "compiler/translator/msl/TranslatorMSL.h" +#endif // ANGLE_ENABLE_METAL + +#ifdef ANGLE_ENABLE_WGPU +# include "compiler/translator/wgsl/TranslatorWGSL.h" +#endif + #include "compiler/translator/util.h" namespace sh @@ -71,6 +79,13 @@ TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput } #endif // ANGLE_ENABLE_METAL +#ifdef ANGLE_ENABLE_WGPU + if (IsOutputWGSL(output)) + { + return new TranslatorWGSL(type, spec, output); + } +#endif // ANGLE_ENABLE_WGPU + // Unsupported compiler or unknown format. Return nullptr per the sh::ConstructCompiler API. return nullptr; } diff --git a/src/compiler/translator/util.cpp b/src/compiler/translator/util.cpp index 4c4c3fb778..40aa16dcf4 100644 --- a/src/compiler/translator/util.cpp +++ b/src/compiler/translator/util.cpp @@ -827,6 +827,10 @@ bool IsOutputMSL(ShShaderOutput output) { return output == SH_MSL_METAL_OUTPUT; } +bool IsOutputWGSL(ShShaderOutput output) +{ + return output == SH_WGSL_OUTPUT; +} bool IsInShaderStorageBlock(TIntermTyped *node) { diff --git a/src/compiler/translator/util.h b/src/compiler/translator/util.h index 97765a74e7..872bca29a5 100644 --- a/src/compiler/translator/util.h +++ b/src/compiler/translator/util.h @@ -84,6 +84,7 @@ bool IsOutputGLSL(ShShaderOutput output); bool IsOutputHLSL(ShShaderOutput output); bool IsOutputSPIRV(ShShaderOutput output); bool IsOutputMSL(ShShaderOutput output); +bool IsOutputWGSL(ShShaderOutput output); bool IsInShaderStorageBlock(TIntermTyped *node); diff --git a/src/compiler/translator/wgsl/TranslatorWGSL.cpp b/src/compiler/translator/wgsl/TranslatorWGSL.cpp new file mode 100644 index 0000000000..bb7c3be5d2 --- /dev/null +++ b/src/compiler/translator/wgsl/TranslatorWGSL.cpp @@ -0,0 +1,58 @@ +// +// Copyright 2024 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/wgsl/TranslatorWGSL.h" + +namespace sh +{ +TranslatorWGSL::TranslatorWGSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) + : TCompiler(type, spec, output) +{} + +bool TranslatorWGSL::translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics) +{ + TInfoSinkBase &sink = getInfoSink().obj; + if (getShaderType() == GL_VERTEX_SHADER) + { + constexpr const char *kVertexShader = R"(@vertex +fn main(@builtin(vertex_index) vertex_index : u32) -> @builtin(position) vec4f +{ + const pos = array( + vec2( 0.0, 0.5), + vec2(-0.5, -0.5), + vec2( 0.5, -0.5) + ); + + return vec4f(pos[vertex_index % 3], 0, 1); +})"; + sink << kVertexShader; + } + else if (getShaderType() == GL_FRAGMENT_SHADER) + { + constexpr const char *kFragmentShader = R"(@fragment +fn main() -> @location(0) vec4f +{ + return vec4(1, 0, 0, 1); +})"; + sink << kFragmentShader; + } + else + { + UNREACHABLE(); + return false; + } + + return true; +} + +bool TranslatorWGSL::shouldFlattenPragmaStdglInvariantAll() +{ + // Not neccesary for WGSL transformation. + return false; +} +} // namespace sh diff --git a/src/compiler/translator/wgsl/TranslatorWGSL.h b/src/compiler/translator/wgsl/TranslatorWGSL.h new file mode 100644 index 0000000000..d5c30e197a --- /dev/null +++ b/src/compiler/translator/wgsl/TranslatorWGSL.h @@ -0,0 +1,29 @@ +// +// Copyright 2024 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_WGSL_H_ +#define COMPILER_TRANSLATOR_WGSL_H_ + +#include "compiler/translator/Compiler.h" + +namespace sh +{ +class TranslatorWGSL : public TCompiler +{ + public: + TranslatorWGSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); + + protected: + bool translate(TIntermBlock *root, + const ShCompileOptions &compileOptions, + PerformanceDiagnostics *perfDiagnostics) override; + + [[nodiscard]] bool shouldFlattenPragmaStdglInvariantAll() override; +}; + +} // namespace sh + +#endif // COMPILER_TRANSLATOR_WGSL_H_ diff --git a/src/libANGLE/renderer/wgpu/CompilerWgpu.cpp b/src/libANGLE/renderer/wgpu/CompilerWgpu.cpp index 35572395b0..61d5edcd34 100644 --- a/src/libANGLE/renderer/wgpu/CompilerWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/CompilerWgpu.cpp @@ -20,7 +20,7 @@ CompilerWgpu::~CompilerWgpu() {} ShShaderOutput CompilerWgpu::getTranslatorOutputType() const { - return SH_ESSL_OUTPUT; + return SH_WGSL_OUTPUT; } } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.cpp b/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.cpp index 2ce7614176..d370660223 100644 --- a/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.cpp @@ -115,4 +115,10 @@ void ProgramExecutableWgpu::getUniformuiv(const gl::Context *context, { // TODO: Write some values. } + +TranslatedWGPUShaderModule &ProgramExecutableWgpu::getShaderModule(gl::ShaderType type) +{ + return mShaderModules[type]; +} + } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.h b/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.h index 9d198a9530..9a44ff02d3 100644 --- a/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.h +++ b/src/libANGLE/renderer/wgpu/ProgramExecutableWgpu.h @@ -12,6 +12,13 @@ #include "libANGLE/ProgramExecutable.h" #include "libANGLE/renderer/ProgramExecutableImpl.h" +#include <dawn/webgpu_cpp.h> + +struct TranslatedWGPUShaderModule +{ + wgpu::ShaderModule module; +}; + namespace rx { class ProgramExecutableWgpu : public ProgramExecutableImpl @@ -74,6 +81,11 @@ class ProgramExecutableWgpu : public ProgramExecutableImpl void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override; void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override; void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override; + + TranslatedWGPUShaderModule &getShaderModule(gl::ShaderType type); + + private: + gl::ShaderMap<TranslatedWGPUShaderModule> mShaderModules; }; } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/ProgramWgpu.cpp b/src/libANGLE/renderer/wgpu/ProgramWgpu.cpp index 98598469b3..0b8819cfff 100644 --- a/src/libANGLE/renderer/wgpu/ProgramWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/ProgramWgpu.cpp @@ -10,15 +10,112 @@ #include "libANGLE/renderer/wgpu/ProgramWgpu.h" #include "common/debug.h" +#include "libANGLE/renderer/wgpu/ProgramExecutableWgpu.h" +#include "libANGLE/renderer/wgpu/wgpu_utils.h" +#include "libANGLE/trace.h" + +#include <dawn/webgpu_cpp.h> namespace rx { namespace { +class CreateWGPUShaderModuleTask : public LinkSubTask +{ + public: + CreateWGPUShaderModuleTask(wgpu::Instance instance, + wgpu::Device device, + const gl::SharedCompiledShaderState &compiledShaderState, + TranslatedWGPUShaderModule &resultShaderModule) + : mInstance(instance), + mDevice(device), + mCompiledShaderState(compiledShaderState), + mShaderModule(resultShaderModule) + {} + + angle::Result getResult(const gl::Context *context, gl::InfoLog &infoLog) override + { + infoLog << mLog.str(); + return mResult; + } + + void operator()() override + { + ANGLE_TRACE_EVENT0("gpu.angle", "CreateWGPUShaderModuleTask"); + + wgpu::ShaderModuleWGSLDescriptor shaderModuleWGSLDescriptor; + shaderModuleWGSLDescriptor.code = mCompiledShaderState->translatedSource.c_str(); + + wgpu::ShaderModuleDescriptor shaderModuleDescriptor; + shaderModuleDescriptor.nextInChain = &shaderModuleWGSLDescriptor; + + mShaderModule.module = mDevice.CreateShaderModule(&shaderModuleDescriptor); + + wgpu::CompilationInfoCallbackInfo callbackInfo; + callbackInfo.mode = wgpu::CallbackMode::WaitAnyOnly; + callbackInfo.callback = [](WGPUCompilationInfoRequestStatus status, + struct WGPUCompilationInfo const *compilationInfo, + void *userdata) { + CreateWGPUShaderModuleTask *task = static_cast<CreateWGPUShaderModuleTask *>(userdata); + + if (status != WGPUCompilationInfoRequestStatus_Success) + { + task->mResult = angle::Result::Stop; + } + + for (size_t msgIdx = 0; msgIdx < compilationInfo->messageCount; ++msgIdx) + { + const WGPUCompilationMessage &message = compilationInfo->messages[msgIdx]; + switch (message.type) + { + case WGPUCompilationMessageType_Error: + task->mLog << "Error: "; + break; + case WGPUCompilationMessageType_Warning: + task->mLog << "Warning: "; + break; + case WGPUCompilationMessageType_Info: + task->mLog << "Info: "; + break; + default: + task->mLog << "Unknown: "; + break; + } + task->mLog << message.lineNum << ":" << message.linePos << ": " << message.message + << std::endl; + } + }; + callbackInfo.userdata = this; + + wgpu::FutureWaitInfo waitInfo; + waitInfo.future = mShaderModule.module.GetCompilationInfo(callbackInfo); + + wgpu::WaitStatus waitStatus = mInstance.WaitAny(1, &waitInfo, -1); + if (waitStatus != wgpu::WaitStatus::Success) + { + mResult = angle::Result::Stop; + } + } + + private: + wgpu::Instance mInstance; + wgpu::Device mDevice; + gl::SharedCompiledShaderState mCompiledShaderState; + + TranslatedWGPUShaderModule &mShaderModule; + + std::ostringstream mLog; + angle::Result mResult = angle::Result::Continue; +}; + class LinkTaskWgpu : public LinkTask { public: + LinkTaskWgpu(wgpu::Instance instance, wgpu::Device device, ProgramWgpu *program) + : mInstance(instance), mDevice(device), mProgram(program) + {} ~LinkTaskWgpu() override = default; + void link(const gl::ProgramLinkedResources &resources, const gl::ProgramMergedVaryings &mergedVaryings, std::vector<std::shared_ptr<LinkSubTask>> *linkSubTasksOut, @@ -27,12 +124,32 @@ class LinkTaskWgpu : public LinkTask ASSERT(linkSubTasksOut && linkSubTasksOut->empty()); ASSERT(postLinkSubTasksOut && postLinkSubTasksOut->empty()); - return; + ProgramExecutableWgpu *executable = + GetImplAs<ProgramExecutableWgpu>(&mProgram->getState().getExecutable()); + + const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders = + mProgram->getState().getAttachedShaders(); + for (gl::ShaderType shaderType : gl::AllShaderTypes()) + { + if (shaders[shaderType]) + { + auto task = std::make_shared<CreateWGPUShaderModuleTask>( + mInstance, mDevice, shaders[shaderType], + executable->getShaderModule(shaderType)); + linkSubTasksOut->push_back(task); + } + } } + angle::Result getResult(const gl::Context *context, gl::InfoLog &infoLog) override { return angle::Result::Continue; } + + private: + wgpu::Instance mInstance; + wgpu::Device mDevice; + ProgramWgpu *mProgram = nullptr; }; } // anonymous namespace @@ -56,10 +173,12 @@ void ProgramWgpu::setBinaryRetrievableHint(bool retrievable) {} void ProgramWgpu::setSeparable(bool separable) {} -angle::Result ProgramWgpu::link(const gl::Context *contextImpl, - std::shared_ptr<LinkTask> *linkTaskOut) +angle::Result ProgramWgpu::link(const gl::Context *context, std::shared_ptr<LinkTask> *linkTaskOut) { - *linkTaskOut = std::shared_ptr<LinkTask>(new LinkTaskWgpu); + wgpu::Device device = webgpu::GetDevice(context); + wgpu::Instance instance = webgpu::GetInstance(context); + + *linkTaskOut = std::shared_ptr<LinkTask>(new LinkTaskWgpu(instance, device, this)); return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/wgpu/ShaderWgpu.cpp b/src/libANGLE/renderer/wgpu/ShaderWgpu.cpp index fe14e9c39a..92d981850e 100644 --- a/src/libANGLE/renderer/wgpu/ShaderWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/ShaderWgpu.cpp @@ -12,10 +12,29 @@ #include "common/debug.h" #include "libANGLE/Context.h" #include "libANGLE/renderer/ContextImpl.h" +#include "libANGLE/trace.h" namespace rx { +namespace +{ +class ShaderTranslateTaskWgpu final : public ShaderTranslateTask +{ + bool translate(ShHandle compiler, + const ShCompileOptions &options, + const std::string &source) override + { + ANGLE_TRACE_EVENT1("gpu.angle", "ShaderTranslateTaskWgpu::translate", "source", source); + + const char *srcStrings[] = {source.c_str()}; + return sh::Compile(compiler, srcStrings, ArraySize(srcStrings), options); + } + + void postTranslate(ShHandle compiler, const gl::CompiledShaderState &compiledState) override {} +}; +} // namespace + ShaderWgpu::ShaderWgpu(const gl::ShaderState &data) : ShaderImpl(data) {} ShaderWgpu::~ShaderWgpu() {} @@ -28,7 +47,10 @@ std::shared_ptr<ShaderTranslateTask> ShaderWgpu::compile(const gl::Context *cont { options->pls = context->getImplementation()->getNativePixelLocalStorageOptions(); } - return std::shared_ptr<ShaderTranslateTask>(new ShaderTranslateTask); + + options->validateAST = true; + + return std::shared_ptr<ShaderTranslateTask>(new ShaderTranslateTaskWgpu); } std::string ShaderWgpu::getDebugInfo() const diff --git a/src/tests/gl_tests/RendererTest.cpp b/src/tests/gl_tests/RendererTest.cpp index 5e798cb8a3..2c1764b169 100644 --- a/src/tests/gl_tests/RendererTest.cpp +++ b/src/tests/gl_tests/RendererTest.cpp @@ -9,15 +9,15 @@ // configured incorrectly. For example, they might be using the D3D11 renderer when the test is // meant to be using the D3D9 renderer. +#include "common/string_utils.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" +#include "util/shader_utils.h" #include "util/test_utils.h" -#include "common/string_utils.h" - using namespace angle; -namespace +namespace angle { class RendererTest : public ANGLETest<> @@ -190,6 +190,24 @@ TEST_P(RendererTest, BufferData) } } +// Compile simple vertex and fragment shaders +TEST_P(RendererTest, CompileShader) +{ + GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Zero()); + EXPECT_NE(vs, 0u); + glDeleteShader(vs); + + GLuint fs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Red()); + EXPECT_NE(fs, 0u); + glDeleteShader(fs); +} + +// Link a simple program +TEST_P(RendererTest, LinkProgram) +{ + ANGLE_GL_PROGRAM(prog, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red()); +} + // Select configurations (e.g. which renderer, which GLES major version) these tests should be run // against. // TODO(http://anglebug.com/8485): move ES2_WEBGPU to the definition of ANGLE_ALL_TEST_PLATFORMS_ES2 @@ -197,4 +215,4 @@ TEST_P(RendererTest, BufferData) ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND_NULL_AND(RendererTest, ANGLE_ALL_TEST_PLATFORMS_GL32_CORE, ES2_WEBGPU()); -} // anonymous namespace +} // namespace angle |