renderer_vulkan: Implement reinterpretation with copy

* Allows reinterpreteration with simply copy on AMD
This commit is contained in:
GPUCode
2023-08-20 21:50:29 +03:00
parent 622c20761c
commit 631c777983
10 changed files with 56 additions and 37 deletions

View File

@@ -1147,11 +1147,14 @@ bool RasterizerCache<T>::ValidateByReinterpretation(Surface& surface, SurfacePar
}
const PAddr addr = boost::icl::lower(interval);
const SurfaceParams copy_params = surface.FromInterval(copy_interval);
const TextureBlit reinterpret = {
const auto src_rect = src_surface.GetScaledSubRect(copy_params);
const auto dst_rect = surface.GetScaledSubRect(copy_params);
const TextureCopy reinterpret = {
.src_level = src_surface.LevelOf(addr),
.dst_level = surface.LevelOf(addr),
.src_rect = src_surface.GetScaledSubRect(copy_params),
.dst_rect = surface.GetScaledSubRect(copy_params),
.src_offset = {src_rect.left, src_rect.bottom},
.dst_offset = {dst_rect.left, dst_rect.bottom},
.extent = {src_rect.GetWidth(), src_rect.GetHeight()},
};
return runtime.Reinterpret(src_surface, surface, reinterpret);
}

View File

@@ -84,7 +84,7 @@ BlitHelper::BlitHelper(const Driver& driver_)
BlitHelper::~BlitHelper() = default;
bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
const VideoCore::TextureBlit& blit) {
const VideoCore::TextureCopy& copy) {
OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
@@ -99,32 +99,35 @@ bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
} else if (blit.src_rect.top > temp_rect.top || blit.src_rect.right > temp_rect.right) {
} else if (copy.extent.width > temp_extent.width || copy.extent.height > temp_extent.height) {
temp_extent = copy.extent;
temp_tex.Release();
temp_tex.Create();
state.texture_units[1].texture_2d = temp_tex.handle;
state.Apply();
glActiveTexture(GL_TEXTURE1);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, blit.src_rect.right,
blit.src_rect.top);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, temp_extent.width,
temp_extent.height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
temp_rect = blit.src_rect;
}
state.texture_units[1].texture_2d = temp_tex.handle;
state.Apply();
glActiveTexture(GL_TEXTURE1);
if (!use_texture_view) {
glCopyImageSubData(source.Handle(), GL_TEXTURE_2D, 0, blit.src_rect.left,
blit.src_rect.bottom, 0, temp_tex.handle, GL_TEXTURE_2D, 0,
blit.src_rect.left, blit.src_rect.bottom, 0, blit.src_rect.GetWidth(),
blit.src_rect.GetHeight(), 1);
glCopyImageSubData(source.Handle(), GL_TEXTURE_2D, 0, copy.src_offset.x, copy.src_offset.y,
0, temp_tex.handle, GL_TEXTURE_2D, 0, copy.src_offset.x,
copy.src_offset.y, 0, copy.extent.width, copy.extent.height, 1);
}
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
SetParams(d24s8_to_rgba8, source.RealExtent(), blit.src_rect);
Draw(d24s8_to_rgba8, dest.Handle(), draw_fbo.handle, 0, blit.dst_rect);
const Common::Rectangle src_rect{copy.src_offset.x, copy.src_offset.y + copy.extent.height,
copy.src_offset.x + copy.extent.width, copy.src_offset.x};
const Common::Rectangle dst_rect{copy.dst_offset.x, copy.dst_offset.y + copy.extent.height,
copy.dst_offset.x + copy.extent.width, copy.dst_offset.x};
SetParams(d24s8_to_rgba8, source.RealExtent(), src_rect);
Draw(d24s8_to_rgba8, dest.Handle(), draw_fbo.handle, 0, dst_rect);
if (use_texture_view) {
temp_tex.Release();
@@ -138,14 +141,18 @@ bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
}
bool BlitHelper::ConvertRGBA4ToRGB5A1(Surface& source, Surface& dest,
const VideoCore::TextureBlit& blit) {
const VideoCore::TextureCopy& copy) {
OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
state.texture_units[0].texture_2d = source.Handle();
SetParams(rgba4_to_rgb5a1, source.RealExtent(), blit.src_rect);
Draw(rgba4_to_rgb5a1, dest.Handle(), draw_fbo.handle, 0, blit.dst_rect);
const Common::Rectangle src_rect{copy.src_offset.x, copy.src_offset.y + copy.extent.height,
copy.src_offset.x + copy.extent.width, copy.src_offset.x};
const Common::Rectangle dst_rect{copy.dst_offset.x, copy.dst_offset.y + copy.extent.height,
copy.dst_offset.x + copy.extent.width, copy.dst_offset.x};
SetParams(rgba4_to_rgb5a1, source.RealExtent(), src_rect);
Draw(rgba4_to_rgb5a1, dest.Handle(), draw_fbo.handle, 0, dst_rect);
return true;
}

