Merge pull request #1516 from billhollings/VK_EXT_descriptor_indexing
MSL: Support run-time sized image and sampler arrays
This commit is contained in:
commit
244839d350
@ -10024,12 +10024,22 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
|||||||
bool pointer = get<SPIRType>(result_type).pointer;
|
bool pointer = get<SPIRType>(result_type).pointer;
|
||||||
|
|
||||||
auto *chain = maybe_get<SPIRAccessChain>(rhs);
|
auto *chain = maybe_get<SPIRAccessChain>(rhs);
|
||||||
|
auto *imgsamp = maybe_get<SPIRCombinedImageSampler>(rhs);
|
||||||
if (chain)
|
if (chain)
|
||||||
{
|
{
|
||||||
// Cannot lower to a SPIRExpression, just copy the object.
|
// Cannot lower to a SPIRExpression, just copy the object.
|
||||||
auto &e = set<SPIRAccessChain>(id, *chain);
|
auto &e = set<SPIRAccessChain>(id, *chain);
|
||||||
e.self = id;
|
e.self = id;
|
||||||
}
|
}
|
||||||
|
else if (imgsamp)
|
||||||
|
{
|
||||||
|
// Cannot lower to a SPIRExpression, just copy the object.
|
||||||
|
// GLSL does not currently use this type and will never get here, but MSL does.
|
||||||
|
// Handled here instead of CompilerMSL for better integration and general handling,
|
||||||
|
// and in case GLSL or other subclasses require it in the future.
|
||||||
|
auto &e = set<SPIRCombinedImageSampler>(id, *imgsamp);
|
||||||
|
e.self = id;
|
||||||
|
}
|
||||||
else if (expression_is_lvalue(rhs) && !pointer)
|
else if (expression_is_lvalue(rhs) && !pointer)
|
||||||
{
|
{
|
||||||
// Need a copy.
|
// Need a copy.
|
||||||
|
@ -103,6 +103,16 @@ bool CompilerMSL::is_msl_resource_binding_used(ExecutionModel model, uint32_t de
|
|||||||
return itr != end(resource_bindings) && itr->second.second;
|
return itr != end(resource_bindings) && itr->second.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the size of the array of resources used by the variable with the specified id.
|
||||||
|
// The returned value is retrieved from the resource binding added using add_msl_resource_binding().
|
||||||
|
uint32_t CompilerMSL::get_resource_array_size(uint32_t id) const
|
||||||
|
{
|
||||||
|
StageSetBinding tuple = { get_entry_point().model, get_decoration(id, DecorationDescriptorSet),
|
||||||
|
get_decoration(id, DecorationBinding) };
|
||||||
|
auto itr = resource_bindings.find(tuple);
|
||||||
|
return itr != end(resource_bindings) ? itr->second.first.count : 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t CompilerMSL::get_automatic_msl_resource_binding(uint32_t id) const
|
uint32_t CompilerMSL::get_automatic_msl_resource_binding(uint32_t id) const
|
||||||
{
|
{
|
||||||
return get_extended_decoration(id, SPIRVCrossDecorationResourceIndexPrimary);
|
return get_extended_decoration(id, SPIRVCrossDecorationResourceIndexPrimary);
|
||||||
@ -8136,7 +8146,7 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &)
|
|||||||
|
|
||||||
// Manufacture automatic sampler arg for SampledImage texture
|
// Manufacture automatic sampler arg for SampledImage texture
|
||||||
if (arg_type.image.dim != DimBuffer)
|
if (arg_type.image.dim != DimBuffer)
|
||||||
decl += join(", thread const ", sampler_type(arg_type), " ", to_sampler_expression(arg.id));
|
decl += join(", thread const ", sampler_type(arg_type, arg.id), " ", to_sampler_expression(arg.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manufacture automatic swizzle arg.
|
// Manufacture automatic swizzle arg.
|
||||||
@ -10449,7 +10459,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
|
|||||||
case SPIRType::Sampler:
|
case SPIRType::Sampler:
|
||||||
if (!ep_args.empty())
|
if (!ep_args.empty())
|
||||||
ep_args += ", ";
|
ep_args += ", ";
|
||||||
ep_args += sampler_type(type) + " " + r.name;
|
ep_args += sampler_type(type, var_id) + " " + r.name;
|
||||||
ep_args += " [[sampler(" + convert_to_string(r.index) + ")]]";
|
ep_args += " [[sampler(" + convert_to_string(r.index) + ")]]";
|
||||||
break;
|
break;
|
||||||
case SPIRType::Image:
|
case SPIRType::Image:
|
||||||
@ -11709,7 +11719,7 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id)
|
|||||||
return image_type_glsl(type, id);
|
return image_type_glsl(type, id);
|
||||||
|
|
||||||
case SPIRType::Sampler:
|
case SPIRType::Sampler:
|
||||||
return sampler_type(type);
|
return sampler_type(type, id);
|
||||||
|
|
||||||
case SPIRType::Void:
|
case SPIRType::Void:
|
||||||
return "void";
|
return "void";
|
||||||
@ -11840,8 +11850,15 @@ std::string CompilerMSL::variable_decl(const SPIRType &type, const std::string &
|
|||||||
return CompilerGLSL::variable_decl(type, name, id);
|
return CompilerGLSL::variable_decl(type, name, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CompilerMSL::sampler_type(const SPIRType &type)
|
std::string CompilerMSL::sampler_type(const SPIRType &type, uint32_t id)
|
||||||
{
|
{
|
||||||
|
auto *var = maybe_get<SPIRVariable>(id);
|
||||||
|
if (var && var->basevariable)
|
||||||
|
{
|
||||||
|
// Check against the base variable, and not a fake ID which might have been generated for this variable.
|
||||||
|
id = var->basevariable;
|
||||||
|
}
|
||||||
|
|
||||||
if (!type.array.empty())
|
if (!type.array.empty())
|
||||||
{
|
{
|
||||||
if (!msl_options.supports_msl_version(2))
|
if (!msl_options.supports_msl_version(2))
|
||||||
@ -11851,12 +11868,16 @@ std::string CompilerMSL::sampler_type(const SPIRType &type)
|
|||||||
SPIRV_CROSS_THROW("Arrays of arrays of samplers are not supported in MSL.");
|
SPIRV_CROSS_THROW("Arrays of arrays of samplers are not supported in MSL.");
|
||||||
|
|
||||||
// Arrays of samplers in MSL must be declared with a special array<T, N> syntax ala C++11 std::array.
|
// Arrays of samplers in MSL must be declared with a special array<T, N> syntax ala C++11 std::array.
|
||||||
|
// If we have a runtime array, it could be a variable-count descriptor set binding.
|
||||||
uint32_t array_size = to_array_size_literal(type);
|
uint32_t array_size = to_array_size_literal(type);
|
||||||
|
if (array_size == 0)
|
||||||
|
array_size = get_resource_array_size(id);
|
||||||
|
|
||||||
if (array_size == 0)
|
if (array_size == 0)
|
||||||
SPIRV_CROSS_THROW("Unsized array of samplers is not supported in MSL.");
|
SPIRV_CROSS_THROW("Unsized array of samplers is not supported in MSL.");
|
||||||
|
|
||||||
auto &parent = get<SPIRType>(get_pointee_type(type).parent_type);
|
auto &parent = get<SPIRType>(get_pointee_type(type).parent_type);
|
||||||
return join("array<", sampler_type(parent), ", ", array_size, ">");
|
return join("array<", sampler_type(parent, id), ", ", array_size, ">");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return "sampler";
|
return "sampler";
|
||||||
@ -11893,7 +11914,11 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
|
|||||||
SPIRV_CROSS_THROW("Arrays of arrays of textures are not supported in MSL.");
|
SPIRV_CROSS_THROW("Arrays of arrays of textures are not supported in MSL.");
|
||||||
|
|
||||||
// Arrays of images in MSL must be declared with a special array<T, N> syntax ala C++11 std::array.
|
// Arrays of images in MSL must be declared with a special array<T, N> syntax ala C++11 std::array.
|
||||||
|
// If we have a runtime array, it could be a variable-count descriptor set binding.
|
||||||
uint32_t array_size = to_array_size_literal(type);
|
uint32_t array_size = to_array_size_literal(type);
|
||||||
|
if (array_size == 0)
|
||||||
|
array_size = get_resource_array_size(id);
|
||||||
|
|
||||||
if (array_size == 0)
|
if (array_size == 0)
|
||||||
SPIRV_CROSS_THROW("Unsized array of images is not supported in MSL.");
|
SPIRV_CROSS_THROW("Unsized array of images is not supported in MSL.");
|
||||||
|
|
||||||
|
@ -60,7 +60,11 @@ struct MSLShaderInput
|
|||||||
|
|
||||||
// Matches the binding index of a MSL resource for a binding within a descriptor set.
|
// Matches the binding index of a MSL resource for a binding within a descriptor set.
|
||||||
// Taken together, the stage, desc_set and binding combine to form a reference to a resource
|
// Taken together, the stage, desc_set and binding combine to form a reference to a resource
|
||||||
// descriptor used in a particular shading stage.
|
// descriptor used in a particular shading stage. The count field indicates the number of
|
||||||
|
// resources consumed by this binding, if the binding represents an array of resources.
|
||||||
|
// If the resource array is a run-time-sized array, which are legal in GLSL or SPIR-V, this value
|
||||||
|
// will be used to declare the array size in MSL, which does not support run-time-sized arrays.
|
||||||
|
// For resources that are not held in a run-time-sized array, the count field does not need to be populated.
|
||||||
// If using MSL 2.0 argument buffers, the descriptor set is not marked as a discrete descriptor set,
|
// If using MSL 2.0 argument buffers, the descriptor set is not marked as a discrete descriptor set,
|
||||||
// and (for iOS only) the resource is not a storage image (sampled != 2), the binding reference we
|
// and (for iOS only) the resource is not a storage image (sampled != 2), the binding reference we
|
||||||
// remap to will become an [[id(N)]] attribute within the "descriptor set" argument buffer structure.
|
// remap to will become an [[id(N)]] attribute within the "descriptor set" argument buffer structure.
|
||||||
@ -71,6 +75,7 @@ struct MSLResourceBinding
|
|||||||
spv::ExecutionModel stage = spv::ExecutionModelMax;
|
spv::ExecutionModel stage = spv::ExecutionModelMax;
|
||||||
uint32_t desc_set = 0;
|
uint32_t desc_set = 0;
|
||||||
uint32_t binding = 0;
|
uint32_t binding = 0;
|
||||||
|
uint32_t count = 0;
|
||||||
uint32_t msl_buffer = 0;
|
uint32_t msl_buffer = 0;
|
||||||
uint32_t msl_texture = 0;
|
uint32_t msl_texture = 0;
|
||||||
uint32_t msl_sampler = 0;
|
uint32_t msl_sampler = 0;
|
||||||
@ -672,7 +677,7 @@ protected:
|
|||||||
std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id = 0) override;
|
std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id = 0) override;
|
||||||
|
|
||||||
std::string image_type_glsl(const SPIRType &type, uint32_t id = 0) override;
|
std::string image_type_glsl(const SPIRType &type, uint32_t id = 0) override;
|
||||||
std::string sampler_type(const SPIRType &type);
|
std::string sampler_type(const SPIRType &type, uint32_t id);
|
||||||
std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;
|
std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;
|
||||||
std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id) override;
|
std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id) override;
|
||||||
std::string to_name(uint32_t id, bool allow_alias = true) const override;
|
std::string to_name(uint32_t id, bool allow_alias = true) const override;
|
||||||
@ -756,6 +761,7 @@ protected:
|
|||||||
void emit_specialization_constants_and_structs();
|
void emit_specialization_constants_and_structs();
|
||||||
void emit_interface_block(uint32_t ib_var_id);
|
void emit_interface_block(uint32_t ib_var_id);
|
||||||
bool maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs);
|
bool maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs);
|
||||||
|
uint32_t get_resource_array_size(uint32_t id) const;
|
||||||
|
|
||||||
void fix_up_shader_inputs_outputs();
|
void fix_up_shader_inputs_outputs();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user