Updated spirv-cross.

This commit is contained in:
Бранимир Караџић
2020-11-29 18:54:52 -08:00
parent cb4977eed5
commit aa9ab978a1
12 changed files with 855 additions and 345 deletions

View File

@@ -566,6 +566,10 @@ struct CLIArguments
uint32_t msl_r32ui_linear_texture_alignment = 4;
uint32_t msl_r32ui_alignment_constant_id = 65535;
bool msl_texture_1d_as_2d = false;
bool msl_ios_use_simdgroup_functions = false;
bool msl_emulate_subgroups = false;
uint32_t msl_fixed_subgroup_size = 0;
bool msl_force_sample_rate_shading = false;
bool glsl_emit_push_constant_as_ubo = false;
bool glsl_emit_ubo_as_plain_uniforms = false;
bool glsl_force_flattened_io_blocks = false;
@@ -779,7 +783,16 @@ static void print_help_msl()
"\t[--msl-r32ui-linear-texture-align-constant-id <id>]:\n\t\tThe function constant ID to use for the linear texture alignment.\n"
"\t\tOn MSL 1.2 or later, you can override the alignment by setting this function constant.\n"
"\t[--msl-texture-1d-as-2d]:\n\t\tEmit Image variables of dimension Dim1D as texture2d.\n"
"\t\tIn Metal, 1D textures do not support all features that 2D textures do. Use this option if your code relies on these features.\n");
"\t\tIn Metal, 1D textures do not support all features that 2D textures do. Use this option if your code relies on these features.\n"
"\t[--msl-ios-use-simdgroup-functions]:\n\t\tUse simd_*() functions for subgroup ops instead of quad_*().\n"
"\t\tRecent Apple GPUs support SIMD-groups larger than a quad. Use this option to take advantage of this support.\n"
"\t[--msl-emulate-subgroups]:\n\t\tAssume subgroups of size 1.\n"
"\t\tIntended for Vulkan Portability implementations where Metal support for SIMD-groups is insufficient for true subgroups.\n"
"\t[--msl-fixed-subgroup-size <size>]:\n\t\tAssign a constant <size> to the SubgroupSize builtin.\n"
"\t\tIntended for Vulkan Portability implementations where VK_EXT_subgroup_size_control is not supported or disabled.\n"
"\t\tIf 0, assume variable subgroup size as actually exposed by Metal.\n"
"\t[--msl-force-sample-rate-shading]:\n\t\tForce fragment shaders to run per sample.\n"
"\t\tThis adds a [[sample_id]] parameter if none is already present.\n");
// clang-format on
}
@@ -1021,6 +1034,10 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
msl_opts.r32ui_linear_texture_alignment = args.msl_r32ui_linear_texture_alignment;
msl_opts.r32ui_alignment_constant_id = args.msl_r32ui_alignment_constant_id;
msl_opts.texture_1D_as_2D = args.msl_texture_1d_as_2d;
msl_opts.ios_use_simdgroup_functions = args.msl_ios_use_simdgroup_functions;
msl_opts.emulate_subgroups = args.msl_emulate_subgroups;
msl_opts.fixed_subgroup_size = args.msl_fixed_subgroup_size;
msl_opts.force_sample_rate_shading = args.msl_force_sample_rate_shading;
msl_comp->set_msl_options(msl_opts);
for (auto &v : args.msl_discrete_descriptor_sets)
msl_comp->add_discrete_descriptor_set(v);
@@ -1370,7 +1387,8 @@ static int main_inner(int argc, char *argv[])
cbs.add("--hlsl-nonwritable-uav-texture-as-srv",
[&args](CLIParser &) { args.hlsl_nonwritable_uav_texture_as_srv = true; });
cbs.add("--hlsl-enable-16bit-types", [&args](CLIParser &) { args.hlsl_enable_16bit_types = true; });
cbs.add("--hlsl-flatten-matrix-vertex-input-semantics", [&args](CLIParser &) { args.hlsl_flatten_matrix_vertex_input_semantics = true; });
cbs.add("--hlsl-flatten-matrix-vertex-input-semantics",
[&args](CLIParser &) { args.hlsl_flatten_matrix_vertex_input_semantics = true; });
cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
cbs.add("-V", [&args](CLIParser &) { args.vulkan_semantics = true; });
cbs.add("--flatten-multidimensional-arrays", [&args](CLIParser &) { args.flatten_multidimensional_arrays = true; });
@@ -1448,6 +1466,11 @@ static int main_inner(int argc, char *argv[])
cbs.add("--msl-r32ui-linear-texture-align-constant-id",
[&args](CLIParser &parser) { args.msl_r32ui_alignment_constant_id = parser.next_uint(); });
cbs.add("--msl-texture-1d-as-2d", [&args](CLIParser &) { args.msl_texture_1d_as_2d = true; });
cbs.add("--msl-ios-use-simdgroup-functions", [&args](CLIParser &) { args.msl_ios_use_simdgroup_functions = true; });
cbs.add("--msl-emulate-subgroups", [&args](CLIParser &) { args.msl_emulate_subgroups = true; });
cbs.add("--msl-fixed-subgroup-size",
[&args](CLIParser &parser) { args.msl_fixed_subgroup_size = parser.next_uint(); });
cbs.add("--msl-force-sample-rate-shading", [&args](CLIParser &) { args.msl_force_sample_rate_shading = true; });
cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
cbs.add("--rename-entry-point", [&args](CLIParser &parser) {
auto old_name = parser.next_string();

View File

@@ -1682,8 +1682,13 @@ size_t Compiler::get_declared_struct_size_runtime_array(const SPIRType &type, si
uint32_t Compiler::evaluate_spec_constant_u32(const SPIRConstantOp &spec) const
{
auto &result_type = get<SPIRType>(spec.basetype);
if (result_type.basetype != SPIRType::UInt && result_type.basetype != SPIRType::Int && result_type.basetype != SPIRType::Boolean)
SPIRV_CROSS_THROW("Only 32-bit integers and booleans are currently supported when evaluating specialization constants.\n");
if (result_type.basetype != SPIRType::UInt && result_type.basetype != SPIRType::Int &&
result_type.basetype != SPIRType::Boolean)
{
SPIRV_CROSS_THROW(
"Only 32-bit integers and booleans are currently supported when evaluating specialization constants.\n");
}
if (!is_scalar(result_type))
SPIRV_CROSS_THROW("Spec constant evaluation must be a scalar.\n");
@@ -1692,7 +1697,11 @@ uint32_t Compiler::evaluate_spec_constant_u32(const SPIRConstantOp &spec) const
const auto eval_u32 = [&](uint32_t id) -> uint32_t {
auto &type = expression_type(id);
if (type.basetype != SPIRType::UInt && type.basetype != SPIRType::Int && type.basetype != SPIRType::Boolean)
SPIRV_CROSS_THROW("Only 32-bit integers and booleans are currently supported when evaluating specialization constants.\n");
{
SPIRV_CROSS_THROW("Only 32-bit integers and booleans are currently supported when evaluating "
"specialization constants.\n");
}
if (!is_scalar(type))
SPIRV_CROSS_THROW("Spec constant evaluation must be a scalar.\n");
if (const auto *c = this->maybe_get<SPIRConstant>(id))
@@ -1701,37 +1710,41 @@ uint32_t Compiler::evaluate_spec_constant_u32(const SPIRConstantOp &spec) const
return evaluate_spec_constant_u32(this->get<SPIRConstantOp>(id));
};
#define binary_spec_op(op, binary_op) \
case Op##op: value = eval_u32(spec.arguments[0]) binary_op eval_u32(spec.arguments[1]); break
#define binary_spec_op_cast(op, binary_op, type) \
case Op##op: value = uint32_t(type(eval_u32(spec.arguments[0])) binary_op type(eval_u32(spec.arguments[1]))); break
#define binary_spec_op(op, binary_op) \
case Op##op: \
value = eval_u32(spec.arguments[0]) binary_op eval_u32(spec.arguments[1]); \
break
#define binary_spec_op_cast(op, binary_op, type) \
case Op##op: \
value = uint32_t(type(eval_u32(spec.arguments[0])) binary_op type(eval_u32(spec.arguments[1]))); \
break
// Support the basic opcodes which are typically used when computing array sizes.
switch (spec.opcode)
{
binary_spec_op(IAdd, +);
binary_spec_op(ISub, -);
binary_spec_op(IMul, *);
binary_spec_op(BitwiseAnd, &);
binary_spec_op(BitwiseOr, |);
binary_spec_op(BitwiseXor, ^);
binary_spec_op(LogicalAnd, &);
binary_spec_op(LogicalOr, |);
binary_spec_op(ShiftLeftLogical, <<);
binary_spec_op(ShiftRightLogical, >>);
binary_spec_op_cast(ShiftRightArithmetic, >>, int32_t);
binary_spec_op(LogicalEqual, ==);
binary_spec_op(LogicalNotEqual, !=);
binary_spec_op(IEqual, ==);
binary_spec_op(INotEqual, !=);
binary_spec_op(ULessThan, <);
binary_spec_op(ULessThanEqual, <=);
binary_spec_op(UGreaterThan, >);
binary_spec_op(UGreaterThanEqual, >=);
binary_spec_op_cast(SLessThan, <, int32_t);
binary_spec_op_cast(SLessThanEqual, <=, int32_t);
binary_spec_op_cast(SGreaterThan, >, int32_t);
binary_spec_op_cast(SGreaterThanEqual, >=, int32_t);
binary_spec_op(IAdd, +);
binary_spec_op(ISub, -);
binary_spec_op(IMul, *);
binary_spec_op(BitwiseAnd, &);
binary_spec_op(BitwiseOr, |);
binary_spec_op(BitwiseXor, ^);
binary_spec_op(LogicalAnd, &);
binary_spec_op(LogicalOr, |);
binary_spec_op(ShiftLeftLogical, <<);
binary_spec_op(ShiftRightLogical, >>);
binary_spec_op_cast(ShiftRightArithmetic, >>, int32_t);
binary_spec_op(LogicalEqual, ==);
binary_spec_op(LogicalNotEqual, !=);
binary_spec_op(IEqual, ==);
binary_spec_op(INotEqual, !=);
binary_spec_op(ULessThan, <);
binary_spec_op(ULessThanEqual, <=);
binary_spec_op(UGreaterThan, >);
binary_spec_op(UGreaterThanEqual, >=);
binary_spec_op_cast(SLessThan, <, int32_t);
binary_spec_op_cast(SLessThanEqual, <=, int32_t);
binary_spec_op_cast(SGreaterThan, >, int32_t);
binary_spec_op_cast(SGreaterThanEqual, >=, int32_t);
#undef binary_spec_op
#undef binary_spec_op_cast

View File

@@ -678,6 +678,22 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
case SPVC_COMPILER_OPTION_MSL_R32UI_ALIGNMENT_CONSTANT_ID:
options->msl.r32ui_alignment_constant_id = value;
break;
case SPVC_COMPILER_OPTION_MSL_IOS_USE_SIMDGROUP_FUNCTIONS:
options->msl.ios_use_simdgroup_functions = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_EMULATE_SUBGROUPS:
options->msl.emulate_subgroups = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_FIXED_SUBGROUP_SIZE:
options->msl.fixed_subgroup_size = value;
break;
case SPVC_COMPILER_OPTION_MSL_FORCE_SAMPLE_RATE_SHADING:
options->msl.force_sample_rate_shading = value != 0;
break;
#endif
default:

View File

@@ -33,7 +33,7 @@ extern "C" {
/* Bumped if ABI or API breaks backwards compatibility. */
#define SPVC_C_API_VERSION_MAJOR 0
/* Bumped if APIs or enumerations are added in a backwards compatible way. */
#define SPVC_C_API_VERSION_MINOR 42
#define SPVC_C_API_VERSION_MINOR 44
/* Bumped if internal implementation details change. */
#define SPVC_C_API_VERSION_PATCH 0
@@ -647,6 +647,11 @@ typedef enum spvc_compiler_option
SPVC_COMPILER_OPTION_HLSL_FLATTEN_MATRIX_VERTEX_INPUT_SEMANTICS = 71 | SPVC_COMPILER_OPTION_HLSL_BIT,
SPVC_COMPILER_OPTION_MSL_IOS_USE_SIMDGROUP_FUNCTIONS = 72 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_EMULATE_SUBGROUPS = 73 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_FIXED_SUBGROUP_SIZE = 74 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_FORCE_SAMPLE_RATE_SHADING = 75 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
} spvc_compiler_option;

View File

@@ -63,7 +63,8 @@ public:
private:
#if defined(_MSC_VER) && _MSC_VER < 1900
// MSVC 2013 workarounds, sigh ...
union {
union
{
char aligned_char[sizeof(T) * N];
double dummy_aligner;
} u;

View File

@@ -526,6 +526,17 @@ void ParsedIR::mark_used_as_array_length(ID id)
}
}
Bitset ParsedIR::get_buffer_block_type_flags(const SPIRType &type) const
{
if (type.member_types.empty())
return {};
Bitset all_members_flags = get_member_decoration_bitset(type.self, 0);
for (uint32_t i = 1; i < uint32_t(type.member_types.size()); i++)
all_members_flags.merge_and(get_member_decoration_bitset(type.self, i));
return all_members_flags;
}
Bitset ParsedIR::get_buffer_block_flags(const SPIRVariable &var) const
{
auto &type = get<SPIRType>(var.basetype);
@@ -542,10 +553,7 @@ Bitset ParsedIR::get_buffer_block_flags(const SPIRVariable &var) const
if (type.member_types.empty())
return base_flags;
Bitset all_members_flags = get_member_decoration_bitset(type.self, 0);
for (uint32_t i = 1; i < uint32_t(type.member_types.size()); i++)
all_members_flags.merge_and(get_member_decoration_bitset(type.self, i));
auto all_members_flags = get_buffer_block_type_flags(type);
base_flags.merge_or(all_members_flags);
return base_flags;
}

View File

@@ -139,6 +139,7 @@ public:
void mark_used_as_array_length(ID id);
uint32_t increase_bound_by(uint32_t count);
Bitset get_buffer_block_flags(const SPIRVariable &var) const;
Bitset get_buffer_block_type_flags(const SPIRType &type) const;
void add_typed_id(Types type, ID id);
void remove_typed_id(Types type, ID id);

View File

@@ -1718,8 +1718,7 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
}
else if (var.storage == StorageClassOutput)
{
if (flags.get(DecorationXfbBuffer) && flags.get(DecorationXfbStride) &&
flags.get(DecorationOffset))
if (flags.get(DecorationXfbBuffer) && flags.get(DecorationXfbStride) && flags.get(DecorationOffset))
{
// XFB for standalone variables, we can emit all decorations.
attr.push_back(join("xfb_buffer = ", get_decoration(var.self, DecorationXfbBuffer)));
@@ -2013,6 +2012,9 @@ void CompilerGLSL::emit_buffer_reference_block(SPIRType &type, bool forward_decl
block_names.insert(buffer_name);
block_ssbo_names.insert(buffer_name);
// Ensure we emit the correct name when emitting non-forward pointer type.
ir.meta[type.self].decoration.alias = buffer_name;
}
else if (type.basetype != SPIRType::Struct)
buffer_name = type_to_glsl(type);
@@ -2022,7 +2024,20 @@ void CompilerGLSL::emit_buffer_reference_block(SPIRType &type, bool forward_decl
if (!forward_declaration)
{
if (type.basetype == SPIRType::Struct)
statement("layout(buffer_reference, ", buffer_to_packing_standard(type, true), ") buffer ", buffer_name);
{
auto flags = ir.get_buffer_block_type_flags(type);
string decorations;
if (flags.get(DecorationRestrict))
decorations += " restrict";
if (flags.get(DecorationCoherent))
decorations += " coherent";
if (flags.get(DecorationNonReadable))
decorations += " writeonly";
if (flags.get(DecorationNonWritable))
decorations += " readonly";
statement("layout(buffer_reference, ", buffer_to_packing_standard(type, true),
")", decorations, " buffer ", buffer_name);
}
else
statement("layout(buffer_reference) buffer ", buffer_name);
@@ -2306,6 +2321,12 @@ void CompilerGLSL::emit_interface_block(const SPIRVariable &var)
{
auto &type = get<SPIRType>(var.basetype);
if (var.storage == StorageClassInput && type.basetype == SPIRType::Double &&
!options.es && options.version < 410)
{
require_extension_internal("GL_ARB_vertex_attrib_64bit");
}
// Either make it plain in/out or in/out blocks depending on what shader is doing ...
bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
const char *qual = to_storage_qualifiers_glsl(var);
@@ -3399,10 +3420,8 @@ void CompilerGLSL::emit_resources()
void CompilerGLSL::emit_extension_workarounds(spv::ExecutionModel model)
{
static const char *workaround_types[] = {
"int", "ivec2", "ivec3", "ivec4", "uint", "uvec2", "uvec3", "uvec4",
"float", "vec2", "vec3", "vec4", "double", "dvec2", "dvec3", "dvec4"
};
static const char *workaround_types[] = { "int", "ivec2", "ivec3", "ivec4", "uint", "uvec2", "uvec3", "uvec4",
"float", "vec2", "vec3", "vec4", "double", "dvec2", "dvec3", "dvec4" };
if (!options.vulkan_semantics)
{
@@ -3809,7 +3828,7 @@ void CompilerGLSL::emit_extension_workarounds(spv::ExecutionModel model)
for (auto &type_id : workaround_ubo_load_overload_types)
{
auto &type = get<SPIRType>(type_id);
statement(type_to_glsl(type), " SPIRV_Cross_workaround_load_row_major(", type_to_glsl(type),
statement(type_to_glsl(type), " spvWorkaroundRowMajor(", type_to_glsl(type),
" wrap) { return wrap; }");
}
statement("");
@@ -3817,7 +3836,7 @@ void CompilerGLSL::emit_extension_workarounds(spv::ExecutionModel model)
if (requires_transpose_2x2)
{
statement("mat2 SPIRV_Cross_Transpose(mat2 m)");
statement("mat2 spvTranspose(mat2 m)");
begin_scope();
statement("return mat2(m[0][0], m[1][0], m[0][1], m[1][1]);");
end_scope();
@@ -3826,7 +3845,7 @@ void CompilerGLSL::emit_extension_workarounds(spv::ExecutionModel model)
if (requires_transpose_3x3)
{
statement("mat3 SPIRV_Cross_Transpose(mat3 m)");
statement("mat3 spvTranspose(mat3 m)");
begin_scope();
statement("return mat3(m[0][0], m[1][0], m[2][0], m[0][1], m[1][1], m[2][1], m[0][2], m[1][2], m[2][2]);");
end_scope();
@@ -3835,9 +3854,10 @@ void CompilerGLSL::emit_extension_workarounds(spv::ExecutionModel model)
if (requires_transpose_4x4)
{
statement("mat4 SPIRV_Cross_Transpose(mat4 m)");
statement("mat4 spvTranspose(mat4 m)");
begin_scope();
statement("return mat4(m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3]);");
statement("return mat4(m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], "
"m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3]);");
end_scope();
statement("");
}
@@ -5726,7 +5746,8 @@ string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtyp
// GLES has very limited support for shadow samplers.
// Basically shadow2D and shadow2DProj work through EXT_shadow_samplers,
// everything else can just throw
if (image_is_comparison(imgtype, tex) && is_legacy_es())
bool is_comparison = image_is_comparison(imgtype, tex);
if (is_comparison && is_legacy_es())
{
if (op == "texture" || op == "textureProj")
require_extension_internal("GL_EXT_shadow_samplers");
@@ -5734,8 +5755,20 @@ string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtyp
SPIRV_CROSS_THROW(join(op, " not allowed on depth samplers in legacy ES"));
}
bool is_es_and_depth = is_legacy_es() && image_is_comparison(imgtype, tex);
std::string type_prefix = image_is_comparison(imgtype, tex) ? "shadow" : "texture";
if (op == "textureSize")
{
if (is_legacy_es())
SPIRV_CROSS_THROW("textureSize not supported in legacy ES");
if (is_comparison)
SPIRV_CROSS_THROW("textureSize not supported on shadow sampler in legacy GLSL");
require_extension_internal("GL_EXT_gpu_shader4");
}
if (op == "texelFetch" && is_legacy_es())
SPIRV_CROSS_THROW("texelFetch not supported in legacy ES");
bool is_es_and_depth = is_legacy_es() && is_comparison;
std::string type_prefix = is_comparison ? "shadow" : "texture";
if (op == "texture")
return is_es_and_depth ? join(type_prefix, type, "EXT") : join(type_prefix, type);
@@ -5754,6 +5787,10 @@ string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtyp
is_legacy_es() ? "ProjGradEXT" : is_legacy_desktop() ? "ProjGradARB" : "ProjGrad");
else if (op == "textureProjLodOffset")
return join(type_prefix, type, "ProjLodOffset");
else if (op == "textureSize")
return join("textureSize", type);
else if (op == "texelFetch")
return join("texelFetch", type);
else
{
SPIRV_CROSS_THROW(join("Unsupported legacy texture op: ", op));
@@ -6162,6 +6199,10 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool sparse, bool
opt = &ops[5];
length -= 5;
gather = true;
if (options.es && options.version < 310)
SPIRV_CROSS_THROW("textureGather requires ESSL 310.");
else if (!options.es && options.version < 400)
SPIRV_CROSS_THROW("textureGather with depth compare requires GLSL 400.");
break;
case OpImageGather:
@@ -6170,6 +6211,14 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool sparse, bool
opt = &ops[5];
length -= 5;
gather = true;
if (options.es && options.version < 310)
SPIRV_CROSS_THROW("textureGather requires ESSL 310.");
else if (!options.es && options.version < 400)
{
if (!expression_is_constant_null(comp))
SPIRV_CROSS_THROW("textureGather with component requires GLSL 400.");
require_extension_internal("GL_ARB_texture_gather");
}
break;
case OpImageFetch:
@@ -6438,7 +6487,7 @@ string CompilerGLSL::to_function_name(const TextureFunctionNameArguments &args)
if (args.is_sparse_feedback || args.has_min_lod)
fname += "ARB";
return is_legacy() ? legacy_tex_op(fname, imgtype, tex) : fname;
return (is_legacy() && !args.base.is_gather) ? legacy_tex_op(fname, imgtype, tex) : fname;
}
std::string CompilerGLSL::convert_separate_image_to_expression(uint32_t id)
@@ -6685,7 +6734,7 @@ string CompilerGLSL::to_function_args(const TextureFunctionArguments &args, bool
farg_str += to_expression(args.bias);
}
if (args.component)
if (args.component && !expression_is_constant_null(args.component))
{
forward = forward && should_forward(args.component);
farg_str += ", ";
@@ -10488,7 +10537,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
{
auto &type = get<SPIRType>(ops[0]);
if (type.vecsize > 1)
GLSL_UFOP(not);
GLSL_UFOP(not );
else
GLSL_UOP(!);
break;
@@ -11151,8 +11200,19 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
{
uint32_t result_type = ops[0];
uint32_t id = ops[1];
uint32_t img = ops[2];
auto expr = join("textureSize(", convert_separate_image_to_expression(ops[2]), ", ",
std::string fname = "textureSize";
if (is_legacy_desktop())
{
auto &type = expression_type(img);
auto &imgtype = get<SPIRType>(type.self);
fname = legacy_tex_op(fname, imgtype, img);
}
else if (is_legacy_es())
SPIRV_CROSS_THROW("textureSize is not supported in ESSL 100.");
auto expr = join(fname, "(", convert_separate_image_to_expression(img), ", ",
bitcast_expression(SPIRType::Int, ops[3]), ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
@@ -11413,13 +11473,24 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
string expr;
if (type.image.sampled == 2)
{
if (!options.es && options.version < 430)
require_extension_internal("GL_ARB_shader_image_size");
else if (options.es && options.version < 310)
SPIRV_CROSS_THROW("At least ESSL 3.10 required for imageSize.");
// The size of an image is always constant.
expr = join("imageSize(", to_expression(ops[2]), ")");
}
else
{
// This path is hit for samplerBuffers and multisampled images which do not have LOD.
expr = join("textureSize(", convert_separate_image_to_expression(ops[2]), ")");
std::string fname = "textureSize";
if (is_legacy())
{
auto &imgtype = get<SPIRType>(type.self);
fname = legacy_tex_op(fname, imgtype, ops[2]);
}
expr = join(fname, "(", convert_separate_image_to_expression(ops[2]), ")");
}
auto &restype = get<SPIRType>(ops[0]);
@@ -12199,7 +12270,7 @@ string CompilerGLSL::convert_row_major_matrix(string exp_str, const SPIRType &ex
}
else
SPIRV_CROSS_THROW("Non-square matrices are not supported in legacy GLSL, cannot transpose.");
return join("SPIRV_Cross_Transpose(", exp_str, ")");
return join("spvTranspose(", exp_str, ")");
}
else
return join("transpose(", exp_str, ")");
@@ -14177,8 +14248,8 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
if (is_legacy_es())
{
uint32_t counter = statement_count;
statement("for (int SPIRV_Cross_Dummy", counter, " = 0; SPIRV_Cross_Dummy", counter,
" < 1; SPIRV_Cross_Dummy", counter, "++)");
statement("for (int spvDummy", counter, " = 0; spvDummy", counter,
" < 1; spvDummy", counter, "++)");
}
else
statement("do");
@@ -14304,7 +14375,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
// The backend is responsible for setting this up, and redirection the return values as appropriate.
if (ir.ids[block.return_value].get_type() != TypeUndef)
{
emit_array_copy("SPIRV_Cross_return_value", block.return_value, StorageClassFunction,
emit_array_copy("spvReturnValue", block.return_value, StorageClassFunction,
get_expression_effective_storage_class(block.return_value));
}
@@ -15006,17 +15077,15 @@ bool CompilerGLSL::variable_is_depth_or_compare(VariableID id) const
const char *CompilerGLSL::ShaderSubgroupSupportHelper::get_extension_name(Candidate c)
{
static const char * const retval[CandidateCount] = {
"GL_KHR_shader_subgroup_ballot",
"GL_KHR_shader_subgroup_basic",
"GL_KHR_shader_subgroup_vote",
"GL_NV_gpu_shader_5",
"GL_NV_shader_thread_group",
"GL_NV_shader_thread_shuffle",
"GL_ARB_shader_ballot",
"GL_ARB_shader_group_vote",
"GL_AMD_gcn_shader"
};
static const char *const retval[CandidateCount] = { "GL_KHR_shader_subgroup_ballot",
"GL_KHR_shader_subgroup_basic",
"GL_KHR_shader_subgroup_vote",
"GL_NV_gpu_shader_5",
"GL_NV_shader_thread_group",
"GL_NV_shader_thread_shuffle",
"GL_ARB_shader_ballot",
"GL_ARB_shader_group_vote",
"GL_AMD_gcn_shader" };
return retval[c];
}
@@ -15046,8 +15115,8 @@ const char *CompilerGLSL::ShaderSubgroupSupportHelper::get_extra_required_extens
}
}
CompilerGLSL::ShaderSubgroupSupportHelper::FeatureVector
CompilerGLSL::ShaderSubgroupSupportHelper::get_feature_dependencies(Feature feature)
CompilerGLSL::ShaderSubgroupSupportHelper::FeatureVector CompilerGLSL::ShaderSubgroupSupportHelper::
get_feature_dependencies(Feature feature)
{
switch (feature)
{
@@ -15064,27 +15133,25 @@ CompilerGLSL::ShaderSubgroupSupportHelper::get_feature_dependencies(Feature feat
}
}
CompilerGLSL::ShaderSubgroupSupportHelper::FeatureMask
CompilerGLSL::ShaderSubgroupSupportHelper::get_feature_dependency_mask(Feature feature)
CompilerGLSL::ShaderSubgroupSupportHelper::FeatureMask CompilerGLSL::ShaderSubgroupSupportHelper::
get_feature_dependency_mask(Feature feature)
{
return build_mask(get_feature_dependencies(feature));
}
bool CompilerGLSL::ShaderSubgroupSupportHelper::can_feature_be_implemented_without_extensions(Feature feature)
{
static const bool retval[FeatureCount] = {
false, false, false, false, false, false,
true, // SubgroupBalloFindLSB_MSB
false, false, false, false,
true, // SubgroupMemBarrier - replaced with workgroup memory barriers
false, false, true, false
};
static const bool retval[FeatureCount] = { false, false, false, false, false, false,
true, // SubgroupBalloFindLSB_MSB
false, false, false, false,
true, // SubgroupMemBarrier - replaced with workgroup memory barriers
false, false, true, false };
return retval[feature];
}
CompilerGLSL::ShaderSubgroupSupportHelper::Candidate
CompilerGLSL::ShaderSubgroupSupportHelper::get_KHR_extension_for_feature(Feature feature)
CompilerGLSL::ShaderSubgroupSupportHelper::Candidate CompilerGLSL::ShaderSubgroupSupportHelper::
get_KHR_extension_for_feature(Feature feature)
{
static const Candidate extensions[FeatureCount] = {
KHR_shader_subgroup_ballot, KHR_shader_subgroup_basic, KHR_shader_subgroup_basic, KHR_shader_subgroup_basic,
@@ -15106,8 +15173,7 @@ bool CompilerGLSL::ShaderSubgroupSupportHelper::is_feature_requested(Feature fea
return (feature_mask & (1u << feature)) != 0;
}
CompilerGLSL::ShaderSubgroupSupportHelper::Result
CompilerGLSL::ShaderSubgroupSupportHelper::resolve() const
CompilerGLSL::ShaderSubgroupSupportHelper::Result CompilerGLSL::ShaderSubgroupSupportHelper::resolve() const
{
Result res;
@@ -15137,8 +15203,8 @@ CompilerGLSL::ShaderSubgroupSupportHelper::resolve() const
return res;
}
CompilerGLSL::ShaderSubgroupSupportHelper::CandidateVector
CompilerGLSL::ShaderSubgroupSupportHelper::get_candidates_for_feature(Feature ft, const Result &r)
CompilerGLSL::ShaderSubgroupSupportHelper::CandidateVector CompilerGLSL::ShaderSubgroupSupportHelper::
get_candidates_for_feature(Feature ft, const Result &r)
{
auto c = get_candidates_for_feature(ft);
auto cmp = [&r](Candidate a, Candidate b) {
@@ -15150,8 +15216,8 @@ CompilerGLSL::ShaderSubgroupSupportHelper::get_candidates_for_feature(Feature ft
return c;
}
CompilerGLSL::ShaderSubgroupSupportHelper::CandidateVector
CompilerGLSL::ShaderSubgroupSupportHelper::get_candidates_for_feature(Feature feature)
CompilerGLSL::ShaderSubgroupSupportHelper::CandidateVector CompilerGLSL::ShaderSubgroupSupportHelper::
get_candidates_for_feature(Feature feature)
{
switch (feature)
{
@@ -15192,8 +15258,8 @@ CompilerGLSL::ShaderSubgroupSupportHelper::get_candidates_for_feature(Feature fe
}
}
CompilerGLSL::ShaderSubgroupSupportHelper::FeatureMask
CompilerGLSL::ShaderSubgroupSupportHelper::build_mask(const SmallVector<Feature> &features)
CompilerGLSL::ShaderSubgroupSupportHelper::FeatureMask CompilerGLSL::ShaderSubgroupSupportHelper::build_mask(
const SmallVector<Feature> &features)
{
FeatureMask mask = 0;
for (Feature f : features)
@@ -15234,8 +15300,7 @@ void CompilerGLSL::rewrite_load_for_wrapped_row_major(std::string &expr, TypeID
return;
auto &backing_type = get<SPIRType>(var->basetype);
bool is_ubo = backing_type.basetype == SPIRType::Struct &&
backing_type.storage == StorageClassUniform &&
bool is_ubo = backing_type.basetype == SPIRType::Struct && backing_type.storage == StorageClassUniform &&
has_decoration(backing_type.self, DecorationBlock);
if (!is_ubo)
return;
@@ -15269,6 +15334,6 @@ void CompilerGLSL::rewrite_load_for_wrapped_row_major(std::string &expr, TypeID
if (rewrite)
{
request_workaround_wrapper_overload(loaded_type);
expr = join("SPIRV_Cross_workaround_load_row_major(", expr, ")");
expr = join("spvWorkaroundRowMajor(", expr, ")");
}
}

View File

@@ -243,7 +243,6 @@ public:
// - Images which are statically used at least once with Dref opcodes.
bool variable_is_depth_or_compare(VariableID id) const;
protected:
struct ShaderSubgroupSupportHelper
{

View File

@@ -1234,8 +1234,7 @@ void CompilerHLSL::declare_undefined_values()
if (options.force_zero_initialized_variables && type_can_zero_initialize(type))
initializer = join(" = ", to_zero_initialized_expression(undef.basetype));
statement("static ", variable_decl(type, to_name(undef.self), undef.self),
initializer, ";");
statement("static ", variable_decl(type, to_name(undef.self), undef.self), initializer, ";");
emitted = true;
});
@@ -1529,14 +1528,14 @@ void CompilerHLSL::emit_resources()
if (requires_fp16_packing)
{
// HLSL does not pack into a single word sadly :(
statement("uint SPIRV_Cross_packHalf2x16(float2 value)");
statement("uint spvPackHalf2x16(float2 value)");
begin_scope();
statement("uint2 Packed = f32tof16(value);");
statement("return Packed.x | (Packed.y << 16);");
end_scope();
statement("");
statement("float2 SPIRV_Cross_unpackHalf2x16(uint value)");
statement("float2 spvUnpackHalf2x16(uint value)");
begin_scope();
statement("return f16tof32(uint2(value & 0xffff, value >> 16));");
end_scope();
@@ -1545,13 +1544,13 @@ void CompilerHLSL::emit_resources()
if (requires_uint2_packing)
{
statement("uint64_t SPIRV_Cross_packUint2x32(uint2 value)");
statement("uint64_t spvPackUint2x32(uint2 value)");
begin_scope();
statement("return (uint64_t(value.y) << 32) | uint64_t(value.x);");
end_scope();
statement("");
statement("uint2 SPIRV_Cross_unpackUint2x32(uint64_t value)");
statement("uint2 spvUnpackUint2x32(uint64_t value)");
begin_scope();
statement("uint2 Unpacked;");
statement("Unpacked.x = uint(value & 0xffffffff);");
@@ -1564,14 +1563,14 @@ void CompilerHLSL::emit_resources()
if (requires_explicit_fp16_packing)
{
// HLSL does not pack into a single word sadly :(
statement("uint SPIRV_Cross_packFloat2x16(min16float2 value)");
statement("uint spvPackFloat2x16(min16float2 value)");
begin_scope();
statement("uint2 Packed = f32tof16(value);");
statement("return Packed.x | (Packed.y << 16);");
end_scope();
statement("");
statement("min16float2 SPIRV_Cross_unpackFloat2x16(uint value)");
statement("min16float2 spvUnpackFloat2x16(uint value)");
begin_scope();
statement("return min16float2(f16tof32(uint2(value & 0xffff, value >> 16)));");
end_scope();
@@ -1581,14 +1580,14 @@ void CompilerHLSL::emit_resources()
// HLSL does not seem to have builtins for these operation, so roll them by hand ...
if (requires_unorm8_packing)
{
statement("uint SPIRV_Cross_packUnorm4x8(float4 value)");
statement("uint spvPackUnorm4x8(float4 value)");
begin_scope();
statement("uint4 Packed = uint4(round(saturate(value) * 255.0));");
statement("return Packed.x | (Packed.y << 8) | (Packed.z << 16) | (Packed.w << 24);");
end_scope();
statement("");
statement("float4 SPIRV_Cross_unpackUnorm4x8(uint value)");
statement("float4 spvUnpackUnorm4x8(uint value)");
begin_scope();
statement("uint4 Packed = uint4(value & 0xff, (value >> 8) & 0xff, (value >> 16) & 0xff, value >> 24);");
statement("return float4(Packed) / 255.0;");
@@ -1598,14 +1597,14 @@ void CompilerHLSL::emit_resources()
if (requires_snorm8_packing)
{
statement("uint SPIRV_Cross_packSnorm4x8(float4 value)");
statement("uint spvPackSnorm4x8(float4 value)");
begin_scope();
statement("int4 Packed = int4(round(clamp(value, -1.0, 1.0) * 127.0)) & 0xff;");
statement("return uint(Packed.x | (Packed.y << 8) | (Packed.z << 16) | (Packed.w << 24));");
end_scope();
statement("");
statement("float4 SPIRV_Cross_unpackSnorm4x8(uint value)");
statement("float4 spvUnpackSnorm4x8(uint value)");
begin_scope();
statement("int SignedValue = int(value);");
statement("int4 Packed = int4(SignedValue << 24, SignedValue << 16, SignedValue << 8, SignedValue) >> 24;");
@@ -1616,14 +1615,14 @@ void CompilerHLSL::emit_resources()
if (requires_unorm16_packing)
{
statement("uint SPIRV_Cross_packUnorm2x16(float2 value)");
statement("uint spvPackUnorm2x16(float2 value)");
begin_scope();
statement("uint2 Packed = uint2(round(saturate(value) * 65535.0));");
statement("return Packed.x | (Packed.y << 16);");
end_scope();
statement("");
statement("float2 SPIRV_Cross_unpackUnorm2x16(uint value)");
statement("float2 spvUnpackUnorm2x16(uint value)");
begin_scope();
statement("uint2 Packed = uint2(value & 0xffff, value >> 16);");
statement("return float2(Packed) / 65535.0;");
@@ -1633,14 +1632,14 @@ void CompilerHLSL::emit_resources()
if (requires_snorm16_packing)
{
statement("uint SPIRV_Cross_packSnorm2x16(float2 value)");
statement("uint spvPackSnorm2x16(float2 value)");
begin_scope();
statement("int2 Packed = int2(round(clamp(value, -1.0, 1.0) * 32767.0)) & 0xffff;");
statement("return uint(Packed.x | (Packed.y << 16));");
end_scope();
statement("");
statement("float2 SPIRV_Cross_unpackSnorm2x16(uint value)");
statement("float2 spvUnpackSnorm2x16(uint value)");
begin_scope();
statement("int SignedValue = int(value);");
statement("int2 Packed = int2(SignedValue << 16, SignedValue) >> 16;");
@@ -1654,7 +1653,7 @@ void CompilerHLSL::emit_resources()
static const char *types[] = { "uint", "uint2", "uint3", "uint4" };
for (auto &type : types)
{
statement(type, " SPIRV_Cross_bitfieldInsert(", type, " Base, ", type, " Insert, uint Offset, uint Count)");
statement(type, " spvBitfieldInsert(", type, " Base, ", type, " Insert, uint Offset, uint Count)");
begin_scope();
statement("uint Mask = Count == 32 ? 0xffffffff : (((1u << Count) - 1) << (Offset & 31));");
statement("return (Base & ~Mask) | ((Insert << Offset) & Mask);");
@@ -1668,7 +1667,7 @@ void CompilerHLSL::emit_resources()
static const char *unsigned_types[] = { "uint", "uint2", "uint3", "uint4" };
for (auto &type : unsigned_types)
{
statement(type, " SPIRV_Cross_bitfieldUExtract(", type, " Base, uint Offset, uint Count)");
statement(type, " spvBitfieldUExtract(", type, " Base, uint Offset, uint Count)");
begin_scope();
statement("uint Mask = Count == 32 ? 0xffffffff : ((1 << Count) - 1);");
statement("return (Base >> Offset) & Mask;");
@@ -1680,7 +1679,7 @@ void CompilerHLSL::emit_resources()
static const char *signed_types[] = { "int", "int2", "int3", "int4" };
for (auto &type : signed_types)
{
statement(type, " SPIRV_Cross_bitfieldSExtract(", type, " Base, int Offset, int Count)");
statement(type, " spvBitfieldSExtract(", type, " Base, int Offset, int Count)");
begin_scope();
statement("int Mask = Count == 32 ? -1 : ((1 << Count) - 1);");
statement(type, " Masked = (Base >> Offset) & Mask;");
@@ -1695,7 +1694,7 @@ void CompilerHLSL::emit_resources()
{
statement("// Returns the inverse of a matrix, by using the algorithm of calculating the classical");
statement("// adjoint and dividing by the determinant. The contents of the matrix are changed.");
statement("float2x2 SPIRV_Cross_Inverse(float2x2 m)");
statement("float2x2 spvInverse(float2x2 m)");
begin_scope();
statement("float2x2 adj; // The adjoint matrix (inverse after dividing by determinant)");
statement_no_indent("");
@@ -1719,29 +1718,29 @@ void CompilerHLSL::emit_resources()
if (requires_inverse_3x3)
{
statement("// Returns the determinant of a 2x2 matrix.");
statement("float SPIRV_Cross_Det2x2(float a1, float a2, float b1, float b2)");
statement("float spvDet2x2(float a1, float a2, float b1, float b2)");
begin_scope();
statement("return a1 * b2 - b1 * a2;");
end_scope();
statement_no_indent("");
statement("// Returns the inverse of a matrix, by using the algorithm of calculating the classical");
statement("// adjoint and dividing by the determinant. The contents of the matrix are changed.");
statement("float3x3 SPIRV_Cross_Inverse(float3x3 m)");
statement("float3x3 spvInverse(float3x3 m)");
begin_scope();
statement("float3x3 adj; // The adjoint matrix (inverse after dividing by determinant)");
statement_no_indent("");
statement("// Create the transpose of the cofactors, as the classical adjoint of the matrix.");
statement("adj[0][0] = SPIRV_Cross_Det2x2(m[1][1], m[1][2], m[2][1], m[2][2]);");
statement("adj[0][1] = -SPIRV_Cross_Det2x2(m[0][1], m[0][2], m[2][1], m[2][2]);");
statement("adj[0][2] = SPIRV_Cross_Det2x2(m[0][1], m[0][2], m[1][1], m[1][2]);");
statement("adj[0][0] = spvDet2x2(m[1][1], m[1][2], m[2][1], m[2][2]);");
statement("adj[0][1] = -spvDet2x2(m[0][1], m[0][2], m[2][1], m[2][2]);");
statement("adj[0][2] = spvDet2x2(m[0][1], m[0][2], m[1][1], m[1][2]);");
statement_no_indent("");
statement("adj[1][0] = -SPIRV_Cross_Det2x2(m[1][0], m[1][2], m[2][0], m[2][2]);");
statement("adj[1][1] = SPIRV_Cross_Det2x2(m[0][0], m[0][2], m[2][0], m[2][2]);");
statement("adj[1][2] = -SPIRV_Cross_Det2x2(m[0][0], m[0][2], m[1][0], m[1][2]);");
statement("adj[1][0] = -spvDet2x2(m[1][0], m[1][2], m[2][0], m[2][2]);");
statement("adj[1][1] = spvDet2x2(m[0][0], m[0][2], m[2][0], m[2][2]);");
statement("adj[1][2] = -spvDet2x2(m[0][0], m[0][2], m[1][0], m[1][2]);");
statement_no_indent("");
statement("adj[2][0] = SPIRV_Cross_Det2x2(m[1][0], m[1][1], m[2][0], m[2][1]);");
statement("adj[2][1] = -SPIRV_Cross_Det2x2(m[0][0], m[0][1], m[2][0], m[2][1]);");
statement("adj[2][2] = SPIRV_Cross_Det2x2(m[0][0], m[0][1], m[1][0], m[1][1]);");
statement("adj[2][0] = spvDet2x2(m[1][0], m[1][1], m[2][0], m[2][1]);");
statement("adj[2][1] = -spvDet2x2(m[0][0], m[0][1], m[2][0], m[2][1]);");
statement("adj[2][2] = spvDet2x2(m[0][0], m[0][1], m[1][0], m[1][1]);");
statement_no_indent("");
statement("// Calculate the determinant as a combination of the cofactors of the first row.");
statement("float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]);");
@@ -1758,7 +1757,7 @@ void CompilerHLSL::emit_resources()
if (!requires_inverse_3x3)
{
statement("// Returns the determinant of a 2x2 matrix.");
statement("float SPIRV_Cross_Det2x2(float a1, float a2, float b1, float b2)");
statement("float spvDet2x2(float a1, float a2, float b1, float b2)");
begin_scope();
statement("return a1 * b2 - b1 * a2;");
end_scope();
@@ -1766,71 +1765,71 @@ void CompilerHLSL::emit_resources()
}
statement("// Returns the determinant of a 3x3 matrix.");
statement("float SPIRV_Cross_Det3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, "
statement("float spvDet3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, "
"float c2, float c3)");
begin_scope();
statement("return a1 * SPIRV_Cross_Det2x2(b2, b3, c2, c3) - b1 * SPIRV_Cross_Det2x2(a2, a3, c2, c3) + c1 * "
"SPIRV_Cross_Det2x2(a2, a3, "
statement("return a1 * spvDet2x2(b2, b3, c2, c3) - b1 * spvDet2x2(a2, a3, c2, c3) + c1 * "
"spvDet2x2(a2, a3, "
"b2, b3);");
end_scope();
statement_no_indent("");
statement("// Returns the inverse of a matrix, by using the algorithm of calculating the classical");
statement("// adjoint and dividing by the determinant. The contents of the matrix are changed.");
statement("float4x4 SPIRV_Cross_Inverse(float4x4 m)");
statement("float4x4 spvInverse(float4x4 m)");
begin_scope();
statement("float4x4 adj; // The adjoint matrix (inverse after dividing by determinant)");
statement_no_indent("");
statement("// Create the transpose of the cofactors, as the classical adjoint of the matrix.");
statement(
"adj[0][0] = SPIRV_Cross_Det3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], "
"adj[0][0] = spvDet3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], "
"m[3][3]);");
statement(
"adj[0][1] = -SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], "
"adj[0][1] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], "
"m[3][3]);");
statement(
"adj[0][2] = SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], "
"adj[0][2] = spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], "
"m[3][3]);");
statement(
"adj[0][3] = -SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], "
"adj[0][3] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], "
"m[2][3]);");
statement_no_indent("");
statement(
"adj[1][0] = -SPIRV_Cross_Det3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], "
"adj[1][0] = -spvDet3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], "
"m[3][3]);");
statement(
"adj[1][1] = SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], "
"adj[1][1] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], "
"m[3][3]);");
statement(
"adj[1][2] = -SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], "
"adj[1][2] = -spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], "
"m[3][3]);");
statement(
"adj[1][3] = SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], "
"adj[1][3] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], "
"m[2][3]);");
statement_no_indent("");
statement(
"adj[2][0] = SPIRV_Cross_Det3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], "
"adj[2][0] = spvDet3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], "
"m[3][3]);");
statement(
"adj[2][1] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], "
"adj[2][1] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], "
"m[3][3]);");
statement(
"adj[2][2] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], "
"adj[2][2] = spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], "
"m[3][3]);");
statement(
"adj[2][3] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], "
"adj[2][3] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], "
"m[2][3]);");
statement_no_indent("");
statement(
"adj[3][0] = -SPIRV_Cross_Det3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], "
"adj[3][0] = -spvDet3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], "
"m[3][2]);");
statement(
"adj[3][1] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], "
"adj[3][1] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], "
"m[3][2]);");
statement(
"adj[3][2] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], "
"adj[3][2] = -spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], "
"m[3][2]);");
statement(
"adj[3][3] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], "
"adj[3][3] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], "
"m[2][2]);");
statement_no_indent("");
statement("// Calculate the determinant as a combination of the cofactors of the first row.");
@@ -1847,7 +1846,7 @@ void CompilerHLSL::emit_resources()
if (requires_scalar_reflect)
{
// FP16/FP64? No templates in HLSL.
statement("float SPIRV_Cross_Reflect(float i, float n)");
statement("float spvReflect(float i, float n)");
begin_scope();
statement("return i - 2.0 * dot(n, i) * n;");
end_scope();
@@ -1857,7 +1856,7 @@ void CompilerHLSL::emit_resources()
if (requires_scalar_refract)
{
// FP16/FP64? No templates in HLSL.
statement("float SPIRV_Cross_Refract(float i, float n, float eta)");
statement("float spvRefract(float i, float n, float eta)");
begin_scope();
statement("float NoI = n * i;");
statement("float NoI2 = NoI * NoI;");
@@ -1877,7 +1876,7 @@ void CompilerHLSL::emit_resources()
if (requires_scalar_faceforward)
{
// FP16/FP64? No templates in HLSL.
statement("float SPIRV_Cross_FaceForward(float n, float i, float nref)");
statement("float spvFaceForward(float n, float i, float nref)");
begin_scope();
statement("return i * nref < 0.0 ? n : -n;");
end_scope();
@@ -1916,7 +1915,7 @@ void CompilerHLSL::emit_texture_size_variants(uint64_t variant_mask, const char
if ((variant_mask & mask) == 0)
continue;
statement(ret_types[index], " SPIRV_Cross_", (uav ? "image" : "texture"), "Size(", (uav ? "RW" : ""),
statement(ret_types[index], " spv", (uav ? "Image" : "Texture"), "Size(", (uav ? "RW" : ""),
dims[index], "<", type_qualifier, types[type_index], vecsize_qualifier, "> Tex, ",
(uav ? "" : "uint Level, "), "out uint Param)");
begin_scope();
@@ -2282,7 +2281,7 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, const Bitset &ret
out_argument += "out ";
out_argument += type_to_glsl(type);
out_argument += " ";
out_argument += "SPIRV_Cross_return_value";
out_argument += "spvReturnValue";
out_argument += type_to_array_glsl(type);
arglist.push_back(move(out_argument));
}
@@ -2996,7 +2995,10 @@ void CompilerHLSL::emit_texture_op(const Instruction &i, bool sparse)
if (dref)
{
if (imgtype.image.dim != spv::Dim1D && imgtype.image.dim != spv::Dim2D)
SPIRV_CROSS_THROW("Depth comparison is only supported for 1D and 2D textures in HLSL shader model 2/3.");
{
SPIRV_CROSS_THROW(
"Depth comparison is only supported for 1D and 2D textures in HLSL shader model 2/3.");
}
if (grad_x || grad_y)
SPIRV_CROSS_THROW("Depth comparison is not supported for grad sampling in HLSL shader model 2/3.");
@@ -3023,8 +3025,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i, bool sparse)
}
else if (proj)
{
coord_expr = "float4(" + coord_expr + ", " +
to_extract_component_expression(coord, coord_components) + ")";
coord_expr = "float4(" + coord_expr + ", " + to_extract_component_expression(coord, coord_components) + ")";
}
else if (dref)
{
@@ -3409,7 +3410,7 @@ string CompilerHLSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &i
requires_explicit_fp16_packing = true;
force_recompile();
}
return "SPIRV_Cross_unpackFloat2x16";
return "spvUnpackFloat2x16";
}
else if (out_type.basetype == SPIRType::UInt && in_type.basetype == SPIRType::Half && in_type.vecsize == 2)
{
@@ -3418,7 +3419,7 @@ string CompilerHLSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &i
requires_explicit_fp16_packing = true;
force_recompile();
}
return "SPIRV_Cross_packFloat2x16";
return "spvPackFloat2x16";
}
else
return "";
@@ -3483,7 +3484,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_fp16_packing = true;
force_recompile();
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_packHalf2x16");
emit_unary_func_op(result_type, id, args[0], "spvPackHalf2x16");
break;
case GLSLstd450UnpackHalf2x16:
@@ -3492,7 +3493,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_fp16_packing = true;
force_recompile();
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackHalf2x16");
emit_unary_func_op(result_type, id, args[0], "spvUnpackHalf2x16");
break;
case GLSLstd450PackSnorm4x8:
@@ -3501,7 +3502,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_snorm8_packing = true;
force_recompile();
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_packSnorm4x8");
emit_unary_func_op(result_type, id, args[0], "spvPackSnorm4x8");
break;
case GLSLstd450UnpackSnorm4x8:
@@ -3510,7 +3511,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_snorm8_packing = true;
force_recompile();
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackSnorm4x8");
emit_unary_func_op(result_type, id, args[0], "spvUnpackSnorm4x8");
break;
case GLSLstd450PackUnorm4x8:
@@ -3519,7 +3520,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_unorm8_packing = true;
force_recompile();
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_packUnorm4x8");
emit_unary_func_op(result_type, id, args[0], "spvPackUnorm4x8");
break;
case GLSLstd450UnpackUnorm4x8:
@@ -3528,7 +3529,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_unorm8_packing = true;
force_recompile();
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackUnorm4x8");
emit_unary_func_op(result_type, id, args[0], "spvUnpackUnorm4x8");
break;
case GLSLstd450PackSnorm2x16:
@@ -3537,7 +3538,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_snorm16_packing = true;
force_recompile();
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_packSnorm2x16");
emit_unary_func_op(result_type, id, args[0], "spvPackSnorm2x16");
break;
case GLSLstd450UnpackSnorm2x16:
@@ -3546,7 +3547,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_snorm16_packing = true;
force_recompile();
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackSnorm2x16");
emit_unary_func_op(result_type, id, args[0], "spvUnpackSnorm2x16");
break;
case GLSLstd450PackUnorm2x16:
@@ -3555,7 +3556,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_unorm16_packing = true;
force_recompile();
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_packUnorm2x16");
emit_unary_func_op(result_type, id, args[0], "spvPackUnorm2x16");
break;
case GLSLstd450UnpackUnorm2x16:
@@ -3564,7 +3565,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_unorm16_packing = true;
force_recompile();
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackUnorm2x16");
emit_unary_func_op(result_type, id, args[0], "spvUnpackUnorm2x16");
break;
case GLSLstd450PackDouble2x32:
@@ -3613,7 +3614,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
force_recompile();
}
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_Inverse");
emit_unary_func_op(result_type, id, args[0], "spvInverse");
break;
}
@@ -3636,7 +3637,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_scalar_reflect = true;
force_recompile();
}
emit_binary_func_op(result_type, id, args[0], args[1], "SPIRV_Cross_Reflect");
emit_binary_func_op(result_type, id, args[0], args[1], "spvReflect");
}
else
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
@@ -3650,7 +3651,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_scalar_refract = true;
force_recompile();
}
emit_trinary_func_op(result_type, id, args[0], args[1], args[2], "SPIRV_Cross_Refract");
emit_trinary_func_op(result_type, id, args[0], args[1], args[2], "spvRefract");
}
else
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
@@ -3664,7 +3665,7 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
requires_scalar_faceforward = true;
force_recompile();
}
emit_trinary_func_op(result_type, id, args[0], args[1], args[2], "SPIRV_Cross_FaceForward");
emit_trinary_func_op(result_type, id, args[0], args[1], args[2], "spvFaceForward");
}
else
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
@@ -4701,9 +4702,9 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
}
if (bitcast_type == CompilerHLSL::TypePackUint2x32)
emit_unary_func_op(ops[0], ops[1], ops[2], "SPIRV_Cross_packUint2x32");
emit_unary_func_op(ops[0], ops[1], ops[2], "spvPackUint2x32");
else
emit_unary_func_op(ops[0], ops[1], ops[2], "SPIRV_Cross_unpackUint2x32");
emit_unary_func_op(ops[0], ops[1], ops[2], "spvUnpackUint2x32");
}
break;
@@ -5088,7 +5089,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
auto dummy_samples_levels = join(get_fallback_name(id), "_dummy_parameter");
statement("uint ", dummy_samples_levels, ";");
auto expr = join("SPIRV_Cross_textureSize(", to_expression(ops[2]), ", ",
auto expr = join("spvTextureSize(", to_expression(ops[2]), ", ",
bitcast_expression(SPIRType::UInt, ops[3]), ", ", dummy_samples_levels, ")");
auto &restype = get<SPIRType>(ops[0]);
@@ -5114,9 +5115,9 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
string expr;
if (uav)
expr = join("SPIRV_Cross_imageSize(", to_expression(ops[2]), ", ", dummy_samples_levels, ")");
expr = join("spvImageSize(", to_expression(ops[2]), ", ", dummy_samples_levels, ")");
else
expr = join("SPIRV_Cross_textureSize(", to_expression(ops[2]), ", 0u, ", dummy_samples_levels, ")");
expr = join("spvTextureSize(", to_expression(ops[2]), ", 0u, ", dummy_samples_levels, ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::UInt, expr);
@@ -5146,9 +5147,9 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
statement(variable_decl(type, to_name(id)), ";");
if (uav)
statement("SPIRV_Cross_imageSize(", to_expression(ops[2]), ", ", to_name(id), ");");
statement("spvImageSize(", to_expression(ops[2]), ", ", to_name(id), ");");
else
statement("SPIRV_Cross_textureSize(", to_expression(ops[2]), ", 0u, ", to_name(id), ");");
statement("spvTextureSize(", to_expression(ops[2]), ", 0u, ", to_name(id), ");");
auto &restype = get<SPIRType>(ops[0]);
auto expr = bitcast_expression(restype, SPIRType::UInt, to_name(id));
@@ -5389,7 +5390,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
force_recompile();
}
auto expr = join("SPIRV_Cross_bitfieldInsert(", to_expression(ops[2]), ", ", to_expression(ops[3]), ", ",
auto expr = join("spvBitfieldInsert(", to_expression(ops[2]), ", ", to_expression(ops[3]), ", ",
to_expression(ops[4]), ", ", to_expression(ops[5]), ")");
bool forward =
@@ -5411,9 +5412,9 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
}
if (opcode == OpBitFieldSExtract)
HLSL_TFOP(SPIRV_Cross_bitfieldSExtract);
HLSL_TFOP(spvBitfieldSExtract);
else
HLSL_TFOP(SPIRV_Cross_bitfieldUExtract);
HLSL_TFOP(spvBitfieldUExtract);
break;
}

File diff suppressed because it is too large Load Diff

View File

@@ -364,6 +364,28 @@ public:
// and will be addressed using the current ViewIndex.
bool arrayed_subpass_input = false;
// Whether to use SIMD-group or quadgroup functions to implement group nnon-uniform
// operations. Some GPUs on iOS do not support the SIMD-group functions, only the
// quadgroup functions.
bool ios_use_simdgroup_functions = false;
// If set, the subgroup size will be assumed to be one, and subgroup-related
// builtins and operations will be emitted accordingly. This mode is intended to
// be used by MoltenVK on hardware/software configurations which do not provide
// sufficient support for subgroups.
bool emulate_subgroups = false;
// If nonzero, a fixed subgroup size to assume. Metal, similarly to VK_EXT_subgroup_size_control,
// allows the SIMD-group size (aka thread execution width) to vary depending on
// register usage and requirements. In certain circumstances--for example, a pipeline
// in MoltenVK without VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT--
// this is undesirable. This fixes the value of the SubgroupSize builtin, instead of
// mapping it to the Metal builtin [[thread_execution_width]]. If the thread
// execution width is reduced, the extra invocations will appear to be inactive.
// If zero, the SubgroupSize will be allowed to vary, and the builtin will be mapped
// to the Metal [[thread_execution_width]] builtin.
uint32_t fixed_subgroup_size = 0;
enum class IndexType
{
None = 0,
@@ -379,6 +401,11 @@ public:
// different shaders for these three scenarios.
IndexType vertex_index_type = IndexType::None;
// If set, a dummy [[sample_id]] input is added to a fragment shader if none is present.
// This will force the shader to run at sample rate, assuming Metal does not optimize
// the extra threads away.
bool force_sample_rate_shading = false;
bool is_ios() const
{
return platform == iOS;
@@ -776,6 +803,7 @@ protected:
std::string to_sampler_expression(uint32_t id);
std::string to_swizzle_expression(uint32_t id);
std::string to_buffer_size_expression(uint32_t id);
bool is_sample_rate() const;
bool is_direct_input_builtin(spv::BuiltIn builtin);
std::string builtin_qualifier(spv::BuiltIn builtin);
std::string builtin_type_decl(spv::BuiltIn builtin, uint32_t id = 0);
@@ -853,6 +881,8 @@ protected:
uint32_t builtin_subgroup_size_id = 0;
uint32_t builtin_dispatch_base_id = 0;
uint32_t builtin_stage_input_size_id = 0;
uint32_t builtin_local_invocation_index_id = 0;
uint32_t builtin_workgroup_size_id = 0;
uint32_t swizzle_buffer_id = 0;
uint32_t buffer_size_buffer_id = 0;
uint32_t view_mask_buffer_id = 0;