mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-02 16:53:17 +00:00
video_core: Add depth buffer support and fix some bugs (#172)
* memory: Avoid crash when alignment is zero * Also remove unused file * shader_recompiler: Add more instructions * Also fix some minor issues with a few existing instructions * control_flow: Don't emit discard for null exports * renderer_vulkan: Add depth buffer support * liverpool: Fix wrong color buffer number type and viewport zscale * Also add some more formats
This commit is contained in:
parent
e5621759a2
commit
998d046210
26 changed files with 295 additions and 172 deletions
|
@ -33,11 +33,23 @@ static vk::Format ConvertPixelFormat(const VideoOutFormat format) {
|
|||
return {};
|
||||
}
|
||||
|
||||
static bool IsDepthStencilFormat(vk::Format format) {
|
||||
switch (format) {
|
||||
case vk::Format::eD16Unorm:
|
||||
case vk::Format::eD16UnormS8Uint:
|
||||
case vk::Format::eD32Sfloat:
|
||||
case vk::Format::eD32SfloatS8Uint:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static vk::ImageUsageFlags ImageUsageFlags(const vk::Format format) {
|
||||
vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eTransferSrc |
|
||||
vk::ImageUsageFlagBits::eTransferDst |
|
||||
vk::ImageUsageFlagBits::eSampled;
|
||||
if (false /*&& IsDepthStencilFormat(format)*/) {
|
||||
if (IsDepthStencilFormat(format)) {
|
||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||
} else {
|
||||
if (format != vk::Format::eBc3SrgbBlock) {
|
||||
|
@ -54,9 +66,9 @@ static vk::ImageType ConvertImageType(AmdGpu::ImageType type) noexcept {
|
|||
case AmdGpu::ImageType::Color2D:
|
||||
case AmdGpu::ImageType::Color1DArray:
|
||||
case AmdGpu::ImageType::Cube:
|
||||
case AmdGpu::ImageType::Color2DArray:
|
||||
return vk::ImageType::e2D;
|
||||
case AmdGpu::ImageType::Color3D:
|
||||
case AmdGpu::ImageType::Color2DArray:
|
||||
return vk::ImageType::e3D;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -98,6 +110,18 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer,
|
|||
guest_size_bytes = buffer.GetSizeAligned();
|
||||
}
|
||||
|
||||
ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer,
|
||||
const AmdGpu::Liverpool::CbDbExtent& hint) noexcept {
|
||||
is_tiled = false;
|
||||
pixel_format = LiverpoolToVK::DepthFormat(buffer.z_info.format, buffer.stencil_info.format);
|
||||
type = vk::ImageType::e2D;
|
||||
size.width = hint.Valid() ? hint.width : buffer.Pitch();
|
||||
size.height = hint.Valid() ? hint.height : buffer.Height();
|
||||
size.depth = 1;
|
||||
pitch = size.width;
|
||||
guest_size_bytes = buffer.GetSizeAligned();
|
||||
}
|
||||
|
||||
ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept {
|
||||
is_tiled = image.IsTiled();
|
||||
tiling_mode = image.GetTilingMode();
|
||||
|
@ -165,6 +189,13 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
|||
info.usage |= vk::ImageUsageFlagBits::eStorage;
|
||||
}
|
||||
|
||||
if (info.pixel_format == vk::Format::eD32Sfloat) {
|
||||
aspect_mask = vk::ImageAspectFlagBits::eDepth;
|
||||
}
|
||||
if (info.pixel_format == vk::Format::eD32SfloatS8Uint) {
|
||||
aspect_mask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil;
|
||||
}
|
||||
|
||||
const vk::ImageCreateInfo image_ci = {
|
||||
.flags = flags,
|
||||
.imageType = info.type,
|
||||
|
@ -187,7 +218,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
|||
if (info.is_tiled) {
|
||||
ImageViewInfo view_info;
|
||||
view_info.format = DemoteImageFormatForDetiling(info.pixel_format);
|
||||
view_for_detiler.emplace(*instance, view_info, image);
|
||||
view_for_detiler.emplace(*instance, view_info, *this);
|
||||
}
|
||||
|
||||
Transit(vk::ImageLayout::eGeneral, vk::AccessFlagBits::eNone);
|
||||
|
@ -198,23 +229,25 @@ void Image::Transit(vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits> ds
|
|||
return;
|
||||
}
|
||||
|
||||
const vk::ImageMemoryBarrier barrier = {.srcAccessMask = access_mask,
|
||||
.dstAccessMask = dst_mask,
|
||||
.oldLayout = layout,
|
||||
.newLayout = dst_layout,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange{
|
||||
.aspectMask = aspect_mask,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
}};
|
||||
const vk::ImageMemoryBarrier barrier = {
|
||||
.srcAccessMask = access_mask,
|
||||
.dstAccessMask = dst_mask,
|
||||
.oldLayout = layout,
|
||||
.newLayout = dst_layout,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange{
|
||||
.aspectMask = aspect_mask,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
};
|
||||
|
||||
// Adjust pipieline stage
|
||||
vk::PipelineStageFlags dst_pl_stage =
|
||||
const vk::PipelineStageFlags dst_pl_stage =
|
||||
(dst_mask == vk::AccessFlagBits::eTransferRead ||
|
||||
dst_mask == vk::AccessFlagBits::eTransferWrite)
|
||||
? vk::PipelineStageFlagBits::eTransfer
|
||||
|
|
|
@ -38,6 +38,8 @@ struct ImageInfo {
|
|||
explicit ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group) noexcept;
|
||||
explicit ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer,
|
||||
const AmdGpu::Liverpool::CbDbExtent& hint = {}) noexcept;
|
||||
explicit ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer,
|
||||
const AmdGpu::Liverpool::CbDbExtent& hint = {}) noexcept;
|
||||
explicit ImageInfo(const AmdGpu::Image& image) noexcept;
|
||||
|
||||
bool is_tiled = false;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||
#include "video_core/texture_cache/image.h"
|
||||
#include "video_core/texture_cache/image_view.h"
|
||||
|
||||
namespace VideoCore {
|
||||
|
@ -58,7 +59,7 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image) noexcept {
|
|||
mapping.a = ConvertComponentSwizzle(image.dst_sel_w);
|
||||
}
|
||||
|
||||
ImageView::ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info_, vk::Image image,
|
||||
ImageView::ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info_, Image& image,
|
||||
std::optional<vk::ImageUsageFlags> usage_override /*= {}*/)
|
||||
: info{info_} {
|
||||
vk::ImageViewUsageCreateInfo usage_ci{};
|
||||
|
@ -66,14 +67,20 @@ ImageView::ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info
|
|||
usage_ci.usage = usage_override.value();
|
||||
}
|
||||
|
||||
// When sampling D32 texture from shader, the T# specifies R32 Float format so adjust it.
|
||||
vk::Format format = info.format;
|
||||
if (image.aspect_mask & vk::ImageAspectFlagBits::eDepth && format == vk::Format::eR32Sfloat) {
|
||||
format = vk::Format::eD32Sfloat;
|
||||
}
|
||||
|
||||
const vk::ImageViewCreateInfo image_view_ci = {
|
||||
.pNext = usage_override.has_value() ? &usage_ci : nullptr,
|
||||
.image = image,
|
||||
.image = image.image,
|
||||
.viewType = info.type,
|
||||
.format = info.format,
|
||||
.format = format,
|
||||
.components = info.mapping,
|
||||
.subresourceRange{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.aspectMask = image.aspect_mask,
|
||||
.baseMipLevel = 0U,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
|
|
|
@ -28,8 +28,10 @@ struct ImageViewInfo {
|
|||
auto operator<=>(const ImageViewInfo&) const = default;
|
||||
};
|
||||
|
||||
struct Image;
|
||||
|
||||
struct ImageView {
|
||||
explicit ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info, vk::Image image,
|
||||
explicit ImageView(const Vulkan::Instance& instance, const ImageViewInfo& info, Image& image,
|
||||
std::optional<vk::ImageUsageFlags> usage_override = {});
|
||||
~ImageView();
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler&
|
|||
ASSERT(null_id.index == 0);
|
||||
|
||||
ImageViewInfo view_info;
|
||||
void(slot_image_views.insert(instance, view_info, slot_images[null_id].image));
|
||||
void(slot_image_views.insert(instance, view_info, slot_images[null_id]));
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache() {
|
||||
|
@ -112,7 +112,7 @@ void TextureCache::OnCpuWrite(VAddr address) {
|
|||
});
|
||||
}
|
||||
|
||||
Image& TextureCache::FindImage(const ImageInfo& info, VAddr cpu_address) {
|
||||
Image& TextureCache::FindImage(const ImageInfo& info, VAddr cpu_address, bool refresh_on_create) {
|
||||
std::unique_lock lock{m_page_table};
|
||||
boost::container::small_vector<ImageId, 2> image_ids;
|
||||
ForEachImageInRegion(cpu_address, info.guest_size_bytes, [&](ImageId image_id, Image& image) {
|
||||
|
@ -132,7 +132,8 @@ Image& TextureCache::FindImage(const ImageInfo& info, VAddr cpu_address) {
|
|||
}
|
||||
|
||||
Image& image = slot_images[image_id];
|
||||
if (True(image.flags & ImageFlagBits::CpuModified)) {
|
||||
if (True(image.flags & ImageFlagBits::CpuModified) &&
|
||||
(!image_ids.empty() || refresh_on_create)) {
|
||||
RefreshImage(image);
|
||||
TrackImage(image, image_id);
|
||||
}
|
||||
|
@ -153,8 +154,7 @@ ImageView& TextureCache::RegisterImageView(Image& image, const ImageViewInfo& vi
|
|||
usage_override = image.info.usage & ~vk::ImageUsageFlagBits::eStorage;
|
||||
}
|
||||
|
||||
const ImageViewId view_id =
|
||||
slot_image_views.insert(instance, view_info, image.image, usage_override);
|
||||
const ImageViewId view_id = slot_image_views.insert(instance, view_info, image, usage_override);
|
||||
image.image_view_infos.emplace_back(view_info);
|
||||
image.image_view_ids.emplace_back(view_id);
|
||||
return slot_image_views[view_id];
|
||||
|
@ -177,6 +177,7 @@ ImageView& TextureCache::RenderTarget(const AmdGpu::Liverpool::ColorBuffer& buff
|
|||
const AmdGpu::Liverpool::CbDbExtent& hint) {
|
||||
const ImageInfo info{buffer, hint};
|
||||
auto& image = FindImage(info, buffer.Address());
|
||||
image.flags &= ~ImageFlagBits::CpuModified;
|
||||
|
||||
image.Transit(vk::ImageLayout::eColorAttachmentOptimal,
|
||||
vk::AccessFlagBits::eColorAttachmentWrite |
|
||||
|
@ -187,6 +188,17 @@ ImageView& TextureCache::RenderTarget(const AmdGpu::Liverpool::ColorBuffer& buff
|
|||
return RegisterImageView(image, view_info);
|
||||
}
|
||||
|
||||
ImageView& TextureCache::DepthTarget(const AmdGpu::Liverpool::DepthBuffer& buffer,
|
||||
const AmdGpu::Liverpool::CbDbExtent& hint) {
|
||||
const ImageInfo info{buffer, hint};
|
||||
auto& image = FindImage(info, buffer.Address(), false);
|
||||
image.flags &= ~ImageFlagBits::CpuModified;
|
||||
|
||||
ImageViewInfo view_info;
|
||||
view_info.format = info.pixel_format;
|
||||
return RegisterImageView(image, view_info);
|
||||
}
|
||||
|
||||
void TextureCache::RefreshImage(Image& image) {
|
||||
// Mark image as validated.
|
||||
image.flags &= ~ImageFlagBits::CpuModified;
|
||||
|
|
|
@ -37,7 +37,8 @@ public:
|
|||
void OnCpuWrite(VAddr address);
|
||||
|
||||
/// Retrieves the image handle of the image with the provided attributes and address.
|
||||
[[nodiscard]] Image& FindImage(const ImageInfo& info, VAddr cpu_address);
|
||||
[[nodiscard]] Image& FindImage(const ImageInfo& info, VAddr cpu_address,
|
||||
bool refresh_on_create = true);
|
||||
|
||||
/// Retrieves an image view with the properties of the specified image descriptor.
|
||||
[[nodiscard]] ImageView& FindImageView(const AmdGpu::Image& image);
|
||||
|
@ -45,6 +46,8 @@ public:
|
|||
/// Retrieves the render target with specified properties
|
||||
[[nodiscard]] ImageView& RenderTarget(const AmdGpu::Liverpool::ColorBuffer& buffer,
|
||||
const AmdGpu::Liverpool::CbDbExtent& hint);
|
||||
[[nodiscard]] ImageView& DepthTarget(const AmdGpu::Liverpool::DepthBuffer& buffer,
|
||||
const AmdGpu::Liverpool::CbDbExtent& hint);
|
||||
|
||||
/// Reuploads image contents.
|
||||
void RefreshImage(Image& image);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue