mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-22 04:24:44 +00:00
video_core: added rebinding of changed textures after overlap resolve
This commit is contained in:
parent
3d2ea32dae
commit
e1a7c737d8
9 changed files with 150 additions and 100 deletions
|
@ -579,6 +579,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||
src/video_core/renderer_vulkan/vk_master_semaphore.h
|
||||
src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
|
||||
src/video_core/renderer_vulkan/vk_pipeline_cache.h
|
||||
src/video_core/renderer_vulkan/vk_pipeline_common.cpp
|
||||
src/video_core/renderer_vulkan/vk_pipeline_common.h
|
||||
src/video_core/renderer_vulkan/vk_platform.cpp
|
||||
src/video_core/renderer_vulkan/vk_platform.h
|
||||
src/video_core/renderer_vulkan/vk_rasterizer.cpp
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "video_core/buffer_cache/buffer_cache.h"
|
||||
#include "video_core/renderer_vulkan/vk_compute_pipeline.h"
|
||||
|
@ -15,7 +16,7 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler
|
|||
DescriptorHeap& desc_heap_, vk::PipelineCache pipeline_cache,
|
||||
u64 compute_key_, const Shader::Info& info_,
|
||||
vk::ShaderModule module)
|
||||
: instance{instance_}, scheduler{scheduler_}, desc_heap{desc_heap_}, compute_key{compute_key_},
|
||||
: Pipeline{instance_, scheduler_, desc_heap_, pipeline_cache}, compute_key{compute_key_},
|
||||
info{&info_} {
|
||||
const vk::PipelineShaderStageCreateInfo shader_ci = {
|
||||
.stage = vk::ShaderStageFlagBits::eCompute,
|
||||
|
@ -213,36 +214,8 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache,
|
|||
});
|
||||
}
|
||||
|
||||
for (const auto& image_desc : info->images) {
|
||||
const auto tsharp = image_desc.GetSharp(*info);
|
||||
if (tsharp.GetDataFmt() != AmdGpu::DataFormat::FormatInvalid) {
|
||||
VideoCore::ImageInfo image_info{tsharp, image_desc.is_depth};
|
||||
VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage};
|
||||
const auto& image_view = texture_cache.FindTexture(image_info, view_info);
|
||||
const auto& image = texture_cache.GetImage(image_view.image_id);
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view,
|
||||
image.last_state.layout);
|
||||
} else if (instance.IsNullDescriptorSupported()) {
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, vk::ImageLayout::eGeneral);
|
||||
} else {
|
||||
auto& null_image = texture_cache.GetImageView(VideoCore::NULL_IMAGE_VIEW_ID);
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, *null_image.image_view,
|
||||
vk::ImageLayout::eGeneral);
|
||||
}
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = image_desc.is_storage ? vk::DescriptorType::eStorageImage
|
||||
: vk::DescriptorType::eSampledImage,
|
||||
.pImageInfo = &image_infos.back(),
|
||||
});
|
||||
BindTextures(texture_cache, *info, binding, set_writes);
|
||||
|
||||
if (texture_cache.IsMeta(tsharp.Address())) {
|
||||
LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a CS shader (texture)");
|
||||
}
|
||||
}
|
||||
for (const auto& sampler : info->samplers) {
|
||||
const auto ssharp = sampler.GetSharp(*info);
|
||||
if (ssharp.force_degamma) {
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include "shader_recompiler/info.h"
|
||||
#include "video_core/renderer_vulkan/vk_common.h"
|
||||
#include "video_core/renderer_vulkan/vk_pipeline_common.h"
|
||||
|
||||
namespace VideoCore {
|
||||
class BufferCache;
|
||||
|
@ -18,27 +17,17 @@ class Instance;
|
|||
class Scheduler;
|
||||
class DescriptorHeap;
|
||||
|
||||
class ComputePipeline {
|
||||
class ComputePipeline : public Pipeline {
|
||||
public:
|
||||
explicit ComputePipeline(const Instance& instance, Scheduler& scheduler,
|
||||
DescriptorHeap& desc_heap, vk::PipelineCache pipeline_cache,
|
||||
u64 compute_key, const Shader::Info& info, vk::ShaderModule module);
|
||||
ComputePipeline(const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap,
|
||||
vk::PipelineCache pipeline_cache, u64 compute_key, const Shader::Info& info,
|
||||
vk::ShaderModule module);
|
||||
~ComputePipeline();
|
||||
|
||||
[[nodiscard]] vk::Pipeline Handle() const noexcept {
|
||||
return *pipeline;
|
||||
}
|
||||
|
||||
bool BindResources(VideoCore::BufferCache& buffer_cache,
|
||||
VideoCore::TextureCache& texture_cache) const;
|
||||
|
||||
private:
|
||||
const Instance& instance;
|
||||
Scheduler& scheduler;
|
||||
DescriptorHeap& desc_heap;
|
||||
vk::UniquePipeline pipeline;
|
||||
vk::UniquePipelineLayout pipeline_layout;
|
||||
vk::UniqueDescriptorSetLayout desc_layout;
|
||||
u64 compute_key;
|
||||
const Shader::Info* info;
|
||||
bool uses_push_descriptors{};
|
||||
|
|
|
@ -21,7 +21,7 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul
|
|||
vk::PipelineCache pipeline_cache,
|
||||
std::span<const Shader::Info*, MaxShaderStages> infos,
|
||||
std::span<const vk::ShaderModule> modules)
|
||||
: instance{instance_}, scheduler{scheduler_}, desc_heap{desc_heap_}, key{key_} {
|
||||
: Pipeline{instance_, scheduler_, desc_heap_, pipeline_cache}, key{key_} {
|
||||
const vk::Device device = instance.GetDevice();
|
||||
std::ranges::copy(infos, stages.begin());
|
||||
BuildDescSetLayout();
|
||||
|
@ -444,45 +444,15 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||
});
|
||||
}
|
||||
|
||||
boost::container::static_vector<AmdGpu::Image, 32> tsharps;
|
||||
for (const auto& image_desc : stage->images) {
|
||||
const auto tsharp = image_desc.GetSharp(*stage);
|
||||
if (tsharp.GetDataFmt() != AmdGpu::DataFormat::FormatInvalid) {
|
||||
tsharps.emplace_back(tsharp);
|
||||
VideoCore::ImageInfo image_info{tsharp, image_desc.is_depth};
|
||||
VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage};
|
||||
const auto& image_view = texture_cache.FindTexture(image_info, view_info);
|
||||
const auto& image = texture_cache.GetImage(image_view.image_id);
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, *image_view.image_view,
|
||||
image.last_state.layout);
|
||||
} else if (instance.IsNullDescriptorSupported()) {
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, vk::ImageLayout::eGeneral);
|
||||
} else {
|
||||
auto& null_image = texture_cache.GetImageView(VideoCore::NULL_IMAGE_VIEW_ID);
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, *null_image.image_view,
|
||||
vk::ImageLayout::eGeneral);
|
||||
}
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = image_desc.is_storage ? vk::DescriptorType::eStorageImage
|
||||
: vk::DescriptorType::eSampledImage,
|
||||
.pImageInfo = &image_infos.back(),
|
||||
});
|
||||
BindTextures(texture_cache, *stage, binding, set_writes);
|
||||
|
||||
if (texture_cache.IsMeta(tsharp.Address())) {
|
||||
LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (texture)");
|
||||
}
|
||||
}
|
||||
for (const auto& sampler : stage->samplers) {
|
||||
auto ssharp = sampler.GetSharp(*stage);
|
||||
if (ssharp.force_degamma) {
|
||||
LOG_WARNING(Render_Vulkan, "Texture requires gamma correction");
|
||||
}
|
||||
if (sampler.disable_aniso) {
|
||||
const auto& tsharp = tsharps[sampler.associated_image];
|
||||
const auto& tsharp = stage->images[sampler.associated_image].GetSharp(*stage);
|
||||
if (tsharp.base_level == 0 && tsharp.last_level == 0) {
|
||||
ssharp.max_aniso.Assign(AmdGpu::AnisoRatio::One);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "common/types.h"
|
||||
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
||||
#include "video_core/renderer_vulkan/vk_common.h"
|
||||
#include "video_core/renderer_vulkan/vk_compute_pipeline.h"
|
||||
#include "video_core/renderer_vulkan/vk_pipeline_common.h"
|
||||
|
||||
namespace VideoCore {
|
||||
class BufferCache;
|
||||
|
@ -50,26 +50,17 @@ struct GraphicsPipelineKey {
|
|||
}
|
||||
};
|
||||
|
||||
class GraphicsPipeline {
|
||||
class GraphicsPipeline : public Pipeline {
|
||||
public:
|
||||
explicit GraphicsPipeline(const Instance& instance, Scheduler& scheduler,
|
||||
DescriptorHeap& desc_heap, const GraphicsPipelineKey& key,
|
||||
vk::PipelineCache pipeline_cache,
|
||||
std::span<const Shader::Info*, MaxShaderStages> stages,
|
||||
std::span<const vk::ShaderModule> modules);
|
||||
GraphicsPipeline(const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap,
|
||||
const GraphicsPipelineKey& key, vk::PipelineCache pipeline_cache,
|
||||
std::span<const Shader::Info*, MaxShaderStages> stages,
|
||||
std::span<const vk::ShaderModule> modules);
|
||||
~GraphicsPipeline();
|
||||
|
||||
void BindResources(const Liverpool::Regs& regs, VideoCore::BufferCache& buffer_cache,
|
||||
VideoCore::TextureCache& texture_cache) const;
|
||||
|
||||
vk::Pipeline Handle() const noexcept {
|
||||
return *pipeline;
|
||||
}
|
||||
|
||||
vk::PipelineLayout GetLayout() const {
|
||||
return *pipeline_layout;
|
||||
}
|
||||
|
||||
const Shader::Info& GetStage(Shader::Stage stage) const noexcept {
|
||||
return *stages[u32(stage)];
|
||||
}
|
||||
|
@ -91,12 +82,6 @@ private:
|
|||
void BuildDescSetLayout();
|
||||
|
||||
private:
|
||||
const Instance& instance;
|
||||
Scheduler& scheduler;
|
||||
DescriptorHeap& desc_heap;
|
||||
vk::UniquePipeline pipeline;
|
||||
vk::UniquePipelineLayout pipeline_layout;
|
||||
vk::UniqueDescriptorSetLayout desc_layout;
|
||||
std::array<const Shader::Info*, MaxShaderStages> stages{};
|
||||
GraphicsPipelineKey key;
|
||||
bool uses_push_descriptors{};
|
||||
|
|
78
src/video_core/renderer_vulkan/vk_pipeline_common.cpp
Normal file
78
src/video_core/renderer_vulkan/vk_pipeline_common.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <boost/container/static_vector.hpp>
|
||||
|
||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||
#include "video_core/renderer_vulkan/vk_pipeline_common.h"
|
||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||
#include "video_core/texture_cache/texture_cache.h"
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
Pipeline::Pipeline(const Instance& instance_, Scheduler& scheduler_, DescriptorHeap& desc_heap_,
|
||||
vk::PipelineCache pipeline_cache)
|
||||
: instance{instance_}, scheduler{scheduler_}, desc_heap{desc_heap_} {}
|
||||
|
||||
Pipeline::~Pipeline() = default;
|
||||
|
||||
void Pipeline::BindTextures(VideoCore::TextureCache& texture_cache, const Shader::Info& stage,
|
||||
u32& binding, DescriptorWrites& set_writes) const {
|
||||
static boost::container::static_vector<vk::DescriptorImageInfo, 32> image_infos;
|
||||
image_infos.clear();
|
||||
|
||||
using ImageBindingInfo = std::tuple<VideoCore::Image*, VideoCore::ImageView*, bool>;
|
||||
boost::container::static_vector<ImageBindingInfo, 32> image_bindings;
|
||||
|
||||
for (const auto& image_desc : stage.images) {
|
||||
const auto tsharp = image_desc.GetSharp(stage);
|
||||
if (tsharp.GetDataFmt() != AmdGpu::DataFormat::FormatInvalid) {
|
||||
VideoCore::ImageInfo image_info{tsharp, image_desc.is_depth};
|
||||
VideoCore::ImageViewInfo view_info{tsharp, image_desc.is_storage};
|
||||
auto& image_view = texture_cache.FindTexture(image_info, view_info);
|
||||
auto& image = texture_cache.GetImage(image_view.image_id);
|
||||
image.flags |= VideoCore::ImageFlagBits::Bound;
|
||||
image_bindings.emplace_back(&image, &image_view, image_desc.is_storage);
|
||||
} else {
|
||||
image_bindings.emplace_back(nullptr, nullptr, image_desc.is_storage);
|
||||
}
|
||||
|
||||
if (texture_cache.IsMeta(tsharp.Address())) {
|
||||
LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (texture)");
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass to re-bind images that were updated after binding
|
||||
for (auto& [image, image_view, is_storage] : image_bindings) {
|
||||
if (!image || !image_view) {
|
||||
if (instance.IsNullDescriptorSupported()) {
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, vk::ImageLayout::eGeneral);
|
||||
} else {
|
||||
auto& null_image = texture_cache.GetImageView(VideoCore::NULL_IMAGE_VIEW_ID);
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, *null_image.image_view,
|
||||
vk::ImageLayout::eGeneral);
|
||||
}
|
||||
} else {
|
||||
vk::ImageLayout layout = image->last_state.layout;
|
||||
if (True(image->flags & VideoCore::ImageFlagBits::NeedsRebind)) {
|
||||
image_view = &texture_cache.FindTexture(image->info, image_view->info);
|
||||
layout = texture_cache.GetImage(image_view->image_id).last_state.layout;
|
||||
}
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, *image_view->image_view, layout);
|
||||
image->flags &=
|
||||
~(VideoCore::ImageFlagBits::NeedsRebind | VideoCore::ImageFlagBits::Bound);
|
||||
}
|
||||
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType =
|
||||
is_storage ? vk::DescriptorType::eStorageImage : vk::DescriptorType::eSampledImage,
|
||||
.pImageInfo = &image_infos.back(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
47
src/video_core/renderer_vulkan/vk_pipeline_common.h
Normal file
47
src/video_core/renderer_vulkan/vk_pipeline_common.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shader_recompiler/info.h"
|
||||
#include "video_core/renderer_vulkan/vk_common.h"
|
||||
|
||||
namespace VideoCore {
|
||||
class BufferCache;
|
||||
class TextureCache;
|
||||
} // namespace VideoCore
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
class Instance;
|
||||
class Scheduler;
|
||||
class DescriptorHeap;
|
||||
|
||||
class Pipeline {
|
||||
public:
|
||||
Pipeline(const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap,
|
||||
vk::PipelineCache pipeline_cache);
|
||||
virtual ~Pipeline();
|
||||
|
||||
vk::Pipeline Handle() const noexcept {
|
||||
return *pipeline;
|
||||
}
|
||||
|
||||
vk::PipelineLayout GetLayout() const noexcept {
|
||||
return *pipeline_layout;
|
||||
}
|
||||
|
||||
using DescriptorWrites = boost::container::small_vector<vk::WriteDescriptorSet, 16>;
|
||||
void BindTextures(VideoCore::TextureCache& texture_cache, const Shader::Info& stage,
|
||||
u32& binding, DescriptorWrites& set_writes) const;
|
||||
|
||||
protected:
|
||||
const Instance& instance;
|
||||
Scheduler& scheduler;
|
||||
DescriptorHeap& desc_heap;
|
||||
vk::UniquePipeline pipeline;
|
||||
vk::UniquePipelineLayout pipeline_layout;
|
||||
vk::UniqueDescriptorSetLayout desc_layout;
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
|
@ -32,6 +32,8 @@ enum ImageFlagBits : u32 {
|
|||
Registered = 1 << 6, ///< True when the image is registered
|
||||
Picked = 1 << 7, ///< Temporary flag to mark the image as picked
|
||||
MetaRegistered = 1 << 8, ///< True when metadata for this surface is known and registered
|
||||
Bound = 1 << 9, ///< True when the image is bound to a descriptor set
|
||||
NeedsRebind = 1 << 10, ///< True when the image needs to be rebound
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits)
|
||||
|
||||
|
|
|
@ -179,6 +179,10 @@ ImageId TextureCache::ExpandImage(const ImageInfo& info, ImageId image_id) {
|
|||
src_image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {});
|
||||
new_image.CopyImage(src_image);
|
||||
|
||||
if (True(src_image.flags & ImageFlagBits::Bound)) {
|
||||
src_image.flags |= ImageFlagBits::NeedsRebind;
|
||||
}
|
||||
|
||||
FreeImage(image_id);
|
||||
|
||||
TrackImage(new_image_id);
|
||||
|
|
Loading…
Add table
Reference in a new issue