diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2021-04-22 14:54:43 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2021-04-22 17:03:08 +0300 |
commit | 532f65583e7a1703458d0c2e162a1f93b91abf16 (patch) | |
tree | 5423ee69083ae9ed9e52c27068e33e0d18480e12 /spirv_hlsl.cpp | |
parent | d137abeef57b2f3fdbdab0ad5590fe99a44ba546 (diff) |
Rewrite how non-uniform qualifiers are handled.
Remove all shenanigans with propagation, and only consume nonuniform
qualifiers exactly where needed (last minute).
Diffstat (limited to 'spirv_hlsl.cpp')
-rw-r--r-- | spirv_hlsl.cpp | 91 |
1 files changed, 48 insertions, 43 deletions
diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index 52c0a167..1dfb96a2 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -2235,7 +2235,7 @@ void CompilerHLSL::emit_push_constant_block(const SPIRVariable &var) string CompilerHLSL::to_sampler_expression(uint32_t id) { - auto expr = join("_", to_expression(id)); + auto expr = join("_", to_non_uniform_aware_expression(id)); auto index = expr.find_first_of('['); if (index == string::npos) { @@ -2740,13 +2740,16 @@ void CompilerHLSL::emit_texture_op(const Instruction &i, bool sparse) bool proj = false; const uint32_t *opt = nullptr; auto *combined_image = maybe_get<SPIRCombinedImageSampler>(img); - auto img_expr = to_expression(combined_image ? combined_image->image : img); - inherited_expressions.push_back(coord); + if (combined_image && has_decoration(img, DecorationNonUniform)) + { + set_decoration(combined_image->image, DecorationNonUniform); + set_decoration(combined_image->sampler, DecorationNonUniform); + } - // Make sure non-uniform decoration is back-propagated to where it needs to be. - if (has_decoration(img, DecorationNonUniformEXT)) - propagate_nonuniform_qualifier(img); + auto img_expr = to_non_uniform_aware_expression(combined_image ? combined_image->image : img); + + inherited_expressions.push_back(coord); switch (op) { @@ -3002,7 +3005,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i, bool sparse) { string sampler_expr; if (combined_image) - sampler_expr = to_expression(combined_image->sampler); + sampler_expr = to_non_uniform_aware_expression(combined_image->sampler); else sampler_expr = to_sampler_expression(img); expr += sampler_expr; @@ -3798,6 +3801,10 @@ void CompilerHLSL::read_access_chain(string *expr, const string &lhs, const SPIR SPIRV_CROSS_THROW("Reading types other than 32-bit from ByteAddressBuffer not yet supported, unless SM 6.2 and " "native 16-bit types are enabled."); + string base = chain.base; + if (has_decoration(chain.self, DecorationNonUniform)) + convert_non_uniform_expression(base, chain.self); + bool templated_load = hlsl_options.shader_model >= 62; string load_expr; @@ -3830,7 +3837,7 @@ void CompilerHLSL::read_access_chain(string *expr, const string &lhs, const SPIR if (templated_load) load_op = "Load"; - load_expr = join(chain.base, ".", load_op, template_expr, "(", chain.dynamic_index, chain.static_index, ")"); + load_expr = join(base, ".", load_op, template_expr, "(", chain.dynamic_index, chain.static_index, ")"); } else if (type.columns == 1) { @@ -3852,7 +3859,7 @@ void CompilerHLSL::read_access_chain(string *expr, const string &lhs, const SPIR for (uint32_t r = 0; r < type.vecsize; r++) { - load_expr += join(chain.base, ".Load", template_expr, "(", chain.dynamic_index, + load_expr += join(base, ".Load", template_expr, "(", chain.dynamic_index, chain.static_index + r * chain.matrix_stride, ")"); if (r + 1 < type.vecsize) load_expr += ", "; @@ -3901,7 +3908,7 @@ void CompilerHLSL::read_access_chain(string *expr, const string &lhs, const SPIR for (uint32_t c = 0; c < type.columns; c++) { - load_expr += join(chain.base, ".", load_op, template_expr, "(", chain.dynamic_index, + load_expr += join(base, ".", load_op, template_expr, "(", chain.dynamic_index, chain.static_index + c * chain.matrix_stride, ")"); if (c + 1 < type.columns) load_expr += ", "; @@ -3930,7 +3937,7 @@ void CompilerHLSL::read_access_chain(string *expr, const string &lhs, const SPIR { for (uint32_t r = 0; r < type.vecsize; r++) { - load_expr += join(chain.base, ".Load", template_expr, "(", chain.dynamic_index, + load_expr += join(base, ".Load", template_expr, "(", chain.dynamic_index, chain.static_index + c * (type.width / 8) + r * chain.matrix_stride, ")"); if ((r + 1 < type.vecsize) || (c + 1 < type.columns)) @@ -3967,9 +3974,6 @@ void CompilerHLSL::emit_load(const Instruction &instruction) uint32_t id = ops[1]; uint32_t ptr = ops[2]; - if (has_decoration(ptr, DecorationNonUniformEXT)) - propagate_nonuniform_qualifier(ptr); - auto &type = get<SPIRType>(result_type); bool composite_load = !type.array.empty() || type.basetype == SPIRType::Struct; @@ -4108,9 +4112,6 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val // Make sure we trigger a read of the constituents in the access chain. track_expression_read(chain.self); - if (has_decoration(chain.self, DecorationNonUniformEXT)) - propagate_nonuniform_qualifier(chain.self); - SPIRType target_type; target_type.basetype = SPIRType::UInt; target_type.vecsize = type.vecsize; @@ -4134,6 +4135,10 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val bool templated_store = hlsl_options.shader_model >= 62; + auto base = chain.base; + if (has_decoration(chain.self, DecorationNonUniform)) + convert_non_uniform_expression(base, chain.self); + string template_expr; if (templated_store) template_expr = join("<", type_to_glsl(type), ">"); @@ -4169,7 +4174,7 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val } else store_op = "Store"; - statement(chain.base, ".", store_op, template_expr, "(", chain.dynamic_index, chain.static_index, ", ", + statement(base, ".", store_op, template_expr, "(", chain.dynamic_index, chain.static_index, ", ", store_expr, ");"); } else if (type.columns == 1) @@ -4200,7 +4205,7 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val store_expr = join(bitcast_op, "(", store_expr, ")"); } - statement(chain.base, ".Store", template_expr, "(", chain.dynamic_index, + statement(base, ".Store", template_expr, "(", chain.dynamic_index, chain.static_index + chain.matrix_stride * r, ", ", store_expr, ");"); } } @@ -4244,7 +4249,7 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val store_expr = join(bitcast_op, "(", store_expr, ")"); } - statement(chain.base, ".", store_op, template_expr, "(", chain.dynamic_index, + statement(base, ".", store_op, template_expr, "(", chain.dynamic_index, chain.static_index + c * chain.matrix_stride, ", ", store_expr, ");"); } } @@ -4268,7 +4273,7 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val auto bitcast_op = bitcast_glsl_op(target_type, type); if (!bitcast_op.empty()) store_expr = join(bitcast_op, "(", store_expr, ")"); - statement(chain.base, ".Store", template_expr, "(", chain.dynamic_index, + statement(base, ".Store", template_expr, "(", chain.dynamic_index, chain.static_index + c * (type.width / 8) + r * chain.matrix_stride, ", ", store_expr, ");"); } } @@ -4370,9 +4375,6 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction) inherit_expression_dependencies(ops[1], ops[i]); add_implied_read_expression(e, ops[i]); } - - if (has_decoration(ops[1], DecorationNonUniformEXT)) - propagate_nonuniform_qualifier(ops[1]); } else { @@ -4472,13 +4474,16 @@ void CompilerHLSL::emit_atomic(const uint32_t *ops, uint32_t length, spv::Op op) if (data_type.storage == StorageClassImage || !chain) { - statement(atomic_op, "(", to_expression(ops[0]), ", ", to_expression(ops[3]), ", ", to_expression(tmp_id), - ");"); + statement(atomic_op, "(", to_non_uniform_aware_expression(ops[0]), ", ", + to_expression(ops[3]), ", ", to_expression(tmp_id), ");"); } else { + string base = chain->base; + if (has_decoration(chain->self, DecorationNonUniform)) + convert_non_uniform_expression(base, chain->self); // RWByteAddress buffer is always uint in its underlying type. - statement(chain->base, ".", atomic_op, "(", chain->dynamic_index, chain->static_index, ", ", + statement(base, ".", atomic_op, "(", chain->dynamic_index, chain->static_index, ", ", to_expression(ops[3]), ", ", to_expression(tmp_id), ");"); } } @@ -4496,14 +4501,17 @@ void CompilerHLSL::emit_atomic(const uint32_t *ops, uint32_t length, spv::Op op) SPIRType::BaseType expr_type; if (data_type.storage == StorageClassImage || !chain) { - statement(atomic_op, "(", to_expression(ops[2]), ", ", value_expr, ", ", to_name(id), ");"); + statement(atomic_op, "(", to_non_uniform_aware_expression(ops[2]), ", ", value_expr, ", ", to_name(id), ");"); expr_type = data_type.basetype; } else { // RWByteAddress buffer is always uint in its underlying type. + string base = chain->base; + if (has_decoration(chain->self, DecorationNonUniform)) + convert_non_uniform_expression(base, chain->self); expr_type = SPIRType::UInt; - statement(chain->base, ".", atomic_op, "(", chain->dynamic_index, chain->static_index, ", ", value_expr, + statement(base, ".", atomic_op, "(", chain->dynamic_index, chain->static_index, ", ", value_expr, ", ", to_name(id), ");"); } @@ -5136,7 +5144,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) auto dummy_samples_levels = join(get_fallback_name(id), "_dummy_parameter"); statement("uint ", dummy_samples_levels, ";"); - auto expr = join("spvTextureSize(", to_expression(ops[2]), ", ", + auto expr = join("spvTextureSize(", to_non_uniform_aware_expression(ops[2]), ", ", bitcast_expression(SPIRType::UInt, ops[3]), ", ", dummy_samples_levels, ")"); auto &restype = get<SPIRType>(ops[0]); @@ -5162,9 +5170,9 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) string expr; if (uav) - expr = join("spvImageSize(", to_expression(ops[2]), ", ", dummy_samples_levels, ")"); + expr = join("spvImageSize(", to_non_uniform_aware_expression(ops[2]), ", ", dummy_samples_levels, ")"); else - expr = join("spvTextureSize(", to_expression(ops[2]), ", 0u, ", dummy_samples_levels, ")"); + expr = join("spvTextureSize(", to_non_uniform_aware_expression(ops[2]), ", 0u, ", dummy_samples_levels, ")"); auto &restype = get<SPIRType>(ops[0]); expr = bitcast_expression(restype, SPIRType::UInt, expr); @@ -5194,9 +5202,9 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) statement(variable_decl(type, to_name(id)), ";"); if (uav) - statement("spvImageSize(", to_expression(ops[2]), ", ", to_name(id), ");"); + statement("spvImageSize(", to_non_uniform_aware_expression(ops[2]), ", ", to_name(id), ");"); else - statement("spvTextureSize(", to_expression(ops[2]), ", 0u, ", to_name(id), ");"); + statement("spvTextureSize(", to_non_uniform_aware_expression(ops[2]), ", 0u, ", to_name(id), ");"); auto &restype = get<SPIRType>(ops[0]); auto expr = bitcast_expression(restype, SPIRType::UInt, to_name(id)); @@ -5227,16 +5235,16 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) if (operands != ImageOperandsSampleMask || instruction.length != 6) SPIRV_CROSS_THROW("Multisampled image used in OpImageRead, but unexpected operand mask was used."); uint32_t sample = ops[5]; - imgexpr = join(to_expression(ops[2]), ".Load(int2(gl_FragCoord.xy), ", to_expression(sample), ")"); + imgexpr = join(to_non_uniform_aware_expression(ops[2]), ".Load(int2(gl_FragCoord.xy), ", to_expression(sample), ")"); } else - imgexpr = join(to_expression(ops[2]), ".Load(int3(int2(gl_FragCoord.xy), 0))"); + imgexpr = join(to_non_uniform_aware_expression(ops[2]), ".Load(int3(int2(gl_FragCoord.xy), 0))"); pure = true; } else { - imgexpr = join(to_expression(ops[2]), "[", to_expression(ops[3]), "]"); + imgexpr = join(to_non_uniform_aware_expression(ops[2]), "[", to_expression(ops[3]), "]"); // The underlying image type in HLSL depends on the image format, unlike GLSL, where all images are "vec4", // except that the underlying type changes how the data is interpreted. @@ -5285,7 +5293,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) value_expr = remap_swizzle(narrowed_type, expression_type(ops[2]).vecsize, value_expr); } - statement(to_expression(ops[0]), "[", to_expression(ops[1]), "] = ", value_expr, ";"); + statement(to_non_uniform_aware_expression(ops[0]), "[", to_expression(ops[1]), "] = ", value_expr, ";"); if (var && variable_storage_is_aliased(*var)) flush_all_aliased_variables(); break; @@ -5297,10 +5305,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) uint32_t id = ops[1]; auto expr = to_expression(ops[2]); - if (has_decoration(id, DecorationNonUniformEXT) || has_decoration(ops[2], DecorationNonUniformEXT)) - convert_non_uniform_expression(expression_type(ops[2]), expr); expr += join("[", to_expression(ops[3]), "]"); - auto &e = set<SPIRExpression>(id, expr, result_type, true); // When using the pointer, we need to know which variable it is actually loaded from. @@ -5478,7 +5483,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) case OpArrayLength: { - auto *var = maybe_get<SPIRVariable>(ops[2]); + auto *var = maybe_get_backing_variable(ops[2]); if (!var) SPIRV_CROSS_THROW("Array length must point directly to an SSBO block."); @@ -5488,7 +5493,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) // This must be 32-bit uint, so we're good to go. emit_uninitialized_temporary_expression(ops[0], ops[1]); - statement(to_expression(ops[2]), ".GetDimensions(", to_expression(ops[1]), ");"); + statement(to_non_uniform_aware_expression(ops[2]), ".GetDimensions(", to_expression(ops[1]), ");"); uint32_t offset = type_struct_member_offset(type, ops[3]); uint32_t stride = type_struct_member_array_stride(type, ops[3]); statement(to_expression(ops[1]), " = (", to_expression(ops[1]), " - ", offset, ") / ", stride, ";"); |