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 @@
"Vulkan format:src/libANGLE/renderer/vulkan/vk_format_map.json":
"0c14ee33bcec99ee02eb6b39da046bc0",
"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":
"1743adf55153edf91363fa7b4350d859",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/PushConstantColor.frag":
......
......@@ -1259,12 +1259,10 @@ angle::Result RendererVk::getFullScreenClearShaderProgram(vk::Context *context,
if (!mFullScreenClearShaderProgram.valid())
{
vk::RefCounted<vk::ShaderAndSerial> *fullScreenQuad = nullptr;
ANGLE_TRY(mShaderLibrary.getShader(context, vk::InternalShaderID::FullScreenQuad_vert,
&fullScreenQuad));
ANGLE_TRY(mShaderLibrary.getFullScreenQuad_vert(context, 0, &fullScreenQuad));
vk::RefCounted<vk::ShaderAndSerial> *pushConstantColor = nullptr;
ANGLE_TRY(mShaderLibrary.getShader(context, vk::InternalShaderID::PushConstantColor_frag,
&pushConstantColor));
ANGLE_TRY(mShaderLibrary.getPushConstantColor_frag(context, 0, &pushConstantColor));
mFullScreenClearShaderProgram.setShader(gl::ShaderType::Vertex, fullScreenQuad);
mFullScreenClearShaderProgram.setShader(gl::ShaderType::Fragment, pushConstantColor);
......
......@@ -20,7 +20,7 @@
#include "libANGLE/renderer/vulkan/QueryVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.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
{
......
......@@ -4,11 +4,13 @@
# found in the LICENSE file.
#
# gen_vk_internal_shaders.py:
# Code generation for internal Vulkan shaders. Should be run when an intenal
# Code generation for internal Vulkan shaders. Should be run when an internal
# shader program is changed, added or removed.
from datetime import date
import json
import os
import re
import subprocess
import sys
......@@ -29,29 +31,39 @@ template_shader_library_cpp = """// GENERATED FILE - DO NOT EDIT.
#include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h"
#include "common/debug.h"
namespace rx
{{
namespace vk
{{
namespace priv
{{
namespace
{{
{internal_shader_includes}
constexpr ShaderBlob kShaderBlobs[] = {{
{internal_shader_array_entries}
// This is SPIR-V binary blob and the size.
struct ShaderBlob
{{
const uint32_t *code;
size_t codeSize;
}};
{shader_tables_cpp}
}} // anonymous namespace
const ShaderBlob &GetInternalShaderBlob(InternalShaderID shaderID)
ShaderLibrary::ShaderLibrary()
{{
ASSERT(static_cast<size_t>(shaderID) < static_cast<size_t>(InternalShaderID::EnumCount));
return kShaderBlobs[static_cast<size_t>(shaderID)];
}}
}} // namespace priv
ShaderLibrary::~ShaderLibrary()
{{
}}
void ShaderLibrary::destroy(VkDevice device)
{{
{shader_destroy_calls}
}}
{shader_get_functions_cpp}
}} // namespace vk
}} // namespace rx
"""
......@@ -69,30 +81,30 @@ template_shader_library_h = """// GENERATED FILE - DO NOT EDIT.
#ifndef LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_AUTOGEN_H_
#define LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_AUTOGEN_H_
#include <stddef.h>
#include <stdint.h>
#include <utility>
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{{
namespace vk
{{
enum class InternalShaderID
namespace InternalShader
{{
{internal_shader_ids}
}};
{shader_variation_definitions}
}} // namespace InternalShader
namespace priv
{{
// This is SPIR-V binary blob and the size.
struct ShaderBlob
class ShaderLibrary final : angle::NonCopyable
{{
const uint32_t *code;
size_t codeSize;
public:
ShaderLibrary();
~ShaderLibrary();
void destroy(VkDevice device);
{shader_get_functions_h}
private:
{shader_tables_h}
}};
const ShaderBlob &GetInternalShaderBlob(InternalShaderID shaderID);
}} // priv
}} // namespace vk
}} // namespace rx
......@@ -115,8 +127,16 @@ angle_vulkan_internal_shaders = [
"""
# Gets the constant variable name for a generated shader.
def get_var_name(shader):
return "k" + os.path.basename(shader).replace(".", "_")
def get_var_name(output, prefix='k'):
return prefix + output.replace(".", "_")
# Gets the namespace name given to constants generated from shader_file
def get_namespace_name(shader_file):
return get_var_name(os.path.basename(shader_file), '')
# Gets the namespace name given to constants generated from shader_file
def get_variation_table_name(shader_file, prefix='k'):
return get_var_name(os.path.basename(shader_file), prefix) + '_shaders'
# Gets the internal ID string for a particular shader.
def get_shader_id(shader):
......@@ -124,8 +144,8 @@ def get_shader_id(shader):
return file.replace(".", "_")
# Returns the name of the generated SPIR-V file for a shader.
def get_output_name(shader):
return os.path.join('shaders', 'gen', os.path.basename(shader) + ".inc")
def get_output_path(name):
return os.path.join('shaders', 'gen', name + ".inc")
# Finds a path to GN's out directory
def find_build_path(path):
......@@ -155,22 +175,68 @@ def slash(s):
def gen_shader_include(shader):
return '#include "libANGLE/renderer/vulkan/%s"' % slash(shader)
def get_shader_variations(shader):
variation_file = shader + '.json'
if not os.path.exists(variation_file):
# If there is no variation file, assume none.
return ({}, [])
with open(variation_file) as fin:
variations = json.loads(fin.read())
flags = {}
enums = []
for key, value in variations.iteritems():
if key == "Description":
continue
elif key == "Flags":
flags = value
elif len(value) > 0:
enums.append((key, value))
# sort enums so the ones with the most waste ends up last, reducing the table size
enums.sort(key=lambda enum: (1 << (len(enum[1]) - 1).bit_length()) / float(len(enum[1])))
return (flags, enums)
def get_variation_bits(flags, enums):
flags_bits = len(flags)
enum_bits = [(len(enum[1]) - 1).bit_length() for enum in enums]
return (flags_bits, enum_bits)
def next_enum_variation(enums, enum_indices):
"""Loop through indices from [0, 0, ...] to [L0-1, L1-1, ...]
where Li is len(enums[i]). The list can be thought of as a number with many
digits, where each digit is in [0, Li), and this function effectively implements
the increment operation, with the least-significant digit being the first item."""
for i in range(len(enums)):
current = enum_indices[i]
# if current digit has room, increment it.
if current + 1 < len(enums[i][1]):
enum_indices[i] = current + 1
return True;
# otherwise reset it to 0 and carry to the next digit.
enum_indices[i] = 0
# if this is reached, the number has overflowed and the loop is finished.
return False
compact_newlines_regex = re.compile(r"\n\s*\n", re.MULTILINE)
def cleanup_preprocessed_shader(shader_text):
return compact_newlines_regex.sub('\n\n', shader_text.strip())
# STEP 0: Handle inputs/outputs for run_code_generation.py's auto_script
shaders_dir = os.path.join('shaders', 'src')
if not os.path.isdir(shaders_dir):
raise Exception("Could not find shaders directory")
input_shaders = sorted([os.path.join(shaders_dir, shader) for shader in os.listdir(shaders_dir)])
output_shaders = sorted([get_output_name(shader) for shader in input_shaders])
outputs = output_shaders + [out_file_cpp, out_file_h]
valid_extensions = ['.vert', '.frag', '.comp']
input_shaders = sorted([os.path.join(shaders_dir, shader)
for shader in os.listdir(shaders_dir)
if any([os.path.splitext(shader)[1] == ext for ext in valid_extensions])])
if len(sys.argv) == 2 and sys.argv[1] == 'inputs':
print(",".join(input_shaders))
sys.exit(0)
elif len(sys.argv) == 2 and sys.argv[1] == 'outputs':
print(",".join(outputs))
sys.exit(0)
# STEP 1: Call glslang to generate the internal shaders into small .inc files.
......@@ -189,40 +255,286 @@ if not os.path.isfile(glslang_path):
raise Exception("Could not find " + glslang_binary)
# b) Iterate over the shaders and call glslang with the right arguments.
for shader_file in input_shaders:
glslang_args = [
glslang_path,
'-V', # Output mode is Vulkan
'--variable-name', get_var_name(shader_file), # C-style variable name
'-o', get_output_name(shader_file), # Output file
shader_file, # Input GLSL shader
]
result = subprocess.call(glslang_args)
if result != 0:
raise Exception("Error compiling " + shader_file)
output_shaders = []
def compile_variation(shader_file, shader_basename, flags, enums,
flags_active, enum_indices, flags_bits, enum_bits, do_compile):
glslang_args = [glslang_path]
# generate -D defines and the output file name
#
# The variations are given a bit pattern to be able to OR different flags into a variation. The
# least significant bits are the flags, where there is one bit per flag. After that, each enum
# takes up as few bits as needed to count that many enum values.
variation_bits = 0
variation_string = ''
for f in range(len(flags)):
if flags_active & (1 << f):
flag_name = flags[f]
glslang_args.append('-D' + flag_name + '=1')
variation_bits |= 1 << f
variation_string += '|' + flag_name
current_bit_start = flags_bits
for e in range(len(enums)):
enum_name = enums[e][1][enum_indices[e]]
glslang_args.append('-D' + enum_name + '=1')
variation_bits |= enum_indices[e] << current_bit_start
current_bit_start += enum_bits[e]
variation_string += '|' + enum_name
output_name = '%s.%08X' % (shader_basename, variation_bits)
output_path = get_output_path(output_name)
output_shaders.append(output_path)
if do_compile:
glslang_preprocessor_output_args = glslang_args + ['-E']
glslang_preprocessor_output_args.append(shader_file) # Input GLSL shader
glslang_args += ['-V'] # Output mode is Vulkan
glslang_args += ['--variable-name', get_var_name(output_name)] # C-style variable name
glslang_args += ['-o', output_path] # Output file
glslang_args.append(shader_file) # Input GLSL shader
print output_path + ': ' + shader_basename + variation_string
result = subprocess.call(glslang_args)
if result != 0:
raise Exception("Error compiling " + shader_file)
with open(output_path, 'a') as incfile:
shader_text = subprocess.check_output(glslang_preprocessor_output_args)
incfile.write('\n\n#if 0 // Generated from:\n')
incfile.write(cleanup_preprocessed_shader(shader_text))
incfile.write('\n#endif // Preprocessed code\n')
class ShaderAndVariations:
def __init__(self, shader_file):
self.shader_file = shader_file
(self.flags, self.enums) = get_shader_variations(shader_file)
get_variation_bits(self.flags, self.enums)
(self.flags_bits, self.enum_bits) = get_variation_bits(self.flags, self.enums)
input_shaders_and_variations = [ShaderAndVariations(shader_file) for shader_file in input_shaders]
print_outputs = len(sys.argv) == 2 and sys.argv[1] == 'outputs'
for shader_and_variation in input_shaders_and_variations:
shader_file = shader_and_variation.shader_file
flags = shader_and_variation.flags
enums = shader_and_variation.enums
flags_bits = shader_and_variation.flags_bits
enum_bits = shader_and_variation.enum_bits
# an array where each element i is in [0, len(enums[i])),
# telling which enum is currently selected
enum_indices = [0] * len(enums)
output_name = os.path.basename(shader_file)
while True:
# a number where each bit says whether a flag is active or not,
# with values in [0, 2^len(flags))
for flags_active in range(1 << len(flags)):
compile_variation(shader_file, output_name, flags, enums,
flags_active, enum_indices, flags_bits, enum_bits, not print_outputs)
if not next_enum_variation(enums, enum_indices):
break
output_shaders = sorted(output_shaders)
outputs = output_shaders + [out_file_cpp, out_file_h]
if print_outputs:
print("\n".join(outputs))
sys.exit(0)
# STEP 2: Consolidate the .inc files into an auto-generated cpp/h library.
def get_variation_definition(shader_and_variation):
shader_file = shader_and_variation.shader_file
flags = shader_and_variation.flags
enums = shader_and_variation.enums
flags_bits = shader_and_variation.flags_bits
enum_bits = shader_and_variation.enum_bits
namespace_name = get_namespace_name(shader_file)
definition = 'namespace %s\n{\n' % namespace_name
if len(flags) > 0:
definition += 'enum flags\n{\n'
definition += ''.join(['k%s = 0x%08X,\n' % (flags[f], 1 << f) for f in range(len(flags))])
definition += 'kFlagsMask = 0x%08X,\n' % ((1 << flags_bits) - 1)
definition += '};\n'
current_bit_start = flags_bits
for e in range(len(enums)):
enum = enums[e]
enum_name = enum[0]
definition += 'enum %s\n{\n' % enum_name
definition += ''.join(['k%s = 0x%08X,\n' %
(enum[1][v], v << current_bit_start) for v in range(len(enum[1]))])
definition += 'k%sMask = 0x%08X,\n' % (enum_name, ((1 << enum_bits[e]) - 1) << current_bit_start)
definition += '};\n'
current_bit_start += enum_bits[e]
definition += '} // namespace %s\n' % namespace_name
return definition
def get_shader_table_h(shader_and_variation):
shader_file = shader_and_variation.shader_file
flags = shader_and_variation.flags
enums = shader_and_variation.enums
table_name = get_variation_table_name(shader_file, 'm')
table = 'RefCounted<ShaderAndSerial> %s[' % table_name
namespace_name = "InternalShader::" + get_namespace_name(shader_file)
first_or = True
if len(flags) > 0:
table += '%s::kFlagsMask' % namespace_name
first_or = False
for e in range(len(enums)):
enum = enums[e]
enum_name = enums[e][0]
if not first_or:
table += ' | '
table += '%s::k%sMask' % (namespace_name, enum_name)
first_or = False
if first_or:
table += '1'
table += '];'
return table
def get_shader_table_cpp(shader_and_variation):
shader_file = shader_and_variation.shader_file
enums = shader_and_variation.enums
flags_bits = shader_and_variation.flags_bits
enum_bits = shader_and_variation.enum_bits
# Cache max and mask value of each enum to quickly know when a possible variation is invalid
enum_maxes = []
enum_masks = []
current_bit_start = flags_bits
for e in range(len(enums)):
enum_values = enums[e][1]
enum_maxes.append((len(enum_values) - 1) << current_bit_start)
enum_masks.append(((1 << enum_bits[e]) - 1) << current_bit_start)
current_bit_start += enum_bits[e]
table_name = get_variation_table_name(shader_file)
var_name = get_var_name(os.path.basename(shader_file))
table = 'constexpr ShaderBlob %s[] = {\n' % table_name
# The last possible variation is every flag enabled and every enum at max
last_variation = ((1 << flags_bits) - 1) | reduce(lambda x, y: x|y, enum_maxes, 0)
for variation in range(last_variation + 1):
# if any variation is invalid, output an empty entry
if any([(variation & enum_masks[e]) > enum_maxes[e] for e in range(len(enums))]):
table += '{nullptr, 0}, // 0x%08X\n' % variation
else:
entry = '%s_%08X' % (var_name, variation)
table += '{%s, sizeof(%s)},\n' % (entry, entry)
table += '};'
return table
def get_get_function_h(shader_and_variation):
shader_file = shader_and_variation.shader_file
function_name = get_var_name(os.path.basename(shader_file), 'get')
definition = 'angle::Result %s' % function_name
definition += '(Context *context, uint32_t shaderFlags, RefCounted<ShaderAndSerial> **shaderOut);'
return definition
def get_get_function_cpp(shader_and_variation):
shader_file = shader_and_variation.shader_file
enums = shader_and_variation.enums
function_name = get_var_name(os.path.basename(shader_file), 'get')
namespace_name = "InternalShader::" + get_namespace_name(shader_file)
member_table_name = get_variation_table_name(shader_file, 'm')
constant_table_name = get_variation_table_name(shader_file)
definition = 'angle::Result ShaderLibrary::%s' % function_name
definition += '(Context *context, uint32_t shaderFlags, RefCounted<ShaderAndSerial> **shaderOut)\n{\n'
definition += 'ASSERT(shaderFlags < ArraySize(%s));\n' % constant_table_name
definition += ''.join(['ASSERT((shaderFlags & %s::k%sMask) >= %s::k%s &&' %
(namespace_name, enums[e][0], namespace_name, enums[e][1][0]) +
'(shaderFlags & %s::k%sMask) <= %s::k%s);\n' %
(namespace_name, enums[e][0], namespace_name, enums[e][1][-1])
for e in range(len(enums))])
definition += 'RefCounted<ShaderAndSerial> &shader = %s[shaderFlags];\n' % member_table_name
definition += '*shaderOut = &shader;\n\n'
definition += 'if (shader.get().valid())\n{\nreturn angle::Result::Continue();\n}\n\n'
definition += '// Create shader lazily. Access will need to be locked for multi-threading.\n'
definition += 'const ShaderBlob &shaderCode = %s[shaderFlags];\n' % constant_table_name
definition += 'return InitShaderAndSerial(context, &shader.get(), shaderCode.code, shaderCode.codeSize);\n'
definition += '}\n'
return definition
def get_destroy_call(shader_and_variation):
shader_file = shader_and_variation.shader_file
table_name = get_variation_table_name(shader_file, 'm')
destroy = 'for (RefCounted<ShaderAndSerial> &shader : %s)\n' % table_name
destroy += '{\nshader.get().destroy(device);\n}'
return destroy
with open(out_file_cpp, 'w') as outfile:
includes = "\n".join([gen_shader_include(shader) for shader in output_shaders])
array_entries = ",\n".join([gen_shader_blob_entry(shader) for shader in output_shaders])
shader_tables_cpp = '\n'.join([get_shader_table_cpp(s)
for s in input_shaders_and_variations])
shader_destroy_calls = '\n'.join([get_destroy_call(s)
for s in input_shaders_and_variations])
shader_get_functions_cpp = '\n'.join([get_get_function_cpp(s)
for s in input_shaders_and_variations])
outcode = template_shader_library_cpp.format(
script_name = __file__,
copyright_year = date.today().year,
out_file_name = out_file_cpp,
input_file_name = 'shaders/src/*',
internal_shader_includes = includes,
internal_shader_array_entries = array_entries)
shader_tables_cpp = shader_tables_cpp,
shader_destroy_calls = shader_destroy_calls,
shader_get_functions_cpp = shader_get_functions_cpp)
outfile.write(outcode)
outfile.close()
with open(out_file_h, 'w') as outfile:
ids = ",\n".join([get_shader_id(shader) for shader in output_shaders] + ["EnumCount"])
shader_variation_definitions = '\n'.join([get_variation_definition(s)
for s in input_shaders_and_variations])
shader_get_functions_h = '\n'.join([get_get_function_h(s)
for s in input_shaders_and_variations])
shader_tables_h = '\n'.join([get_shader_table_h(s)
for s in input_shaders_and_variations])
outcode = template_shader_library_h.format(
script_name = __file__,
copyright_year = date.today().year,
out_file_name = out_file_h,
input_file_name = 'shaders/src/*',
internal_shader_ids = ids)
shader_variation_definitions = shader_variation_definitions,
shader_get_functions_h = shader_get_functions_h,
shader_tables_h = shader_tables_h)
outfile.write(outcode)
outfile.close()
......
// 7.7.2767
// 7.10.2904
#pragma once
const uint32_t kFullScreenQuad_vert[] = {
const uint32_t kFullScreenQuad_vert_00000000[] = {
0x07230203,0x00010000,0x00080007,0x00000024,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0007000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000d,0x0000001b,0x00030003,
......@@ -34,4 +34,22 @@ const uint32_t kFullScreenQuad_vert[] = {
0x0000001c,0x0000001b,0x0003003e,0x0000001e,0x00000019,0x00050041,0x0000001f,0x00000020,
0x0000001e,0x0000001c,0x0004003d,0x00000007,0x00000021,0x00000020,0x00050041,0x00000022,
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
const uint32_t kPushConstantColor_frag[] = {
const uint32_t kPushConstantColor_frag_00000000[] = {
0x07230203,0x00010000,0x00080007,0x00000012,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0006000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x00030010,0x00000004,
......@@ -17,4 +17,19 @@ const uint32_t kPushConstantColor_frag[] = {
0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,
0x0000000f,0x00000010,0x0000000c,0x0000000e,0x0004003d,0x00000007,0x00000011,0x00000010,
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 @@
#include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h"
#include "common/debug.h"
namespace rx
{
namespace vk
{
namespace priv
{
namespace
{
#include "libANGLE/renderer/vulkan/shaders/gen/FullScreenQuad.vert.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/PushConstantColor.frag.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/FullScreenQuad.vert.00000000.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/PushConstantColor.frag.00000000.inc"
constexpr ShaderBlob kShaderBlobs[] = {{kFullScreenQuad_vert, sizeof(kFullScreenQuad_vert)},
{kPushConstantColor_frag, sizeof(kPushConstantColor_frag)}};
// This is SPIR-V binary blob and the size.
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
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));
return kShaderBlobs[static_cast<size_t>(shaderID)];
for (RefCounted<ShaderAndSerial> &shader : mFullScreenQuad_vert_shaders)
{
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 rx
......@@ -9,6 +9,6 @@
# List of generated shaders for inclusion in ANGLE's build process.
angle_vulkan_internal_shaders = [
"shaders/gen/FullScreenQuad.vert.inc",
"shaders/gen/PushConstantColor.frag.inc",
"shaders/gen/FullScreenQuad.vert.00000000.inc",
"shaders/gen/PushConstantColor.frag.00000000.inc",
]
......@@ -11,32 +11,41 @@
#ifndef LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_AUTOGEN_H_
#define LIBANGLE_RENDERER_VULKAN_VK_INTERNAL_SHADERS_AUTOGEN_H_
#include <stddef.h>
#include <stdint.h>
#include <utility>
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{
namespace vk
{
enum class InternalShaderID
namespace InternalShader
{
FullScreenQuad_vert,
PushConstantColor_frag,
EnumCount
};
namespace FullScreenQuad_vert
{} // namespace FullScreenQuad_vert
namespace priv
{
// This is SPIR-V binary blob and the size.
struct ShaderBlob
namespace PushConstantColor_frag
{} // namespace PushConstantColor_frag
} // namespace InternalShader
class ShaderLibrary final : angle::NonCopyable
{
const uint32_t *code;
size_t codeSize;
public:
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 rx
......
......@@ -748,8 +748,6 @@ libangle_vulkan_sources = [
"src/libANGLE/renderer/vulkan/vk_format_utils.cpp",
"src/libANGLE/renderer/vulkan/vk_helpers.cpp",
"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.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