mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-03 16:02:26 +00:00
texture_cache: Use buffer cache in all cases for data source
* Allows to correctly handle compute written micro tiled textures
This commit is contained in:
parent
0f2892a93a
commit
e2b63bf4c8
@ -404,27 +404,19 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule
|
|||||||
|
|
||||||
const VAddr image_addr = image.info.guest_address;
|
const VAddr image_addr = image.info.guest_address;
|
||||||
const size_t image_size = image.info.guest_size_bytes;
|
const size_t image_size = image.info.guest_size_bytes;
|
||||||
vk::Buffer buffer{};
|
const auto [vk_buffer, buf_offset] = buffer_cache.ObtainTempBuffer(image_addr, image_size);
|
||||||
u32 offset{};
|
// The obtained buffer may be written by a shader so we need to emit a barrier to prevent RAW
|
||||||
if (auto upload_buffer = tile_manager.TryDetile(image); upload_buffer) {
|
// hazard
|
||||||
buffer = *upload_buffer;
|
if (auto barrier = vk_buffer->GetBarrier(vk::AccessFlagBits2::eTransferRead,
|
||||||
} else {
|
vk::PipelineStageFlagBits2::eTransfer)) {
|
||||||
const auto [vk_buffer, buf_offset] = buffer_cache.ObtainTempBuffer(image_addr, image_size);
|
auto dependencies = vk::DependencyInfo{
|
||||||
buffer = vk_buffer->Handle();
|
.bufferMemoryBarrierCount = 1,
|
||||||
offset = buf_offset;
|
.pBufferMemoryBarriers = &barrier.value(),
|
||||||
|
};
|
||||||
// The obtained buffer may be written by a shader so we need to emit a barrier to prevent
|
cmdbuf.pipelineBarrier2(dependencies);
|
||||||
// RAW hazard
|
|
||||||
if (auto barrier = vk_buffer->GetBarrier(vk::AccessFlagBits2::eTransferRead,
|
|
||||||
vk::PipelineStageFlagBits2::eTransfer)) {
|
|
||||||
auto dependencies = vk::DependencyInfo{
|
|
||||||
.bufferMemoryBarrierCount = 1,
|
|
||||||
.pBufferMemoryBarriers = &barrier.value(),
|
|
||||||
};
|
|
||||||
cmdbuf.pipelineBarrier2(dependencies);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto [buffer, offset] = tile_manager.TryDetile(vk_buffer->Handle(), buf_offset, image);
|
||||||
for (auto& copy : image_copy) {
|
for (auto& copy : image_copy) {
|
||||||
copy.bufferOffset += offset;
|
copy.bufferOffset += offset;
|
||||||
}
|
}
|
||||||
|
@ -377,9 +377,10 @@ void TileManager::FreeBuffer(ScratchBuffer buffer) {
|
|||||||
vmaDestroyBuffer(instance.GetAllocator(), buffer.first, buffer.second);
|
vmaDestroyBuffer(instance.GetAllocator(), buffer.first, buffer.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<vk::Buffer> TileManager::TryDetile(Image& image) {
|
std::pair<vk::Buffer, u32> TileManager::TryDetile(vk::Buffer in_buffer, u32 in_offset,
|
||||||
|
Image& image) {
|
||||||
if (!image.info.props.is_tiled) {
|
if (!image.info.props.is_tiled) {
|
||||||
return std::nullopt;
|
return {in_buffer, in_offset};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto* detiler = GetDetiler(image);
|
const auto* detiler = GetDetiler(image);
|
||||||
@ -388,19 +389,10 @@ std::optional<vk::Buffer> TileManager::TryDetile(Image& image) {
|
|||||||
LOG_ERROR(Render_Vulkan, "Unsupported tiled image: {} ({})",
|
LOG_ERROR(Render_Vulkan, "Unsupported tiled image: {} ({})",
|
||||||
vk::to_string(image.info.pixel_format), NameOf(image.info.tiling_mode));
|
vk::to_string(image.info.pixel_format), NameOf(image.info.tiling_mode));
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return {in_buffer, in_offset};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare input buffer
|
|
||||||
const u32 image_size = image.info.guest_size_bytes;
|
const u32 image_size = image.info.guest_size_bytes;
|
||||||
const auto [in_buffer, in_offset] = [&] -> std::pair<vk::Buffer, u32> {
|
|
||||||
// Request temporary host buffer for larger sizes.
|
|
||||||
auto in_buffer = AllocBuffer(image_size);
|
|
||||||
const auto addr = reinterpret_cast<const void*>(image.info.guest_address);
|
|
||||||
Upload(in_buffer, addr, image_size);
|
|
||||||
scheduler.DeferOperation([=, this]() { FreeBuffer(in_buffer); });
|
|
||||||
return {in_buffer.first, 0};
|
|
||||||
}();
|
|
||||||
|
|
||||||
// Prepare output buffer
|
// Prepare output buffer
|
||||||
auto out_buffer = AllocBuffer(image_size, true);
|
auto out_buffer = AllocBuffer(image_size, true);
|
||||||
@ -471,7 +463,7 @@ std::optional<vk::Buffer> TileManager::TryDetile(Image& image) {
|
|||||||
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
|
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
|
||||||
{}, post_barrier, {});
|
{}, post_barrier, {});
|
||||||
|
|
||||||
return {out_buffer.first};
|
return {out_buffer.first, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
@ -39,7 +39,7 @@ public:
|
|||||||
TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler);
|
TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler);
|
||||||
~TileManager();
|
~TileManager();
|
||||||
|
|
||||||
std::optional<vk::Buffer> TryDetile(Image& image);
|
std::pair<vk::Buffer, u32> TryDetile(vk::Buffer in_buffer, u32 in_offset, Image& image);
|
||||||
|
|
||||||
ScratchBuffer AllocBuffer(u32 size, bool is_storage = false);
|
ScratchBuffer AllocBuffer(u32 size, bool is_storage = false);
|
||||||
void Upload(ScratchBuffer buffer, const void* data, size_t size);
|
void Upload(ScratchBuffer buffer, const void* data, size_t size);
|
||||||
|
Loading…
Reference in New Issue
Block a user