mirror of https://github.com/bkaradzic/bgfx
Updated spirv-cross.
This commit is contained in:
parent
8c9826c7a3
commit
c10fd5ed24
|
@ -675,6 +675,7 @@ struct CLIArguments
|
|||
bool msl_force_sample_rate_shading = false;
|
||||
bool msl_manual_helper_invocation_updates = true;
|
||||
bool msl_check_discarded_frag_stores = false;
|
||||
bool msl_sample_dref_lod_array_as_grad = false;
|
||||
const char *msl_combined_sampler_suffix = nullptr;
|
||||
bool glsl_emit_push_constant_as_ubo = false;
|
||||
bool glsl_emit_ubo_as_plain_uniforms = false;
|
||||
|
@ -947,6 +948,10 @@ static void print_help_msl()
|
|||
"\t\tSome Metal devices have a bug where stores to resources from a fragment shader\n"
|
||||
"\t\tcontinue to execute, even when the fragment is discarded. These checks\n"
|
||||
"\t\tprevent these stores from executing.\n"
|
||||
"\t[--msl-sample-dref-lod-array-as-grad]:\n\t\tUse a gradient instead of a level argument.\n"
|
||||
"\t\tSome Metal devices have a bug where the level() argument to\n"
|
||||
"\t\tdepth2d_array<T>::sample_compare() in a fragment shader is biased by some\n"
|
||||
"\t\tunknown amount. This prevents the bias from being added.\n"
|
||||
"\t[--msl-combined-sampler-suffix <suffix>]:\n\t\tUses a custom suffix for combined samplers.\n");
|
||||
// clang-format on
|
||||
}
|
||||
|
@ -1221,6 +1226,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
|
|||
msl_opts.force_sample_rate_shading = args.msl_force_sample_rate_shading;
|
||||
msl_opts.manual_helper_invocation_updates = args.msl_manual_helper_invocation_updates;
|
||||
msl_opts.check_discarded_frag_stores = args.msl_check_discarded_frag_stores;
|
||||
msl_opts.sample_dref_lod_array_as_grad = args.msl_sample_dref_lod_array_as_grad;
|
||||
msl_opts.ios_support_base_vertex_instance = true;
|
||||
msl_comp->set_msl_options(msl_opts);
|
||||
for (auto &v : args.msl_discrete_descriptor_sets)
|
||||
|
@ -1774,6 +1780,8 @@ static int main_inner(int argc, char *argv[])
|
|||
cbs.add("--msl-no-manual-helper-invocation-updates",
|
||||
[&args](CLIParser &) { args.msl_manual_helper_invocation_updates = false; });
|
||||
cbs.add("--msl-check-discarded-frag-stores", [&args](CLIParser &) { args.msl_check_discarded_frag_stores = true; });
|
||||
cbs.add("--msl-sample-dref-lod-array-as-grad",
|
||||
[&args](CLIParser &) { args.msl_sample_dref_lod_array_as_grad = true; });
|
||||
cbs.add("--msl-combined-sampler-suffix", [&args](CLIParser &parser) {
|
||||
args.msl_combined_sampler_suffix = parser.next_string();
|
||||
});
|
||||
|
|
|
@ -738,6 +738,10 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
|
|||
case SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS_TIER:
|
||||
options->msl.argument_buffers_tier = static_cast<CompilerMSL::Options::ArgumentBuffersTier>(value);
|
||||
break;
|
||||
|
||||
case SPVC_COMPILER_OPTION_MSL_SAMPLE_DREF_LOD_ARRAY_AS_GRAD:
|
||||
options->msl.sample_dref_lod_array_as_grad = value != 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
|
|
|
@ -40,7 +40,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 54
|
||||
#define SPVC_C_API_VERSION_MINOR 55
|
||||
/* Bumped if internal implementation details change. */
|
||||
#define SPVC_C_API_VERSION_PATCH 0
|
||||
|
||||
|
@ -724,6 +724,7 @@ typedef enum spvc_compiler_option
|
|||
SPVC_COMPILER_OPTION_GLSL_ENABLE_ROW_MAJOR_LOAD_WORKAROUND = 83 | SPVC_COMPILER_OPTION_GLSL_BIT,
|
||||
|
||||
SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS_TIER = 84 | SPVC_COMPILER_OPTION_MSL_BIT,
|
||||
SPVC_COMPILER_OPTION_MSL_SAMPLE_DREF_LOD_ARRAY_AS_GRAD = 85 | SPVC_COMPILER_OPTION_MSL_BIT,
|
||||
|
||||
SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
|
||||
} spvc_compiler_option;
|
||||
|
|
|
@ -6467,7 +6467,10 @@ void CompilerGLSL::emit_unary_func_op(uint32_t result_type, uint32_t result_id,
|
|||
void CompilerGLSL::emit_binary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1,
|
||||
const char *op)
|
||||
{
|
||||
bool forward = should_forward(op0) && should_forward(op1);
|
||||
// Opaque types (e.g. OpTypeSampledImage) must always be forwarded in GLSL
|
||||
const auto &type = get_type(result_type);
|
||||
bool must_forward = type_is_opaque_value(type);
|
||||
bool forward = must_forward || (should_forward(op0) && should_forward(op1));
|
||||
emit_op(result_type, result_id, join(op, "(", to_unpacked_expression(op0), ", ", to_unpacked_expression(op1), ")"),
|
||||
forward);
|
||||
inherit_expression_dependencies(result_id, op0);
|
||||
|
|
|
@ -3494,9 +3494,9 @@ void CompilerHLSL::emit_texture_op(const Instruction &i, bool sparse)
|
|||
else
|
||||
{
|
||||
auto &imgformat = get<SPIRType>(imgtype.image.type);
|
||||
if (imgformat.basetype != SPIRType::Float)
|
||||
if (hlsl_options.shader_model < 67 && imgformat.basetype != SPIRType::Float)
|
||||
{
|
||||
SPIRV_CROSS_THROW("Sampling non-float textures is not supported in HLSL.");
|
||||
SPIRV_CROSS_THROW("Sampling non-float textures is not supported in HLSL SM < 6.7.");
|
||||
}
|
||||
|
||||
if (hlsl_options.shader_model >= 40)
|
||||
|
|
|
@ -1856,6 +1856,7 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
|
|||
case OpAtomicIIncrement:
|
||||
case OpAtomicIDecrement:
|
||||
case OpAtomicIAdd:
|
||||
case OpAtomicFAddEXT:
|
||||
case OpAtomicISub:
|
||||
case OpAtomicSMin:
|
||||
case OpAtomicUMin:
|
||||
|
@ -7344,6 +7345,15 @@ void CompilerMSL::emit_specialization_constants_and_structs()
|
|||
emitted = false;
|
||||
declared_structs.clear();
|
||||
|
||||
// It is possible to have multiple spec constants that use the same spec constant ID.
|
||||
// The most common cause of this is defining spec constants in GLSL while also declaring
|
||||
// the workgroup size to use those spec constants. But, Metal forbids declaring more than
|
||||
// one variable with the same function constant ID.
|
||||
// In this case, we must only declare one variable with the [[function_constant(id)]]
|
||||
// attribute, and use its initializer to initialize all the spec constants with
|
||||
// that ID.
|
||||
std::unordered_map<uint32_t, ConstantID> unique_func_constants;
|
||||
|
||||
for (auto &id_ : ir.ids_for_constant_undef_or_type)
|
||||
{
|
||||
auto &id = ir.ids[id_];
|
||||
|
@ -7367,7 +7377,11 @@ void CompilerMSL::emit_specialization_constants_and_structs()
|
|||
string sc_type_name = type_to_glsl(type);
|
||||
add_resource_name(c.self);
|
||||
string sc_name = to_name(c.self);
|
||||
string sc_tmp_name = sc_name + "_tmp";
|
||||
uint32_t constant_id = get_decoration(c.self, DecorationSpecId);
|
||||
if (!unique_func_constants.count(constant_id))
|
||||
unique_func_constants.insert(make_pair(constant_id, c.self));
|
||||
SPIRType::BaseType sc_tmp_type = expression_type(unique_func_constants[constant_id]).basetype;
|
||||
string sc_tmp_name = to_name(unique_func_constants[constant_id]) + "_tmp";
|
||||
|
||||
// Function constants are only supported in MSL 1.2 and later.
|
||||
// If we don't support it just declare the "default" directly.
|
||||
|
@ -7377,12 +7391,13 @@ void CompilerMSL::emit_specialization_constants_and_structs()
|
|||
if (msl_options.supports_msl_version(1, 2) && has_decoration(c.self, DecorationSpecId) &&
|
||||
!c.is_used_as_array_length)
|
||||
{
|
||||
uint32_t constant_id = get_decoration(c.self, DecorationSpecId);
|
||||
// Only scalar, non-composite values can be function constants.
|
||||
statement("constant ", sc_type_name, " ", sc_tmp_name, " [[function_constant(", constant_id,
|
||||
")]];");
|
||||
if (unique_func_constants[constant_id] == c.self)
|
||||
statement("constant ", sc_type_name, " ", sc_tmp_name, " [[function_constant(", constant_id,
|
||||
")]];");
|
||||
statement("constant ", sc_type_name, " ", sc_name, " = is_function_constant_defined(", sc_tmp_name,
|
||||
") ? ", sc_tmp_name, " : ", constant_expression(c), ";");
|
||||
") ? ", bitcast_expression(type, sc_tmp_type, sc_tmp_name), " : ", constant_expression(c),
|
||||
";");
|
||||
}
|
||||
else if (has_decoration(c.self, DecorationSpecId))
|
||||
{
|
||||
|
@ -8593,6 +8608,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
|
|||
break;
|
||||
|
||||
case OpAtomicIAdd:
|
||||
case OpAtomicFAddEXT:
|
||||
MSL_AFMO(add);
|
||||
break;
|
||||
|
||||
|
@ -10823,7 +10839,8 @@ string CompilerMSL::to_function_args(const TextureFunctionArguments &args, bool
|
|||
// We will detect a compile-time constant 0 value for gradient and promote that to level(0) on MSL.
|
||||
bool constant_zero_x = !grad_x || expression_is_constant_null(grad_x);
|
||||
bool constant_zero_y = !grad_y || expression_is_constant_null(grad_y);
|
||||
if (constant_zero_x && constant_zero_y)
|
||||
if (constant_zero_x && constant_zero_y &&
|
||||
(!imgtype.image.arrayed || !msl_options.sample_dref_lod_array_as_grad))
|
||||
{
|
||||
lod = 0;
|
||||
grad_x = 0;
|
||||
|
@ -10869,6 +10886,52 @@ string CompilerMSL::to_function_args(const TextureFunctionArguments &args, bool
|
|||
{
|
||||
farg_str += ", " + to_expression(lod);
|
||||
}
|
||||
else if (msl_options.sample_dref_lod_array_as_grad && args.dref && imgtype.image.arrayed)
|
||||
{
|
||||
if (msl_options.is_macos() && !msl_options.supports_msl_version(2, 3))
|
||||
SPIRV_CROSS_THROW("Using non-constant 0.0 gradient() qualifier for sample_compare. This is not "
|
||||
"supported on macOS prior to MSL 2.3.");
|
||||
// Some Metal devices have a bug where the LoD is erroneously biased upward
|
||||
// when using a level() argument. Since this doesn't happen as much with gradient2d(),
|
||||
// if we perform the LoD calculation in reverse, we can pass a gradient
|
||||
// instead.
|
||||
// lod = log2(rhoMax/eta) -> exp2(lod) = rhoMax/eta
|
||||
// If we make all of the scale factors the same, eta will be 1 and
|
||||
// exp2(lod) = rho.
|
||||
// rhoX = dP/dx * extent; rhoY = dP/dy * extent
|
||||
// Therefore, dP/dx = dP/dy = exp2(lod)/extent.
|
||||
// (Subtracting 0.5 before exponentiation gives better results.)
|
||||
string grad_opt, extent;
|
||||
switch (imgtype.image.dim)
|
||||
{
|
||||
case Dim1D:
|
||||
grad_opt = "2d";
|
||||
extent = join("float2(", to_expression(img), ".get_width(), 1.0)");
|
||||
break;
|
||||
case Dim2D:
|
||||
grad_opt = "2d";
|
||||
extent = join("float2(", to_expression(img), ".get_width(), ", to_expression(img), ".get_height())");
|
||||
break;
|
||||
case DimCube:
|
||||
if (imgtype.image.arrayed && msl_options.emulate_cube_array)
|
||||
{
|
||||
grad_opt = "2d";
|
||||
extent = join("float2(", to_expression(img), ".get_width())");
|
||||
}
|
||||
else
|
||||
{
|
||||
grad_opt = "cube";
|
||||
extent = join("float3(", to_expression(img), ".get_width())");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
grad_opt = "unsupported_gradient_dimension";
|
||||
extent = "float3(1.0)";
|
||||
break;
|
||||
}
|
||||
farg_str += join(", gradient", grad_opt, "(exp2(", to_expression(lod), " - 0.5) / ", extent, ", exp2(",
|
||||
to_expression(lod), " - 0.5) / ", extent, ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
farg_str += ", level(" + to_expression(lod) + ")";
|
||||
|
@ -11002,7 +11065,7 @@ string CompilerMSL::to_function_args(const TextureFunctionArguments &args, bool
|
|||
// If the texture coordinates are floating point, invokes MSL round() function to round them.
|
||||
string CompilerMSL::round_fp_tex_coords(string tex_coords, bool coord_is_fp)
|
||||
{
|
||||
return coord_is_fp ? ("round(" + tex_coords + ")") : tex_coords;
|
||||
return coord_is_fp ? ("rint(" + tex_coords + ")") : tex_coords;
|
||||
}
|
||||
|
||||
// Returns a string to use in an image sampling function argument.
|
||||
|
@ -16253,6 +16316,7 @@ bool CompilerMSL::OpCodePreprocessor::handle(Op opcode, const uint32_t *args, ui
|
|||
case OpAtomicIIncrement:
|
||||
case OpAtomicIDecrement:
|
||||
case OpAtomicIAdd:
|
||||
case OpAtomicFAddEXT:
|
||||
case OpAtomicISub:
|
||||
case OpAtomicSMin:
|
||||
case OpAtomicUMin:
|
||||
|
@ -16458,6 +16522,7 @@ CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op o
|
|||
case OpAtomicIIncrement:
|
||||
case OpAtomicIDecrement:
|
||||
case OpAtomicIAdd:
|
||||
case OpAtomicFAddEXT:
|
||||
case OpAtomicISub:
|
||||
case OpAtomicSMin:
|
||||
case OpAtomicUMin:
|
||||
|
|
|
@ -487,6 +487,15 @@ public:
|
|||
// only when the bug is present.
|
||||
bool check_discarded_frag_stores = false;
|
||||
|
||||
// If set, Lod operands to OpImageSample*DrefExplicitLod for 1D and 2D array images
|
||||
// will be implemented using a gradient instead of passing the level operand directly.
|
||||
// Some Metal devices have a bug where the level() argument to depth2d_array<T>::sample_compare()
|
||||
// in a fragment shader is biased by some unknown amount, possibly dependent on the
|
||||
// partial derivatives of the texture coordinates. This is a workaround that is only
|
||||
// expected to be needed until the bug is fixed in Metal; it is provided as an option
|
||||
// so it can be enabled only when the bug is present.
|
||||
bool sample_dref_lod_array_as_grad = false;
|
||||
|
||||
bool is_ios() const
|
||||
{
|
||||
return platform == iOS;
|
||||
|
|
Loading…
Reference in New Issue