CompilerMSL support larger texel buffers by using 2D Metal textures.

Add CompilerMSL::Options::texture_width_max.
Emit and use spvTexelBufferCoord() function to convert 1D
texel buffer coordinates to 2D Metal texture coordinates.
This commit is contained in:
Bill Hollings 2018-06-26 17:30:21 -04:00
parent 314f39a7c4
commit 4c5142b9d3
5 changed files with 63 additions and 16 deletions

View File

@ -1,3 +1,5 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
@ -8,10 +10,16 @@ struct main0_out
float4 gl_Position [[position]];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
vertex main0_out main0(texture2d<float> uSamp [[texture(4)]], texture2d<float> uSampo [[texture(5)]])
{
main0_out out = {};
out.gl_Position = uSamp.read(uint2(10, 0)) + uSampo.read(uint2(100, 0));
out.gl_Position = uSamp.read(spvTexelBufferCoord(10)) + uSampo.read(spvTexelBufferCoord(100));
return out;
}

View File

@ -36,6 +36,12 @@ struct main0_out
float4 gl_Position [[position]];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
attr_desc fetch_desc(thread const int& location, constant VertexBuffer& v_227)
{
int attribute_flags = v_227.input_attributes[location].w;
@ -76,10 +82,10 @@ float4 fetch_attr(thread const attr_desc& desc, thread const int& vertex_id, thr
{
int _131 = first_byte;
first_byte = _131 + 1;
tmp.x = input_stream.read(uint2(_131, 0)).x;
tmp.x = input_stream.read(spvTexelBufferCoord(_131)).x;
int _138 = first_byte;
first_byte = _138 + 1;
tmp.y = input_stream.read(uint2(_138, 0)).x;
tmp.y = input_stream.read(spvTexelBufferCoord(_138)).x;
uint4 param = tmp;
int param_1 = desc.swap_bytes;
result[n] = float(get_bits(param, param_1));
@ -89,16 +95,16 @@ float4 fetch_attr(thread const attr_desc& desc, thread const int& vertex_id, thr
{
int _156 = first_byte;
first_byte = _156 + 1;
tmp.x = input_stream.read(uint2(_156, 0)).x;
tmp.x = input_stream.read(spvTexelBufferCoord(_156)).x;
int _163 = first_byte;
first_byte = _163 + 1;
tmp.y = input_stream.read(uint2(_163, 0)).x;
tmp.y = input_stream.read(spvTexelBufferCoord(_163)).x;
int _170 = first_byte;
first_byte = _170 + 1;
tmp.z = input_stream.read(uint2(_170, 0)).x;
tmp.z = input_stream.read(spvTexelBufferCoord(_170)).x;
int _177 = first_byte;
first_byte = _177 + 1;
tmp.w = input_stream.read(uint2(_177, 0)).x;
tmp.w = input_stream.read(spvTexelBufferCoord(_177)).x;
uint4 param_2 = tmp;
int param_3 = desc.swap_bytes;
result[n] = as_type<float>(get_bits(param_2, param_3));
@ -108,7 +114,7 @@ float4 fetch_attr(thread const attr_desc& desc, thread const int& vertex_id, thr
{
int _195 = first_byte;
first_byte = _195 + 1;
result[n] = float(input_stream.read(uint2(_195, 0)).x);
result[n] = float(input_stream.read(spvTexelBufferCoord(_195)).x);
reverse_order = desc.swap_bytes != 0;
break;
}

View File

@ -1,3 +1,5 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
@ -8,10 +10,16 @@ struct main0_out
float4 gl_Position [[position]];
};
// Returns 2D texture coords corresponding to 1D texel buffer coords
uint2 spvTexelBufferCoord(uint tc)
{
return uint2(tc % 4096, tc / 4096);
}
vertex main0_out main0(texture2d<float> uSamp [[texture(4)]], texture2d<float> uSampo [[texture(5)]])
{
main0_out out = {};
out.gl_Position = uSamp.read(uint2(10, 0)) + uSampo.read(uint2(100, 0));
out.gl_Position = uSamp.read(spvTexelBufferCoord(10)) + uSampo.read(spvTexelBufferCoord(100));
return out;
}

View File

@ -1173,6 +1173,18 @@ void CompilerMSL::emit_custom_functions()
statement("");
break;
case SPVFuncImplTexelBufferCoords:
{
string max_width_str = convert_to_string(msl_options.texture_width_max);
statement("// Returns 2D texture coords corresponding to 1D texel buffer coords");
statement("uint2 spvTexelBufferCoord(uint tc)");
begin_scope();
statement(join("return uint2(tc % ", max_width_str, ", tc / ", max_width_str, ");"));
end_scope();
statement("");
break;
}
case SPVFuncImplInverse4x4:
statement("// Returns the determinant of a 2x2 matrix.");
statement("inline float spvDet2x2(float a1, float a2, float b1, float b2)");
@ -2454,8 +2466,9 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
if (coord_type.vecsize > 1)
tex_coords += ".x";
// Metal texel buffer textures are 2D
if (is_fetch)
tex_coords = "uint2(" + round_fp_tex_coords(tex_coords, coord_is_fp) + ", 0)"; // Metal textures are 2D
tex_coords = "spvTexelBufferCoord(" + round_fp_tex_coords(tex_coords, coord_is_fp) + ")";
alt_coord = ".y";
@ -4053,8 +4066,8 @@ CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op o
auto &return_type = compiler.get<SPIRType>(args[0]);
if (!return_type.array.empty())
return SPVFuncImplArrayCopy;
else
return SPVFuncImplNone;
break;
}
case OpStore:
@ -4072,14 +4085,24 @@ CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op o
else
{
// Or ... an expression.
if (result_types[id_rhs] != 0)
type = &compiler.get<SPIRType>(result_types[id_rhs]);
uint32_t tid = result_types[id_rhs];
if (tid)
type = &compiler.get<SPIRType>(tid);
}
if (type && compiler.is_array(*type))
return SPVFuncImplArrayCopy;
else
return SPVFuncImplNone;
break;
}
case OpImageFetch:
{
// Retrieve the image type, and if it's a Buffer, emit a texel coordinate function
uint32_t tid = result_types[args[2]];
if (tid && compiler.get<SPIRType>(tid).image.dim == DimBuffer)
return SPVFuncImplTexelBufferCoords;
break;
}

View File

@ -152,6 +152,7 @@ public:
Platform platform = macOS;
uint32_t msl_version = make_msl_version(1, 2);
uint32_t texture_width_max = 4096;
bool enable_point_size_builtin = true;
bool resolve_specialized_array_lengths = true;
@ -215,6 +216,7 @@ public:
SPVFuncImplFindSMsb,
SPVFuncImplFindUMsb,
SPVFuncImplArrayCopy,
SPVFuncImplTexelBufferCoords,
SPVFuncImplInverse4x4,
SPVFuncImplInverse3x3,
SPVFuncImplInverse2x2,