Commit a1442ecd by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Uber-shader support

For each internal shader, there is now possibly a companion .json file that defines shader variations. The variations consist of a set of flags and a set of enums. Each enum defines a variation that takes one of a few values. Flags are shorthands for 2-value enums. In the shader code, #if can be used to change the shader based on variations derived from flags and enums. On the C++ side, those variations are combined into an index and the appropriate shader is retrieved from a table. Bug: angleproject:2958 Change-Id: Ic4fc7061adb20c047c26624305285e3005092aab Reviewed-on: https://chromium-review.googlesource.com/c/1351117 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 5f01324f
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
"Vulkan format:src/libANGLE/renderer/vulkan/vk_format_map.json": "Vulkan format:src/libANGLE/renderer/vulkan/vk_format_map.json":
"0c14ee33bcec99ee02eb6b39da046bc0", "0c14ee33bcec99ee02eb6b39da046bc0",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/gen_vk_internal_shaders.py": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/gen_vk_internal_shaders.py":
"c1cc895645db3fe1cd284352890c219e", "b666933fa621018c3ac0e1767a0f7bc1",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/FullScreenQuad.vert": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/FullScreenQuad.vert":
"1743adf55153edf91363fa7b4350d859", "1743adf55153edf91363fa7b4350d859",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/PushConstantColor.frag": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/PushConstantColor.frag":
......
...@@ -1259,12 +1259,10 @@ angle::Result RendererVk::getFullScreenClearShaderProgram(vk::Context *context, ...@@ -1259,12 +1259,10 @@ angle::Result RendererVk::getFullScreenClearShaderProgram(vk::Context *context,
if (!mFullScreenClearShaderProgram.valid()) if (!mFullScreenClearShaderProgram.valid())
{ {
vk::RefCounted<vk::ShaderAndSerial> *fullScreenQuad = nullptr; vk::RefCounted<vk::ShaderAndSerial> *fullScreenQuad = nullptr;
ANGLE_TRY(mShaderLibrary.getShader(context, vk::InternalShaderID::FullScreenQuad_vert, ANGLE_TRY(mShaderLibrary.getFullScreenQuad_vert(context, 0, &fullScreenQuad));
&fullScreenQuad));
vk::RefCounted<vk::ShaderAndSerial> *pushConstantColor = nullptr; vk::RefCounted<vk::ShaderAndSerial> *pushConstantColor = nullptr;
ANGLE_TRY(mShaderLibrary.getShader(context, vk::InternalShaderID::PushConstantColor_frag, ANGLE_TRY(mShaderLibrary.getPushConstantColor_frag(context, 0, &pushConstantColor));
&pushConstantColor));
mFullScreenClearShaderProgram.setShader(gl::ShaderType::Vertex, fullScreenQuad); mFullScreenClearShaderProgram.setShader(gl::ShaderType::Vertex, fullScreenQuad);
mFullScreenClearShaderProgram.setShader(gl::ShaderType::Fragment, pushConstantColor); mFullScreenClearShaderProgram.setShader(gl::ShaderType::Fragment, pushConstantColor);
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "libANGLE/renderer/vulkan/QueryVk.h" #include "libANGLE/renderer/vulkan/QueryVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h" #include "libANGLE/renderer/vulkan/vk_format_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "libANGLE/renderer/vulkan/vk_internal_shaders.h" #include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h"
namespace egl namespace egl
{ {
......
// 7.7.2767 // 7.10.2904
#pragma once #pragma once
const uint32_t kFullScreenQuad_vert[] = { const uint32_t kFullScreenQuad_vert_00000000[] = {
0x07230203,0x00010000,0x00080007,0x00000024,0x00000000,0x00020011,0x00000001,0x0006000b, 0x07230203,0x00010000,0x00080007,0x00000024,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0007000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000d,0x0000001b,0x00030003, 0x0007000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000d,0x0000001b,0x00030003,
...@@ -34,4 +34,22 @@ const uint32_t kFullScreenQuad_vert[] = { ...@@ -34,4 +34,22 @@ const uint32_t kFullScreenQuad_vert[] = {
0x0000001c,0x0000001b,0x0003003e,0x0000001e,0x00000019,0x00050041,0x0000001f,0x00000020, 0x0000001c,0x0000001b,0x0003003e,0x0000001e,0x00000019,0x00050041,0x0000001f,0x00000020,
0x0000001e,0x0000001c,0x0004003d,0x00000007,0x00000021,0x00000020,0x00050041,0x00000022, 0x0000001e,0x0000001c,0x0004003d,0x00000007,0x00000021,0x00000020,0x00050041,0x00000022,
0x00000023,0x0000000d,0x0000000f,0x0003003e,0x00000023,0x00000021,0x000100fd,0x00010038 0x00000023,0x0000000d,0x0000000f,0x0003003e,0x00000023,0x00000021,0x000100fd,0x00010038
}; };
\ No newline at end of file
#if 0 // Generated from:
#version 450 core
const vec4 kQuadVertices[]= {
vec4(- 1, 1, 0, 1),
vec4(- 1, - 1, 0, 1),
vec4(1, - 1, 0, 1),
vec4(- 1, 1, 0, 1),
vec4(1, - 1, 0, 1),
vec4(1, 1, 0, 1),
};
void main()
{
gl_Position = kQuadVertices[gl_VertexIndex];
}
#endif // Preprocessed code
// 7.7.2767 // 7.10.2904
#pragma once #pragma once
const uint32_t kPushConstantColor_frag[] = { const uint32_t kPushConstantColor_frag_00000000[] = {
0x07230203,0x00010000,0x00080007,0x00000012,0x00000000,0x00020011,0x00000001,0x0006000b, 0x07230203,0x00010000,0x00080007,0x00000012,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0006000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x00030010,0x00000004, 0x0006000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x00030010,0x00000004,
...@@ -17,4 +17,19 @@ const uint32_t kPushConstantColor_frag[] = { ...@@ -17,4 +17,19 @@ const uint32_t kPushConstantColor_frag[] = {
0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041, 0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,
0x0000000f,0x00000010,0x0000000c,0x0000000e,0x0004003d,0x00000007,0x00000011,0x00000010, 0x0000000f,0x00000010,0x0000000c,0x0000000e,0x0004003d,0x00000007,0x00000011,0x00000010,
0x0003003e,0x00000009,0x00000011,0x000100fd,0x00010038 0x0003003e,0x00000009,0x00000011,0x000100fd,0x00010038
}; };
\ No newline at end of file
#if 0 // Generated from:
#version 450 core
layout(push_constant)uniform block {
vec4 colorIn;
};
layout(location = 0)out vec4 colorOut;
void main()
{
colorOut = colorIn;
}
#endif // Preprocessed code
# Shader Variations
To build multiple variations of a shader, add a file named X.json corresponding to shader file X. A
variation is generated by building the shader with different definitions (a la glslang_validator's
-DName=1). These definitions come from flags and enumerations defined in the json file.
There are multiple possible fields in the json file:
- "Description": This contains the license and other comments, which will be ignored.
- "Flags": this is a list of flags. Each flag FLAG defines a shader variation with or without the
define FLAG=1.
- other: any other field is a similar list to flags, except that each entry in this enumeration is a
variation. Similar to "flags", every entry ENTRY results in an ENTRY=1 define.
Flags are shorthand for 2-entry enumerations. Given n flags, there are 2^n variations where every
flag is either present or not. For enumerations, only one entry is active in any variation. Thus,
an enumeration with n entries generates n variations.
## Example
Here is an example json file:
{
"Description": [
"Copyright 2018 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.",
"",
"RayTrace.comp.json: Build parameters for RayTrace.comp."
],
"Flags": [
"NanFilter",
"WorkaroundIntelBug"
],
"RayTraceQuality": [
"IsRTLowRes",
"IsRTHighRes",
"IsRTAwesome"
],
"ImageType": [
"IsR",
"IsRG",
"IsRGB",
"IsRGBA"
]
}
This will generate 2^2 * 3 * 4 shaders.
//
// Copyright 2018 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.
//
// vk_internal_shaders.cpp:
// Pre-generated shader library for the ANGLE Vulkan back-end.
#include "libANGLE/renderer/vulkan/vk_internal_shaders.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
{
namespace vk
{
ShaderLibrary::ShaderLibrary() {}
ShaderLibrary::~ShaderLibrary() {}
void ShaderLibrary::destroy(VkDevice device)
{
for (RefCounted<ShaderAndSerial> &shader : mShaders)
{
shader.get().destroy(device);
}
}
angle::Result ShaderLibrary::getShader(vk::Context *context,
InternalShaderID shaderID,
RefCounted<ShaderAndSerial> **shaderOut)
{
RefCounted<ShaderAndSerial> &shader = mShaders[shaderID];
*shaderOut = &shader;
if (shader.get().valid())
{
return angle::Result::Continue();
}
// Create shader lazily. Access will need to be locked for multi-threading.
const priv::ShaderBlob &shaderCode = priv::GetInternalShaderBlob(shaderID);
return InitShaderAndSerial(context, &shader.get(), shaderCode.code, shaderCode.codeSize);
}
} // namespace vk
} // namespace rx
//
// Copyright 2018 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.
//
// vk_internal_shaders.h:
// Pre-generated shader library for the ANGLE Vulkan back-end.
#ifndef LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_H_
#define LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_H_
#include "common/PackedEnums.h"
#include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{
namespace vk
{
class ShaderLibrary final : angle::NonCopyable
{
public:
ShaderLibrary();
~ShaderLibrary();
angle::Result getShader(Context *context,
InternalShaderID shaderID,
RefCounted<ShaderAndSerial> **shaderOut);
void destroy(VkDevice device);
private:
angle::PackedEnumMap<InternalShaderID, RefCounted<ShaderAndSerial>> mShaders;
};
} // namespace vk
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_H_
...@@ -10,28 +10,81 @@ ...@@ -10,28 +10,81 @@
#include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h" #include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h"
#include "common/debug.h"
namespace rx namespace rx
{ {
namespace vk namespace vk
{ {
namespace priv
{
namespace namespace
{ {
#include "libANGLE/renderer/vulkan/shaders/gen/FullScreenQuad.vert.inc" #include "libANGLE/renderer/vulkan/shaders/gen/FullScreenQuad.vert.00000000.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/PushConstantColor.frag.inc" #include "libANGLE/renderer/vulkan/shaders/gen/PushConstantColor.frag.00000000.inc"
constexpr ShaderBlob kShaderBlobs[] = {{kFullScreenQuad_vert, sizeof(kFullScreenQuad_vert)}, // This is SPIR-V binary blob and the size.
{kPushConstantColor_frag, sizeof(kPushConstantColor_frag)}}; struct ShaderBlob
{
const uint32_t *code;
size_t codeSize;
};
constexpr ShaderBlob kFullScreenQuad_vert_shaders[] = {
{kFullScreenQuad_vert_00000000, sizeof(kFullScreenQuad_vert_00000000)},
};
constexpr ShaderBlob kPushConstantColor_frag_shaders[] = {
{kPushConstantColor_frag_00000000, sizeof(kPushConstantColor_frag_00000000)},
};
} // anonymous namespace } // anonymous namespace
const ShaderBlob &GetInternalShaderBlob(InternalShaderID shaderID) ShaderLibrary::ShaderLibrary() {}
ShaderLibrary::~ShaderLibrary() {}
void ShaderLibrary::destroy(VkDevice device)
{ {
ASSERT(static_cast<size_t>(shaderID) < static_cast<size_t>(InternalShaderID::EnumCount)); for (RefCounted<ShaderAndSerial> &shader : mFullScreenQuad_vert_shaders)
return kShaderBlobs[static_cast<size_t>(shaderID)]; {
shader.get().destroy(device);
}
for (RefCounted<ShaderAndSerial> &shader : mPushConstantColor_frag_shaders)
{
shader.get().destroy(device);
}
} }
} // namespace priv
angle::Result ShaderLibrary::getFullScreenQuad_vert(Context *context,
uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut)
{
ASSERT(shaderFlags < ArraySize(kFullScreenQuad_vert_shaders));
RefCounted<ShaderAndSerial> &shader = mFullScreenQuad_vert_shaders[shaderFlags];
*shaderOut = &shader;
if (shader.get().valid())
{
return angle::Result::Continue();
}
// Create shader lazily. Access will need to be locked for multi-threading.
const ShaderBlob &shaderCode = kFullScreenQuad_vert_shaders[shaderFlags];
return InitShaderAndSerial(context, &shader.get(), shaderCode.code, shaderCode.codeSize);
}
angle::Result ShaderLibrary::getPushConstantColor_frag(Context *context,
uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut)
{
ASSERT(shaderFlags < ArraySize(kPushConstantColor_frag_shaders));
RefCounted<ShaderAndSerial> &shader = mPushConstantColor_frag_shaders[shaderFlags];
*shaderOut = &shader;
if (shader.get().valid())
{
return angle::Result::Continue();
}
// Create shader lazily. Access will need to be locked for multi-threading.
const ShaderBlob &shaderCode = kPushConstantColor_frag_shaders[shaderFlags];
return InitShaderAndSerial(context, &shader.get(), shaderCode.code, shaderCode.codeSize);
}
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
...@@ -9,6 +9,6 @@ ...@@ -9,6 +9,6 @@
# List of generated shaders for inclusion in ANGLE's build process. # List of generated shaders for inclusion in ANGLE's build process.
angle_vulkan_internal_shaders = [ angle_vulkan_internal_shaders = [
"shaders/gen/FullScreenQuad.vert.inc", "shaders/gen/FullScreenQuad.vert.00000000.inc",
"shaders/gen/PushConstantColor.frag.inc", "shaders/gen/PushConstantColor.frag.00000000.inc",
] ]
...@@ -11,32 +11,41 @@ ...@@ -11,32 +11,41 @@
#ifndef LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_AUTOGEN_H_ #ifndef LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_AUTOGEN_H_
#define LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_AUTOGEN_H_ #define LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_AUTOGEN_H_
#include <stddef.h> #include "libANGLE/renderer/vulkan/vk_utils.h"
#include <stdint.h>
#include <utility>
namespace rx namespace rx
{ {
namespace vk namespace vk
{ {
enum class InternalShaderID namespace InternalShader
{ {
FullScreenQuad_vert, namespace FullScreenQuad_vert
PushConstantColor_frag, {} // namespace FullScreenQuad_vert
EnumCount
};
namespace priv namespace PushConstantColor_frag
{ {} // namespace PushConstantColor_frag
// This is SPIR-V binary blob and the size.
struct ShaderBlob } // namespace InternalShader
class ShaderLibrary final : angle::NonCopyable
{ {
const uint32_t *code; public:
size_t codeSize; ShaderLibrary();
~ShaderLibrary();
void destroy(VkDevice device);
angle::Result getFullScreenQuad_vert(Context *context,
uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut);
angle::Result getPushConstantColor_frag(Context *context,
uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut);
private:
RefCounted<ShaderAndSerial> mFullScreenQuad_vert_shaders[1];
RefCounted<ShaderAndSerial> mPushConstantColor_frag_shaders[1];
}; };
const ShaderBlob &GetInternalShaderBlob(InternalShaderID shaderID);
} // namespace priv
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
......
...@@ -748,8 +748,6 @@ libangle_vulkan_sources = [ ...@@ -748,8 +748,6 @@ libangle_vulkan_sources = [
"src/libANGLE/renderer/vulkan/vk_format_utils.cpp", "src/libANGLE/renderer/vulkan/vk_format_utils.cpp",
"src/libANGLE/renderer/vulkan/vk_helpers.cpp", "src/libANGLE/renderer/vulkan/vk_helpers.cpp",
"src/libANGLE/renderer/vulkan/vk_helpers.h", "src/libANGLE/renderer/vulkan/vk_helpers.h",
"src/libANGLE/renderer/vulkan/vk_internal_shaders.cpp",
"src/libANGLE/renderer/vulkan/vk_internal_shaders.h",
"src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h", "src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h",
"src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp", "src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp",
"src/libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp", "src/libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp",
......
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