mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 15:18:45 +00:00
renderer_vulkan: skip unnecessary metadata updates
This commit is contained in:
parent
a05d0063fc
commit
cfdfda97a2
6 changed files with 44 additions and 19 deletions
|
@ -82,7 +82,7 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler
|
||||||
|
|
||||||
ComputePipeline::~ComputePipeline() = default;
|
ComputePipeline::~ComputePipeline() = default;
|
||||||
|
|
||||||
void ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& staging,
|
bool ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& staging,
|
||||||
VideoCore::TextureCache& texture_cache) const {
|
VideoCore::TextureCache& texture_cache) const {
|
||||||
// Bind resource buffers and textures.
|
// Bind resource buffers and textures.
|
||||||
boost::container::static_vector<vk::DescriptorBufferInfo, 4> buffer_infos;
|
boost::container::static_vector<vk::DescriptorBufferInfo, 4> buffer_infos;
|
||||||
|
@ -93,12 +93,11 @@ void ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& s
|
||||||
for (const auto& buffer : info.buffers) {
|
for (const auto& buffer : info.buffers) {
|
||||||
const auto vsharp = info.ReadUd<AmdGpu::Buffer>(buffer.sgpr_base, buffer.dword_offset);
|
const auto vsharp = info.ReadUd<AmdGpu::Buffer>(buffer.sgpr_base, buffer.dword_offset);
|
||||||
const u32 size = vsharp.GetSize();
|
const u32 size = vsharp.GetSize();
|
||||||
const VAddr addr = vsharp.base_address.Value();
|
const VAddr address = vsharp.base_address.Value();
|
||||||
texture_cache.OnCpuWrite(addr);
|
texture_cache.OnCpuWrite(address);
|
||||||
const u32 offset = staging.Copy(addr, size,
|
const u32 offset = staging.Copy(address, size,
|
||||||
buffer.is_storage ? instance.StorageMinAlignment()
|
buffer.is_storage ? instance.StorageMinAlignment()
|
||||||
: instance.UniformMinAlignment());
|
: instance.UniformMinAlignment());
|
||||||
// const auto [vk_buffer, offset] = memory->GetVulkanBuffer(addr);
|
|
||||||
buffer_infos.emplace_back(staging.Handle(), offset, size);
|
buffer_infos.emplace_back(staging.Handle(), offset, size);
|
||||||
set_writes.push_back({
|
set_writes.push_back({
|
||||||
.dstSet = VK_NULL_HANDLE,
|
.dstSet = VK_NULL_HANDLE,
|
||||||
|
@ -110,12 +109,18 @@ void ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& s
|
||||||
.pBufferInfo = &buffer_infos.back(),
|
.pBufferInfo = &buffer_infos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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 (buffer.is_storage) {
|
||||||
// In most of the cases we can skip the whole dispatch when meta is written
|
if (texture_cache.TouchMeta(address, true)) {
|
||||||
texture_cache.TouchMeta(addr, true);
|
LOG_TRACE(Render_Vulkan, "Metadata update skipped");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (texture_cache.IsMeta(addr)) {
|
if (texture_cache.IsMeta(address)) {
|
||||||
LOG_WARNING(Render_Vulkan, "Unexpected meta data read by a CS shader");
|
LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a CS shader (buffer)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,6 +138,10 @@ void ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& s
|
||||||
: vk::DescriptorType::eSampledImage,
|
: vk::DescriptorType::eSampledImage,
|
||||||
.pImageInfo = &image_infos.back(),
|
.pImageInfo = &image_infos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (texture_cache.IsMeta(tsharp.Address())) {
|
||||||
|
LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a CS shader (texture)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (const auto& sampler : info.samplers) {
|
for (const auto& sampler : info.samplers) {
|
||||||
const auto ssharp = info.ReadUd<AmdGpu::Sampler>(sampler.sgpr_base, sampler.dword_offset);
|
const auto ssharp = info.ReadUd<AmdGpu::Sampler>(sampler.sgpr_base, sampler.dword_offset);
|
||||||
|
@ -148,11 +157,13 @@ void ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& s
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!set_writes.empty()) {
|
if (set_writes.empty()) {
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
return false;
|
||||||
cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eCompute, *pipeline_layout, 0,
|
|
||||||
set_writes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
|
cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eCompute, *pipeline_layout, 0, set_writes);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
return *pipeline;
|
return *pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindResources(Core::MemoryManager* memory, StreamBuffer& staging,
|
bool BindResources(Core::MemoryManager* memory, StreamBuffer& staging,
|
||||||
VideoCore::TextureCache& texture_cache) const;
|
VideoCore::TextureCache& texture_cache) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -327,8 +327,9 @@ void GraphicsPipeline::BindResources(Core::MemoryManager* memory, StreamBuffer&
|
||||||
for (const auto& stage : stages) {
|
for (const auto& stage : stages) {
|
||||||
for (const auto& buffer : stage.buffers) {
|
for (const auto& buffer : stage.buffers) {
|
||||||
const auto vsharp = stage.ReadUd<AmdGpu::Buffer>(buffer.sgpr_base, buffer.dword_offset);
|
const auto vsharp = stage.ReadUd<AmdGpu::Buffer>(buffer.sgpr_base, buffer.dword_offset);
|
||||||
|
const VAddr address = vsharp.base_address.Value();
|
||||||
const u32 size = vsharp.GetSize();
|
const u32 size = vsharp.GetSize();
|
||||||
const u32 offset = staging.Copy(vsharp.base_address.Value(), size,
|
const u32 offset = staging.Copy(address, size,
|
||||||
buffer.is_storage ? instance.StorageMinAlignment()
|
buffer.is_storage ? instance.StorageMinAlignment()
|
||||||
: instance.UniformMinAlignment());
|
: instance.UniformMinAlignment());
|
||||||
buffer_infos.emplace_back(staging.Handle(), offset, size);
|
buffer_infos.emplace_back(staging.Handle(), offset, size);
|
||||||
|
@ -341,6 +342,10 @@ void GraphicsPipeline::BindResources(Core::MemoryManager* memory, StreamBuffer&
|
||||||
: vk::DescriptorType::eUniformBuffer,
|
: vk::DescriptorType::eUniformBuffer,
|
||||||
.pBufferInfo = &buffer_infos.back(),
|
.pBufferInfo = &buffer_infos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (texture_cache.IsMeta(address)) {
|
||||||
|
LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (buffer)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& image : stage.images) {
|
for (const auto& image : stage.images) {
|
||||||
|
@ -357,6 +362,10 @@ void GraphicsPipeline::BindResources(Core::MemoryManager* memory, StreamBuffer&
|
||||||
: vk::DescriptorType::eSampledImage,
|
: vk::DescriptorType::eSampledImage,
|
||||||
.pImageInfo = &image_infos.back(),
|
.pImageInfo = &image_infos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (texture_cache.IsMeta(tsharp.Address())) {
|
||||||
|
LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (texture)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (const auto& sampler : stage.samplers) {
|
for (const auto& sampler : stage.samplers) {
|
||||||
const auto ssharp =
|
const auto ssharp =
|
||||||
|
|
|
@ -128,7 +128,10 @@ void Rasterizer::DispatchDirect() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline->BindResources(memory, vertex_index_buffer, texture_cache);
|
const auto has_resources = pipeline->BindResources(memory, vertex_index_buffer, texture_cache);
|
||||||
|
if (!has_resources) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->Handle());
|
cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->Handle());
|
||||||
cmdbuf.dispatch(cs_program.dim_x, cs_program.dim_y, cs_program.dim_z);
|
cmdbuf.dispatch(cs_program.dim_x, cs_program.dim_y, cs_program.dim_z);
|
||||||
|
|
|
@ -268,7 +268,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
||||||
}
|
}
|
||||||
|
|
||||||
Transit(vk::ImageLayout::eGeneral, vk::AccessFlagBits::eNone);
|
Transit(vk::ImageLayout::eGeneral, vk::AccessFlagBits::eNone);
|
||||||
} // namespace VideoCore
|
}
|
||||||
|
|
||||||
void Image::Transit(vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits> dst_mask) {
|
void Image::Transit(vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits> dst_mask) {
|
||||||
if (dst_layout == layout && dst_mask == access_mask) {
|
if (dst_layout == layout && dst_mask == access_mask) {
|
||||||
|
|
|
@ -84,11 +84,13 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TouchMeta(VAddr address, bool is_clear) {
|
bool TouchMeta(VAddr address, bool is_clear) {
|
||||||
auto it = surface_metas.find(address);
|
auto it = surface_metas.find(address);
|
||||||
if (it != surface_metas.end()) {
|
if (it != surface_metas.end()) {
|
||||||
it.value().is_cleared = is_clear;
|
it.value().is_cleared = is_clear;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue