rsx: Blit engine fixes

- Ignore unlocked blit sections [TODO]
- Do not attempt blit on hw if bytesize is unsupported
- gl: Implement typeless memory transfers
  Uses pbo to handle type-agnostic memory transfer
This commit is contained in:
kd-11 2018-04-07 18:16:52 +03:00 committed by kd-11
parent bb5622401c
commit 9abbbb79ae
9 changed files with 304 additions and 74 deletions

View File

@ -29,6 +29,34 @@ namespace rsx
flush_once = 1 flush_once = 1
}; };
struct typeless_xfer
{
bool src_is_typeless = false;
bool dst_is_typeless = false;
bool src_is_depth = false;
bool dst_is_depth = false;
u32 src_gcm_format = 0;
u32 dst_gcm_format = 0;
f32 src_scaling_hint = 1.f;
f32 dst_scaling_hint = 1.f;
void analyse()
{
if (src_is_typeless && dst_is_typeless)
{
if (src_scaling_hint == dst_scaling_hint &&
src_scaling_hint != 1.f)
{
if (src_is_depth == dst_is_depth)
{
src_is_typeless = dst_is_typeless = false;
src_scaling_hint = dst_scaling_hint = 1.f;
}
}
}
}
};
struct cached_texture_section : public rsx::buffered_section struct cached_texture_section : public rsx::buffered_section
{ {
u16 width; u16 width;
@ -76,7 +104,7 @@ namespace rsx
if (depth && depth != this->depth) if (depth && depth != this->depth)
return false; return false;
if (mipmaps && mipmaps != this->mipmaps) if (mipmaps && mipmaps > this->mipmaps)
return false; return false;
return true; return true;
@ -1717,7 +1745,8 @@ namespace rsx
{ {
for (const auto &surface : overlapping_surfaces) for (const auto &surface : overlapping_surfaces)
{ {
if (surface->get_context() != rsx::texture_upload_context::blit_engine_dst) if (surface->get_context() != rsx::texture_upload_context::blit_engine_dst ||
!surface->is_locked())
continue; continue;
if (surface->get_width() >= tex_width && surface->get_height() >= tex_height) if (surface->get_width() >= tex_width && surface->get_height() >= tex_height)
@ -1791,19 +1820,23 @@ namespace rsx
bool dst_is_argb8 = (dst.format == rsx::blit_engine::transfer_destination_format::a8r8g8b8); bool dst_is_argb8 = (dst.format == rsx::blit_engine::transfer_destination_format::a8r8g8b8);
bool src_is_argb8 = (src.format == rsx::blit_engine::transfer_source_format::a8r8g8b8); bool src_is_argb8 = (src.format == rsx::blit_engine::transfer_source_format::a8r8g8b8);
typeless_xfer typeless_info = {};
image_resource_type vram_texture = 0; image_resource_type vram_texture = 0;
image_resource_type dest_texture = 0; image_resource_type dest_texture = 0;
const u32 src_address = (u32)((u64)src.pixels - (u64)vm::base(0)); const u32 src_address = (u32)((u64)src.pixels - (u64)vm::base(0));
const u32 dst_address = (u32)((u64)dst.pixels - (u64)vm::base(0)); const u32 dst_address = (u32)((u64)dst.pixels - (u64)vm::base(0));
float scale_x = dst.scale_x; f32 scale_x = dst.scale_x;
float scale_y = dst.scale_y; f32 scale_y = dst.scale_y;
//Offset in x and y for src is 0 (it is already accounted for when getting pixels_src) //Offset in x and y for src is 0 (it is already accounted for when getting pixels_src)
//Reproject final clip onto source... //Reproject final clip onto source...
const u16 src_w = (const u16)((f32)dst.clip_width / scale_x); u16 src_w = (const u16)((f32)dst.clip_width / scale_x);
const u16 src_h = (const u16)((f32)dst.clip_height / scale_y); u16 src_h = (const u16)((f32)dst.clip_height / scale_y);
u16 dst_w = dst.clip_width;
u16 dst_h = dst.clip_height;
//Check if src/dst are parts of render targets //Check if src/dst are parts of render targets
auto dst_subres = m_rtts.get_surface_subresource_if_applicable(dst_address, dst.width, dst.clip_height, dst.pitch, true, false, false); auto dst_subres = m_rtts.get_surface_subresource_if_applicable(dst_address, dst.width, dst.clip_height, dst.pitch, true, false, false);
@ -1847,6 +1880,51 @@ namespace rsx
if (!g_cfg.video.use_gpu_texture_scaling && !(src_is_render_target || dst_is_render_target)) if (!g_cfg.video.use_gpu_texture_scaling && !(src_is_render_target || dst_is_render_target))
return false; return false;
if (src_is_render_target)
{
const auto surf = src_subres.surface;
auto src_bpp = surf->get_native_pitch() / surf->get_surface_width();
auto expected_bpp = src_is_argb8 ? 4 : 2;
if (src_bpp != expected_bpp)
{
//Enable type scaling in src
typeless_info.src_is_typeless = true;
typeless_info.src_is_depth = src_subres.is_depth_surface;
typeless_info.src_scaling_hint = (f32)src_bpp / expected_bpp;
typeless_info.src_gcm_format = src_is_argb8 ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_R5G6B5;
src_w = (u16)(src_w / typeless_info.src_scaling_hint);
if (!src_subres.is_clipped)
src_subres.w = (u16)(src_subres.w / typeless_info.src_scaling_hint);
else
src_subres = m_rtts.get_surface_subresource_if_applicable(src_address, src_w, src_h, src.pitch, true, false, false);
verify(HERE), src_subres.surface != nullptr;
}
}
if (dst_is_render_target)
{
auto dst_bpp = dst_subres.surface->get_native_pitch() / dst_subres.surface->get_surface_width();
auto expected_bpp = dst_is_argb8 ? 4 : 2;
if (dst_bpp != expected_bpp)
{
//Enable type scaling in dst
typeless_info.dst_is_typeless = true;
typeless_info.dst_is_depth = dst_subres.is_depth_surface;
typeless_info.dst_scaling_hint = (f32)dst_bpp / expected_bpp;
typeless_info.dst_gcm_format = dst_is_argb8 ? CELL_GCM_TEXTURE_A8R8G8B8 : CELL_GCM_TEXTURE_R5G6B5;
dst_w = (u16)(dst_w / typeless_info.dst_scaling_hint);
if (!dst_subres.is_clipped)
dst_subres.w = (u16)(dst_subres.w / typeless_info.dst_scaling_hint);
else
dst_subres = m_rtts.get_surface_subresource_if_applicable(dst_address, dst_w, dst_h, dst.pitch, true, false, false);
verify(HERE), dst_subres.surface != nullptr;
}
}
reader_lock lock(m_cache_mutex); reader_lock lock(m_cache_mutex);
//Check if trivial memcpy can perform the same task //Check if trivial memcpy can perform the same task
@ -1870,7 +1948,7 @@ namespace rsx
u16 max_dst_width = dst.width; u16 max_dst_width = dst.width;
u16 max_dst_height = dst.height; u16 max_dst_height = dst.height;
areai src_area = { 0, 0, src_w, src_h }; areai src_area = { 0, 0, src_w, src_h };
areai dst_area = { 0, 0, dst.clip_width, dst.clip_height }; areai dst_area = { 0, 0, dst_w, dst_h };
//1024 height is a hack (for ~720p buffers) //1024 height is a hack (for ~720p buffers)
//It is possible to have a large buffer that goes up to around 4kx4k but anything above 1280x720 is rare //It is possible to have a large buffer that goes up to around 4kx4k but anything above 1280x720 is rare
@ -1948,7 +2026,7 @@ namespace rsx
dest_texture = dst_subres.surface->get_surface(); dest_texture = dst_subres.surface->get_surface();
max_dst_width = dst_subres.surface->get_surface_width(); max_dst_width = (u16)(dst_subres.surface->get_surface_width() * typeless_info.dst_scaling_hint);
max_dst_height = dst_subres.surface->get_surface_height(); max_dst_height = dst_subres.surface->get_surface_height();
} }
@ -2019,7 +2097,7 @@ namespace rsx
u16 src_subres_h = src_subres.h; u16 src_subres_h = src_subres.h;
get_rsx_dimensions(src_subres_w, src_subres_h, src_subres.surface); get_rsx_dimensions(src_subres_w, src_subres_h, src_subres.surface);
const int dst_width = (int)(src_subres_w * scale_x); const int dst_width = (int)(src_subres_w * scale_x * typeless_info.src_scaling_hint);
const int dst_height = (int)(src_subres_h * scale_y); const int dst_height = (int)(src_subres_h * scale_y);
dst_area.x2 = dst_area.x1 + dst_width; dst_area.x2 = dst_area.x1 + dst_width;
@ -2055,14 +2133,37 @@ namespace rsx
} }
else if (src_is_render_target && cached_dest) else if (src_is_render_target && cached_dest)
{ {
if (!cached_dest->has_compatible_format(src_subres.surface)) switch (cached_dest->get_gcm_format())
{
case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_DEPTH24_D8:
format_mismatch = !dst_is_argb8;
break;
case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_DEPTH16:
format_mismatch = dst_is_argb8;
break;
default:
format_mismatch = true; format_mismatch = true;
break;
}
} }
//TODO: Check for other types of format mismatch //TODO: Check for other types of format mismatch
if (format_mismatch) if (format_mismatch)
{ {
lock.upgrade(); lock.upgrade();
//Mark for removal as the memory is not reusable now
if (cached_dest->is_locked())
{
cached_dest->unprotect();
m_cache[get_block_address(cached_dest->get_section_base())].remove_one();
}
cached_dest->set_dirty(true);
m_unreleased_texture_objects++;
invalidate_range_impl_base(cached_dest->get_section_base(), cached_dest->get_section_size(), true, false, false, true, std::forward<Args>(extras)...); invalidate_range_impl_base(cached_dest->get_section_base(), cached_dest->get_section_size(), true, false, false, true, std::forward<Args>(extras)...);
dest_texture = 0; dest_texture = 0;
@ -2097,7 +2198,7 @@ namespace rsx
//Reproject clip offsets onto source to simplify blit //Reproject clip offsets onto source to simplify blit
if (dst.clip_x || dst.clip_y) if (dst.clip_x || dst.clip_y)
{ {
const u16 scaled_clip_offset_x = (const u16)((f32)dst.clip_x / scale_x); const u16 scaled_clip_offset_x = (const u16)((f32)dst.clip_x / (scale_x * typeless_info.src_scaling_hint));
const u16 scaled_clip_offset_y = (const u16)((f32)dst.clip_y / scale_y); const u16 scaled_clip_offset_y = (const u16)((f32)dst.clip_y / scale_y);
src_area.x1 += scaled_clip_offset_x; src_area.x1 += scaled_clip_offset_x;
@ -2140,14 +2241,42 @@ namespace rsx
cached_dest->touch(); cached_dest->touch();
} }
const f32 scale = rsx::get_resolution_scale(); if (rsx::get_resolution_scale_percent() != 100)
if (src_is_render_target) {
src_area = src_area * scale; const f32 resolution_scale = rsx::get_resolution_scale();
if (src_is_render_target)
{
if (src_subres.surface->get_surface_width() > g_cfg.video.min_scalable_dimension)
{
src_area.x1 = (u16)(src_area.x1 * resolution_scale);
src_area.x2 = (u16)(src_area.x2 * resolution_scale);
}
if (dst_is_render_target) if (src_subres.surface->get_surface_height() > g_cfg.video.min_scalable_dimension)
dst_area = dst_area * scale; {
src_area.y1 = (u16)(src_area.y1 * resolution_scale);
src_area.y2 = (u16)(src_area.y2 * resolution_scale);
}
}
blitter.scale_image(vram_texture, dest_texture, src_area, dst_area, interpolate, is_depth_blit); if (dst_is_render_target)
{
if (dst_subres.surface->get_surface_width() > g_cfg.video.min_scalable_dimension)
{
dst_area.x1 = (u16)(dst_area.x1 * resolution_scale);
dst_area.x2 = (u16)(dst_area.x2 * resolution_scale);
}
if (dst_subres.surface->get_surface_height() > g_cfg.video.min_scalable_dimension)
{
dst_area.y1 = (u16)(dst_area.y1 * resolution_scale);
dst_area.y2 = (u16)(dst_area.y2 * resolution_scale);
}
}
}
typeless_info.analyse();
blitter.scale_image(vram_texture, dest_texture, src_area, dst_area, interpolate, is_depth_blit, typeless_info);
notify_surface_changed(dst.rsx_address); notify_surface_changed(dst.rsx_address);
blit_op_result result = true; blit_op_result result = true;

View File

@ -737,24 +737,24 @@ namespace gl
glGenBuffers(1, &m_id); glGenBuffers(1, &m_id);
} }
void create(GLsizeiptr size, const void* data_ = nullptr) void create(GLsizeiptr size, const void* data_ = nullptr, GLenum usage = GL_STREAM_DRAW)
{ {
create(); create();
data(size, data_); data(size, data_, usage);
} }
void create(target target_, GLsizeiptr size, const void* data_ = nullptr) void create(target target_, GLsizeiptr size, const void* data_ = nullptr, GLenum usage = GL_STREAM_DRAW)
{ {
create(); create();
m_target = target_; m_target = target_;
data(size, data_); data(size, data_, usage);
} }
void data(GLsizeiptr size, const void* data_ = nullptr) void data(GLsizeiptr size, const void* data_ = nullptr, GLenum usage = GL_STREAM_DRAW)
{ {
target target_ = current_target(); target target_ = current_target();
save_binding_state save(target_, *this); save_binding_state save(target_, *this);
glBufferData((GLenum)target_, size, data_, GL_STREAM_DRAW); glBufferData((GLenum)target_, size, data_, usage);
m_size = size; m_size = size;
} }

View File

@ -80,7 +80,7 @@ depth_format rsx::internals::surface_depth_format_to_gl(rsx::surface_depth_forma
LOG_ERROR(RSX, "Surface depth buffer: Unsupported surface depth format (0x%x)", (u32)depth_format); LOG_ERROR(RSX, "Surface depth buffer: Unsupported surface depth format (0x%x)", (u32)depth_format);
case rsx::surface_depth_format::z24s8: case rsx::surface_depth_format::z24s8:
if (g_cfg.video.force_high_precision_z_buffer && ::gl::get_driver_caps().ARB_depth_buffer_float_supported) if (g_cfg.video.force_high_precision_z_buffer && ::gl::get_driver_caps().ARB_depth_buffer_float_supported)
return{ ::gl::texture::type::float32_uint8, ::gl::texture::format::depth_stencil, ::gl::texture::internal_format::depth32f_stencil8 }; return{ ::gl::texture::type::uint_24_8, ::gl::texture::format::depth_stencil, ::gl::texture::internal_format::depth32f_stencil8 };
else else
return{ ::gl::texture::type::uint_24_8, ::gl::texture::format::depth_stencil, ::gl::texture::internal_format::depth24_stencil8 }; return{ ::gl::texture::type::uint_24_8, ::gl::texture::format::depth_stencil, ::gl::texture::internal_format::depth24_stencil8 };
} }

View File

@ -1,6 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "GLTexture.h" #include "GLTexture.h"
#include "GLHelpers.h"
#include "../GCM.h" #include "../GCM.h"
#include "../RSXThread.h" #include "../RSXThread.h"
#include "../RSXTexture.h" #include "../RSXTexture.h"
@ -8,6 +7,8 @@
namespace gl namespace gl
{ {
static buffer g_typeless_transfer_buffer;
GLenum get_target(rsx::texture_dimension_extended type) GLenum get_target(rsx::texture_dimension_extended type)
{ {
switch (type) switch (type)
@ -90,6 +91,38 @@ namespace gl
fmt::throw_exception("Compressed or unknown texture format 0x%x" HERE, texture_format); fmt::throw_exception("Compressed or unknown texture format 0x%x" HERE, texture_format);
} }
std::tuple<GLenum, GLenum, bool> get_format_type(texture::internal_format format)
{
switch (format)
{
case texture::internal_format::compressed_rgba_s3tc_dxt1:
case texture::internal_format::compressed_rgba_s3tc_dxt3:
case texture::internal_format::compressed_rgba_s3tc_dxt5:
return std::make_tuple(GL_RGBA, GL_UNSIGNED_BYTE, false);
case texture::internal_format::r8:
return std::make_tuple(GL_R, GL_UNSIGNED_BYTE, false);
case texture::internal_format::r32f:
return std::make_tuple(GL_R, GL_FLOAT, true);
case texture::internal_format::r5g6b5:
return std::make_tuple(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, true);
case texture::internal_format::rg8:
return std::make_tuple(GL_RG, GL_UNSIGNED_BYTE, false);
case texture::internal_format::rgba8:
return std::make_tuple(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, false);
case texture::internal_format::rgba16f:
return std::make_tuple(GL_RGBA, GL_HALF_FLOAT, true);
case texture::internal_format::rgba32f:
return std::make_tuple(GL_RGBA, GL_FLOAT, true);
case texture::internal_format::depth16:
return std::make_tuple(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, true);
case texture::internal_format::depth24_stencil8:
case texture::internal_format::depth32f_stencil8:
return std::make_tuple(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, true);
default:
fmt::throw_exception("Unexpected internal format 0x%X" HERE, (u32)format);
}
}
GLenum get_srgb_format(GLenum in_format) GLenum get_srgb_format(GLenum in_format)
{ {
switch (in_format) switch (in_format)
@ -562,4 +595,32 @@ namespace gl
const GLenum gl_type = std::get<1>(format_type); const GLenum gl_type = std::get<1>(format_type);
fill_texture(type, mipmaps, gcm_format, width, height, depth, subresources_layout, is_swizzled, gl_format, gl_type, data_upload_buf); fill_texture(type, mipmaps, gcm_format, width, height, depth, subresources_layout, is_swizzled, gl_format, gl_type, data_upload_buf);
} }
void copy_typeless(texture * dst, const texture * src)
{
GLsizeiptr src_mem = src->width() * src->height();
GLsizeiptr dst_mem = dst->width() * dst->height();
auto max_mem = std::max(src_mem, dst_mem) * 16;
if (!g_typeless_transfer_buffer || max_mem > g_typeless_transfer_buffer.size())
{
if (g_typeless_transfer_buffer) g_typeless_transfer_buffer.remove();
g_typeless_transfer_buffer.create(buffer::target::pixel_pack, max_mem, nullptr, GL_STATIC_COPY);
}
auto format_type = get_format_type(src->get_internal_format());
pixel_pack_settings pack_settings{};
pack_settings.swap_bytes(std::get<2>(format_type));
g_typeless_transfer_buffer.bind(buffer::target::pixel_pack);
src->copy_to(nullptr, (texture::format)std::get<0>(format_type), (texture::type)std::get<1>(format_type), pack_settings);
format_type = get_format_type(dst->get_internal_format());
pixel_unpack_settings unpack_settings{};
unpack_settings.swap_bytes(std::get<2>(format_type));
g_typeless_transfer_buffer.bind(buffer::target::pixel_unpack);
dst->copy_from(nullptr, (texture::format)std::get<0>(format_type), (texture::type)std::get<1>(format_type), unpack_settings);
glBindBuffer(GL_PIXEL_PACK_BUFFER, GL_NONE);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, GL_NONE);
}
} }

