Commit 5b7c5b34 by Le Hoang Quyen Committed by Commit Bot

Metal: don't precompile default shaders.

Default shaders will be compiled from source at runtime, this is because they depend on ANGLE format table and there is currently no way to pre-compile metal shaders in a cross-platform manner. Using default shaders' source instead of pre-compiled form seems to reduce the libGLESv2's binary size. However, the startup time will be increased due to runtime cost of compilation, thus the compilation now will be done asynchronously. Bug: angleproject:5186 Change-Id: I0e1987d6c76692d5169255736fbb8e215185c33b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2482405Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Le Hoang Quyen <le.hoang.q@gmail.com>
parent 9047954c
......@@ -6,49 +6,25 @@
"src/libANGLE/renderer/gen_angle_format_table.py":
"34ab57bb88958e320f509bd5fbd04495",
"src/libANGLE/renderer/metal/shaders/blit.metal":
"502660301ee21e5cd4a5dd42a8a24e82",
"2f6286729703039d41d0f6a109a23ac2",
"src/libANGLE/renderer/metal/shaders/clear.metal":
"37ef05208eb5d12110a7d277a4bbcbe1",
"src/libANGLE/renderer/metal/shaders/common.h":
"0cadef47fb785aa3102acb2a6eae94bb",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_2_1_debug_ios_autogen.inc":
"2dfc9dc2496c93fe6c4d46661d77a14b",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_2_1_debug_ios_sim_autogen.inc":
"e4d6ce5e3081e18908b8c95f7ed372b2",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_2_1_debug_mac_autogen.inc":
"79cb485ee377adac2632adaa21e2c8ac",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_2_1_ios_autogen.inc":
"55abd74424bdd88b5523534ec867f715",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_2_1_ios_sim_autogen.inc":
"1cf20c8cb47ed5990c8c165b7faa1c0d",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_2_1_mac_autogen.inc":
"a4b9067e64c6d0dcfcff3422f833779c",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_debug_ios_autogen.inc":
"af51783bbc7dc7d6ad17f88cc5409222",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_debug_ios_sim_autogen.inc":
"25e0ecdaf8829af2ebed1738bf57b2d9",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_debug_mac_autogen.inc":
"34885f0482b73513f1736eb8be340d66",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_ios_autogen.inc":
"f22b1f09a53bc5d1f9a462f4552aa116",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_ios_sim_autogen.inc":
"7de301390d329a1493a557c60ac9888c",
"src/libANGLE/renderer/metal/shaders/compiled/compiled_default_metallib_mac_autogen.inc":
"cd1dbbd9b961aaef467cc24c5c1abcb0",
"src/libANGLE/renderer/metal/shaders/compiled/mtl_default_shaders_autogen.inc":
"634a127f4e94f6bc3123e89850d010ee",
"ac1bdd21a1cee65d88cfc4e0e61894da",
"src/libANGLE/renderer/metal/shaders/constants.h":
"dad1a869a1095be669b7da5651901d38",
"src/libANGLE/renderer/metal/shaders/copy_buffer.metal":
"97b258edbade1ed088e4c03a1102f974",
"813e16a38d6e3ba858b62a712b1b316d",
"src/libANGLE/renderer/metal/shaders/format_autogen.h":
"b1d6512b904a7eb151b0095b7898b0e5",
"src/libANGLE/renderer/metal/shaders/gen_indices.metal":
"87a76d5e12825111c0595f69e79f5d20",
"add45aa44305b1a64c4bb8ece1e3d2fc",
"src/libANGLE/renderer/metal/shaders/gen_mipmap.metal":
"54dca94c48bead446624079070b9b309",
"src/libANGLE/renderer/metal/shaders/gen_mtl_internal_shaders.py":
"d5f23d645c0cb9d487e40d490414a772",
"9f538745533b6bb14fbbc9e4252f31e0",
"src/libANGLE/renderer/metal/shaders/mtl_default_shaders_src_autogen.inc":
"2a0b015ebec36ee1304ae64a7187abb8",
"src/libANGLE/renderer/metal/shaders/visibility.metal":
"998d705656c63849edd0187cd8062fc7"
"b82aa740cf4b0aed606aacef1024beea"
}
\ No newline at end of file
......@@ -62,21 +62,9 @@ _metal_backend_sources = [
"mtl_state_cache.mm",
"mtl_utils.h",
"mtl_utils.mm",
"shaders/compiled/compiled_default_metallib_2_1_debug_ios_autogen.inc",
"shaders/compiled/compiled_default_metallib_2_1_debug_ios_sim_autogen.inc",
"shaders/compiled/compiled_default_metallib_2_1_debug_mac_autogen.inc",
"shaders/compiled/compiled_default_metallib_2_1_ios_autogen.inc",
"shaders/compiled/compiled_default_metallib_2_1_ios_sim_autogen.inc",
"shaders/compiled/compiled_default_metallib_2_1_mac_autogen.inc",
"shaders/compiled/compiled_default_metallib_debug_ios_autogen.inc",
"shaders/compiled/compiled_default_metallib_debug_ios_sim_autogen.inc",
"shaders/compiled/compiled_default_metallib_debug_mac_autogen.inc",
"shaders/compiled/compiled_default_metallib_ios_autogen.inc",
"shaders/compiled/compiled_default_metallib_ios_sim_autogen.inc",
"shaders/compiled/compiled_default_metallib_mac_autogen.inc",
"shaders/compiled/mtl_default_shaders_autogen.inc",
"shaders/constants.h",
"shaders/format_autogen.h",
"shaders/mtl_default_shaders_src_autogen.inc",
]
config("angle_metal_backend_config") {
......
......@@ -32,6 +32,8 @@ class ShareGroupMtl : public ShareGroupImpl
class ContextMtl;
struct DefaultShaderAsyncInfoMtl;
class DisplayMtl : public DisplayImpl
{
public:
......@@ -123,7 +125,7 @@ class DisplayMtl : public DisplayImpl
mtl::RenderUtils &getUtils() { return mUtils; }
mtl::StateCache &getStateCache() { return mStateCache; }
id<MTLLibrary> getDefaultShadersLib() const { return mDefaultShaders; }
id<MTLLibrary> getDefaultShadersLib();
id<MTLDepthStencilState> getDepthStencilState(const mtl::DepthStencilDesc &desc)
{
......@@ -175,7 +177,7 @@ class DisplayMtl : public DisplayImpl
mtl::RenderUtils mUtils;
// Built-in Shaders
mtl::AutoObjCPtr<id<MTLLibrary>> mDefaultShaders = nil;
std::shared_ptr<DefaultShaderAsyncInfoMtl> mDefaultShadersAsyncInfo;
#if ANGLE_MTL_EVENT_AVAILABLE
mtl::AutoObjCObj<MTLSharedEventListener> mSharedEventListener;
#endif
......
......@@ -17,7 +17,7 @@
#include "libANGLE/renderer/metal/SurfaceMtl.h"
#include "libANGLE/renderer/metal/SyncMtl.h"
#include "libANGLE/renderer/metal/mtl_common.h"
#include "libANGLE/renderer/metal/shaders/compiled/mtl_default_shaders_autogen.inc"
#include "libANGLE/renderer/metal/shaders/mtl_default_shaders_src_autogen.inc"
#include "platform/Platform.h"
#include "EGL/eglext.h"
......@@ -44,6 +44,18 @@ DisplayImpl *CreateMetalDisplay(const egl::DisplayState &state)
return new DisplayMtl(state);
}
struct DefaultShaderAsyncInfoMtl
{
mtl::AutoObjCPtr<id<MTLLibrary>> defaultShaders;
mtl::AutoObjCPtr<NSError *> defaultShadersCompileError;
// Synchronization primitives for compiling default shaders in back-ground
std::condition_variable cv;
std::mutex lock;
bool compiled = false;
};
DisplayMtl::DisplayMtl(const egl::DisplayState &state)
: DisplayImpl(state), mUtils(this), mGlslangInitialized(false)
{}
......@@ -100,8 +112,8 @@ void DisplayMtl::terminate()
{
mUtils.onDestroy();
mCmdQueue.reset();
mDefaultShaders = nil;
mMetalDevice = nil;
mDefaultShadersAsyncInfo = nullptr;
mMetalDevice = nil;
#if ANGLE_MTL_EVENT_AVAILABLE
mSharedEventListener = nil;
#endif
......@@ -751,48 +763,62 @@ void DisplayMtl::initializeFeatures()
angle::Result DisplayMtl::initializeShaderLibrary()
{
mtl::AutoObjCObj<NSError> err = nil;
mDefaultShadersAsyncInfo.reset(new DefaultShaderAsyncInfoMtl);
const uint8_t *compiled_shader_binary;
size_t compiled_shader_binary_len;
// Create references to async info struct since it might be released in terminate(), but the
// callback might still not be fired yet.
std::shared_ptr<DefaultShaderAsyncInfoMtl> asyncRef = mDefaultShadersAsyncInfo;
#if !defined(NDEBUG)
if (getFeatures().hasStencilOutput.enabled)
{
compiled_shader_binary = compiled_default_metallib_2_1_debug;
compiled_shader_binary_len = compiled_default_metallib_2_1_debug_len;
}
else
{
compiled_shader_binary = compiled_default_metallib_debug;
compiled_shader_binary_len = compiled_default_metallib_debug_len;
}
#else
if (getFeatures().hasStencilOutput.enabled)
// Compile the default shaders asynchronously
ANGLE_MTL_OBJC_SCOPE
{
compiled_shader_binary = compiled_default_metallib_2_1;
compiled_shader_binary_len = compiled_default_metallib_2_1_len;
auto nsSource = [[NSString alloc] initWithBytesNoCopy:gDefaultMetallibSrc
length:sizeof(gDefaultMetallibSrc)
encoding:NSUTF8StringEncoding
freeWhenDone:NO];
auto options = [[[MTLCompileOptions alloc] init] ANGLE_MTL_AUTORELEASE];
[getMetalDevice() newLibraryWithSource:nsSource
options:options
completionHandler:^(id<MTLLibrary> library, NSError *error) {
std::unique_lock<std::mutex> lg(asyncRef->lock);
asyncRef->defaultShaders = std::move(library);
asyncRef->defaultShadersCompileError = std::move(error);
asyncRef->compiled = true;
asyncRef->cv.notify_one();
}];
[nsSource ANGLE_MTL_AUTORELEASE];
}
else
return angle::Result::Continue;
}
id<MTLLibrary> DisplayMtl::getDefaultShadersLib()
{
std::unique_lock<std::mutex> lg(mDefaultShadersAsyncInfo->lock);
if (!mDefaultShadersAsyncInfo->compiled)
{
compiled_shader_binary = compiled_default_metallib;
compiled_shader_binary_len = compiled_default_metallib_len;
// Wait for async compilation
mDefaultShadersAsyncInfo->cv.wait(lg,
[this] { return mDefaultShadersAsyncInfo->compiled; });
}
#endif
mDefaultShaders = CreateShaderLibraryFromBinary(getMetalDevice(), compiled_shader_binary,
compiled_shader_binary_len, &err);
if (err && !mDefaultShaders)
if (mDefaultShadersAsyncInfo->defaultShadersCompileError &&
!mDefaultShadersAsyncInfo->defaultShaders)
{
ANGLE_MTL_OBJC_SCOPE
{
ERR() << "Internal error: " << err.get().localizedDescription.UTF8String;
ERR() << "Internal error: "
<< mDefaultShadersAsyncInfo->defaultShadersCompileError.get()
.localizedDescription.UTF8String;
}
return angle::Result::Stop;
// This is not supposed to happen
UNREACHABLE();
}
return angle::Result::Continue;
return mDefaultShadersAsyncInfo->defaultShaders;
}
bool DisplayMtl::supportsIOSGPUFamily(uint8_t iOSFamily) const
......
......@@ -334,7 +334,7 @@ kernel void blitStencilToBufferCS(ushort2 gIndices [[thread_position_in_grid]],
}
// Fragment's stencil output is only available since Metal 2.1
#if __METAL_VERSION__ >= 210
@@#if __METAL_VERSION__ >= 210
struct FragmentStencilOut
{
......@@ -397,4 +397,4 @@ fragment FragmentDepthStencilOut blitDepthStencilFS(
srcStencilTextureCube, input.texCoords, options.srcLevel, options.srcLayer);
return re;
}
#endif // __METAL_VERSION__ >= 210
@@#endif // __METAL_VERSION__ >= 210
......@@ -8,9 +8,10 @@
#ifndef LIBANGLE_RENDERER_METAL_SHADERS_COMMON_H_
#define LIBANGLE_RENDERER_METAL_SHADERS_COMMON_H_
// clang-format off
#ifndef SKIP_STD_HEADERS
# include <simd/simd.h>
# include <metal_stdlib>
@@# include <simd/simd.h>
@@# include <metal_stdlib>
#endif
#include "constants.h"
......@@ -22,6 +23,7 @@
}
using namespace metal;
// clang-format on
// Common constant defined number of color outputs
constant uint32_t kNumColorOutputs [[function_constant(0)]];
......
......@@ -9,17 +9,17 @@
// be a pain to implement without the use of macros.
//
#include <metal_pack>
@@#include <metal_pack>
#include "common.h"
#include "format_autogen.h"
using namespace rx::mtl_shader;
constant int kCopyFormatType [[function_constant(1)]];
constant int kCopyFormatType [[function_constant(10)]];
/* -------- copy pixel data between buffer and texture ---------*/
constant int kCopyTextureType [[function_constant(2)]];
constant int kCopyTextureType [[function_constant(20)]];
constant bool kCopyTextureType2D = kCopyTextureType == kTextureType2D;
constant bool kCopyTextureType2DArray = kCopyTextureType == kTextureType2DArray;
constant bool kCopyTextureType2DMS = kCopyTextureType == kTextureType2DMultisample;
......
......@@ -9,10 +9,10 @@
using namespace rx::mtl_shader;
// function_constant(0) is already used by common.h
constant bool kSourceBufferAligned[[function_constant(1)]];
constant bool kSourceIndexIsU8[[function_constant(2)]];
constant bool kSourceIndexIsU16[[function_constant(3)]];
constant bool kSourceIndexIsU32[[function_constant(4)]];
constant bool kSourceBufferAligned[[function_constant(100)]];
constant bool kSourceIndexIsU8[[function_constant(200)]];
constant bool kSourceIndexIsU16[[function_constant(300)]];
constant bool kSourceIndexIsU32[[function_constant(400)]];
constant bool kSourceBufferUnaligned = !kSourceBufferAligned;
constant bool kUseSourceBufferU8 = kSourceIndexIsU8 || kSourceBufferUnaligned;
constant bool kUseSourceBufferU16 = kSourceIndexIsU16 && kSourceBufferAligned;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -6,7 +6,7 @@
#include "common.h"
constant bool kCombineWithExistingResult [[function_constant(1)]];
constant bool kCombineWithExistingResult [[function_constant(1000)]];
// Combine the visibility result of current render pass with previous value from previous render
// pass
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment