Updated spirv-cross.

This commit is contained in:
Бранимир Караџић 2020-04-04 18:56:27 -07:00
parent 6a0b5b5b5c
commit b249692519
8 changed files with 117 additions and 18 deletions

View File

@ -277,6 +277,8 @@ static void print_resources(const Compiler &compiler, const char *tag, const Sma
fprintf(stderr, " (Set : %u)", compiler.get_decoration(res.id, DecorationDescriptorSet));
if (mask.get(DecorationBinding))
fprintf(stderr, " (Binding : %u)", compiler.get_decoration(res.id, DecorationBinding));
if (static_cast<const CompilerGLSL &>(compiler).variable_is_depth_or_compare(res.id))
fprintf(stderr, " (comparison)");
if (mask.get(DecorationInputAttachmentIndex))
fprintf(stderr, " (Attachment : %u)", compiler.get_decoration(res.id, DecorationInputAttachmentIndex));
if (mask.get(DecorationNonReadable))
@ -560,6 +562,7 @@ struct CLIArguments
bool hlsl_compat = false;
bool hlsl_support_nonzero_base = false;
bool hlsl_force_storage_buffer_as_uav = false;
bool hlsl_nonwritable_uav_texture_as_srv = false;
HLSLBindingFlags hlsl_binding_flags = 0;
bool vulkan_semantics = false;
bool flatten_multidimensional_arrays = false;
@ -632,6 +635,7 @@ static void print_help()
"\t[--hlsl-support-nonzero-basevertex-baseinstance]\n"
"\t[--hlsl-auto-binding (push, cbv, srv, uav, sampler, all)]\n"
"\t[--hlsl-force-storage-buffer-as-uav]\n"
"\t[--hlsl-nonwritable-uav-texture-as-srv]\n"
"\t[--separate-shader-objects]\n"
"\t[--pls-in format input-name]\n"
"\t[--pls-out format output-name]\n"
@ -988,6 +992,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
hlsl_opts.support_nonzero_base_vertex_base_instance = args.hlsl_support_nonzero_base;
hlsl_opts.force_storage_buffer_as_uav = args.hlsl_force_storage_buffer_as_uav;
hlsl_opts.nonwritable_uav_texture_as_srv = args.hlsl_nonwritable_uav_texture_as_srv;
hlsl->set_hlsl_options(hlsl_opts);
hlsl->set_resource_binding_flags(args.hlsl_binding_flags);
}
@ -1053,14 +1058,6 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
}
}
if (args.dump_resources)
{
print_resources(*compiler, res);
print_push_constant_resources(*compiler, res.push_constant_buffers);
print_spec_constants(*compiler);
print_capabilities_and_extensions(*compiler);
}
if (combined_image_samplers)
{
compiler->build_combined_image_samplers();
@ -1092,7 +1089,17 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
static_cast<CompilerHLSL *>(compiler.get())->add_vertex_attribute_remap(remap);
}
return compiler->compile();
auto ret = compiler->compile();
if (args.dump_resources)
{
print_resources(*compiler, res);
print_push_constant_resources(*compiler, res.push_constant_buffers);
print_spec_constants(*compiler);
print_capabilities_and_extensions(*compiler);
}
return ret;
}
static int main_inner(int argc, char *argv[])
@ -1154,6 +1161,8 @@ static int main_inner(int argc, char *argv[])
});
cbs.add("--hlsl-force-storage-buffer-as-uav",
[&args](CLIParser &) { args.hlsl_force_storage_buffer_as_uav = true; });
cbs.add("--hlsl-nonwritable-uav-texture-as-srv",
[&args](CLIParser &) { args.hlsl_nonwritable_uav_texture_as_srv = 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; });

View File

