зеркало из https://github.com/AvaloniaUI/angle.git
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 <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Родитель
653ee5f115
Коммит
a5a04ac0f9
|
@ -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
|
||||
|
|
8
DEPS
8
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',
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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<int> 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
#include <spirv_msl.hpp>
|
||||
|
||||
#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 <BindingField bindingField1, BindingField bindingField2 = bindingField1>
|
||||
angle::Result BindResources(spirv_cross::CompilerMSL *compiler,
|
||||
const spirv_cross::SmallVector<spirv_cross::Resource> &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<sh::Uniform> &uniforms,
|
||||
gl::Shader *shader,
|
||||
sh::BlockLayoutMap *blockLayoutMapOut,
|
||||
|
@ -214,7 +295,7 @@ std::unique_ptr<LinkEvent> 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<LinkEventDone>(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<std::vector<uint32_t>> 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<uint32_t> *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));
|
||||
|
|
|
@ -18,19 +18,15 @@ namespace rx
|
|||
{
|
||||
namespace mtl
|
||||
{
|
||||
class GlslangUtils
|
||||
{
|
||||
public:
|
||||
static void GetShaderSource(const gl::ProgramState &programState,
|
||||
const gl::ProgramLinkedResources &resources,
|
||||
gl::ShaderMap<std::string> *shaderSourcesOut);
|
||||
void GlslangGetShaderSource(const gl::ProgramState &programState,
|
||||
const gl::ProgramLinkedResources &resources,
|
||||
gl::ShaderMap<std::string> *shaderSourcesOut);
|
||||
|
||||
static angle::Result GetShaderCode(ErrorHandler *context,
|
||||
const gl::Caps &glCaps,
|
||||
bool enableLineRasterEmulation,
|
||||
const gl::ShaderMap<std::string> &shaderSources,
|
||||
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut);
|
||||
};
|
||||
angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
|
||||
const gl::Caps &glCaps,
|
||||
bool enableLineRasterEmulation,
|
||||
const gl::ShaderMap<std::string> &shaderSources,
|
||||
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut);
|
||||
} // namespace mtl
|
||||
} // namespace rx
|
||||
|
||||
|
|
|
@ -14,24 +14,50 @@ namespace rx
|
|||
{
|
||||
namespace mtl
|
||||
{
|
||||
|
||||
// static
|
||||
void GlslangUtils::GetShaderSource(const gl::ProgramState &programState,
|
||||
const gl::ProgramLinkedResources &resources,
|
||||
gl::ShaderMap<std::string> *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<std::string> &shaderSources,
|
||||
gl::ShaderMap<std::vector<uint32_t>> *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<std::string> *shaderSourcesOut)
|
||||
{
|
||||
rx::GlslangGetShaderSource(CreateSourceOptions(), false, programState, resources,
|
||||
shaderSourcesOut);
|
||||
}
|
||||
|
||||
angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
|
||||
const gl::Caps &glCaps,
|
||||
bool enableLineRasterEmulation,
|
||||
const gl::ShaderMap<std::string> &shaderSources,
|
||||
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
|
||||
{
|
||||
return rx::GlslangGetShaderSpirvCode(
|
||||
[context](GlslangError error) { return HandleError(context, error); }, glCaps,
|
||||
enableLineRasterEmulation, shaderSources, shaderCodeOut);
|
||||
}
|
||||
} // namespace mtl
|
||||
} // namespace rx
|
||||
|
|
|
@ -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.
|
Загрузка…
Ссылка в новой задаче