From 0912427046f03e7ea77c1ff7d1179fe25729843a Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Fri, 9 Feb 2018 11:27:23 +0100 Subject: [PATCH] Begin implementing subpassLoad in MSL. --- spirv_msl.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++++---- spirv_msl.hpp | 1 + 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 71a32b5e..b1b3ff4d 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -52,6 +52,55 @@ CompilerMSL::CompilerMSL(const uint32_t *ir, size_t word_count, MSLVertexAttr *p resource_bindings.push_back(&p_res_bindings[i]); } +void CompilerMSL::build_implicit_builtins() +{ + if (need_subpass_input) + { + bool has_frag_coord = false; + + for (auto &id : ids) + { + if (id.get_type() != TypeVariable) + continue; + + auto &var = id.get(); + + if (var.storage == StorageClassInput && + meta[var.self].decoration.builtin && + meta[var.self].decoration.builtin_type == BuiltInFragCoord) + { + has_frag_coord = true; + break; + } + } + + if (!has_frag_coord) + { + uint32_t offset = increase_bound_by(3); + uint32_t type_id = offset; + uint32_t type_ptr_id = offset + 1; + uint32_t var_id = offset + 2; + + // Create gl_FragCoord. + SPIRType vec4_type; + vec4_type.basetype = SPIRType::Float; + vec4_type.vecsize = 4; + set(type_id, vec4_type); + + SPIRType vec4_type_ptr; + vec4_type_ptr = vec4_type; + vec4_type_ptr.pointer = true; + vec4_type_ptr.parent_type = type_id; + vec4_type_ptr.storage = StorageClassInput; + auto &ptr_type = set(type_ptr_id, vec4_type_ptr); + ptr_type.self = offset; + + set(var_id, type_ptr_id, StorageClassInput); + set_decoration(var_id, DecorationBuiltIn, BuiltInFragCoord); + } + } +} + string CompilerMSL::compile() { // Force a classic "C" locale, reverts when function returns @@ -60,7 +109,7 @@ string CompilerMSL::compile() // Do not deal with GLES-isms like precision, older extensions and such. CompilerGLSL::options.vulkan_semantics = true; CompilerGLSL::options.es = false; - CompilerGLSL::options.version = 120; + CompilerGLSL::options.version = 450; backend.float_literal_suffix = false; backend.uint32_t_literal_suffix = true; backend.basic_int_type = "int"; @@ -81,6 +130,9 @@ string CompilerMSL::compile() struct_member_padding.clear(); update_active_builtins(); + analyze_image_and_sampler_usage(); + build_implicit_builtins(); + fixup_image_load_store_access(); set_enabled_interface_variables(get_active_interface_variables()); @@ -273,6 +325,7 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std:: switch (op) { case OpLoad: + case OpInBoundsAccessChain: case OpAccessChain: { uint32_t base_id = ops[2]; @@ -1462,11 +1515,15 @@ void CompilerMSL::emit_instruction(const Instruction &instruction) { // Mark that this shader reads from this image uint32_t img_id = ops[2]; - auto *p_var = maybe_get_backing_variable(img_id); - if (p_var && has_decoration(p_var->self, DecorationNonReadable)) + auto &type = expression_type(img_id); + if (type.image.dim != DimSubpassData) { - unset_decoration(p_var->self, DecorationNonReadable); - force_recompile = true; + auto *p_var = maybe_get_backing_variable(img_id); + if (p_var && has_decoration(p_var->self, DecorationNonReadable)) + { + unset_decoration(p_var->self, DecorationNonReadable); + force_recompile = true; + } } emit_texture_op(instruction); @@ -2141,6 +2198,13 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool break; + case DimSubpassData: + if (imgtype.image.ms) + tex_coords = "uint2(gl_FragCoord.xy)"; + else + tex_coords = join("uint2(gl_FragCoord.xy), 0"); + break; + case Dim2D: if (coord_type.vecsize > 2) tex_coords += ".xy"; @@ -3192,6 +3256,7 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id) break; case DimBuffer: case Dim2D: + case DimSubpassData: img_type_name += (img_type.ms ? "texture2d_ms" : (img_type.arrayed ? "texture2d_array" : "texture2d")); break; case Dim3D: @@ -3213,7 +3278,7 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id) // For unsampled images, append the sample/read/write access qualifier. // For kernel images, the access qualifier my be supplied directly by SPIR-V. // Otherwise it may be set based on whether the image is read from or written to within the shader. - if (type.basetype == SPIRType::Image && type.image.sampled == 2) + if (type.basetype == SPIRType::Image && type.image.sampled == 2 && type.image.dim != DimSubpassData) { switch (img_type.access) { diff --git a/spirv_msl.hpp b/spirv_msl.hpp index f54839fb..d3ee4652 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -267,6 +267,7 @@ protected: void add_pragma_line(const std::string &line); void emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uint32_t id_mem_sem); void emit_array_copy(const std::string &lhs, uint32_t rhs_id) override; + void build_implicit_builtins(); Options options; std::set spv_function_implementations;