Support array of images and samplers in MSL.

This commit is contained in:
Hans-Kristian Arntzen 2018-04-03 14:00:34 +02:00
parent 81eb72a9a0
commit 5827dd54ea
2 changed files with 68 additions and 13 deletions

View File

@ -2292,7 +2292,11 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &)
// Manufacture automatic sampler arg for SampledImage texture // Manufacture automatic sampler arg for SampledImage texture
auto &arg_type = get<SPIRType>(arg.type); auto &arg_type = get<SPIRType>(arg.type);
if (arg_type.basetype == SPIRType::SampledImage && arg_type.image.dim != DimBuffer) if (arg_type.basetype == SPIRType::SampledImage && arg_type.image.dim != DimBuffer)
decl += ", thread const sampler& " + to_sampler_expression(arg.id); {
//const char *reference = arg_type.array.empty() ? "& " : " ";
const char *reference = " ";
decl += join(", thread const ", sampler_type(arg_type), reference, to_sampler_expression(arg.id));
}
if (&arg != &func.arguments.back()) if (&arg != &func.arguments.back())
decl += ", "; decl += ", ";
@ -2594,14 +2598,9 @@ string CompilerMSL::to_func_call_arg(uint32_t id)
string arg_str = CompilerGLSL::to_func_call_arg(id); string arg_str = CompilerGLSL::to_func_call_arg(id);
// Manufacture automatic sampler arg if the arg is a SampledImage texture. // Manufacture automatic sampler arg if the arg is a SampledImage texture.
Variant &id_v = ids[id]; auto &type = expression_type(id);
if (id_v.get_type() == TypeVariable) if (type.basetype == SPIRType::SampledImage && type.image.dim != DimBuffer)
{ arg_str += ", " + to_sampler_expression(id);
auto &var = id_v.get<SPIRVariable>();
auto &type = get<SPIRType>(var.basetype);
if (type.basetype == SPIRType::SampledImage && type.image.dim != DimBuffer)
arg_str += ", " + to_sampler_expression(id);
}
return arg_str; return arg_str;
} }
@ -2611,8 +2610,18 @@ string CompilerMSL::to_func_call_arg(uint32_t id)
// by appending a suffix to the expression constructed from the ID. // by appending a suffix to the expression constructed from the ID.
string CompilerMSL::to_sampler_expression(uint32_t id) string CompilerMSL::to_sampler_expression(uint32_t id)
{ {
auto expr = to_expression(id);
auto index = expr.find_first_of('[');
uint32_t samp_id = meta[id].sampler; uint32_t samp_id = meta[id].sampler;
return samp_id ? to_expression(samp_id) : to_expression(id) + sampler_name_suffix;
if (index == string::npos)
return samp_id ? to_expression(samp_id) : expr + sampler_name_suffix;
else
{
auto image_expr = expr.substr(0, index);
auto array_expr = expr.substr(index);
return samp_id ? to_expression(samp_id) : (image_expr + sampler_name_suffix + array_expr);
}
} }
// Checks whether the ID is a row_major matrix that requires conversion before use // Checks whether the ID is a row_major matrix that requires conversion before use
@ -3110,7 +3119,7 @@ string CompilerMSL::entry_point_args(bool append_comma)
case SPIRType::Sampler: case SPIRType::Sampler:
if (!ep_args.empty()) if (!ep_args.empty())
ep_args += ", "; ep_args += ", ";
ep_args += "sampler " + r.name; ep_args += type_to_glsl(type) + " " + 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:
@ -3215,6 +3224,15 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
auto &type = expression_type(arg.id); auto &type = expression_type(arg.id);
bool constref = !arg.alias_global_variable && (!type.pointer || arg.write_count == 0); bool constref = !arg.alias_global_variable && (!type.pointer || arg.write_count == 0);
bool type_is_image =
type.basetype == SPIRType::Image ||
type.basetype == SPIRType::SampledImage ||
type.basetype == SPIRType::Sampler;
// Arrays of images/samplers in MSL are always const.
if (!type.array.empty() && type_is_image)
constref = true;
// TODO: Check if this arg is an uniform pointer // TODO: Check if this arg is an uniform pointer
bool pointer = type.storage == StorageClassUniformConstant; bool pointer = type.storage == StorageClassUniformConstant;
@ -3227,7 +3245,8 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
else else
decl += type_to_glsl(type, arg.id); decl += type_to_glsl(type, arg.id);
if (is_array(type)) // Arrays of images and samplers are special cased.
if (is_array(type) && !type_is_image)
{ {
decl += " (&"; decl += " (&";
decl += to_expression(var.self); decl += to_expression(var.self);
@ -3383,7 +3402,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"; return sampler_type(type);
case SPIRType::Void: case SPIRType::Void:
return "void"; return "void";
@ -3435,9 +3454,44 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id)
return type_name; return type_name;
} }
std::string CompilerMSL::sampler_type(const SPIRType &type)
{
if (!type.array.empty())
{
// Arrays of samplers in MSL must be declared with a special array<T, N> syntax ala C++11 std::array.
auto *parent = &type;
while (parent->pointer)
parent = &get<SPIRType>(parent->parent_type);
parent = &get<SPIRType>(parent->parent_type);
uint32_t array_size = type.array_size_literal.back() ?
type.array.back() : get<SPIRConstant>(type.array.back()).scalar();
if (array_size == 0)
SPIRV_CROSS_THROW("Unsized array of samplers is not supported in MSL.");
return join("array<", sampler_type(*parent), ", ", array_size, ">");
}
else
return "sampler";
}
// Returns an MSL string describing the SPIR-V image type // Returns an MSL string describing the SPIR-V image type
string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id) string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
{ {
if (!type.array.empty())
{
// Arrays of images in MSL must be declared with a special array<T, N> syntax ala C++11 std::array.
auto *parent = &type;
while (parent->pointer)
parent = &get<SPIRType>(parent->parent_type);
parent = &get<SPIRType>(parent->parent_type);
uint32_t array_size = type.array_size_literal.back() ? type.array.back() : get<SPIRConstant>(type.array.back()).scalar();
if (array_size == 0)
SPIRV_CROSS_THROW("Unsized array of images is not supported in MSL.");
return join("array<", image_type_glsl(*parent, id), ", ", array_size, ">");
}
string img_type_name; string img_type_name;
// Bypass pointers because we need the real image struct // Bypass pointers because we need the real image struct

View File

@ -202,6 +202,7 @@ protected:
const std::string &qualifier = "", uint32_t base_offset = 0) override; const std::string &qualifier = "", uint32_t base_offset = 0) override;
std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override; std::string type_to_glsl(const SPIRType &type, 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 builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override; std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;
std::string constant_expression(const SPIRConstant &c) override; std::string constant_expression(const SPIRConstant &c) override;
size_t get_declared_struct_member_size(const SPIRType &struct_type, uint32_t index) const override; size_t get_declared_struct_member_size(const SPIRType &struct_type, uint32_t index) const override;