Skip to content

Commit

Permalink
video_core: added rebinding of changed textures after overlap resolve
Browse files Browse the repository at this point in the history
  • Loading branch information
psucien committed Sep 13, 2024
1 parent be14545 commit d09d900
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 92 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,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
Expand Down
29 changes: 3 additions & 26 deletions src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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,
Expand Down Expand Up @@ -213,32 +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 {
image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, 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) {
Expand Down
21 changes: 5 additions & 16 deletions src/video_core/renderer_vulkan/vk_compute_pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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{};
Expand Down
32 changes: 3 additions & 29 deletions src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -450,41 +450,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 {
image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, 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);
}
Expand Down
27 changes: 6 additions & 21 deletions src/video_core/renderer_vulkan/vk_graphics_pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -57,26 +57,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)];
}
Expand All @@ -98,12 +89,6 @@ class GraphicsPipeline {
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{};
Expand Down
72 changes: 72 additions & 0 deletions src/video_core/renderer_vulkan/vk_pipeline_common.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// 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) {
image_infos.emplace_back(VK_NULL_HANDLE, VK_NULL_HANDLE, 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 changes: 47 additions & 0 deletions src/video_core/renderer_vulkan/vk_pipeline_common.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions src/video_core/texture_cache/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
4 changes: 4 additions & 0 deletions src/video_core/texture_cache/texture_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,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);
Expand Down

0 comments on commit d09d900

Please sign in to comment.