diff --git a/spirv_cross.cpp b/spirv_cross.cpp index f5519900..cf75b6fc 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -3176,12 +3176,17 @@ bool Compiler::DummySamplerForCombinedImageHandler::handle(Op opcode, const uint if (length < 3) return false; - auto &type = compiler.get(args[0]); + uint32_t result_type = args[0]; + auto &type = compiler.get(result_type); bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1 && type.image.dim != DimBuffer; - if (separate_image) - SPIRV_CROSS_THROW("Attempting to use arrays or structs of separate images. This is not possible to " - "statically remap to plain GLSL."); + if (!separate_image) + return true; + + uint32_t id = args[1]; + uint32_t ptr = args[2]; + compiler.set(id, "", result_type, true); + compiler.register_read(id, ptr, true); break; } @@ -3233,16 +3238,26 @@ bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *ar // but this seems ridiculously complicated for a problem which is easy to work around. // Checking access chains like this assumes we don't have samplers or textures inside uniform structs, but this makes no sense. - auto &type = compiler.get(args[0]); + uint32_t result_type = args[0]; + + auto &type = compiler.get(result_type); bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1; bool separate_sampler = type.basetype == SPIRType::Sampler; - if (separate_image) - SPIRV_CROSS_THROW("Attempting to use arrays or structs of separate images. This is not possible to " - "statically remap to plain GLSL."); + //if (separate_image) + // SPIRV_CROSS_THROW("Attempting to use arrays or structs of separate images. This is not possible to " + // "statically remap to plain GLSL."); if (separate_sampler) SPIRV_CROSS_THROW( "Attempting to use arrays or structs of separate samplers. This is not possible to statically " "remap to plain GLSL."); + + if (separate_image) + { + uint32_t id = args[1]; + uint32_t ptr = args[2]; + compiler.set(id, "", result_type, true); + compiler.register_read(id, ptr, true); + } return true; } @@ -3325,6 +3340,7 @@ bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *ar type = compiler.expression_type(args[2]); type.self = sampled_type; type.basetype = SPIRType::SampledImage; + } else { @@ -3354,6 +3370,15 @@ bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *ar if (old_flags.get(DecorationRelaxedPrecision)) new_flags.set(DecorationRelaxedPrecision); + // Propagate the array type for the original image as well. + auto *var = compiler.maybe_get_backing_variable(image_id); + if (var) + { + auto &parent_type = compiler.get(var->basetype); + type.array = parent_type.array; + type.array_size_literal = parent_type.array_size_literal; + } + compiler.combined_image_samplers.push_back({ combined_id, image_id, sampler_id }); } diff --git a/spirv_cross.hpp b/spirv_cross.hpp index 0f17e732..43b7a532 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -384,6 +384,8 @@ public: // so this can be added before compile() if desired. // // Combined image samplers originating from this set are always considered active variables. + // Arrays of separate samplers are not supported, but arrays of separate images are supported. + // Array of images + sampler -> Array of combined image samplers. void build_combined_image_samplers(); // Gets a remapping for the combined image samplers. diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 1832ef4a..6ecc2c2e 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -3609,6 +3609,14 @@ void CompilerGLSL::emit_mix_op(uint32_t result_type, uint32_t id, uint32_t left, string CompilerGLSL::to_combined_image_sampler(uint32_t image_id, uint32_t samp_id) { + // Keep track of the array indices we have used to load the image. + // We'll need to use the same array index into the combined image sampler array. + auto image_expr = to_expression(image_id); + string array_expr; + auto array_index = image_expr.find_first_of('['); + if (array_index != string::npos) + array_expr = image_expr.substr(array_index, string::npos); + auto &args = current_function->arguments; // For GLSL and ESSL targets, we must enumerate all possible combinations for sampler2D(texture2D, sampler) and redirect @@ -3641,7 +3649,7 @@ string CompilerGLSL::to_combined_image_sampler(uint32_t image_id, uint32_t samp_ }); if (itr != end(combined)) - return to_expression(itr->id); + return to_expression(itr->id) + array_expr; else { SPIRV_CROSS_THROW( @@ -3658,7 +3666,7 @@ string CompilerGLSL::to_combined_image_sampler(uint32_t image_id, uint32_t samp_ }); if (itr != end(combined_image_samplers)) - return to_expression(itr->combined_id); + return to_expression(itr->combined_id) + array_expr; else { SPIRV_CROSS_THROW("Cannot find mapping for combined sampler, was build_combined_image_samplers() used "