View File

@ -1,6 +1,7 @@
#include "OpenGL.h" #include "OpenGL.h"
#include "../GCM.h" #include "../GCM.h"
#include "../Common/TextureUtils.h" #include "../Common/TextureUtils.h"
#include "GLHelpers.h"
namespace rsx namespace rsx
{ {
@ -10,17 +11,17 @@ namespace rsx
namespace gl namespace gl
{ {
class texture;
GLenum get_target(rsx::texture_dimension_extended type); GLenum get_target(rsx::texture_dimension_extended type);
GLenum get_sized_internal_format(u32 gcm_format); GLenum get_sized_internal_format(u32 gcm_format);
std::tuple<GLenum, GLenum> get_format_type(u32 texture_format); std::tuple<GLenum, GLenum> get_format_type(u32 texture_format);
std::tuple<GLenum, GLenum, bool> get_format_type(texture::internal_format format);
GLenum wrap_mode(rsx::texture_wrap_mode wrap); GLenum wrap_mode(rsx::texture_wrap_mode wrap);
float max_aniso(rsx::texture_max_anisotropy aniso); float max_aniso(rsx::texture_max_anisotropy aniso);
std::array<GLenum, 4> get_swizzle_remap(u32 texture_format); std::array<GLenum, 4> get_swizzle_remap(u32 texture_format);
texture* create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace); texture* create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type, rsx::texture_colorspace colorspace);
void copy_typeless(texture* dst, const texture* src);
/** /**
* is_swizzled - determines whether input bytes are in morton order * is_swizzled - determines whether input bytes are in morton order
* subresources_layout - descriptor of the mipmap levels in memory * subresources_layout - descriptor of the mipmap levels in memory

View File

@ -27,6 +27,7 @@ namespace gl
class blitter; class blitter;
extern GLenum get_sized_internal_format(u32); extern GLenum get_sized_internal_format(u32);
extern void copy_typeless(texture*, const texture*);
extern blitter *g_hw_blitter; extern blitter *g_hw_blitter;
class blitter class blitter
@ -48,8 +49,38 @@ namespace gl
blit_src.remove(); blit_src.remove();
} }
void scale_image(texture* src, texture* dst, areai src_rect, areai dst_rect, bool linear_interpolation, bool is_depth_copy) void scale_image(const texture* src, texture* dst, areai src_rect, areai dst_rect, bool linear_interpolation,
bool is_depth_copy, const rsx::typeless_xfer& xfer_info)
{ {
std::unique_ptr<texture> typeless_src;
std::unique_ptr<texture> typeless_dst;
u32 src_id = src->id();
u32 dst_id = dst->id();
if (xfer_info.src_is_typeless)
{
const auto internal_width = (u16)(src->width() * xfer_info.src_scaling_hint);
const auto internal_fmt = get_sized_internal_format(xfer_info.src_gcm_format);
typeless_src = std::make_unique<texture>(GL_TEXTURE_2D, internal_width, src->height(), 1, 1, internal_fmt);
copy_typeless(typeless_src.get(), src);
src_id = typeless_src->id();
src_rect.x1 = (u16)(src_rect.x1 * xfer_info.src_scaling_hint);
src_rect.x2 = (u16)(src_rect.x2 * xfer_info.src_scaling_hint);
}
if (xfer_info.dst_is_typeless)
{
const auto internal_width = (u16)(dst->width() * xfer_info.dst_scaling_hint);
const auto internal_fmt = get_sized_internal_format(xfer_info.dst_gcm_format);
typeless_dst = std::make_unique<texture>(GL_TEXTURE_2D, internal_width, dst->height(), 1, 1, internal_fmt);
copy_typeless(typeless_dst.get(), dst);
dst_id = typeless_dst->id();
dst_rect.x1 = (u16)(dst_rect.x1 * xfer_info.dst_scaling_hint);
dst_rect.x2 = (u16)(dst_rect.x2 * xfer_info.dst_scaling_hint);
}
s32 old_fbo = 0; s32 old_fbo = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo);
@ -57,11 +88,11 @@ namespace gl
GLenum attachment = is_depth_copy ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0; GLenum attachment = is_depth_copy ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0;
blit_src.bind(); blit_src.bind();
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, src->id(), 0); glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, src_id, 0);
blit_src.check(); blit_src.check();
blit_dst.bind(); blit_dst.bind();
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, dst->id(), 0); glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, dst_id, 0);
blit_dst.check(); blit_dst.check();
GLboolean scissor_test_enabled = glIsEnabled(GL_SCISSOR_TEST); GLboolean scissor_test_enabled = glIsEnabled(GL_SCISSOR_TEST);
@ -70,6 +101,12 @@ namespace gl
blit_src.blit(blit_dst, src_rect, dst_rect, is_depth_copy ? buffers::depth : buffers::color, interp); blit_src.blit(blit_dst, src_rect, dst_rect, is_depth_copy ? buffers::depth : buffers::color, interp);
if (xfer_info.dst_is_typeless)
{
//Transfer contents from typeless dst back to original dst
copy_typeless(dst, typeless_dst.get());
}
blit_src.bind(); blit_src.bind();
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0);
@ -360,7 +397,7 @@ namespace gl
} }
bool linear_interp = false; //TODO: Make optional or detect full sized sources bool linear_interp = false; //TODO: Make optional or detect full sized sources
g_hw_blitter->scale_image(vram_texture, scaled_texture.get(), src_area, dst_area, linear_interp, is_depth); g_hw_blitter->scale_image(vram_texture, scaled_texture.get(), src_area, dst_area, linear_interp, is_depth, {});
target_texture = scaled_texture->id(); target_texture = scaled_texture->id();
} }
} }
@ -380,7 +417,7 @@ namespace gl
if (GLenum err = glGetError()) if (GLenum err = glGetError())
{ {
bool recovered = false; bool recovered = false;
if (target_texture == scaled_texture->id()) if (scaled_texture && (target_texture == scaled_texture->id()))
{ {
if (get_driver_caps().EXT_dsa_supported) if (get_driver_caps().EXT_dsa_supported)
glGetTextureImageEXT(vram_texture->id(), GL_TEXTURE_2D, 0, (GLenum)format, (GLenum)type, nullptr); glGetTextureImageEXT(vram_texture->id(), GL_TEXTURE_2D, 0, (GLenum)format, (GLenum)type, nullptr);
@ -861,6 +898,7 @@ namespace gl
cached.set_depth_flag(depth_flag); cached.set_depth_flag(depth_flag);
cached.set_view_flags(flags); cached.set_view_flags(flags);
cached.set_context(context); cached.set_context(context);
cached.set_gcm_format(gcm_format);
cached.set_sampler_status(rsx::texture_sampler_status::status_uninitialized); cached.set_sampler_status(rsx::texture_sampler_status::status_uninitialized);
cached.set_image_type(type); cached.set_image_type(type);

View File

@ -973,6 +973,7 @@ namespace vk
region.create(width, height, section_depth, mipmaps, view, image, 0, true, gcm_format); region.create(width, height, section_depth, mipmaps, view, image, 0, true, gcm_format);
region.set_dirty(false); region.set_dirty(false);
region.set_context(context); region.set_context(context);
region.set_gcm_format(gcm_format);
region.set_sampler_status(rsx::texture_sampler_status::status_uninitialized); region.set_sampler_status(rsx::texture_sampler_status::status_uninitialized);
region.set_image_type(type); region.set_image_type(type);
@ -1275,7 +1276,7 @@ namespace vk
vk::image* deferred_op_src = nullptr; vk::image* deferred_op_src = nullptr;
vk::image* deferred_op_dst = nullptr; vk::image* deferred_op_dst = nullptr;
void scale_image(vk::image* src, vk::image* dst, areai src_area, areai dst_area, bool /*interpolate*/, bool is_depth) void scale_image(vk::image* src, vk::image* dst, areai src_area, areai dst_area, bool /*interpolate*/, bool is_depth, const rsx::typeless_xfer& /*typeless*/)
{ {
VkImageAspectFlagBits aspect = VK_IMAGE_ASPECT_COLOR_BIT; VkImageAspectFlagBits aspect = VK_IMAGE_ASPECT_COLOR_BIT;
if (is_depth) aspect = (VkImageAspectFlagBits)(src->info.format == VK_FORMAT_D16_UNORM ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); if (is_depth) aspect = (VkImageAspectFlagBits)(src->info.format == VK_FORMAT_D16_UNORM ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);

View File

@ -9,47 +9,6 @@
namespace rsx namespace rsx
{ {
struct blit_src_info
{
blit_engine::transfer_source_format format;
blit_engine::transfer_origin origin;
u16 offset_x;
u16 offset_y;
u16 width;
u16 height;
u16 slice_h;
u16 pitch;
void *pixels;
bool compressed_x;
bool compressed_y;
u32 rsx_address;
};
struct blit_dst_info
{
blit_engine::transfer_destination_format format;
u16 offset_x;
u16 offset_y;
u16 width;
u16 height;
u16 pitch;
u16 clip_x;
u16 clip_y;
u16 clip_width;
u16 clip_height;
u16 max_tile_h;
f32 scale_x;
f32 scale_y;
bool swizzled;
void *pixels;
bool compressed_x;
bool compressed_y;
u32 rsx_address;
};
enum protection_policy enum protection_policy
{ {
protect_policy_one_page, //Only guard one page, preferrably one where this section 'wholly' fits protect_policy_one_page, //Only guard one page, preferrably one where this section 'wholly' fits

View File

@ -60,6 +60,47 @@ namespace rsx
f32 gamma = 1.f; //NO GAMMA CORRECTION f32 gamma = 1.f; //NO GAMMA CORRECTION
}; };
struct blit_src_info
{
blit_engine::transfer_source_format format;
blit_engine::transfer_origin origin;
u16 offset_x;
u16 offset_y;
u16 width;
u16 height;
u16 slice_h;
u16 pitch;
void *pixels;
bool compressed_x;
bool compressed_y;
u32 rsx_address;
};
struct blit_dst_info
{
blit_engine::transfer_destination_format format;
u16 offset_x;
u16 offset_y;
u16 width;
u16 height;
u16 pitch;
u16 clip_x;
u16 clip_y;
u16 clip_width;
u16 clip_height;
u16 max_tile_h;
f32 scale_x;
f32 scale_y;
bool swizzled;
void *pixels;
bool compressed_x;
bool compressed_y;
u32 rsx_address;
};
static const std::pair<std::array<u8, 4>, std::array<u8, 4>> default_remap_vector = static const std::pair<std::array<u8, 4>, std::array<u8, 4>> default_remap_vector =
{ {
{ CELL_GCM_TEXTURE_REMAP_FROM_A, CELL_GCM_TEXTURE_REMAP_FROM_R, CELL_GCM_TEXTURE_REMAP_FROM_G, CELL_GCM_TEXTURE_REMAP_FROM_B }, { CELL_GCM_TEXTURE_REMAP_FROM_A, CELL_GCM_TEXTURE_REMAP_FROM_R, CELL_GCM_TEXTURE_REMAP_FROM_G, CELL_GCM_TEXTURE_REMAP_FROM_B },