mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-14 08:12:16 +00:00
vulkan: Handle incompatible depth format using null binding. (#2892)
Co-authored-by: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com>
This commit is contained in:
parent
8e7c5a4d99
commit
b130fe6ed5
7 changed files with 55 additions and 17 deletions
|
@ -281,6 +281,11 @@ constexpr AmdGpu::Image ImageResource::GetSharp(const Info& info) const noexcept
|
|||
// Fall back to null image if unbound.
|
||||
return AmdGpu::Image::Null();
|
||||
}
|
||||
const auto data_fmt = image.GetDataFmt();
|
||||
if (is_depth && data_fmt != AmdGpu::DataFormat::Format16 &&
|
||||
data_fmt != AmdGpu::DataFormat::Format32) {
|
||||
return AmdGpu::Image::NullDepth();
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
|
|
|
@ -363,6 +363,12 @@ void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors&
|
|||
LOG_ERROR(Render_Vulkan, "Shader compiled with unbound image!");
|
||||
image = AmdGpu::Image::Null();
|
||||
}
|
||||
const auto data_fmt = image.GetDataFmt();
|
||||
if (inst_info.is_depth && data_fmt != AmdGpu::DataFormat::Format16 &&
|
||||
data_fmt != AmdGpu::DataFormat::Format32) {
|
||||
LOG_ERROR(Render_Vulkan, "Shader compiled using non-depth image with depth instruction!");
|
||||
image = AmdGpu::Image::NullDepth();
|
||||
}
|
||||
ASSERT(image.GetType() != AmdGpu::ImageType::Invalid);
|
||||
const bool is_written = inst.GetOpcode() == IR::Opcode::ImageWrite;
|
||||
|
||||
|
|
|
@ -219,6 +219,19 @@ struct Image {
|
|||
return image;
|
||||
}
|
||||
|
||||
static constexpr Image NullDepth() {
|
||||
Image image{};
|
||||
image.data_format = u64(DataFormat::Format32);
|
||||
image.num_format = u64(NumberFormat::Float);
|
||||
image.dst_sel_x = u64(CompSwizzle::Red);
|
||||
image.dst_sel_y = u64(CompSwizzle::Green);
|
||||
image.dst_sel_z = u64(CompSwizzle::Blue);
|
||||
image.dst_sel_w = u64(CompSwizzle::Alpha);
|
||||
image.tiling_index = u64(TilingMode::Texture_MicroTiled);
|
||||
image.type = u64(ImageType::Color2D);
|
||||
return image;
|
||||
}
|
||||
|
||||
bool Valid() const {
|
||||
return (type & 0x8u) != 0;
|
||||
}
|
||||
|
|
|
@ -618,8 +618,9 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin
|
|||
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,
|
||||
auto& null_image_view =
|
||||
texture_cache.FindTexture(VideoCore::NULL_IMAGE_ID, desc.view_info);
|
||||
image_infos.emplace_back(VK_NULL_HANDLE, *null_image_view.image_view,
|
||||
vk::ImageLayout::eGeneral);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -34,8 +34,6 @@ struct ImageViewInfo {
|
|||
|
||||
struct Image;
|
||||
|
||||
constexpr Common::SlotId NULL_IMAGE_VIEW_ID{0};
|
||||
|
||||
struct ImageView {
|
||||
ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info, Image& image,
|
||||
ImageId image_id);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "common/debug.h"
|
||||
#include "video_core/buffer_cache/buffer_cache.h"
|
||||
#include "video_core/page_manager.h"
|
||||
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||
#include "video_core/texture_cache/host_compatibility.h"
|
||||
|
@ -23,31 +24,41 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler&
|
|||
BufferCache& buffer_cache_, PageManager& tracker_)
|
||||
: instance{instance_}, scheduler{scheduler_}, buffer_cache{buffer_cache_}, tracker{tracker_},
|
||||
tile_manager{instance, scheduler} {
|
||||
// Create basic null image at fixed image ID.
|
||||
const auto null_id = GetNullImage(vk::Format::eR8G8B8A8Unorm);
|
||||
ASSERT(null_id.index == NULL_IMAGE_ID.index);
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache() = default;
|
||||
|
||||
ImageId TextureCache::GetNullImage(const vk::Format format) {
|
||||
const auto existing_image = null_images.find(format);
|
||||
if (existing_image != null_images.end()) {
|
||||
return existing_image->second;
|
||||
}
|
||||
|
||||
ImageInfo info{};
|
||||
info.pixel_format = vk::Format::eR8G8B8A8Unorm;
|
||||
info.pixel_format = format;
|
||||
info.type = vk::ImageType::e2D;
|
||||
info.tiling_idx = u32(AmdGpu::TilingMode::Texture_MicroTiled);
|
||||
info.tiling_idx = static_cast<u32>(AmdGpu::TilingMode::Texture_MicroTiled);
|
||||
info.num_bits = 32;
|
||||
info.UpdateSize();
|
||||
|
||||
const ImageId null_id = slot_images.insert(instance, scheduler, info);
|
||||
ASSERT(null_id.index == NULL_IMAGE_ID.index);
|
||||
auto& img = slot_images[null_id];
|
||||
|
||||
const vk::Image& null_image = img.image;
|
||||
Vulkan::SetObjectName(instance.GetDevice(), null_image, "Null Image");
|
||||
Vulkan::SetObjectName(instance.GetDevice(), null_image,
|
||||
fmt::format("Null Image ({})", vk::to_string(format)));
|
||||
|
||||
img.flags = ImageFlagBits::Empty;
|
||||
img.track_addr = img.info.guest_address;
|
||||
img.track_addr_end = img.info.guest_address + img.info.guest_size;
|
||||
|
||||
ImageViewInfo view_info;
|
||||
const auto null_view_id =
|
||||
slot_image_views.insert(instance, view_info, slot_images[null_id], null_id);
|
||||
ASSERT(null_view_id.index == NULL_IMAGE_VIEW_ID.index);
|
||||
const vk::ImageView& null_image_view = slot_image_views[null_view_id].image_view.get();
|
||||
Vulkan::SetObjectName(instance.GetDevice(), null_image_view, "Null Image View");
|
||||
null_images.emplace(format, null_id);
|
||||
return null_id;
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache() = default;
|
||||
|
||||
void TextureCache::MarkAsMaybeDirty(ImageId image_id, Image& image) {
|
||||
if (image.hash == 0) {
|
||||
// Initialize hash
|
||||
|
@ -296,7 +307,7 @@ ImageId TextureCache::FindImage(BaseDesc& desc, FindFlags flags) {
|
|||
const auto& info = desc.info;
|
||||
|
||||
if (info.guest_address == 0) [[unlikely]] {
|
||||
return NULL_IMAGE_ID;
|
||||
return GetNullImage(info.pixel_format);
|
||||
}
|
||||
|
||||
std::scoped_lock lock{mutex};
|
||||
|
|
|
@ -246,6 +246,9 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
/// Gets or creates a null image for a particular format.
|
||||
ImageId GetNullImage(vk::Format format);
|
||||
|
||||
/// Create an image from the given parameters
|
||||
[[nodiscard]] ImageId InsertImage(const ImageInfo& info, VAddr cpu_addr);
|
||||
|
||||
|
@ -285,6 +288,7 @@ private:
|
|||
Common::SlotVector<Image> slot_images;
|
||||
Common::SlotVector<ImageView> slot_image_views;
|
||||
tsl::robin_map<u64, Sampler> samplers;
|
||||
tsl::robin_map<vk::Format, ImageId> null_images;
|
||||
PageTable page_table;
|
||||
std::mutex mutex;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue