diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2021-10-29 18:48:47 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2021-10-29 19:01:31 +0300 |
commit | 639d1cb978cc631ad64d7c0fa95b091241047465 (patch) | |
tree | c62b508ff17e2b925f7650fe66c87c5a626e9e7f /dxil_converter.cpp | |
parent | b485cb39356de248180316be1b7b0648d2fe4417 (diff) |
Handle typed load-store to U64 atomic resources.
Diffstat (limited to 'dxil_converter.cpp')
-rw-r--r-- | dxil_converter.cpp | 104 |
1 files changed, 86 insertions, 18 deletions
diff --git a/dxil_converter.cpp b/dxil_converter.cpp index 703e897..fb86d56 100644 --- a/dxil_converter.cpp +++ b/dxil_converter.cpp @@ -4303,20 +4303,59 @@ void Converter::Impl::fixup_load_type_typed(DXIL::ComponentType &component_type, auto output_component_type = component_type; auto input_component_type = get_effective_typed_resource_type(component_type); - if (component_type_is_16bit(output_component_type) && !support_16bit_operations()) - output_component_type = convert_16bit_component_to_32bit(output_component_type); - else if (target_type->getTypeID() == llvm::Type::TypeID::FloatTyID) - { - // Only convert if we actually want half here. - // Certain operations always return float even if the resource type is half for some silly reason. - output_component_type = DXIL::ComponentType::F32; + if (output_component_type == DXIL::ComponentType::U64 && target_type->getIntegerBitWidth() == 32) + { + // If the component type is U64 it's used for atomics, but load/store interface is still 32-bit. + // Bit-cast rather than value cast. + auto *bitcast_op = allocate(spv::OpCompositeExtract, builder().makeUintType(64)); + bitcast_op->add_id(value_id); + bitcast_op->add_literal(0); + add(bitcast_op); + + auto *u32_cast_op = allocate(spv::OpBitcast, builder().makeVectorType(builder().makeUintType(32), 2)); + u32_cast_op->add_id(bitcast_op->id); + add(u32_cast_op); + output_component_type = DXIL::ComponentType::U32; + + if (components > 2) + { + auto *composite_op = + allocate(spv::OpCompositeConstruct, + builder().makeVectorType(builder().makeUintType(32), components)); + composite_op->add_id(u32_cast_op->id); + for (unsigned i = 2; i < components; i++) + composite_op->add_id(builder().makeUintConstant(0)); + add(composite_op); + value_id = composite_op->id; + } + else if (components == 1) + { + auto *extract_op = allocate(spv::OpCompositeExtract, builder().makeUintType(32)); + extract_op->add_id(u32_cast_op->id); + extract_op->add_literal(0); + add(extract_op); + value_id = extract_op->id; + } + else + value_id = u32_cast_op->id; } + else + { + if (component_type_is_16bit(output_component_type) && !support_16bit_operations()) + output_component_type = convert_16bit_component_to_32bit(output_component_type); + else if (target_type->getTypeID() == llvm::Type::TypeID::FloatTyID) + { + // Only convert if we actually want half here. + // Certain operations always return float even if the resource type is half for some silly reason. + output_component_type = DXIL::ComponentType::F32; + } - output_component_type = convert_component_to_unsigned(output_component_type); + output_component_type = convert_component_to_unsigned(output_component_type); - if (output_component_type != input_component_type) - value_id = build_value_cast(value_id, input_component_type, output_component_type, components); - component_type = output_component_type; + if (output_component_type != input_component_type) + value_id = build_value_cast(value_id, input_component_type, output_component_type, components); + component_type = output_component_type; + } } void Converter::Impl::fixup_load_type_typed(DXIL::ComponentType component_type, unsigned components, @@ -4367,15 +4406,44 @@ spv::Id Converter::Impl::fixup_store_type_atomic(DXIL::ComponentType component_t spv::Id Converter::Impl::fixup_store_type_typed(DXIL::ComponentType component_type, unsigned components, spv::Id value) { - auto output_component_type = get_effective_typed_resource_type(component_type); - auto input_component_type = component_type; + if (component_type == DXIL::ComponentType::U64) + { + // If the component type is U64 it's used for atomics, but load/store interface is still 32-bit. + // Bit-cast rather than value cast. + spv::Id u64_ids[4] = {}; + for (unsigned i = 0; i < components / 2; i++) + { + auto *shuffle_op = allocate(spv::OpVectorShuffle, builder().makeVectorType(builder().makeUintType(32), 2)); + shuffle_op->add_id(value); + shuffle_op->add_id(value); + shuffle_op->add_literal(2 * i + 0); + shuffle_op->add_literal(2 * i + 1); + add(shuffle_op); - if (component_type_is_16bit(input_component_type) && !support_16bit_operations()) - input_component_type = convert_16bit_component_to_32bit(input_component_type); - input_component_type = convert_component_to_unsigned(input_component_type); + auto *cast_op = allocate(spv::OpBitcast, builder().makeUintType(64)); + cast_op->add_id(shuffle_op->id); + add(cast_op); + u64_ids[i] = cast_op->id; + } + + for (unsigned i = components / 2; i < components; i++) + u64_ids[i] = builder().makeUint64Constant(0); + + value = build_vector(builder().makeUintType(64), u64_ids, components); + } + else + { + auto output_component_type = get_effective_typed_resource_type(component_type); + auto input_component_type = component_type; + + if (component_type_is_16bit(input_component_type) && !support_16bit_operations()) + input_component_type = convert_16bit_component_to_32bit(input_component_type); + input_component_type = convert_component_to_unsigned(input_component_type); + + if (output_component_type != input_component_type) + value = build_value_cast(value, input_component_type, output_component_type, components); + } - if (output_component_type != input_component_type) - value = build_value_cast(value, input_component_type, output_component_type, components); return value; } |