View File

@@ -5,12 +5,14 @@
#pragma once
#include "common/math_util.h"
#include "video_core/rasterizer_cache/utils.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_state.h"
namespace VideoCore {
struct Extent;
struct TextureBlit;
struct TextureCopy;
} // namespace VideoCore
namespace OpenGL {
@@ -25,9 +27,9 @@ public:
bool Filter(Surface& surface, const VideoCore::TextureBlit& blit);
bool ConvertDS24S8ToRGBA8(Surface& source, Surface& dest, const VideoCore::TextureBlit& blit);
bool ConvertDS24S8ToRGBA8(Surface& source, Surface& dest, const VideoCore::TextureCopy& copy);
bool ConvertRGBA4ToRGB5A1(Surface& source, Surface& dest, const VideoCore::TextureBlit& blit);
bool ConvertRGBA4ToRGB5A1(Surface& source, Surface& dest, const VideoCore::TextureCopy& copy);
private:
void FilterAnime4K(Surface& surface, const VideoCore::TextureBlit& blit);
@@ -68,7 +70,7 @@ private:
OGLProgram rgba4_to_rgb5a1;
OGLTexture temp_tex;
Common::Rectangle<u32> temp_rect{};
VideoCore::Extent temp_extent{};
bool use_texture_view{true};
};

View File

@@ -170,14 +170,14 @@ const FormatTuple& TextureRuntime::GetFormatTuple(VideoCore::CustomPixelFormat p
}
bool TextureRuntime::Reinterpret(Surface& source, Surface& dest,
const VideoCore::TextureBlit& blit) {
const VideoCore::TextureCopy& copy) {
const PixelFormat src_format = source.pixel_format;
const PixelFormat dst_format = dest.pixel_format;
ASSERT_MSG(src_format != dst_format, "Reinterpretation with the same format is invalid");
if (src_format == PixelFormat::D24S8 && dst_format == PixelFormat::RGBA8) {
blit_helper.ConvertDS24S8ToRGBA8(source, dest, blit);
blit_helper.ConvertDS24S8ToRGBA8(source, dest, copy);
} else if (src_format == PixelFormat::RGBA4 && dst_format == PixelFormat::RGB5A1) {
blit_helper.ConvertRGBA4ToRGB5A1(source, dest, blit);
blit_helper.ConvertRGBA4ToRGB5A1(source, dest, copy);
} else {
LOG_WARNING(Render_OpenGL, "Unimplemented reinterpretation {} -> {}",
VideoCore::PixelFormatAsString(src_format),

View File

@@ -59,7 +59,7 @@ public:
const FormatTuple& GetFormatTuple(VideoCore::CustomPixelFormat pixel_format);
/// Attempts to reinterpret a rectangle of source to another rectangle of dest
bool Reinterpret(Surface& source, Surface& dest, const VideoCore::TextureBlit& blit);
bool Reinterpret(Surface& source, Surface& dest, const VideoCore::TextureCopy& copy);
/// Fills the rectangle of the texture with the clear value provided
void ClearTexture(Surface& surface, const VideoCore::TextureClear& clear);

View File

@@ -297,7 +297,7 @@ bool BlitHelper::BlitDepthStencil(Surface& source, Surface& dest,
}
bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
const VideoCore::TextureBlit& blit) {
const VideoCore::TextureCopy& copy) {
std::array<DescriptorData, 3> textures{};
textures[0].image_info = vk::DescriptorImageInfo{
.imageView = source.DepthView(),
@@ -315,7 +315,7 @@ bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
const auto descriptor_set = compute_provider.Acquire(textures);
renderpass_cache.EndRendering();
scheduler.Record([this, descriptor_set, blit, src_image = source.Image(),
scheduler.Record([this, descriptor_set, copy, src_image = source.Image(),
dst_image = dest.Image()](vk::CommandBuffer cmdbuf) {
const std::array pre_barriers = {
vk::ImageMemoryBarrier{
@@ -397,15 +397,15 @@ bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, d24s8_to_rgba8_pipeline);
const ComputeInfo info = {
.src_offset = Common::Vec2i{static_cast<int>(blit.src_rect.left),
static_cast<int>(blit.src_rect.bottom)},
.dst_offset = Common::Vec2i{static_cast<int>(blit.dst_rect.left),
static_cast<int>(blit.dst_rect.bottom)},
.src_offset = Common::Vec2i{static_cast<int>(copy.src_offset.x),
static_cast<int>(copy.src_offset.y)},
.dst_offset = Common::Vec2i{static_cast<int>(copy.dst_offset.x),
static_cast<int>(copy.dst_offset.y)},
};
cmdbuf.pushConstants(compute_pipeline_layout, vk::ShaderStageFlagBits::eCompute, 0,
sizeof(info), &info);
cmdbuf.dispatch(blit.src_rect.GetWidth() / 8, blit.src_rect.GetHeight() / 8, 1);
cmdbuf.dispatch(copy.extent.width / 8, copy.extent.height / 8, 1);
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader,
vk::PipelineStageFlagBits::eEarlyFragmentTests |

View File

@@ -4,11 +4,11 @@
#pragma once
#include "video_core/rasterizer_cache/pixel_format.h"
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
namespace VideoCore {
struct TextureBlit;
struct TextureCopy;
struct BufferTextureCopy;
} // namespace VideoCore
@@ -29,7 +29,7 @@ public:
bool BlitDepthStencil(Surface& source, Surface& dest, const VideoCore::TextureBlit& blit);
bool ConvertDS24S8ToRGBA8(Surface& source, Surface& dest, const VideoCore::TextureBlit& blit);
bool ConvertDS24S8ToRGBA8(Surface& source, Surface& dest, const VideoCore::TextureCopy& copy);
bool DepthToBuffer(Surface& source, vk::Buffer buffer,
const VideoCore::BufferTextureCopy& copy);

View File

@@ -198,7 +198,7 @@ bool GraphicsPipeline::Build(bool fail_on_compile_required) {
.pScissors = &scissor,
};
boost::container::static_vector<vk::DynamicState, 20> dynamic_states = {
boost::container::static_vector<vk::DynamicState, 14> dynamic_states = {
vk::DynamicState::eViewport, vk::DynamicState::eScissor,
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
vk::DynamicState::eStencilReference, vk::DynamicState::eBlendConstants,

View File

@@ -283,12 +283,19 @@ void TextureRuntime::Finish() {
}
bool TextureRuntime::Reinterpret(Surface& source, Surface& dest,
const VideoCore::TextureBlit& blit) {
const VideoCore::TextureCopy& copy) {
const PixelFormat src_format = source.pixel_format;
const PixelFormat dst_format = dest.pixel_format;
ASSERT_MSG(src_format != dst_format, "Reinterpretation with the same format is invalid");
if (!source.traits.needs_conversion && !dest.traits.needs_conversion &&
source.type == dest.type) {
CopyTextures(source, dest, copy);
return true;
}
if (src_format == PixelFormat::D24S8 && dst_format == PixelFormat::RGBA8) {
blit_helper.ConvertDS24S8ToRGBA8(source, dest, blit);
blit_helper.ConvertDS24S8ToRGBA8(source, dest, copy);
} else {
LOG_WARNING(Render_Vulkan, "Unimplemented reinterpretation {} -> {}",
VideoCore::PixelFormatAsString(src_format),

View File

@@ -68,7 +68,7 @@ public:
VideoCore::StagingData FindStaging(u32 size, bool upload);
/// Attempts to reinterpret a rectangle of source to another rectangle of dest
bool Reinterpret(Surface& source, Surface& dest, const VideoCore::TextureBlit& blit);
bool Reinterpret(Surface& source, Surface& dest, const VideoCore::TextureCopy& copy);
/// Fills the rectangle of the texture with the clear value provided
bool ClearTexture(Surface& surface, const VideoCore::TextureClear& clear);