@ -481,6 +481,10 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
case SPVC_COMPILER_OPTION_HLSL_FORCE_STORAGE_BUFFER_AS_UAV:
options->hlsl.force_storage_buffer_as_uav = value != 0;
break;
case SPVC_COMPILER_OPTION_HLSL_NONWRITABLE_UAV_TEXTURE_AS_SRV:
options->hlsl.nonwritable_uav_texture_as_srv = value != 0;
break;
#endif
#if SPIRV_CROSS_C_API_MSL
@ -707,6 +711,23 @@ spvc_result spvc_compiler_flatten_buffer_block(spvc_compiler compiler, spvc_vari
#endif
}
spvc_bool spvc_compiler_variable_is_depth_or_compare(spvc_compiler compiler, spvc_variable_id id)
{
#if SPIRV_CROSS_C_API_GLSL
if (compiler->backend == SPVC_BACKEND_NONE)
{
compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
return SPVC_ERROR_INVALID_ARGUMENT;
}
return static_cast<CompilerGLSL *>(compiler->compiler.get())->variable_is_depth_or_compare(id) ? SPVC_TRUE : SPVC_FALSE;
#else
(void)id;
compiler->context->report_error("Cross-compilation related option used on NONE backend which only supports reflection.");
return SPVC_FALSE;
#endif
}
spvc_result spvc_compiler_hlsl_set_root_constants_layout(spvc_compiler compiler,
const spvc_hlsl_root_constants *constant_info,
size_t count)

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 28
#define SPVC_C_API_VERSION_MINOR 30
/* Bumped if internal implementation details change. */
#define SPVC_C_API_VERSION_PATCH 0
@ -580,6 +580,8 @@ typedef enum spvc_compiler_option
SPVC_COMPILER_OPTION_FORCE_ZERO_INITIALIZED_VARIABLES = 54 | SPVC_COMPILER_OPTION_COMMON_BIT,
SPVC_COMPILER_OPTION_HLSL_NONWRITABLE_UAV_TEXTURE_AS_SRV = 55 | SPVC_COMPILER_OPTION_HLSL_BIT,
SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
} spvc_compiler_option;
@ -640,6 +642,8 @@ SPVC_PUBLIC_API spvc_result spvc_compiler_add_header_line(spvc_compiler compiler
SPVC_PUBLIC_API spvc_result spvc_compiler_require_extension(spvc_compiler compiler, const char *ext);
SPVC_PUBLIC_API spvc_result spvc_compiler_flatten_buffer_block(spvc_compiler compiler, spvc_variable_id id);
SPVC_PUBLIC_API spvc_bool spvc_compiler_variable_is_depth_or_compare(spvc_compiler compiler, spvc_variable_id id);
/*
* HLSL specifics.
* Maps to C++ API.

View File

@ -2543,7 +2543,7 @@ void CompilerGLSL::fixup_image_load_store_access()
ir.for_each_typed_id<SPIRVariable>([&](uint32_t var, const SPIRVariable &) {
auto &vartype = expression_type(var);
if (vartype.basetype == SPIRType::Image)
if (vartype.basetype == SPIRType::Image && vartype.image.sampled == 2)
{
// Very old glslangValidator and HLSL compilers do not emit required qualifiers here.
// Solve this by making the image access as restricted as possible and loosen up if we need to.
@ -13702,3 +13702,8 @@ void CompilerGLSL::emit_inout_fragment_outputs_copy_to_subpass_inputs()
});
}
}
bool CompilerGLSL::variable_is_depth_or_compare(VariableID id) const
{
return image_is_comparison(get<SPIRType>(get<SPIRVariable>(id).basetype), id);
}

View File

@ -228,6 +228,14 @@ public:
// The name of the uniform array will be the same as the interface block name.
void flatten_buffer_block(VariableID id);
// After compilation, query if a variable ID was used as a depth resource.
// This is meaningful for MSL since descriptor types depend on this knowledge.
// Cases which return true:
// - Images which are declared with depth = 1 image type.
// - Samplers which are statically used at least once with Dref opcodes.
// - Images which are statically used at least once with Dref opcodes.
bool variable_is_depth_or_compare(VariableID id) const;
protected:
void reset();
void emit_function(SPIRFunction &func, const Bitset &return_flags);

View File

@ -210,6 +210,8 @@ string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type, uint32_t id)
bool typed_load = false;
uint32_t components = 4;
bool force_image_srv = hlsl_options.nonwritable_uav_texture_as_srv && has_decoration(id, DecorationNonWritable);
switch (type.image.dim)
{
case Dim1D:
@ -239,7 +241,14 @@ string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type, uint32_t id)
if (interlocked_resources.count(id))
return join("RasterizerOrderedBuffer<", image_format_to_type(type.image.format, imagetype.basetype),
">");
return join("RWBuffer<", image_format_to_type(type.image.format, imagetype.basetype), ">");
typed_load = !force_image_srv && type.image.sampled == 2;
const char *rw = force_image_srv ? "" : "RW";
return join(rw, "Buffer<",
typed_load ? image_format_to_type(type.image.format, imagetype.basetype) :
join(type_to_glsl(imagetype), components),
">");
}
else
SPIRV_CROSS_THROW("Sampler buffers must be either sampled or unsampled. Cannot deduce in runtime.");
@ -252,9 +261,14 @@ string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type, uint32_t id)
}
const char *arrayed = type.image.arrayed ? "Array" : "";
const char *ms = type.image.ms ? "MS" : "";
const char *rw = typed_load ? "RW" : "";
const char *rw = typed_load && !force_image_srv ? "RW" : "";
if (force_image_srv)
typed_load = false;
if (typed_load && interlocked_resources.count(id))
rw = "RasterizerOrdered";
return join(rw, "Texture", dim, ms, arrayed, "<",
typed_load ? image_format_to_type(type.image.format, imagetype.basetype) :
join(type_to_glsl(imagetype), components),
@ -2971,8 +2985,16 @@ string CompilerHLSL::to_resource_binding(const SPIRVariable &var)
case SPIRType::Image:
if (type.image.sampled == 2 && type.image.dim != DimSubpassData)
{
space = 'u'; // UAV
resource_flags = HLSL_BINDING_AUTO_UAV_BIT;
if (has_decoration(var.self, DecorationNonWritable) && hlsl_options.nonwritable_uav_texture_as_srv)
{
space = 't'; // SRV
resource_flags = HLSL_BINDING_AUTO_SRV_BIT;
}
else
{
space = 'u'; // UAV
resource_flags = HLSL_BINDING_AUTO_UAV_BIT;
}
}
else
{
@ -4813,7 +4835,12 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
imgexpr = join(to_expression(ops[2]), "[", to_expression(ops[3]), "]");
// The underlying image type in HLSL depends on the image format, unlike GLSL, where all images are "vec4",
// except that the underlying type changes how the data is interpreted.
if (var && !subpass_data)
bool force_srv =
hlsl_options.nonwritable_uav_texture_as_srv && var && has_decoration(var->self, DecorationNonWritable);
pure = force_srv;
if (var && !subpass_data && !force_srv)
imgexpr = remap_swizzle(get<SPIRType>(result_type),
image_format_to_components(get<SPIRType>(var->basetype).image.format), imgexpr);
}

View File

@ -113,6 +113,11 @@ public:
// Forces a storage buffer to always be declared as UAV, even if the readonly decoration is used.
// By default, a readonly storage buffer will be declared as ByteAddressBuffer (SRV) instead.
bool force_storage_buffer_as_uav = false;
// Forces any storage image type marked as NonWritable to be considered an SRV instead.
// For this to work with function call parameters, NonWritable must be considered to be part of the type system
// so that NonWritable image arguments are also translated to Texture rather than RWTexture.
bool nonwritable_uav_texture_as_srv = false;
};
explicit CompilerHLSL(std::vector<uint32_t> spirv_)

View File

@ -174,6 +174,7 @@ void CompilerMSL::build_implicit_builtins()
if (need_subpass_input && (!msl_options.is_ios() || !msl_options.ios_use_framebuffer_fetch_subpasses) &&
builtin == BuiltInFragCoord)
{
mark_implicit_builtin(StorageClassInput, BuiltInFragCoord, var.self);
builtin_frag_coord_id = var.self;
has_frag_coord = true;
}
@ -181,6 +182,7 @@ void CompilerMSL::build_implicit_builtins()
if (need_sample_pos && builtin == BuiltInSampleId)
{
builtin_sample_id_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInSampleId, var.self);
has_sample_id = true;
}
@ -190,18 +192,22 @@ void CompilerMSL::build_implicit_builtins()
{
case BuiltInVertexIndex:
builtin_vertex_idx_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInVertexIndex, var.self);
has_vertex_idx = true;
break;
case BuiltInBaseVertex:
builtin_base_vertex_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInBaseVertex, var.self);
has_base_vertex = true;
break;
case BuiltInInstanceIndex:
builtin_instance_idx_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInInstanceIndex, var.self);
has_instance_idx = true;
break;
case BuiltInBaseInstance:
builtin_base_instance_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInBaseInstance, var.self);
has_base_instance = true;
break;
default:
@ -215,10 +221,12 @@ void CompilerMSL::build_implicit_builtins()
{
case BuiltInInvocationId:
builtin_invocation_id_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInInvocationId, var.self);
has_invocation_id = true;
break;
case BuiltInPrimitiveId:
builtin_primitive_id_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInPrimitiveId, var.self);
has_primitive_id = true;
break;
default:
@ -229,12 +237,14 @@ void CompilerMSL::build_implicit_builtins()
if ((need_subgroup_mask || needs_subgroup_invocation_id) && builtin == BuiltInSubgroupLocalInvocationId)
{
builtin_subgroup_invocation_id_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInSubgroupLocalInvocationId, var.self);
has_subgroup_invocation_id = true;
}
if (need_subgroup_ge_mask && builtin == BuiltInSubgroupSize)
{
builtin_subgroup_size_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInSubgroupSize, var.self);
has_subgroup_size = true;
}
@ -245,10 +255,12 @@ void CompilerMSL::build_implicit_builtins()
case BuiltInInstanceIndex:
// The view index here is derived from the instance index.
builtin_instance_idx_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInInstanceIndex, var.self);
has_instance_idx = true;
break;
case BuiltInViewIndex:
builtin_view_idx_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInViewIndex, var.self);
has_view_idx = true;
break;
default:
@ -645,7 +657,10 @@ void CompilerMSL::mark_implicit_builtin(StorageClass storage, BuiltIn builtin, u
assert(active_builtins != nullptr);
active_builtins->set(builtin);
get_entry_point().interface_variables.push_back(id);
auto &var = get_entry_point().interface_variables;
if (find(begin(var), end(var), VariableID(id)) == end(var))
var.push_back(id);
}
uint32_t CompilerMSL::build_constant_uint_array_pointer()
@ -10505,7 +10520,12 @@ string CompilerMSL::to_member_reference(uint32_t base, const SPIRType &type, uin
if (var)
{
bool is_buffer_variable = var->storage == StorageClassUniform || var->storage == StorageClassStorageBuffer;
// Only allow -> dereference for block types. This is so we get expressions like
// buffer[i]->first_member.second_member, rather than buffer[i]->first->second.
bool is_block = has_decoration(type.self, DecorationBlock) || has_decoration(type.self, DecorationBufferBlock);
bool is_buffer_variable =
is_block && (var->storage == StorageClassUniform || var->storage == StorageClassStorageBuffer);
declared_as_pointer = is_buffer_variable && is_array(get<SPIRType>(var->basetype));
}