video_core: Query storage flag with runtime state
This commit is contained in:
parent
347096b78f
commit
5c1de381c4
|
@ -329,11 +329,12 @@ void EmitContext::DefinePushDataBlock() {
|
|||
void EmitContext::DefineBuffers() {
|
||||
boost::container::small_vector<Id, 8> type_ids;
|
||||
for (u32 i = 0; const auto& buffer : info.buffers) {
|
||||
const auto sharp = buffer.GetVsharp(info);
|
||||
const bool is_storage = buffer.IsStorage(sharp);
|
||||
const auto* data_types = True(buffer.used_types & IR::Type::F32) ? &F32 : &U32;
|
||||
const Id data_type = (*data_types)[1];
|
||||
const Id record_array_type{buffer.is_storage
|
||||
? TypeRuntimeArray(data_type)
|
||||
: TypeArray(data_type, ConstU32(buffer.length))};
|
||||
const Id record_array_type{is_storage ? TypeRuntimeArray(data_type)
|
||||
: TypeArray(data_type, ConstU32(buffer.length))};
|
||||
const Id struct_type{TypeStruct(record_array_type)};
|
||||
if (std::ranges::find(type_ids, record_array_type.value, &Id::value) == type_ids.end()) {
|
||||
Decorate(record_array_type, spv::Decoration::ArrayStride, 4);
|
||||
|
@ -350,13 +351,13 @@ void EmitContext::DefineBuffers() {
|
|||
}
|
||||
|
||||
const auto storage_class =
|
||||
buffer.is_storage ? spv::StorageClass::StorageBuffer : spv::StorageClass::Uniform;
|
||||
is_storage ? spv::StorageClass::StorageBuffer : spv::StorageClass::Uniform;
|
||||
const Id struct_pointer_type{TypePointer(storage_class, struct_type)};
|
||||
const Id pointer_type = TypePointer(storage_class, data_type);
|
||||
const Id id{AddGlobalVariable(struct_pointer_type, storage_class)};
|
||||
Decorate(id, spv::Decoration::Binding, binding);
|
||||
Decorate(id, spv::Decoration::DescriptorSet, 0U);
|
||||
Name(id, fmt::format("{}_{}", buffer.is_storage ? "ssbo" : "cbuf", buffer.sgpr_base));
|
||||
Name(id, fmt::format("{}_{}", is_storage ? "ssbo" : "cbuf", buffer.sgpr_base));
|
||||
|
||||
buffers.push_back({
|
||||
.id = id,
|
||||
|
|
|
@ -401,7 +401,6 @@ void Translator::EmitFetch(const GcnInst& inst) {
|
|||
.dword_offset = attrib.dword_offset,
|
||||
.length = buffer.num_records,
|
||||
.used_types = IR::Type::F32,
|
||||
.is_storage = true, // we may not fit into UBO with large meshes
|
||||
.is_instance_data = true,
|
||||
});
|
||||
instance_buf_handle = s32(info.buffers.size() - 1);
|
||||
|
|
|
@ -220,7 +220,6 @@ public:
|
|||
})};
|
||||
auto& buffer = buffer_resources[index];
|
||||
ASSERT(buffer.length == desc.length);
|
||||
buffer.is_storage |= desc.is_storage;
|
||||
buffer.used_types |= desc.used_types;
|
||||
buffer.is_written |= desc.is_written;
|
||||
return index;
|
||||
|
@ -412,7 +411,6 @@ s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors,
|
|||
.length = BufferLength(cbuf),
|
||||
.used_types = BufferDataType(inst, cbuf.GetNumberFmt()),
|
||||
.inline_cbuf = cbuf,
|
||||
.is_storage = IsBufferStore(inst) || cbuf.GetSize() > MaxUboSize,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -424,15 +422,13 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
|
|||
IR::Inst* handle = inst.Arg(0).InstRecursive();
|
||||
IR::Inst* producer = handle->Arg(0).InstRecursive();
|
||||
const auto sharp = TrackSharp(producer);
|
||||
const bool is_store = IsBufferStore(inst);
|
||||
buffer = info.ReadUd<AmdGpu::Buffer>(sharp.sgpr_base, sharp.dword_offset);
|
||||
binding = descriptors.Add(BufferResource{
|
||||
.sgpr_base = sharp.sgpr_base,
|
||||
.dword_offset = sharp.dword_offset,
|
||||
.length = BufferLength(buffer),
|
||||
.used_types = BufferDataType(inst, buffer.GetNumberFmt()),
|
||||
.is_storage = is_store || buffer.GetSize() > MaxUboSize,
|
||||
.is_written = is_store,
|
||||
.is_written = IsBufferStore(inst),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -83,18 +83,22 @@ struct BufferResource {
|
|||
AmdGpu::Buffer inline_cbuf;
|
||||
AmdGpu::DataFormat dfmt;
|
||||
AmdGpu::NumberFormat nfmt;
|
||||
bool is_storage{};
|
||||
bool is_instance_data{};
|
||||
bool is_written{};
|
||||
|
||||
static constexpr size_t MaxUboSize = 65536;
|
||||
|
||||
bool IsStorage(AmdGpu::Buffer buffer) const noexcept {
|
||||
return buffer.GetSize() > MaxUboSize || is_written;
|
||||
}
|
||||
|
||||
u64 GetKey(const Info& info) const {
|
||||
static constexpr size_t MaxUboSize = 65536;
|
||||
const auto sharp = GetVsharp(info);
|
||||
const u32 stride = sharp.GetStride();
|
||||
u64 key = stride | (sharp.data_format << 14) | (sharp.num_format << 18);
|
||||
if (!is_written) {
|
||||
key <<= 1;
|
||||
key |= (stride * sharp.num_records) > MaxUboSize;
|
||||
key |= IsStorage(sharp);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
|
|
@ -24,10 +24,11 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler
|
|||
u32 binding{};
|
||||
boost::container::small_vector<vk::DescriptorSetLayoutBinding, 32> bindings;
|
||||
for (const auto& buffer : info->buffers) {
|
||||
const auto sharp = buffer.GetVsharp(*info);
|
||||
bindings.push_back({
|
||||
.binding = binding++,
|
||||
.descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer
|
||||
: vk::DescriptorType::eUniformBuffer,
|
||||
.descriptorType = buffer.IsStorage(sharp) ? vk::DescriptorType::eStorageBuffer
|
||||
: vk::DescriptorType::eUniformBuffer,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
});
|
||||
|
@ -98,12 +99,13 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache,
|
|||
|
||||
for (const auto& buffer : info->buffers) {
|
||||
const auto vsharp = buffer.GetVsharp(*info);
|
||||
const bool is_storage = buffer.IsStorage(vsharp);
|
||||
const VAddr address = vsharp.base_address;
|
||||
// Most of the time when a metadata is updated with a shader it gets cleared. It means we
|
||||
// can skip the whole dispatch and update the tracked state instead. Also, it is not
|
||||
// intended to be consumed and in such rare cases (e.g. HTile introspection, CRAA) we will
|
||||
// need its full emulation anyways. For cases of metadata read a warning will be logged.
|
||||
if (buffer.is_storage) {
|
||||
if (is_storage) {
|
||||
if (texture_cache.TouchMeta(address, true)) {
|
||||
LOG_WARNING(Render_Vulkan, "Metadata update skipped");
|
||||
return false;
|
||||
|
@ -118,7 +120,7 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache,
|
|||
texture_cache.InvalidateMemory(address, size, true);
|
||||
}
|
||||
const u32 alignment =
|
||||
buffer.is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment();
|
||||
is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment();
|
||||
const auto [vk_buffer, offset] =
|
||||
buffer_cache.ObtainBuffer(address, size, buffer.is_written);
|
||||
const u32 offset_aligned = Common::AlignDown(offset, alignment);
|
||||
|
@ -133,8 +135,8 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache,
|
|||
.dstBinding = binding++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer
|
||||
: vk::DescriptorType::eUniformBuffer,
|
||||
.descriptorType = is_storage ? vk::DescriptorType::eStorageBuffer
|
||||
: vk::DescriptorType::eUniformBuffer,
|
||||
.pBufferInfo = &buffer_infos.back(),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -307,10 +307,11 @@ void GraphicsPipeline::BuildDescSetLayout() {
|
|||
continue;
|
||||
}
|
||||
for (const auto& buffer : stage->buffers) {
|
||||
const auto sharp = buffer.GetVsharp(*stage);
|
||||
bindings.push_back({
|
||||
.binding = binding++,
|
||||
.descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer
|
||||
: vk::DescriptorType::eUniformBuffer,
|
||||
.descriptorType = buffer.IsStorage(sharp) ? vk::DescriptorType::eStorageBuffer
|
||||
: vk::DescriptorType::eUniformBuffer,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment,
|
||||
});
|
||||
|
@ -361,14 +362,15 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||
}
|
||||
for (const auto& buffer : stage->buffers) {
|
||||
const auto vsharp = buffer.GetVsharp(*stage);
|
||||
const bool is_storage = buffer.IsStorage(vsharp);
|
||||
if (vsharp) {
|
||||
const VAddr address = vsharp.base_address;
|
||||
if (texture_cache.IsMeta(address)) {
|
||||
LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (buffer)");
|
||||
}
|
||||
const u32 size = vsharp.GetSize();
|
||||
const u32 alignment = buffer.is_storage ? instance.StorageMinAlignment()
|
||||
: instance.UniformMinAlignment();
|
||||
const u32 alignment =
|
||||
is_storage ? instance.StorageMinAlignment() : instance.UniformMinAlignment();
|
||||
const auto [vk_buffer, offset] =
|
||||
buffer_cache.ObtainBuffer(address, size, buffer.is_written);
|
||||
const u32 offset_aligned = Common::AlignDown(offset, alignment);
|
||||
|
@ -386,8 +388,8 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||
.dstBinding = binding++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = buffer.is_storage ? vk::DescriptorType::eStorageBuffer
|
||||
: vk::DescriptorType::eUniformBuffer,
|
||||
.descriptorType = is_storage ? vk::DescriptorType::eStorageBuffer
|
||||
: vk::DescriptorType::eUniformBuffer,
|
||||
.pBufferInfo = &buffer_infos.back(),
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue