Added a new 'emulate_cube_array' option to SPIRV-Cross to cope with translating TextureCubeArray into texture2d_array for iOS where this type is not available. (Original Author: Mark Satterthwaite)

This commit is contained in:
Lukas Hermanns 2019-09-13 17:24:27 -04:00
parent 9573faa56d
commit 7cf5d4f7a1
2 changed files with 160 additions and 87 deletions

View File

@ -980,14 +980,22 @@ void CompilerMSL::preprocess_op_codes()
}
/* UE Change Begin: Allow Metal to use the array<T> template to make arrays a value type */
// UnsafeArray
{
if (msl_options.invariant_float_math)
{
add_header_line("template <typename T> T fmul(T l, T r) { return metal::fma(l, r, T(0)); }");
add_header_line("template <typename T> T fadd(T l, T r) { return metal::fma(T(1), l, r); }");
add_header_line("template <typename T, int Cols, int Rows> metal::vec<T, Rows> fmul_mv(metal::matrix<T, Cols, Rows> m, metal::vec<T, Cols> v) { metal::vec<T, Rows> res = metal::vec<T, Rows>(0); for(uint i = Cols; i > 0; --i) { res = metal::fma(m[i-1], metal::vec<T, Rows>(v[i-1]), res); } return res; }");
add_header_line("template <typename T, int Cols, int Rows>");
add_header_line("metal::vec<T, Rows> fmul_mv(metal::matrix<T, Cols, Rows> m, metal::vec<T, Cols> v)");
add_header_line("{");
add_header_line(" metal::vec<T, Rows> res = metal::vec<T, Rows>(0);");
add_header_line(" for(uint i = Cols; i > 0; --i)");
add_header_line(" {");
add_header_line(" res = metal::fma(m[i-1], metal::vec<T, Rows>(v[i-1]), res);");
add_header_line(" }");
add_header_line(" return res;");
add_header_line("}");
add_header_line("template <typename T, int LCols, int LRows, int RCols, int RRows>");
add_header_line("metal::matrix<T, RCols, LRows> fmul_mat(metal::matrix<T, LCols, LRows> l, metal::matrix<T, RCols, RRows> r)");
@ -1006,6 +1014,43 @@ void CompilerMSL::preprocess_op_codes()
add_header_line("}");
}
if (msl_options.emulate_cube_array)
{
add_header_line("static inline __attribute__((always_inline)) float3 spvCubemapTo2DArrayFace(float3 P)");
add_header_line("{");
add_header_line(" float3 Coords = metal::abs(P.xyz);");
add_header_line(" float CubeFace = 0;");
add_header_line(" float ProjectionAxis = 0;");
add_header_line(" float u = 0;");
add_header_line(" float v = 0;");
add_header_line(" if(Coords.x >= Coords.y && Coords.x >= Coords.z)");
add_header_line(" {");
add_header_line(" CubeFace = P.x >= 0 ? 0 : 1;");
add_header_line(" ProjectionAxis = Coords.x;");
add_header_line(" u = P.x >= 0 ? -P.z : P.z;");
add_header_line(" v = -P.y;");
add_header_line(" }");
add_header_line(" else if(Coords.y >= Coords.x && Coords.y >= Coords.z)");
add_header_line(" {");
add_header_line(" CubeFace = P.y >= 0 ? 2 : 3;");
add_header_line(" ProjectionAxis = Coords.y;");
add_header_line(" u = P.x;");
add_header_line(" v = P.y >= 0 ? P.z : -P.z;");
add_header_line(" }");
add_header_line(" else");
add_header_line(" {");
add_header_line(" CubeFace = P.z >= 0 ? 4 : 5;");
add_header_line(" ProjectionAxis = Coords.z;");
add_header_line(" u = P.z >= 0 ? P.x : -P.x;");
add_header_line(" v = -P.y;");
add_header_line(" }");
add_header_line(" u = 0.5 * (u/ProjectionAxis + 1);");
add_header_line(" v = 0.5 * (v/ProjectionAxis + 1);");
add_header_line(" return float3(u, v, CubeFace);");
add_header_line("}");
}
// UnsafeArray
add_header_line("template <typename T, size_t Num>");
add_header_line("struct unsafe_array");
add_header_line("{");
@ -5673,7 +5718,11 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
expr += ", " + img_exp + ".get_depth(" + lod + ")";
if (img_is_array)
{
expr += ", " + img_exp + ".get_array_size()";
if (img_dim == DimCube && msl_options.emulate_cube_array)
expr += " / 6";
}
expr += ")";
@ -7300,6 +7349,18 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
if (!farg_str.empty())
farg_str += ", ";
if (imgtype.image.arrayed && msl_options.emulate_cube_array)
{
farg_str += "spvCubemapTo2DArrayFace(" + tex_coords + ").xy";
if (is_cube_fetch)
farg_str += ", uint(" + to_extract_component_expression(coord, 2) + ")";
else
farg_str += ", uint(spvCubemapTo2DArrayFace(" + tex_coords + ").z) + (uint(" + to_extract_component_expression(coord, 2) + ") * 6u)";
}
else
{
farg_str += tex_coords;
// If fetch from cube, add face explicitly
@ -7319,9 +7380,8 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
if (imgtype.image.dim == DimCube && is_fetch)
farg_str += ", uint(" + to_extract_component_expression(coord, 2) + ") / 6u";
else
farg_str += ", uint(" +
round_fp_tex_coords(to_extract_component_expression(coord, alt_coord_component), coord_is_fp) +
")";
farg_str += ", uint(" + round_fp_tex_coords(to_extract_component_expression(coord, alt_coord_component), coord_is_fp) + ")";
}
}
// Depth compare reference value
@ -7426,6 +7486,9 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
grad_opt = "3d";
break;
case DimCube:
if (imgtype.image.arrayed && msl_options.emulate_cube_array)
grad_opt = "2d";
else
grad_opt = "cube";
break;
default:
@ -10366,7 +10429,10 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
img_type_name += "depth3d_unsupported_by_metal";
break;
case DimCube:
if (!msl_options.emulate_cube_array)
img_type_name += (img_type.arrayed ? "depthcube_array" : "depthcube");
else
img_type_name += (img_type.arrayed ? "depth2d_array" : "depthcube");
break;
default:
img_type_name += "unknown_depth_texture_type";
@ -10416,7 +10482,10 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
img_type_name += "texture3d";
break;
case DimCube:
if (!msl_options.emulate_cube_array)
img_type_name += (img_type.arrayed ? "texturecube_array" : "texturecube");
else
img_type_name += (img_type.arrayed ? "texture2d_array" : "texturecube");
break;
default:
img_type_name += "unknown_texture_type";

View File

@ -301,6 +301,10 @@ public:
bool invariant_float_math = false;
/* UE Change Begin: Emulate texturecube_array with texture2d_array for iOS where this type is not available */
bool emulate_cube_array = false;
/* UE Change End: Emulate texturecube_array with texture2d_array for iOS where this type is not available */
// Requires MSL 2.1, use the native support for texel buffers.
bool texture_buffer_native = false;