renderer_vulkan: Implement reinterpretation with copy
* Allows reinterpreteration with simply copy on AMD
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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};
|
||||
};
|
||||
|
||||
|
@@ -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),
|
||||
|
@@ -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);
|
||||
|
@@ -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 |
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
|
@@ -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),
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user