Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/HansKristian-Work/dxil-spirv.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Kristian Arntzen <post@arntzen-software.no>2022-03-29 16:27:38 +0300
committerHans-Kristian Arntzen <post@arntzen-software.no>2022-03-30 15:27:06 +0300
commit670d48838b4fcc236c6997f51aaec1334bc8c8e9 (patch)
treedbb87370fad431342f34999198d8dbd85179fd3e /dxil_converter.cpp
parent2f4fc91bf21a2b8366c581f10db01c97c8f556de (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.cpp183
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);
+ }
}
}