From a5a04ac0f9bb6b4d7db61ba66ad8b400d665c78f Mon Sep 17 00:00:00 2001 From: Le Quyen Date: Tue, 29 Oct 2019 22:57:55 +0800 Subject: [PATCH] Metal backend pt3: shader translator Implementation of GLSL to MSL translator Bug: angleproject:2634 Change-Id: I66e2374b461548fac46163ea79790a488515e6b0 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1887251 Commit-Queue: Jamie Madill Reviewed-by: Jamie Madill --- .gitignore | 1 + DEPS | 8 ++ build_overrides/angle.gni | 1 + .../translator/OutputVulkanGLSLForMetal.h | 6 + .../translator/OutputVulkanGLSLForMetal.mm | 67 ++++++++- src/compiler/translator/TranslatorMetal.cpp | 86 ++++++++++-- src/compiler/translator/TranslatorMetal.h | 13 +- src/compiler/translator/TranslatorVulkan.cpp | 42 +++++- src/compiler/translator/TranslatorVulkan.h | 11 ++ src/libANGLE/renderer/metal/BUILD.gn | 4 + src/libANGLE/renderer/metal/ProgramMtl.mm | 129 +++++++++++++++++- .../renderer/metal/mtl_glslang_utils.h | 20 ++- .../renderer/metal/mtl_glslang_utils.mm | 54 ++++++-- third_party/spirv-cross/README.angle | 10 ++ 14 files changed, 392 insertions(+), 60 deletions(-) create mode 100644 third_party/spirv-cross/README.angle diff --git a/.gitignore b/.gitignore index f85340cdf..d33402ed8 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ /third_party/qemu-linux-x64 /third_party/qemu-mac-x64 /third_party/rapidjson/src +/third_party/spirv-cross/src /third_party/spirv-headers/src /third_party/spirv-tools/src /third_party/SwiftShader diff --git a/DEPS b/DEPS index edbce7e52..edb1c5b6f 100644 --- a/DEPS +++ b/DEPS @@ -41,6 +41,9 @@ vars = { # Note: this dep cannot be auto-rolled b/c of nesting. 'patched_yasm_revision': '720b70524a4424b15fc57e82263568c8ba0496ad', + # Current revision of spirv-cross, the Khronos SPIRV cross compiler. + 'spirv_cross_revision': 'd253f41e17e27285756d031d8ba43bf370264e1f', + # Current revision fo the SPIRV-Headers Vulkan support library. 'spirv_headers_revision': 'af64a9e826bf5bb5fcd2434dd71be1e41e922563', @@ -160,6 +163,11 @@ deps = { 'url': '{chromium_git}/external/github.com/Tencent/rapidjson@7484e06c589873e1ed80382d262087e4fa80fb63', }, + 'third_party/spirv-cross/src': { + 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@{spirv_cross_revision}', + 'condition': 'not build_with_chromium', + }, + 'third_party/spirv-headers/src': { 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@{spirv_headers_revision}', 'condition': 'not build_with_chromium', diff --git a/build_overrides/angle.gni b/build_overrides/angle.gni index 5bf1aa22a..dbaf832fe 100644 --- a/build_overrides/angle.gni +++ b/build_overrides/angle.gni @@ -14,4 +14,5 @@ angle_googletest_dir = "//third_party/googletest/src" angle_libjpeg_turbo_dir = "//third_party/libjpeg_turbo" angle_jsoncpp_dir = "//third_party/jsoncpp" angle_libpng_dir = "//third_party/libpng" +angle_spirv_cross_dir = "//third_party/spirv-cross/src" angle_spirv_tools_dir = "//third_party/spirv-tools/src" diff --git a/src/compiler/translator/OutputVulkanGLSLForMetal.h b/src/compiler/translator/OutputVulkanGLSLForMetal.h index 901ec0e6c..218a04b6f 100644 --- a/src/compiler/translator/OutputVulkanGLSLForMetal.h +++ b/src/compiler/translator/OutputVulkanGLSLForMetal.h @@ -25,6 +25,12 @@ class TOutputVulkanGLSLForMetal : public TOutputVulkanGLSL int shaderVersion, ShShaderOutput output, ShCompileOptions compileOptions); + + static void RemoveInvariantForTest(bool remove); + + protected: + bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; + void writeVariableType(const TType &type, const TSymbol *symbol) override; }; } // namespace sh \ No newline at end of file diff --git a/src/compiler/translator/OutputVulkanGLSLForMetal.mm b/src/compiler/translator/OutputVulkanGLSLForMetal.mm index 6aed5de35..a0065f3c4 100644 --- a/src/compiler/translator/OutputVulkanGLSLForMetal.mm +++ b/src/compiler/translator/OutputVulkanGLSLForMetal.mm @@ -10,11 +10,50 @@ #include "compiler/translator/OutputVulkanGLSLForMetal.h" -#include "common/debug.h" +#include "common/apple_platform_utils.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/util.h" namespace sh { +namespace +{ +bool gOverrideRemoveInvariant = false; + +bool ShoudRemoveInvariant(const TType &type) +{ + if (gOverrideRemoveInvariant) + { + return true; + } + + if (type.getQualifier() != EvqPosition) + { + // Metal only supports invariant for gl_Position + return true; + } + + if (ANGLE_APPLE_AVAILABLE_XCI(10.14, 13.0, 12)) + { + return false; + } + else + { + // Metal 2.1 is not available, so we need to remove "invariant" keyword + return true; + } +} + +} + +// static +void TOutputVulkanGLSLForMetal::RemoveInvariantForTest(bool remove) +{ + gOverrideRemoveInvariant = remove; +} + TOutputVulkanGLSLForMetal::TOutputVulkanGLSLForMetal(TInfoSinkBase &objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, @@ -33,8 +72,32 @@ TOutputVulkanGLSLForMetal::TOutputVulkanGLSLForMetal(TInfoSinkBase &objSink, shaderVersion, output, compileOptions) +{} + +void TOutputVulkanGLSLForMetal::writeVariableType(const TType &type, const TSymbol *symbol) { - UNIMPLEMENTED(); + TType overrideType(type); + + // Remove invariant keyword if required. + if (type.isInvariant() && ShoudRemoveInvariant(type)) + { + overrideType.setInvariant(false); + } + + TOutputVulkanGLSL::writeVariableType(overrideType, symbol); } +bool TOutputVulkanGLSLForMetal::visitInvariantDeclaration(Visit visit, + TIntermInvariantDeclaration *node) +{ + TInfoSinkBase &out = objSink(); + ASSERT(visit == PreVisit); + const TIntermSymbol *symbol = node->getSymbol(); + if (!ShoudRemoveInvariant(symbol->getType())) + { + out << "invariant "; + } + out << hashName(&symbol->variable()); + return false; +} } // namespace sh diff --git a/src/compiler/translator/TranslatorMetal.cpp b/src/compiler/translator/TranslatorMetal.cpp index 838142d4c..5c9d7f34a 100644 --- a/src/compiler/translator/TranslatorMetal.cpp +++ b/src/compiler/translator/TranslatorMetal.cpp @@ -4,40 +4,96 @@ // found in the LICENSE file. // // TranslatorMetal: -// Translator for Metal backend. +// A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl. +// It takes into account some considerations for Metal backend also. +// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side). +// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt +// +// The SPIR-V will then be translated to Metal Shading Language later in Metal backend. // #include "compiler/translator/TranslatorMetal.h" -#include "common/debug.h" +#include "angle_gl.h" +#include "common/utilities.h" #include "compiler/translator/OutputVulkanGLSLForMetal.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/tree_util/BuiltIn.h" +#include "compiler/translator/tree_util/RunAtTheEndOfShader.h" +#include "compiler/translator/util.h" namespace sh { -TranslatorMetal::TranslatorMetal(sh::GLenum type, ShShaderSpec spec) - : TCompiler(type, spec, SH_GLSL_450_CORE_OUTPUT) +namespace +{ + +// Unlike Vulkan having auto viewport flipping extension, in Metal we have to flip gl_Position.y +// manually. +// This operation performs flipping the gl_Position.y using this expression: +// gl_Position.y = gl_Position.y * negViewportScaleY +ANGLE_NO_DISCARD bool AppendVertexShaderPositionYCorrectionToMain(TCompiler *compiler, + TIntermBlock *root, + TSymbolTable *symbolTable, + TIntermBinary *negViewportYScale) +{ + // Create a symbol reference to "gl_Position" + const TVariable *position = BuiltInVariable::gl_Position(); + TIntermSymbol *positionRef = new TIntermSymbol(position); + + // Create a swizzle to "gl_Position.y" + TVector swizzleOffsetY; + swizzleOffsetY.push_back(1); + TIntermSwizzle *positionY = new TIntermSwizzle(positionRef, swizzleOffsetY); + + // Create the expression "gl_Position.y * negViewportScaleY" + TIntermBinary *inverseY = new TIntermBinary(EOpMul, positionY->deepCopy(), negViewportYScale); + + // Create the assignment "gl_Position.y = gl_Position.y * negViewportScaleY + TIntermTyped *positionYLHS = positionY->deepCopy(); + TIntermBinary *assignment = new TIntermBinary(TOperator::EOpAssign, positionYLHS, inverseY); + + // Append the assignment as a statement at the end of the shader. + return RunAtTheEndOfShader(compiler, root, assignment, symbolTable); +} + +} // anonymous namespace + +TranslatorMetal::TranslatorMetal(sh::GLenum type, ShShaderSpec spec) : TranslatorVulkan(type, spec) {} bool TranslatorMetal::translate(TIntermBlock *root, ShCompileOptions compileOptions, - PerformanceDiagnostics * /*perfDiagnostics*/) + PerformanceDiagnostics *perfDiagnostics) { TInfoSinkBase &sink = getInfoSink().obj; - TOutputVulkanGLSLForMetal outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), - getNameMap(), &getSymbolTable(), getShaderType(), - getShaderVersion(), getOutputType(), compileOptions); + TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), + getNameMap(), &getSymbolTable(), getShaderType(), + getShaderVersion(), getOutputType(), compileOptions); - UNIMPLEMENTED(); + const TVariable *driverUniforms = nullptr; + if (!TranslatorVulkan::translateImpl(root, compileOptions, perfDiagnostics, &driverUniforms, + &outputGLSL)) + { + return false; + } + if (getShaderType() == GL_VERTEX_SHADER) + { + auto negViewportYScale = getDriverUniformNegViewportYScaleRef(driverUniforms); + + // Append gl_Position.y correction to main + if (!AppendVertexShaderPositionYCorrectionToMain(this, root, &getSymbolTable(), + negViewportYScale)) + { + return false; + } + } + + // Write translated shader. root->traverse(&outputGLSL); - return false; -} -bool TranslatorMetal::shouldFlattenPragmaStdglInvariantAll() -{ - UNIMPLEMENTED(); - return false; + return true; } } // namespace sh diff --git a/src/compiler/translator/TranslatorMetal.h b/src/compiler/translator/TranslatorMetal.h index 5be5b2ddd..f70294a79 100644 --- a/src/compiler/translator/TranslatorMetal.h +++ b/src/compiler/translator/TranslatorMetal.h @@ -4,18 +4,23 @@ // found in the LICENSE file. // // TranslatorMetal: -// Translator for Metal backend. +// A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl. +// It takes into account some considerations for Metal backend also. +// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side). +// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt +// +// The SPIR-V will then be translated to Metal Shading Language later in Metal backend. // #ifndef LIBANGLE_RENDERER_METAL_TRANSLATORMETAL_H_ #define LIBANGLE_RENDERER_METAL_TRANSLATORMETAL_H_ -#include "compiler/translator/Compiler.h" +#include "compiler/translator/TranslatorVulkan.h" namespace sh { -class TranslatorMetal : public TCompiler +class TranslatorMetal : public TranslatorVulkan { public: TranslatorMetal(sh::GLenum type, ShShaderSpec spec); @@ -24,8 +29,6 @@ class TranslatorMetal : public TCompiler ANGLE_NO_DISCARD bool translate(TIntermBlock *root, ShCompileOptions compileOptions, PerformanceDiagnostics *perfDiagnostics) override; - - bool shouldFlattenPragmaStdglInvariantAll() override; }; } // namespace sh diff --git a/src/compiler/translator/TranslatorVulkan.cpp b/src/compiler/translator/TranslatorVulkan.cpp index 880d711b1..0eaa26fbb 100644 --- a/src/compiler/translator/TranslatorVulkan.cpp +++ b/src/compiler/translator/TranslatorVulkan.cpp @@ -656,14 +656,13 @@ TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec) : TCompiler(type, spec, SH_GLSL_450_CORE_OUTPUT) {} -bool TranslatorVulkan::translate(TIntermBlock *root, - ShCompileOptions compileOptions, - PerformanceDiagnostics * /*perfDiagnostics*/) +bool TranslatorVulkan::translateImpl(TIntermBlock *root, + ShCompileOptions compileOptions, + PerformanceDiagnostics * /*perfDiagnostics*/, + const TVariable **driverUniformsOut, + TOutputVulkanGLSL *outputGLSL) { TInfoSinkBase &sink = getInfoSink().obj; - TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), - getNameMap(), &getSymbolTable(), getShaderType(), - getShaderVersion(), getOutputType(), compileOptions); if (getShaderType() == GL_VERTEX_SHADER) { @@ -727,7 +726,7 @@ bool TranslatorVulkan::translate(TIntermBlock *root, defaultUniformCount -= removedUniformsCount; // We must declare the struct types before using them. - DeclareStructTypesTraverser structTypesTraverser(&outputGLSL); + DeclareStructTypesTraverser structTypesTraverser(outputGLSL); root->traverse(&structTypesTraverser); if (!structTypesTraverser.updateTree(this, root)) { @@ -939,6 +938,29 @@ bool TranslatorVulkan::translate(TIntermBlock *root, return false; } + if (driverUniformsOut) + { + *driverUniformsOut = driverUniforms; + } + + return true; +} + +bool TranslatorVulkan::translate(TIntermBlock *root, + ShCompileOptions compileOptions, + PerformanceDiagnostics *perfDiagnostics) +{ + + TInfoSinkBase &sink = getInfoSink().obj; + TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), + getNameMap(), &getSymbolTable(), getShaderType(), + getShaderVersion(), getOutputType(), compileOptions); + + if (!translateImpl(root, compileOptions, perfDiagnostics, nullptr, &outputGLSL)) + { + return false; + } + // Write translated shader. root->traverse(&outputGLSL); @@ -951,4 +973,10 @@ bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll() return false; } +TIntermBinary *TranslatorVulkan::getDriverUniformNegViewportYScaleRef( + const TVariable *driverUniforms) const +{ + return CreateDriverUniformRef(driverUniforms, kNegViewportYScale); +} + } // namespace sh diff --git a/src/compiler/translator/TranslatorVulkan.h b/src/compiler/translator/TranslatorVulkan.h index bee741cc0..121ebd410 100644 --- a/src/compiler/translator/TranslatorVulkan.h +++ b/src/compiler/translator/TranslatorVulkan.h @@ -17,6 +17,8 @@ namespace sh { +class TOutputVulkanGLSL; + class TranslatorVulkan : public TCompiler { public: @@ -27,6 +29,15 @@ class TranslatorVulkan : public TCompiler ShCompileOptions compileOptions, PerformanceDiagnostics *perfDiagnostics) override; bool shouldFlattenPragmaStdglInvariantAll() override; + + TIntermBinary *getDriverUniformNegViewportYScaleRef(const TVariable *driverUniforms) const; + // Subclass can call this method to transform the AST before writing the final output. + // See TranslatorMetal.cpp. + ANGLE_NO_DISCARD bool translateImpl(TIntermBlock *root, + ShCompileOptions compileOptions, + PerformanceDiagnostics *perfDiagnostics, + const TVariable **driverUniformsOut, + TOutputVulkanGLSL *outputGLSL); }; } // namespace sh diff --git a/src/libANGLE/renderer/metal/BUILD.gn b/src/libANGLE/renderer/metal/BUILD.gn index 902487ece..9c2f77eee 100644 --- a/src/libANGLE/renderer/metal/BUILD.gn +++ b/src/libANGLE/renderer/metal/BUILD.gn @@ -83,6 +83,10 @@ angle_source_set("angle_metal_backend") { "${angle_root}:libANGLE_headers", ] + deps = [ + "${angle_spirv_cross_dir}/gn:spirv_cross_sources", + ] + objc_flags = [ "-Wno-nullability-completeness", "-Wno-unguarded-availability", diff --git a/src/libANGLE/renderer/metal/ProgramMtl.mm b/src/libANGLE/renderer/metal/ProgramMtl.mm index 84ac65835..cc74734d7 100644 --- a/src/libANGLE/renderer/metal/ProgramMtl.mm +++ b/src/libANGLE/renderer/metal/ProgramMtl.mm @@ -13,6 +13,8 @@ #include +#include + #include "common/debug.h" #include "libANGLE/Context.h" #include "libANGLE/ProgramLinkedResources.h" @@ -31,6 +33,85 @@ namespace #define SHADER_ENTRY_NAME @"main0" +spv::ExecutionModel ShaderTypeToSpvExecutionModel(gl::ShaderType shaderType) +{ + switch (shaderType) + { + case gl::ShaderType::Vertex: + return spv::ExecutionModelVertex; + case gl::ShaderType::Fragment: + return spv::ExecutionModelFragment; + default: + UNREACHABLE(); + return spv::ExecutionModelMax; + } +} + +// Some GLSL variables need 2 binding points in metal. For example, +// glsl sampler will be converted to 2 metal objects: texture and sampler. +// Thus we need to set 2 binding points for one glsl sampler variable. +using BindingField = uint32_t spirv_cross::MSLResourceBinding::*; +template +angle::Result BindResources(spirv_cross::CompilerMSL *compiler, + const spirv_cross::SmallVector &resources, + gl::ShaderType shaderType) +{ + auto &compilerMsl = *compiler; + + for (const spirv_cross::Resource &resource : resources) + { + spirv_cross::MSLResourceBinding resBinding; + resBinding.stage = ShaderTypeToSpvExecutionModel(shaderType); + + if (compilerMsl.has_decoration(resource.id, spv::DecorationDescriptorSet)) + { + resBinding.desc_set = + compilerMsl.get_decoration(resource.id, spv::DecorationDescriptorSet); + } + + if (!compilerMsl.has_decoration(resource.id, spv::DecorationBinding)) + { + continue; + } + + resBinding.binding = compilerMsl.get_decoration(resource.id, spv::DecorationBinding); + + uint32_t bindingPoint; + // NOTE(hqle): We use separate discrete binding point for now, in future, we should use + // one argument buffer for each descriptor set. + switch (resBinding.desc_set) + { + case 0: + // Use resBinding.binding as binding point. + bindingPoint = resBinding.binding; + break; + case mtl::kDriverUniformsBindingIndex: + bindingPoint = mtl::kDriverUniformsBindingIndex; + break; + case mtl::kDefaultUniformsBindingIndex: + // NOTE(hqle): Properly handle transform feedbacks and UBO binding once ES 3.0 is + // implemented. + bindingPoint = mtl::kDefaultUniformsBindingIndex; + break; + default: + // We don't support this descriptor set. + continue; + } + + // bindingField can be buffer or texture, which will be translated to [[buffer(d)]] or + // [[texture(d)]] or [[sampler(d)]] + resBinding.*bindingField1 = bindingPoint; + if (bindingField1 != bindingField2) + { + resBinding.*bindingField2 = bindingPoint; + } + + compilerMsl.add_msl_resource_binding(resBinding); + } + + return angle::Result::Continue; +} + void InitDefaultUniformBlock(const std::vector &uniforms, gl::Shader *shader, sh::BlockLayoutMap *blockLayoutMapOut, @@ -214,7 +295,7 @@ std::unique_ptr ProgramMtl::link(const gl::Context *context, // assignment done in that function. linkResources(resources); - mtl::GlslangUtils::GetShaderSource(mState, resources, &mShaderSource); + mtl::GlslangGetShaderSource(mState, resources, &mShaderSource); // NOTE(hqle): Parallelize linking. return std::make_unique(linkImpl(context, infoLog)); @@ -231,8 +312,8 @@ angle::Result ProgramMtl::linkImpl(const gl::Context *glContext, gl::InfoLog &in // Convert GLSL to spirv code gl::ShaderMap> shaderCodes; - ANGLE_TRY(mtl::GlslangUtils::GetShaderCode(contextMtl, contextMtl->getCaps(), false, - mShaderSource, &shaderCodes)); + ANGLE_TRY(mtl::GlslangGetShaderSpirvCode(contextMtl, contextMtl->getCaps(), false, + mShaderSource, &shaderCodes)); // Convert spirv code to MSL ANGLE_TRY(convertToMsl(glContext, gl::ShaderType::Vertex, infoLog, @@ -339,9 +420,47 @@ angle::Result ProgramMtl::convertToMsl(const gl::Context *glContext, gl::InfoLog &infoLog, std::vector *sprivCode) { - std::string translatedMsl = "TODO"; + ContextMtl *contextMtl = mtl::GetImpl(glContext); - UNIMPLEMENTED(); + spirv_cross::CompilerMSL compilerMsl(std::move(*sprivCode)); + + spirv_cross::CompilerMSL::Options compOpt; +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST + compOpt.platform = spirv_cross::CompilerMSL::Options::macOS; +#else + compOpt.platform = spirv_cross::CompilerMSL::Options::iOS; +#endif + + if (ANGLE_APPLE_AVAILABLE_XCI(10.14, 13.0, 12)) + { + // Use Metal 2.1 + compOpt.set_msl_version(2, 1); + } + else + { + // Always use at least Metal 2.0. + compOpt.set_msl_version(2); + } + + compilerMsl.set_msl_options(compOpt); + + // Tell spirv-cross to map default & driver uniform blocks & samplers as we want + spirv_cross::ShaderResources mslRes = compilerMsl.get_shader_resources(); + + ANGLE_TRY(BindResources<&spirv_cross::MSLResourceBinding::msl_buffer>( + &compilerMsl, mslRes.uniform_buffers, shaderType)); + + ANGLE_TRY((BindResources<&spirv_cross::MSLResourceBinding::msl_sampler, + &spirv_cross::MSLResourceBinding::msl_texture>( + &compilerMsl, mslRes.sampled_images, shaderType))); + + // NOTE(hqle): spirv-cross uses exceptions to report error, what should we do here + // in case of error? + std::string translatedMsl = compilerMsl.compile(); + if (translatedMsl.size() == 0) + { + ANGLE_MTL_CHECK(contextMtl, false, GL_INVALID_OPERATION); + } // Create actual Metal shader ANGLE_TRY(createMslShader(glContext, shaderType, infoLog, translatedMsl)); diff --git a/src/libANGLE/renderer/metal/mtl_glslang_utils.h b/src/libANGLE/renderer/metal/mtl_glslang_utils.h index becc765d3..fe94d01bf 100644 --- a/src/libANGLE/renderer/metal/mtl_glslang_utils.h +++ b/src/libANGLE/renderer/metal/mtl_glslang_utils.h @@ -18,19 +18,15 @@ namespace rx { namespace mtl { -class GlslangUtils -{ - public: - static void GetShaderSource(const gl::ProgramState &programState, - const gl::ProgramLinkedResources &resources, - gl::ShaderMap *shaderSourcesOut); +void GlslangGetShaderSource(const gl::ProgramState &programState, + const gl::ProgramLinkedResources &resources, + gl::ShaderMap *shaderSourcesOut); - static angle::Result GetShaderCode(ErrorHandler *context, - const gl::Caps &glCaps, - bool enableLineRasterEmulation, - const gl::ShaderMap &shaderSources, - gl::ShaderMap> *shaderCodeOut); -}; +angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context, + const gl::Caps &glCaps, + bool enableLineRasterEmulation, + const gl::ShaderMap &shaderSources, + gl::ShaderMap> *shaderCodeOut); } // namespace mtl } // namespace rx diff --git a/src/libANGLE/renderer/metal/mtl_glslang_utils.mm b/src/libANGLE/renderer/metal/mtl_glslang_utils.mm index ae95cae74..21faa7f74 100644 --- a/src/libANGLE/renderer/metal/mtl_glslang_utils.mm +++ b/src/libANGLE/renderer/metal/mtl_glslang_utils.mm @@ -14,24 +14,50 @@ namespace rx { namespace mtl { - -// static -void GlslangUtils::GetShaderSource(const gl::ProgramState &programState, - const gl::ProgramLinkedResources &resources, - gl::ShaderMap *shaderSourcesOut) +namespace { - UNIMPLEMENTED(); +angle::Result HandleError(ErrorHandler *context, GlslangError) +{ + ANGLE_MTL_TRY(context, false); + return angle::Result::Stop; } -// static -angle::Result GlslangUtils::GetShaderCode(ErrorHandler *context, - const gl::Caps &glCaps, - bool enableLineRasterEmulation, - const gl::ShaderMap &shaderSources, - gl::ShaderMap> *shaderCodeOut) +GlslangSourceOptions CreateSourceOptions() { - UNIMPLEMENTED(); - return angle::Result::Stop; + GlslangSourceOptions options; + // We don't actually use descriptor set for now, the actual binding will be done inside + // ProgramMtl using spirv-cross. + options.uniformsAndXfbDescriptorSetIndex = kDefaultUniformsBindingIndex; + options.textureDescriptorSetIndex = 0; + options.driverUniformsDescriptorSetIndex = kDriverUniformsBindingIndex; + // NOTE(hqle): Unused for now, until we support ES 3.0 + options.shaderResourceDescriptorSetIndex = -1; + options.xfbBindingIndexStart = -1; + + static_assert(kDefaultUniformsBindingIndex != 0, "kDefaultUniformsBindingIndex must not be 0"); + static_assert(kDriverUniformsBindingIndex != 0, "kDriverUniformsBindingIndex must not be 0"); + + return options; +} +} // namespace + +void GlslangGetShaderSource(const gl::ProgramState &programState, + const gl::ProgramLinkedResources &resources, + gl::ShaderMap *shaderSourcesOut) +{ + rx::GlslangGetShaderSource(CreateSourceOptions(), false, programState, resources, + shaderSourcesOut); +} + +angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context, + const gl::Caps &glCaps, + bool enableLineRasterEmulation, + const gl::ShaderMap &shaderSources, + gl::ShaderMap> *shaderCodeOut) +{ + return rx::GlslangGetShaderSpirvCode( + [context](GlslangError error) { return HandleError(context, error); }, glCaps, + enableLineRasterEmulation, shaderSources, shaderCodeOut); } } // namespace mtl } // namespace rx diff --git a/third_party/spirv-cross/README.angle b/third_party/spirv-cross/README.angle new file mode 100644 index 000000000..9e9f1d9b2 --- /dev/null +++ b/third_party/spirv-cross/README.angle @@ -0,0 +1,10 @@ +Name: Khronos SPIRV-Cross +Short Name: spirv-cross +URL: https://github.com/KhronosGroup/SPIRV-Cross +Version: N/A +Security Critical: yes +License: Apache 2.0 +License File: LICENSE + +Description: +A tool designed for parsing and converting SPIR-V to other shader languages. \ No newline at end of file