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 PAddr addr = boost::icl::lower(interval);
|
||||||
const SurfaceParams copy_params = surface.FromInterval(copy_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),
|
.src_level = src_surface.LevelOf(addr),
|
||||||
.dst_level = surface.LevelOf(addr),
|
.dst_level = surface.LevelOf(addr),
|
||||||
.src_rect = src_surface.GetScaledSubRect(copy_params),
|
.src_offset = {src_rect.left, src_rect.bottom},
|
||||||
.dst_rect = surface.GetScaledSubRect(copy_params),
|
.dst_offset = {dst_rect.left, dst_rect.bottom},
|
||||||
|
.extent = {src_rect.GetWidth(), src_rect.GetHeight()},
|
||||||
};
|
};
|
||||||
return runtime.Reinterpret(src_surface, surface, reinterpret);
|
return runtime.Reinterpret(src_surface, surface, reinterpret);
|
||||||
}
|
}
|
||||||
|
@@ -84,7 +84,7 @@ BlitHelper::BlitHelper(const Driver& driver_)
|
|||||||
BlitHelper::~BlitHelper() = default;
|
BlitHelper::~BlitHelper() = default;
|
||||||
|
|
||||||
bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
|
bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
|
||||||
const VideoCore::TextureBlit& blit) {
|
const VideoCore::TextureCopy& copy) {
|
||||||
OpenGLState prev_state = OpenGLState::GetCurState();
|
OpenGLState prev_state = OpenGLState::GetCurState();
|
||||||
SCOPE_EXIT({ prev_state.Apply(); });
|
SCOPE_EXIT({ prev_state.Apply(); });
|
||||||
|
|
||||||
@@ -99,32 +99,35 @@ bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
|
|||||||
1);
|
1);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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.Release();
|
||||||
temp_tex.Create();
|
temp_tex.Create();
|
||||||
state.texture_units[1].texture_2d = temp_tex.handle;
|
state.texture_units[1].texture_2d = temp_tex.handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, blit.src_rect.right,
|
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, temp_extent.width,
|
||||||
blit.src_rect.top);
|
temp_extent.height);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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.texture_units[1].texture_2d = temp_tex.handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
if (!use_texture_view) {
|
if (!use_texture_view) {
|
||||||
glCopyImageSubData(source.Handle(), GL_TEXTURE_2D, 0, blit.src_rect.left,
|
glCopyImageSubData(source.Handle(), GL_TEXTURE_2D, 0, copy.src_offset.x, copy.src_offset.y,
|
||||||
blit.src_rect.bottom, 0, temp_tex.handle, GL_TEXTURE_2D, 0,
|
0, temp_tex.handle, GL_TEXTURE_2D, 0, copy.src_offset.x,
|
||||||
blit.src_rect.left, blit.src_rect.bottom, 0, blit.src_rect.GetWidth(),
|
copy.src_offset.y, 0, copy.extent.width, copy.extent.height, 1);
|
||||||
blit.src_rect.GetHeight(), 1);
|
|
||||||
}
|
}
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
|
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
|
||||||
|
|
||||||
SetParams(d24s8_to_rgba8, source.RealExtent(), blit.src_rect);
|
const Common::Rectangle src_rect{copy.src_offset.x, copy.src_offset.y + copy.extent.height,
|
||||||
Draw(d24s8_to_rgba8, dest.Handle(), draw_fbo.handle, 0, blit.dst_rect);
|
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) {
|
if (use_texture_view) {
|
||||||
temp_tex.Release();
|
temp_tex.Release();
|
||||||
@@ -138,14 +141,18 @@ bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BlitHelper::ConvertRGBA4ToRGB5A1(Surface& source, Surface& dest,
|
bool BlitHelper::ConvertRGBA4ToRGB5A1(Surface& source, Surface& dest,
|
||||||
const VideoCore::TextureBlit& blit) {
|
const VideoCore::TextureCopy& copy) {
|
||||||
OpenGLState prev_state = OpenGLState::GetCurState();
|
OpenGLState prev_state = OpenGLState::GetCurState();
|
||||||
SCOPE_EXIT({ prev_state.Apply(); });
|
SCOPE_EXIT({ prev_state.Apply(); });
|
||||||
|
|
||||||
state.texture_units[0].texture_2d = source.Handle();
|
state.texture_units[0].texture_2d = source.Handle();
|
||||||
|
|
||||||
SetParams(rgba4_to_rgb5a1, source.RealExtent(), blit.src_rect);
|
const Common::Rectangle src_rect{copy.src_offset.x, copy.src_offset.y + copy.extent.height,
|
||||||
Draw(rgba4_to_rgb5a1, dest.Handle(), draw_fbo.handle, 0, blit.dst_rect);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -5,12 +5,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/math_util.h"
|
#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_resource_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_state.h"
|
#include "video_core/renderer_opengl/gl_state.h"
|
||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
struct Extent;
|
struct Extent;
|
||||||
struct TextureBlit;
|
struct TextureBlit;
|
||||||
|
struct TextureCopy;
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
@@ -25,9 +27,9 @@ public:
|
|||||||
|
|
||||||
bool Filter(Surface& surface, const VideoCore::TextureBlit& blit);
|
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:
|
private:
|
||||||
void FilterAnime4K(Surface& surface, const VideoCore::TextureBlit& blit);
|
void FilterAnime4K(Surface& surface, const VideoCore::TextureBlit& blit);
|
||||||
@@ -68,7 +70,7 @@ private:
|
|||||||
OGLProgram rgba4_to_rgb5a1;
|
OGLProgram rgba4_to_rgb5a1;
|
||||||
|
|
||||||
OGLTexture temp_tex;
|
OGLTexture temp_tex;
|
||||||
Common::Rectangle<u32> temp_rect{};
|
VideoCore::Extent temp_extent{};
|
||||||
bool use_texture_view{true};
|
bool use_texture_view{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -170,14 +170,14 @@ const FormatTuple& TextureRuntime::GetFormatTuple(VideoCore::CustomPixelFormat p
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TextureRuntime::Reinterpret(Surface& source, Surface& dest,
|
bool TextureRuntime::Reinterpret(Surface& source, Surface& dest,
|
||||||
const VideoCore::TextureBlit& blit) {
|
const VideoCore::TextureCopy& copy) {
|
||||||
const PixelFormat src_format = source.pixel_format;
|
const PixelFormat src_format = source.pixel_format;
|
||||||
const PixelFormat dst_format = dest.pixel_format;
|
const PixelFormat dst_format = dest.pixel_format;
|
||||||
ASSERT_MSG(src_format != dst_format, "Reinterpretation with the same format is invalid");
|
ASSERT_MSG(src_format != dst_format, "Reinterpretation with the same format is invalid");
|
||||||
if (src_format == PixelFormat::D24S8 && dst_format == PixelFormat::RGBA8) {
|
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) {
|
} else if (src_format == PixelFormat::RGBA4 && dst_format == PixelFormat::RGB5A1) {
|
||||||
blit_helper.ConvertRGBA4ToRGB5A1(source, dest, blit);
|
blit_helper.ConvertRGBA4ToRGB5A1(source, dest, copy);
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(Render_OpenGL, "Unimplemented reinterpretation {} -> {}",
|
LOG_WARNING(Render_OpenGL, "Unimplemented reinterpretation {} -> {}",
|
||||||
VideoCore::PixelFormatAsString(src_format),
|
VideoCore::PixelFormatAsString(src_format),
|
||||||
|
@@ -59,7 +59,7 @@ public:
|
|||||||
const FormatTuple& GetFormatTuple(VideoCore::CustomPixelFormat pixel_format);
|
const FormatTuple& GetFormatTuple(VideoCore::CustomPixelFormat pixel_format);
|
||||||
|
|
||||||
/// Attempts to reinterpret a rectangle of source to another rectangle of dest
|
/// 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
|
/// Fills the rectangle of the texture with the clear value provided
|
||||||
void ClearTexture(Surface& surface, const VideoCore::TextureClear& clear);
|
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,
|
bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
|
||||||
const VideoCore::TextureBlit& blit) {
|
const VideoCore::TextureCopy& copy) {
|
||||||
std::array<DescriptorData, 3> textures{};
|
std::array<DescriptorData, 3> textures{};
|
||||||
textures[0].image_info = vk::DescriptorImageInfo{
|
textures[0].image_info = vk::DescriptorImageInfo{
|
||||||
.imageView = source.DepthView(),
|
.imageView = source.DepthView(),
|
||||||
@@ -315,7 +315,7 @@ bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
|
|||||||
const auto descriptor_set = compute_provider.Acquire(textures);
|
const auto descriptor_set = compute_provider.Acquire(textures);
|
||||||
|
|
||||||
renderpass_cache.EndRendering();
|
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) {
|
dst_image = dest.Image()](vk::CommandBuffer cmdbuf) {
|
||||||
const std::array pre_barriers = {
|
const std::array pre_barriers = {
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
@@ -397,15 +397,15 @@ bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
|
|||||||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, d24s8_to_rgba8_pipeline);
|
cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, d24s8_to_rgba8_pipeline);
|
||||||
|
|
||||||
const ComputeInfo info = {
|
const ComputeInfo info = {
|
||||||
.src_offset = Common::Vec2i{static_cast<int>(blit.src_rect.left),
|
.src_offset = Common::Vec2i{static_cast<int>(copy.src_offset.x),
|
||||||
static_cast<int>(blit.src_rect.bottom)},
|
static_cast<int>(copy.src_offset.y)},
|
||||||
.dst_offset = Common::Vec2i{static_cast<int>(blit.dst_rect.left),
|
.dst_offset = Common::Vec2i{static_cast<int>(copy.dst_offset.x),
|
||||||
static_cast<int>(blit.dst_rect.bottom)},
|
static_cast<int>(copy.dst_offset.y)},
|
||||||
};
|
};
|
||||||
cmdbuf.pushConstants(compute_pipeline_layout, vk::ShaderStageFlagBits::eCompute, 0,
|
cmdbuf.pushConstants(compute_pipeline_layout, vk::ShaderStageFlagBits::eCompute, 0,
|
||||||
sizeof(info), &info);
|
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,
|
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader,
|
||||||
vk::PipelineStageFlagBits::eEarlyFragmentTests |
|
vk::PipelineStageFlagBits::eEarlyFragmentTests |
|
||||||
|
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "video_core/rasterizer_cache/pixel_format.h"
|
|
||||||
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
|
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
|
||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
struct TextureBlit;
|
struct TextureBlit;
|
||||||
|
struct TextureCopy;
|
||||||
struct BufferTextureCopy;
|
struct BufferTextureCopy;
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ public:
|
|||||||
|
|
||||||
bool BlitDepthStencil(Surface& source, Surface& dest, const VideoCore::TextureBlit& blit);
|
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,
|
bool DepthToBuffer(Surface& source, vk::Buffer buffer,
|
||||||
const VideoCore::BufferTextureCopy& copy);
|
const VideoCore::BufferTextureCopy& copy);
|
||||||
|
@@ -198,7 +198,7 @@ bool GraphicsPipeline::Build(bool fail_on_compile_required) {
|
|||||||
.pScissors = &scissor,
|
.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::eViewport, vk::DynamicState::eScissor,
|
||||||
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
|
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
|
||||||
vk::DynamicState::eStencilReference, vk::DynamicState::eBlendConstants,
|
vk::DynamicState::eStencilReference, vk::DynamicState::eBlendConstants,
|
||||||
|
@@ -283,12 +283,19 @@ void TextureRuntime::Finish() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TextureRuntime::Reinterpret(Surface& source, Surface& dest,
|
bool TextureRuntime::Reinterpret(Surface& source, Surface& dest,
|
||||||
const VideoCore::TextureBlit& blit) {
|
const VideoCore::TextureCopy& copy) {
|
||||||
const PixelFormat src_format = source.pixel_format;
|
const PixelFormat src_format = source.pixel_format;
|
||||||
const PixelFormat dst_format = dest.pixel_format;
|
const PixelFormat dst_format = dest.pixel_format;
|
||||||
ASSERT_MSG(src_format != dst_format, "Reinterpretation with the same format is invalid");
|
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) {
|
if (src_format == PixelFormat::D24S8 && dst_format == PixelFormat::RGBA8) {
|
||||||
blit_helper.ConvertDS24S8ToRGBA8(source, dest, blit);
|
blit_helper.ConvertDS24S8ToRGBA8(source, dest, copy);
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(Render_Vulkan, "Unimplemented reinterpretation {} -> {}",
|
LOG_WARNING(Render_Vulkan, "Unimplemented reinterpretation {} -> {}",
|
||||||
VideoCore::PixelFormatAsString(src_format),
|
VideoCore::PixelFormatAsString(src_format),
|
||||||
|
@@ -68,7 +68,7 @@ public:
|
|||||||
VideoCore::StagingData FindStaging(u32 size, bool upload);
|
VideoCore::StagingData FindStaging(u32 size, bool upload);
|
||||||
|
|
||||||
/// Attempts to reinterpret a rectangle of source to another rectangle of dest
|
/// 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
|
/// Fills the rectangle of the texture with the clear value provided
|
||||||
bool ClearTexture(Surface& surface, const VideoCore::TextureClear& clear);
|
bool ClearTexture(Surface& surface, const VideoCore::TextureClear& clear);
|
||||||
|
Reference in New Issue
Block a user