diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-03-29 16:27:38 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-03-30 15:27:06 +0300 |
commit | 670d48838b4fcc236c6997f51aaec1334bc8c8e9 (patch) | |
tree | dbb87370fad431342f34999198d8dbd85179fd3e /dxil_converter.cpp | |
parent | 2f4fc91bf21a2b8366c581f10db01c97c8f556de (diff) |
Implement non-legacy CBV.
Need to treat CBVs similar to SSBOs where we consider aliases and such,
so we need to refactor resource creation to work like we expect.
Diffstat (limited to 'dxil_converter.cpp')
-rw-r--r-- | dxil_converter.cpp | 183 |
1 files changed, 147 insertions, 36 deletions
diff --git a/dxil_converter.cpp b/dxil_converter.cpp index b93f55b..f36052a 100644 --- a/dxil_converter.cpp +++ b/dxil_converter.cpp @@ -280,6 +280,42 @@ Converter::Impl::create_bindless_heap_variable_alias_group(const BindlessInfo &b return decls; } +spv::Id Converter::Impl::create_ubo_variable(const RawDeclaration &raw_decl, uint32_t range_size, const String &name, + unsigned cbv_size) +{ + auto &builder = spirv_module.get_builder(); + + unsigned element_size = raw_width_to_bits(raw_decl.width) * raw_vecsize_to_vecsize(raw_decl.vecsize) / 8; + unsigned array_length = (cbv_size + element_size - 1) / element_size; + + // It seems like we will have to bitcast ourselves away from vec4 here after loading. + spv::Id size_id = builder.makeUintConstant(array_length, false); + spv::Id element_type = builder.makeFloatType(raw_width_to_bits(raw_decl.width)); + if (raw_decl.vecsize != RawVecSize::V1) + element_type = builder.makeVectorType(element_type, raw_vecsize_to_vecsize(raw_decl.vecsize)); + spv::Id member_array_type = builder.makeArrayType(element_type, size_id, element_size); + + builder.addDecoration(member_array_type, spv::DecorationArrayStride, element_size); + + spv::Id type_id = get_struct_type({ member_array_type }, name.c_str()); + builder.addMemberDecoration(type_id, 0, spv::DecorationOffset, 0); + builder.addDecoration(type_id, spv::DecorationBlock); + + if (range_size != 1) + { + if (range_size == ~0u) + type_id = builder.makeRuntimeArray(type_id); + else + type_id = builder.makeArrayType(type_id, builder.makeUintConstant(range_size), 0); + } + + if (raw_decl.width == RawWidth::B16) + builder.addCapability(spv::CapabilityUniformAndStorageBuffer16BitAccess); + + return create_variable(spv::StorageClassUniform, + type_id, name.empty() ? nullptr : name.c_str()); +} + spv::Id Converter::Impl::create_raw_ssbo_variable(const RawDeclaration &raw_decl, uint32_t range_size, const String &name) { spv::Id type_id = build_ssbo_runtime_array_type(*this, @@ -293,8 +329,9 @@ spv::Id Converter::Impl::create_raw_ssbo_variable(const RawDeclaration &raw_decl return create_variable(spv::StorageClassStorageBuffer, type_id, name.empty() ? nullptr : name.c_str()); } -Vector<Converter::Impl::RawDeclarationVariable> Converter::Impl::create_variable_alias_group( - const Vector<RawDeclaration> &raw_decls, uint32_t range_size, const String &name) +Vector<Converter::Impl::RawDeclarationVariable> Converter::Impl::create_raw_ssbo_variable_alias_group( + const Vector<RawDeclaration> &raw_decls, + uint32_t range_size, const String &name) { Vector<RawDeclarationVariable> group; group.reserve(raw_decls.size()); @@ -303,6 +340,17 @@ Vector<Converter::Impl::RawDeclarationVariable> Converter::Impl::create_variable return group; } +Vector<Converter::Impl::RawDeclarationVariable> Converter::Impl::create_ubo_variable_alias_group( + const Vector<RawDeclaration> &raw_decls, + uint32_t range_size, const String &name, unsigned cbv_size) +{ + Vector<RawDeclarationVariable> group; + group.reserve(raw_decls.size()); + for (auto &decl : raw_decls) + group.push_back({ decl, create_ubo_variable(decl, range_size, name, cbv_size) }); + return group; +} + spv::Id Converter::Impl::create_bindless_heap_variable(const BindlessInfo &info) { auto itr = std::find_if(bindless_resources.begin(), bindless_resources.end(), [&](const BindlessResource &resource) { @@ -471,9 +519,29 @@ spv::Id Converter::Impl::create_bindless_heap_variable(const BindlessInfo &info) case DXIL::ResourceType::CBV: { - type_id = builder().makeVectorType(builder().makeFloatType(32), 4); - type_id = builder().makeArrayType(type_id, builder().makeUintConstant(64 * 1024 / 16), 16); - builder().addDecoration(type_id, spv::DecorationArrayStride, 16); + unsigned bits; + if (info.component == DXIL::ComponentType::U16) + bits = 16; + else if (info.component == DXIL::ComponentType::U32) + bits = 32; + else if (info.component == DXIL::ComponentType::U64) + bits = 64; + else + { + LOGE("Invalid component type for UBO.\n"); + return 0; + } + + unsigned vecsize = raw_vecsize_to_vecsize(info.raw_vecsize); + type_id = builder().makeFloatType(bits); + if (vecsize > 1) + type_id = builder().makeVectorType(type_id, vecsize); + + unsigned element_size = (bits / 8) * vecsize; + unsigned num_elements = 0x10000 / element_size; + + type_id = builder().makeArrayType(type_id, builder().makeUintConstant(num_elements), element_size); + builder().addDecoration(type_id, spv::DecorationArrayStride, element_size); type_id = get_struct_type({ type_id }, "BindlessCBV"); builder().addDecoration(type_id, spv::DecorationBlock); if (options.bindless_cbv_ssbo_emulation) @@ -481,6 +549,14 @@ spv::Id Converter::Impl::create_bindless_heap_variable(const BindlessInfo &info) builder().addMemberDecoration(type_id, 0, spv::DecorationOffset, 0); type_id = builder().makeRuntimeArray(type_id); storage = options.bindless_cbv_ssbo_emulation ? spv::StorageClassStorageBuffer : spv::StorageClassUniform; + + if (bits == 16) + { + if (options.bindless_cbv_ssbo_emulation) + builder().addCapability(spv::CapabilityStorageBuffer16BitAccess); + else + builder().addCapability(spv::CapabilityUniformAndStorageBuffer16BitAccess); + } break; } @@ -1076,7 +1152,7 @@ bool Converter::Impl::emit_srvs(const llvm::MDNode *srvs) if (type_id) ref.var_id = create_variable(storage, type_id, name.empty() ? nullptr : name.c_str()); else if (aliased_access.requires_alias_decoration) - ref.var_alias_group = create_variable_alias_group(aliased_access.raw_declarations, range_size, name); + ref.var_alias_group = create_raw_ssbo_variable_alias_group(aliased_access.raw_declarations, range_size, name); else { assert(aliased_access.raw_declarations.size() == 1); @@ -1623,7 +1699,7 @@ bool Converter::Impl::emit_uavs(const llvm::MDNode *uavs) storage = spv::StorageClassStorageBuffer; if (aliased_access.requires_alias_decoration) - var_alias_group = create_variable_alias_group(aliased_access.raw_declarations, range_size, name); + var_alias_group = create_raw_ssbo_variable_alias_group(aliased_access.raw_declarations, range_size, name); else { assert(aliased_access.raw_declarations.size() == 1); @@ -1783,6 +1859,11 @@ bool Converter::Impl::emit_cbvs(const llvm::MDNode *cbvs) if (need_resource_remapping && resource_mapping_iface && !resource_mapping_iface->remap_cbv(d3d_binding, vulkan_binding)) return false; + auto &access_meta = cbv_access_tracking[index]; + AliasedAccess aliased_access; + if (!analyze_aliased_access(access_meta, VulkanDescriptorType::UBO, aliased_access)) + return false; + cbv_index_to_reference.resize(std::max(cbv_index_to_reference.size(), size_t(index + 1))); if (range_size != 1) @@ -1804,6 +1885,8 @@ bool Converter::Impl::emit_cbvs(const llvm::MDNode *cbvs) bindless_info.kind = DXIL::ResourceKind::CBuffer; bindless_info.desc_set = vulkan_binding.buffer.descriptor_set; bindless_info.binding = vulkan_binding.buffer.binding; + bindless_info.component = aliased_access.primary_component_type; + bindless_info.raw_vecsize = aliased_access.primary_raw_vecsize; if (local_root_signature_entry >= 0) { @@ -1816,8 +1899,6 @@ bool Converter::Impl::emit_cbvs(const llvm::MDNode *cbvs) return false; } - spv::Id var_id = create_bindless_heap_variable(bindless_info); - uint32_t heap_offset = local_table_entry.offset_in_heap; heap_offset += bind_register - local_table_entry.register_index; @@ -1828,7 +1909,17 @@ bool Converter::Impl::emit_cbvs(const llvm::MDNode *cbvs) } auto &ref = cbv_index_to_reference[index]; - ref.var_id = var_id; + + if (aliased_access.requires_alias_decoration) + { + ref.var_alias_group = create_bindless_heap_variable_alias_group( + bindless_info, aliased_access.raw_declarations); + } + else + { + ref.var_id = create_bindless_heap_variable(bindless_info); + } + ref.base_offset = heap_offset; ref.base_resource_is_array = range_size != 1; ref.bindless = true; @@ -1878,8 +1969,6 @@ bool Converter::Impl::emit_cbvs(const llvm::MDNode *cbvs) } else if (vulkan_binding.buffer.bindless.use_heap) { - spv::Id var_id = create_bindless_heap_variable(bindless_info); - // DXIL already applies the t# register offset to any dynamic index, so counteract that here. // The exception is with lib_* where we access resources by variable, not through // createResource() >_____<. @@ -1888,7 +1977,17 @@ bool Converter::Impl::emit_cbvs(const llvm::MDNode *cbvs) heap_offset -= bind_register; auto &ref = cbv_index_to_reference[index]; - ref.var_id = var_id; + + if (aliased_access.requires_alias_decoration) + { + ref.var_alias_group = create_bindless_heap_variable_alias_group( + bindless_info, aliased_access.raw_declarations); + } + else + { + ref.var_id = create_bindless_heap_variable(bindless_info); + } + ref.push_constant_member = vulkan_binding.buffer.root_constant_index + root_descriptor_count; ref.base_offset = heap_offset; ref.base_resource_is_array = range_size != 1; @@ -1897,35 +1996,47 @@ bool Converter::Impl::emit_cbvs(const llvm::MDNode *cbvs) } else { - unsigned vec4_length = (cbv_size + 15) / 16; - - // It seems like we will have to bitcast ourselves away from vec4 here after loading. - spv::Id member_array_type = builder.makeArrayType(builder.makeVectorType(builder.makeFloatType(32), 4), - builder.makeUintConstant(vec4_length, false), 16); - - builder.addDecoration(member_array_type, spv::DecorationArrayStride, 16); - - spv::Id type_id = get_struct_type({ member_array_type }, name.c_str()); - builder.addMemberDecoration(type_id, 0, spv::DecorationOffset, 0); - builder.addDecoration(type_id, spv::DecorationBlock); + auto &ref = cbv_index_to_reference[index]; - if (range_size != 1) + if (aliased_access.requires_alias_decoration) { - if (range_size == ~0u) - type_id = builder.makeRuntimeArray(type_id); - else - type_id = builder.makeArrayType(type_id, builder.makeUintConstant(range_size), 0); + ref.var_alias_group = create_ubo_variable_alias_group( + aliased_access.raw_declarations, range_size, name, cbv_size); + } + else + { + assert(aliased_access.raw_declarations.size() == 1); + ref.var_id = create_ubo_variable(aliased_access.raw_declarations.front(), range_size, name, cbv_size); } - spv::Id var_id = create_variable(spv::StorageClassUniform, type_id, name.empty() ? nullptr : name.c_str()); - - builder.addDecoration(var_id, spv::DecorationDescriptorSet, vulkan_binding.buffer.descriptor_set); - builder.addDecoration(var_id, spv::DecorationBinding, vulkan_binding.buffer.binding); - - auto &ref = cbv_index_to_reference[index]; - ref.var_id = var_id; ref.base_resource_is_array = range_size != 1; ref.resource_kind = DXIL::ResourceKind::CBuffer; + + if (ref.var_id) + { + auto &meta = handle_to_resource_meta[ref.var_id]; + meta = {}; + meta.kind = ref.resource_kind; + meta.var_id = ref.var_id; + meta.storage = spv::StorageClassUniform; + meta.component_type = aliased_access.primary_component_type; + meta.raw_component_vecsize = aliased_access.primary_raw_vecsize; + builder.addDecoration(meta.var_id, spv::DecorationDescriptorSet, vulkan_binding.buffer.descriptor_set); + builder.addDecoration(meta.var_id, spv::DecorationBinding, vulkan_binding.buffer.binding); + } + + for (auto &var : ref.var_alias_group) + { + auto &meta = handle_to_resource_meta[var.var_id]; + meta = {}; + meta.kind = ref.resource_kind; + meta.var_id = var.var_id; + meta.storage = spv::StorageClassUniform; + meta.component_type = raw_width_to_component_type(var.declaration.width); + meta.raw_component_vecsize = var.declaration.vecsize; + builder.addDecoration(meta.var_id, spv::DecorationDescriptorSet, vulkan_binding.buffer.descriptor_set); + builder.addDecoration(meta.var_id, spv::DecorationBinding, vulkan_binding.buffer.binding); + } } } |