From 4c5142b9d378ee3885ab6e49070d745f7e1e9318 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Tue, 26 Jun 2018 17:30:21 -0400 Subject: [PATCH 1/2] 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. --- .../opt/shaders-msl/vert/texture_buffer.vert | 10 ++++- .../vert/functions_nested.vert | 20 ++++++---- .../shaders-msl/vert/texture_buffer.vert | 10 ++++- spirv_msl.cpp | 37 +++++++++++++++---- spirv_msl.hpp | 2 + 5 files changed, 63 insertions(+), 16 deletions(-) diff --git a/reference/opt/shaders-msl/vert/texture_buffer.vert b/reference/opt/shaders-msl/vert/texture_buffer.vert index f7bcb791..c45d2981 100644 --- a/reference/opt/shaders-msl/vert/texture_buffer.vert +++ b/reference/opt/shaders-msl/vert/texture_buffer.vert @@ -1,3 +1,5 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + #include #include @@ -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 uSamp [[texture(4)]], texture2d 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; } diff --git a/reference/shaders-msl-no-opt/vert/functions_nested.vert b/reference/shaders-msl-no-opt/vert/functions_nested.vert index 43a50861..037ead39 100644 --- a/reference/shaders-msl-no-opt/vert/functions_nested.vert +++ b/reference/shaders-msl-no-opt/vert/functions_nested.vert @@ -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(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; } diff --git a/reference/shaders-msl/vert/texture_buffer.vert b/reference/shaders-msl/vert/texture_buffer.vert index f7bcb791..c45d2981 100644 --- a/reference/shaders-msl/vert/texture_buffer.vert +++ b/reference/shaders-msl/vert/texture_buffer.vert @@ -1,3 +1,5 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + #include #include @@ -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 uSamp [[texture(4)]], texture2d 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; } diff --git a/spirv_msl.cpp b/spirv_msl.cpp index c1595eed..97771b77 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -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(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(result_types[id_rhs]); + uint32_t tid = result_types[id_rhs]; + if (tid) + type = &compiler.get(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(tid).image.dim == DimBuffer) + return SPVFuncImplTexelBufferCoords; + break; } diff --git a/spirv_msl.hpp b/spirv_msl.hpp index 7b601275..87b0f15d 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -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, From 9bf226cb05d4b6ffb976053ea2817f617f1e75af Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Wed, 27 Jun 2018 10:34:15 -0400 Subject: [PATCH 2/2] Fixes for code review of PR 626. --- spirv_msl.cpp | 6 +++--- spirv_msl.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 97771b77..73637b75 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -1175,11 +1175,11 @@ void CompilerMSL::emit_custom_functions() case SPVFuncImplTexelBufferCoords: { - string max_width_str = convert_to_string(msl_options.texture_width_max); + string tex_width_str = convert_to_string(msl_options.texel_buffer_texture_width); 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, ");")); + statement(join("return uint2(tc % ", tex_width_str, ", tc / ", tex_width_str, ");")); end_scope(); statement(""); break; @@ -2466,7 +2466,7 @@ 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 + // Metal texel buffer textures are 2D, so convert 1D coord to 2D. if (is_fetch) tex_coords = "spvTexelBufferCoord(" + round_fp_tex_coords(tex_coords, coord_is_fp) + ")"; diff --git a/spirv_msl.hpp b/spirv_msl.hpp index 87b0f15d..71ab604c 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -152,7 +152,7 @@ public: Platform platform = macOS; uint32_t msl_version = make_msl_version(1, 2); - uint32_t texture_width_max = 4096; + uint32_t texel_buffer_texture_width = 4096; // Width of 2D Metal textures used as 1D texel buffers bool enable_point_size_builtin = true; bool resolve_specialized_array_lengths = true;