mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
rsx: Fixups
This commit is contained in:
parent
571dbfb7b1
commit
3836b40bf7
6 changed files with 252 additions and 192 deletions
|
@ -17,7 +17,79 @@ namespace rsx
|
|||
enum texture_upload_context
|
||||
{
|
||||
shader_read = 0,
|
||||
blit_engine_src = 1
|
||||
blit_engine_src = 1,
|
||||
blit_engine_dst = 2
|
||||
};
|
||||
|
||||
struct cached_texture_section : public rsx::buffered_section
|
||||
{
|
||||
u16 width;
|
||||
u16 height;
|
||||
u16 depth;
|
||||
u16 mipmaps;
|
||||
|
||||
u16 real_pitch;
|
||||
u16 rsx_pitch;
|
||||
|
||||
rsx::texture_create_flags view_flags = rsx::texture_create_flags::default_component_order;
|
||||
rsx::texture_upload_context context = rsx::texture_upload_context::shader_read;
|
||||
|
||||
bool matches(const u32 rsx_address, const u32 rsx_size)
|
||||
{
|
||||
return rsx::buffered_section::matches(rsx_address, rsx_size);
|
||||
}
|
||||
|
||||
bool matches(const u32 rsx_address, const u32 width, const u32 height, const u32 mipmaps)
|
||||
{
|
||||
if (rsx_address == cpu_address_base)
|
||||
{
|
||||
if (!width && !height && !mipmaps)
|
||||
return true;
|
||||
|
||||
if (width && width != this->width)
|
||||
return false;
|
||||
|
||||
if (height && height != this->height)
|
||||
return false;
|
||||
|
||||
if (mipmaps && mipmaps != this->mipmaps)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void set_view_flags(const rsx::texture_create_flags flags)
|
||||
{
|
||||
view_flags = flags;
|
||||
}
|
||||
|
||||
void set_context(const rsx::texture_upload_context upload_context)
|
||||
{
|
||||
context = upload_context;
|
||||
}
|
||||
|
||||
u32 get_width() const
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
u32 get_height() const
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
rsx::texture_create_flags get_view_flags() const
|
||||
{
|
||||
return view_flags;
|
||||
}
|
||||
|
||||
rsx::texture_upload_context get_context() const
|
||||
{
|
||||
return context;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename commandbuffer_type, typename section_storage_type, typename image_resource_type, typename image_view_type, typename image_storage_type, typename texture_format>
|
||||
|
@ -87,7 +159,7 @@ namespace rsx
|
|||
virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_resource_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) = 0;
|
||||
virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_storage_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) = 0;
|
||||
virtual section_storage_type* create_new_texture(commandbuffer_type&, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, const u32 gcm_format,
|
||||
const rsx::texture_dimension_extended type, const texture_create_flags flags, std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) = 0;
|
||||
const rsx::texture_upload_context context, const rsx::texture_dimension_extended type, const texture_create_flags flags, std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) = 0;
|
||||
virtual section_storage_type* upload_image_from_cpu(commandbuffer_type&, u32 rsx_address, u16 width, u16 height, u16 depth, u16 mipmaps, u16 pitch, const u32 gcm_format, const texture_upload_context context,
|
||||
std::vector<rsx_subresource_layout>& subresource_layout, const rsx::texture_dimension_extended type, const bool swizzled, std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) = 0;
|
||||
virtual void enforce_surface_creation_type(section_storage_type& section, const texture_create_flags expected) = 0;
|
||||
|
@ -247,8 +319,9 @@ namespace rsx
|
|||
virtual bool is_depth_texture(const u32) = 0;
|
||||
virtual void on_frame_end() = 0;
|
||||
|
||||
section_storage_type *find_texture_from_range(u32 rsx_address, u32 range)
|
||||
std::vector<section_storage_type*> find_texture_from_range(u32 rsx_address, u32 range)
|
||||
{
|
||||
std::vector<section_storage_type*> results;
|
||||
auto test = std::make_pair(rsx_address, range);
|
||||
for (auto &address_range : m_cache)
|
||||
{
|
||||
|
@ -261,11 +334,11 @@ namespace rsx
|
|||
continue;
|
||||
|
||||
if (!tex.is_dirty() && tex.overlaps(test, true))
|
||||
return &tex;
|
||||
results.push_back(&tex);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return results;
|
||||
}
|
||||
|
||||
section_storage_type *find_texture_from_dimensions(u32 rsx_address, u16 width = 0, u16 height = 0, u16 mipmaps = 0)
|
||||
|
@ -644,6 +717,35 @@ namespace rsx
|
|||
{
|
||||
return cached_texture->get_raw_view();
|
||||
}
|
||||
|
||||
//Find based on range instead
|
||||
auto overlapping_surfaces = find_texture_from_range(texaddr, tex_pitch * tex_height);
|
||||
if (!overlapping_surfaces.empty())
|
||||
{
|
||||
for (auto surface : overlapping_surfaces)
|
||||
{
|
||||
if (surface->get_context() != rsx::texture_upload_context::blit_engine_dst)
|
||||
continue;
|
||||
|
||||
if (surface->get_width() >= tex_width && surface->get_height() >= tex_height)
|
||||
{
|
||||
u16 offset_x = 0, offset_y = 0;
|
||||
if (const u32 address_offset = texaddr - surface->get_section_base())
|
||||
{
|
||||
const auto bpp = get_format_block_size_in_bytes(format);
|
||||
offset_y = address_offset / tex_pitch;
|
||||
offset_x = (address_offset % tex_pitch) / bpp;
|
||||
}
|
||||
|
||||
if ((offset_x + tex_width) <= surface->get_width() &&
|
||||
(offset_y + tex_height) <= surface->get_height())
|
||||
{
|
||||
auto src_image = surface->get_raw_texture();
|
||||
return create_temporary_subresource_view(cmd, &src_image, format, offset_x, offset_y, tex_width, tex_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we are re-sampling a subresource of an RTV/DSV texture, bound or otherwise
|
||||
|
@ -666,8 +768,6 @@ namespace rsx
|
|||
}
|
||||
else
|
||||
{
|
||||
image_view_type bound_surface = 0;
|
||||
|
||||
if (format == CELL_GCM_TEXTURE_COMPRESSED_DXT1 || format == CELL_GCM_TEXTURE_COMPRESSED_DXT23 || format == CELL_GCM_TEXTURE_COMPRESSED_DXT45)
|
||||
{
|
||||
LOG_WARNING(RSX, "Performing an RTT blit but request is for a compressed texture");
|
||||
|
@ -686,16 +786,13 @@ namespace rsx
|
|||
return rsc.surface->get_view();
|
||||
}
|
||||
else
|
||||
bound_surface = create_temporary_subresource_view(cmd, rsc.surface, format, rsc.x, rsc.y, rsc.w, rsc.h);
|
||||
return create_temporary_subresource_view(cmd, rsc.surface, format, rsc.x, rsc.y, rsc.w, rsc.h);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr);
|
||||
bound_surface = create_temporary_subresource_view(cmd, rsc.surface, format, rsc.x, rsc.y, rsc.w, rsc.h);
|
||||
return create_temporary_subresource_view(cmd, rsc.surface, format, rsc.x, rsc.y, rsc.w, rsc.h);
|
||||
}
|
||||
|
||||
if (bound_surface)
|
||||
return bound_surface;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -750,17 +847,18 @@ namespace rsx
|
|||
const u32 src_address = (u32)((u64)src.pixels - (u64)vm::base(0));
|
||||
const u32 dst_address = (u32)((u64)dst.pixels - (u64)vm::base(0));
|
||||
|
||||
//Check if src/dst are parts of render targets
|
||||
auto dst_subres = m_rtts.get_surface_subresource_if_applicable(dst.rsx_address, dst.width, dst.clip_height, dst.pitch, true, true, false, dst.compressed_y);
|
||||
dst_is_render_target = dst_subres.surface != nullptr;
|
||||
u32 framebuffer_src_address = src_address;
|
||||
|
||||
//TODO: Handle cases where src or dst can be a depth texture while the other is a color texture - requires a render pass to emulate
|
||||
auto src_subres = m_rtts.get_surface_subresource_if_applicable(src.rsx_address, src.width, src.slice_h, src.pitch, true, true, false, src.compressed_y);
|
||||
src_is_render_target = src_subres.surface != nullptr;
|
||||
//Correct for tile compression
|
||||
//TODO: Investigate whether DST compression also affects alignment
|
||||
if (src.compressed_x || src.compressed_y)
|
||||
{
|
||||
const u32 x_bytes = src_is_argb8 ? (src.offset_x * 4) : (src.offset_x * 2);
|
||||
const u32 y_bytes = src.pitch * src.offset_y;
|
||||
|
||||
//Always use GPU blit if src or dst is in the surface store
|
||||
if (!g_cfg.video.use_gpu_texture_scaling && !(src_is_render_target || dst_is_render_target))
|
||||
return false;
|
||||
if (src.offset_x <= 16 && src.offset_y <= 16)
|
||||
framebuffer_src_address -= (x_bytes + y_bytes);
|
||||
}
|
||||
|
||||
u16 max_dst_width = dst.width;
|
||||
u16 max_dst_height = dst.height;
|
||||
|
@ -779,11 +877,30 @@ namespace rsx
|
|||
scale_y *= 2.f;
|
||||
}
|
||||
|
||||
//Offset in x and y for src is 0 (it is already accounted for when getting pixels_src)
|
||||
//Reproject final clip onto source...
|
||||
const u16 src_w = (const u16)((f32)dst.clip_width / scale_x);
|
||||
const u16 src_h = (const u16)((f32)dst.clip_height / scale_y);
|
||||
|
||||
areai src_area = { 0, 0, src_w, src_h };
|
||||
areai dst_area = { 0, 0, dst.clip_width, dst.clip_height };
|
||||
|
||||
//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, true, false, dst.compressed_y);
|
||||
dst_is_render_target = dst_subres.surface != nullptr;
|
||||
|
||||
//TODO: Handle cases where src or dst can be a depth texture while the other is a color texture - requires a render pass to emulate
|
||||
auto src_subres = m_rtts.get_surface_subresource_if_applicable(framebuffer_src_address, src_w, src_h, src.pitch, true, true, false, src.compressed_y);
|
||||
src_is_render_target = src_subres.surface != nullptr;
|
||||
|
||||
//Always use GPU blit if src or dst is in the surface store
|
||||
if (!g_cfg.video.use_gpu_texture_scaling && !(src_is_render_target || dst_is_render_target))
|
||||
return false;
|
||||
|
||||
//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
|
||||
//RSX only handles 512x512 tiles so texture 'stitching' will eventually be needed to be completely accurate
|
||||
//Sections will be submitted as (512x512 + 512x512 + 256x512 + 512x208 + 512x208 + 256x208) to blit a 720p surface to the backbuffer for example
|
||||
|
||||
int practical_height;
|
||||
if (dst.max_tile_h < dst.height || !src_is_render_target)
|
||||
practical_height = (s32)dst.height;
|
||||
|
@ -795,14 +912,6 @@ namespace rsx
|
|||
|
||||
size2i dst_dimensions = { dst.pitch / (dst_is_argb8 ? 4 : 2), practical_height };
|
||||
|
||||
//Offset in x and y for src is 0 (it is already accounted for when getting pixels_src)
|
||||
//Reproject final clip onto source...
|
||||
const u16 src_w = (const u16)((f32)dst.clip_width / scale_x);
|
||||
const u16 src_h = (const u16)((f32)dst.clip_height / scale_y);
|
||||
|
||||
areai src_area = { 0, 0, src_w, src_h };
|
||||
areai dst_area = { 0, 0, dst.clip_width, dst.clip_height };
|
||||
|
||||
//Check if trivial memcpy can perform the same task
|
||||
//Used to copy programs to the GPU in some cases
|
||||
bool is_memcpy = false;
|
||||
|
@ -824,49 +933,65 @@ namespace rsx
|
|||
|
||||
if (!dst_is_render_target)
|
||||
{
|
||||
//Apply region offsets
|
||||
dst_area.x1 += dst.offset_x;
|
||||
dst_area.x2 += dst.offset_x;
|
||||
dst_area.y1 += dst.offset_y;
|
||||
dst_area.y2 += dst.offset_y;
|
||||
|
||||
//First check if this surface exists in VRAM with exact dimensions
|
||||
//Since scaled GPU resources are not invalidated by the CPU, we need to reuse older surfaces if possible
|
||||
cached_dest = find_texture_from_dimensions(dst.rsx_address, dst_dimensions.width, dst_dimensions.height);
|
||||
|
||||
//Check for any available region that will fit this one
|
||||
if (!cached_dest) cached_dest = find_texture_from_range(dst_address, dst.pitch * dst.clip_height);
|
||||
|
||||
if (cached_dest)
|
||||
if (!cached_dest)
|
||||
{
|
||||
//Prep surface
|
||||
enforce_surface_creation_type(*cached_dest, dst.swizzled ? rsx::texture_create_flags::swapped_native_component_order : rsx::texture_create_flags::native_component_order);
|
||||
auto overlapping_surfaces = find_texture_from_range(dst_address, dst.pitch * dst.clip_height);
|
||||
|
||||
const auto old_dst_area = dst_area;
|
||||
if (const u32 address_offset = dst_address - cached_dest->get_section_base())
|
||||
for (auto surface: overlapping_surfaces)
|
||||
{
|
||||
const u16 bpp = dst_is_argb8 ? 4 : 2;
|
||||
const u16 offset_y = address_offset / dst.pitch;
|
||||
const u16 offset_x = address_offset % dst.pitch;
|
||||
const u16 offset_x_in_block = offset_x / bpp;
|
||||
if (surface->get_context() != rsx::texture_upload_context::blit_engine_dst)
|
||||
continue;
|
||||
|
||||
dst_area.x1 += offset_x_in_block;
|
||||
dst_area.x2 += offset_x_in_block;
|
||||
dst_area.y1 += offset_y;
|
||||
dst_area.y2 += offset_y;
|
||||
}
|
||||
const auto old_dst_area = dst_area;
|
||||
if (const u32 address_offset = dst_address - surface->get_section_base())
|
||||
{
|
||||
const u16 bpp = dst_is_argb8 ? 4 : 2;
|
||||
const u16 offset_y = address_offset / dst.pitch;
|
||||
const u16 offset_x = address_offset % dst.pitch;
|
||||
const u16 offset_x_in_block = offset_x / bpp;
|
||||
|
||||
//Validate clipping region
|
||||
if ((unsigned)dst_area.x2 <= cached_dest->get_width() &&
|
||||
(unsigned)dst_area.y2 <= cached_dest->get_height())
|
||||
{
|
||||
dest_texture = cached_dest->get_raw_texture();
|
||||
dst_area.x1 += offset_x_in_block;
|
||||
dst_area.x2 += offset_x_in_block;
|
||||
dst_area.y1 += offset_y;
|
||||
dst_area.y2 += offset_y;
|
||||
}
|
||||
|
||||
max_dst_width = cached_dest->get_width();
|
||||
max_dst_height = cached_dest->get_height();
|
||||
}
|
||||
else
|
||||
{
|
||||
cached_dest = nullptr;
|
||||
dst_area = old_dst_area;
|
||||
//Validate clipping region
|
||||
if ((unsigned)dst_area.x2 <= surface->get_width() &&
|
||||
(unsigned)dst_area.y2 <= surface->get_height())
|
||||
{
|
||||
cached_dest = surface;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_area = old_dst_area;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cached_dest && is_memcpy)
|
||||
if (cached_dest)
|
||||
{
|
||||
dest_texture = cached_dest->get_raw_texture();
|
||||
|
||||
max_dst_width = cached_dest->get_width();
|
||||
max_dst_height = cached_dest->get_height();
|
||||
|
||||
//Prep surface
|
||||
enforce_surface_creation_type(*cached_dest, dst.swizzled ? rsx::texture_create_flags::swapped_native_component_order : rsx::texture_create_flags::native_component_order);
|
||||
}
|
||||
else if (is_memcpy)
|
||||
{
|
||||
lock.upgrade();
|
||||
flush_address_impl(src_address, std::forward<Args>(extras)...);
|
||||
|
@ -877,9 +1002,11 @@ namespace rsx
|
|||
}
|
||||
else
|
||||
{
|
||||
dst_area.x1 += dst_subres.x;
|
||||
//TODO: Investigate effects of tile compression
|
||||
|
||||
dst_area.x1 = dst_subres.x;
|
||||
dst_area.y1 = dst_subres.y;
|
||||
dst_area.x2 += dst_subres.x;
|
||||
dst_area.y1 += dst_subres.y;
|
||||
dst_area.y2 += dst_subres.y;
|
||||
|
||||
dest_texture = dst_subres.surface->get_surface();
|
||||
|
@ -952,9 +1079,9 @@ namespace rsx
|
|||
src_area.x2 = src_subres.w;
|
||||
src_area.y2 = src_subres.h;
|
||||
|
||||
src_area.x1 += src_subres.x;
|
||||
src_area.x1 = src_subres.x;
|
||||
src_area.y1 = src_subres.y;
|
||||
src_area.x2 += src_subres.x;
|
||||
src_area.y1 += src_subres.y;
|
||||
src_area.y2 += src_subres.y;
|
||||
|
||||
vram_texture = src_subres.surface->get_surface();
|
||||
|
@ -1017,7 +1144,7 @@ namespace rsx
|
|||
|
||||
dest_texture = create_new_texture(cmd, dst.rsx_address, dst.pitch * dst_dimensions.height,
|
||||
dst_dimensions.width, dst_dimensions.height, 1, 1,
|
||||
gcm_format, rsx::texture_dimension_extended::texture_dimension_2d,
|
||||
gcm_format, rsx::texture_upload_context::blit_engine_dst, rsx::texture_dimension_extended::texture_dimension_2d,
|
||||
dst.swizzled? rsx::texture_create_flags::swapped_native_component_order : rsx::texture_create_flags::native_component_order,
|
||||
default_remap_vector)->get_raw_texture();
|
||||
}
|
||||
|
|
|
@ -467,10 +467,11 @@ void GLGSRender::end()
|
|||
m_gl_texture_cache.upload_and_bind_texture(i, get_gl_target_for_texture(rsx::method_registers.fragment_textures[i]), rsx::method_registers.fragment_textures[i], m_rtts);
|
||||
|
||||
if (m_textures_dirty[i])
|
||||
{
|
||||
m_gl_sampler_states[i].apply(rsx::method_registers.fragment_textures[i]);
|
||||
m_textures_dirty[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
m_textures_dirty[i] = false;
|
||||
}
|
||||
|
||||
//Vertex textures
|
||||
|
@ -969,6 +970,7 @@ void GLGSRender::load_program(u32 vertex_base, u32 vertex_count)
|
|||
vertex_program.skip_vertex_input_check = true; //not needed for us since decoding is done server side
|
||||
void* pipeline_properties = nullptr;
|
||||
|
||||
auto old_program = m_program;
|
||||
m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, pipeline_properties);
|
||||
m_program->use();
|
||||
|
||||
|
@ -1093,7 +1095,7 @@ void GLGSRender::flip(int buffer)
|
|||
//The render might have been done offscreen and a blit used to display
|
||||
//Check the texture cache for a blitted copy
|
||||
const u32 size = buffer_pitch * buffer_height;
|
||||
auto surface = m_gl_texture_cache.find_texture_from_range(absolute_address, size);
|
||||
auto surface = m_gl_texture_cache.find_texture_from_dimensions(absolute_address);
|
||||
|
||||
if (surface != nullptr)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace gl
|
|||
{
|
||||
extern GLenum get_sized_internal_format(u32);
|
||||
|
||||
class cached_texture_section : public rsx::buffered_section
|
||||
class cached_texture_section : public rsx::cached_texture_section
|
||||
{
|
||||
private:
|
||||
fence m_fence;
|
||||
|
@ -38,17 +38,10 @@ namespace gl
|
|||
bool flushed = false;
|
||||
bool is_depth = false;
|
||||
|
||||
u32 current_width = 0;
|
||||
u32 current_height = 0;
|
||||
u32 current_pitch = 0;
|
||||
u32 real_pitch = 0;
|
||||
|
||||
texture::format format = texture::format::rgba;
|
||||
texture::type type = texture::type::ubyte;
|
||||
bool pack_unpack_swap_bytes = false;
|
||||
|
||||
rsx::texture_create_flags view_flags = rsx::texture_create_flags::default_component_order;
|
||||
|
||||
u8 get_pixel_size(texture::format fmt_, texture::type type_)
|
||||
{
|
||||
u8 size = 1;
|
||||
|
@ -150,7 +143,7 @@ namespace gl
|
|||
}
|
||||
|
||||
void create(const u16 w, const u16 h, const u16 /*depth*/, const u16 /*mipmaps*/, void*,
|
||||
gl::texture* image, const u32 native_pitch, bool read_only,
|
||||
gl::texture* image, const u32 rsx_pitch, bool read_only,
|
||||
gl::texture::format gl_format, gl::texture::type gl_type, bool swap_bytes)
|
||||
{
|
||||
if (!read_only && pbo_id == 0)
|
||||
|
@ -160,9 +153,9 @@ namespace gl
|
|||
copied = false;
|
||||
is_depth = false;
|
||||
|
||||
current_width = w;
|
||||
current_height = h;
|
||||
current_pitch = native_pitch;
|
||||
this->width = w;
|
||||
this->height = h;
|
||||
this->rsx_pitch = rsx_pitch;
|
||||
|
||||
vram_texture = image->id();
|
||||
set_format(gl_format, gl_type, swap_bytes);
|
||||
|
@ -171,39 +164,19 @@ namespace gl
|
|||
void create_read_only(const u32 id, const u32 width, const u32 height)
|
||||
{
|
||||
//Only to be used for ro memory, we dont care about most members, just dimensions and the vram texture handle
|
||||
current_width = width;
|
||||
current_height = height;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
vram_texture = id;
|
||||
|
||||
current_pitch = 0;
|
||||
rsx_pitch = 0;
|
||||
real_pitch = 0;
|
||||
}
|
||||
|
||||
bool matches(const u32 rsx_address, const u32 rsx_size)
|
||||
{
|
||||
return rsx::buffered_section::matches(rsx_address, rsx_size);
|
||||
}
|
||||
|
||||
bool matches(const u32 rsx_address, const u32 width, const u32 height, const u32 mipmaps)
|
||||
{
|
||||
if (cpu_address_base == rsx_address && !dirty)
|
||||
{
|
||||
//Mostly only used to debug; matches textures without checking dimensions
|
||||
if (width == 0 && height == 0)
|
||||
return true;
|
||||
|
||||
return (current_width == width && current_height == height);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void set_dimensions(u32 width, u32 height, u32 pitch)
|
||||
{
|
||||
current_width = width;
|
||||
current_height = height;
|
||||
current_pitch = pitch;
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
rsx_pitch = pitch;
|
||||
real_pitch = width * get_pixel_size(format, type);
|
||||
}
|
||||
|
||||
|
@ -213,7 +186,7 @@ namespace gl
|
|||
type = gl_type;
|
||||
pack_unpack_swap_bytes = swap_bytes;
|
||||
|
||||
real_pitch = current_width * get_pixel_size(format, type);
|
||||
real_pitch = width * get_pixel_size(format, type);
|
||||
}
|
||||
|
||||
void set_depth_flag(bool is_depth_fmt)
|
||||
|
@ -226,11 +199,6 @@ namespace gl
|
|||
vram_texture = source.id();
|
||||
}
|
||||
|
||||
void set_view_flags(const rsx::texture_create_flags flags)
|
||||
{
|
||||
view_flags = flags;
|
||||
}
|
||||
|
||||
void copy_texture(bool=false)
|
||||
{
|
||||
if (!glIsTexture(vram_texture))
|
||||
|
@ -261,8 +229,8 @@ namespace gl
|
|||
return;
|
||||
}
|
||||
|
||||
u32 min_width = std::min((u32)tex->width(), current_width);
|
||||
u32 min_height = std::min((u32)tex->height(), current_height);
|
||||
u32 min_width = std::min((u16)tex->width(), width);
|
||||
u32 min_height = std::min((u16)tex->height(), height);
|
||||
|
||||
tex->bind();
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, pack_unpack_swap_bytes);
|
||||
|
@ -297,7 +265,7 @@ namespace gl
|
|||
//throw if map failed since we'll segfault anyway
|
||||
verify(HERE), data != nullptr;
|
||||
|
||||
if (real_pitch >= current_pitch)
|
||||
if (real_pitch >= rsx_pitch)
|
||||
{
|
||||
memcpy(dst, data, cpu_address_range);
|
||||
}
|
||||
|
@ -307,8 +275,8 @@ namespace gl
|
|||
//TODO: Fall back to bilinear filtering if samples > 2
|
||||
|
||||
const u8 pixel_size = get_pixel_size(format, type);
|
||||
const u8 samples = current_pitch / real_pitch;
|
||||
rsx::scale_image_nearest(dst, const_cast<const void*>(data), current_width, current_height, current_pitch, real_pitch, pixel_size, samples);
|
||||
const u8 samples = rsx_pitch / real_pitch;
|
||||
rsx::scale_image_nearest(dst, const_cast<const void*>(data), width, height, rsx_pitch, real_pitch, pixel_size, samples);
|
||||
}
|
||||
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
|
@ -388,16 +356,6 @@ namespace gl
|
|||
return vram_texture;
|
||||
}
|
||||
|
||||
u32 get_width() const
|
||||
{
|
||||
return current_width;
|
||||
}
|
||||
|
||||
u32 get_height() const
|
||||
{
|
||||
return current_height;
|
||||
}
|
||||
|
||||
bool is_depth_texture() const
|
||||
{
|
||||
return is_depth;
|
||||
|
@ -416,11 +374,6 @@ namespace gl
|
|||
|
||||
return (gl::texture::format)fmt == tex->get_internal_format();
|
||||
}
|
||||
|
||||
rsx::texture_create_flags get_view_flags() const
|
||||
{
|
||||
return view_flags;
|
||||
}
|
||||
};
|
||||
|
||||
class texture_cache : public rsx::texture_cache<void*, cached_texture_section, u32, u32, gl::texture, gl::texture::format>
|
||||
|
@ -575,7 +528,8 @@ namespace gl
|
|||
}
|
||||
|
||||
cached_texture_section* create_new_texture(void*&, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, const u32 gcm_format,
|
||||
const rsx::texture_dimension_extended type, const rsx::texture_create_flags flags, std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
const rsx::texture_upload_context context, const rsx::texture_dimension_extended type, const rsx::texture_create_flags flags,
|
||||
std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
{
|
||||
u32 vram_texture = gl::create_texture(gcm_format, width, height, depth, mipmaps, type);
|
||||
bool depth_flag = false;
|
||||
|
@ -602,6 +556,7 @@ namespace gl
|
|||
cached.set_dirty(false);
|
||||
cached.set_depth_flag(depth_flag);
|
||||
cached.set_view_flags(flags);
|
||||
cached.set_context(context);
|
||||
|
||||
return &cached;
|
||||
}
|
||||
|
@ -611,7 +566,7 @@ namespace gl
|
|||
std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
{
|
||||
void* unused = nullptr;
|
||||
auto section = create_new_texture(unused, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, type,
|
||||
auto section = create_new_texture(unused, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, context, type,
|
||||
rsx::texture_create_flags::default_component_order, remap_vector);
|
||||
|
||||
//Swizzling is ignored for blit engine copy and emulated using remapping
|
||||
|
@ -669,8 +624,20 @@ namespace gl
|
|||
{
|
||||
reader_lock lock(m_cache_mutex);
|
||||
|
||||
auto section = find_texture_from_range(rsx_address, 64u);
|
||||
if (section != nullptr) return section->is_depth_texture();
|
||||
/* auto found = m_cache.find(rsx_address);
|
||||
if (found == m_cache.end())
|
||||
return false;
|
||||
|
||||
if (found->second.valid_count == 0)
|
||||
return false;
|
||||
|
||||
for (auto& tex : found->second.data)
|
||||
{
|
||||
if (tex.is_dirty())
|
||||
continue;
|
||||
|
||||
return tex.is_depth_texture();
|
||||
}*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1355,8 +1355,14 @@ namespace rsx
|
|||
case CELL_GCM_TEXTURE_DEPTH16:
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||
{
|
||||
const auto compare_mode = (rsx::comparison_function)tex.zfunc();
|
||||
if (result.textures_alpha_kill[i] == 0 &&
|
||||
compare_mode < rsx::comparison_function::always &&
|
||||
compare_mode > rsx::comparison_function::never)
|
||||
result.shadow_textures |= (1 << i);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR(RSX, "Depth texture bound to pipeline with unexpected format 0x%X", format);
|
||||
}
|
||||
|
|
|
@ -12,19 +12,12 @@ extern u64 get_system_time();
|
|||
|
||||
namespace vk
|
||||
{
|
||||
class cached_texture_section : public rsx::buffered_section
|
||||
class cached_texture_section : public rsx::cached_texture_section
|
||||
{
|
||||
u16 pitch;
|
||||
u16 width;
|
||||
u16 height;
|
||||
u16 depth;
|
||||
u16 mipmaps;
|
||||
|
||||
std::unique_ptr<vk::image_view> uploaded_image_view;
|
||||
std::unique_ptr<vk::image> managed_texture = nullptr;
|
||||
|
||||
//DMA relevant data
|
||||
u16 native_pitch;
|
||||
VkFence dma_fence = VK_NULL_HANDLE;
|
||||
bool synchronized = false;
|
||||
u64 sync_timestamp = 0;
|
||||
|
@ -46,7 +39,7 @@ namespace vk
|
|||
rsx::buffered_section::reset(base, length, policy);
|
||||
}
|
||||
|
||||
void create(const u16 w, const u16 h, const u16 depth, const u16 mipmaps, vk::image_view *view, vk::image *image, const u32 native_pitch = 0, bool managed=true)
|
||||
void create(const u16 w, const u16 h, const u16 depth, const u16 mipmaps, vk::image_view *view, vk::image *image, const u32 rsx_pitch = 0, bool managed=true)
|
||||
{
|
||||
width = w;
|
||||
height = h;
|
||||
|
@ -59,8 +52,8 @@ namespace vk
|
|||
if (managed) managed_texture.reset(image);
|
||||
|
||||
//TODO: Properly compute these values
|
||||
this->native_pitch = native_pitch;
|
||||
pitch = cpu_address_range / height;
|
||||
this->rsx_pitch = rsx_pitch;
|
||||
real_pitch = cpu_address_range / height;
|
||||
|
||||
//Even if we are managing the same vram section, we cannot guarantee contents are static
|
||||
//The create method is only invoked when a new mangaged session is required
|
||||
|
@ -83,48 +76,11 @@ namespace vk
|
|||
}
|
||||
}
|
||||
|
||||
bool matches(u32 rsx_address, u32 rsx_size) const
|
||||
{
|
||||
return rsx::buffered_section::matches(rsx_address, rsx_size);
|
||||
}
|
||||
|
||||
bool matches(u32 rsx_address, u32 width, u32 height, u32 mipmaps) const
|
||||
{
|
||||
if (rsx_address == cpu_address_base)
|
||||
{
|
||||
if (!width && !height && !mipmaps)
|
||||
return true;
|
||||
|
||||
if (width && width != this->width)
|
||||
return false;
|
||||
|
||||
if (height && height != this->height)
|
||||
return false;
|
||||
|
||||
if (mipmaps && mipmaps != this->mipmaps)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exists() const
|
||||
{
|
||||
return (vram_texture != nullptr);
|
||||
}
|
||||
|
||||
u16 get_width() const
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
u16 get_height() const
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
std::unique_ptr<vk::image_view>& get_view()
|
||||
{
|
||||
return uploaded_image_view;
|
||||
|
@ -253,9 +209,9 @@ namespace vk
|
|||
void* pixels_src = dma_buffer->map(0, cpu_address_range);
|
||||
void* pixels_dst = vm::base(cpu_address_base);
|
||||
|
||||
const u8 bpp = native_pitch / width;
|
||||
const u8 bpp = real_pitch / width;
|
||||
|
||||
if (pitch == native_pitch)
|
||||
if (real_pitch == rsx_pitch)
|
||||
{
|
||||
//We have to do our own byte swapping since the driver doesnt do it for us
|
||||
switch (bpp)
|
||||
|
@ -280,9 +236,9 @@ namespace vk
|
|||
{
|
||||
//Scale image to fit
|
||||
//usually we can just get away with nearest filtering
|
||||
const u8 samples = pitch / native_pitch;
|
||||
const u8 samples = rsx_pitch / real_pitch;
|
||||
|
||||
rsx::scale_image_nearest(pixels_dst, pixels_src, width, height, pitch, native_pitch, bpp, samples, true);
|
||||
rsx::scale_image_nearest(pixels_dst, pixels_src, width, height, rsx_pitch, real_pitch, bpp, samples, true);
|
||||
}
|
||||
|
||||
dma_buffer->unmap();
|
||||
|
@ -395,7 +351,7 @@ namespace vk
|
|||
image.reset(new vk::image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
source->info.imageType,
|
||||
source->info.format,
|
||||
source->width(), source->height(), source->depth(), 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
w, h, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, source->info.flags));
|
||||
|
||||
VkImageSubresourceRange view_range = { aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 };
|
||||
|
@ -429,7 +385,8 @@ namespace vk
|
|||
}
|
||||
|
||||
cached_texture_section* create_new_texture(vk::command_buffer& cmd, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, const u32 gcm_format,
|
||||
const rsx::texture_dimension_extended type, const rsx::texture_create_flags flags, std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
const rsx::texture_upload_context context, const rsx::texture_dimension_extended type, const rsx::texture_create_flags flags,
|
||||
std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
{
|
||||
const bool is_cubemap = type == rsx::texture_dimension_extended::texture_dimension_cubemap;
|
||||
VkFormat vk_format;
|
||||
|
@ -538,6 +495,7 @@ namespace vk
|
|||
region.create(width, height, depth, mipmaps, view, image);
|
||||
region.protect(utils::protection::ro);
|
||||
region.set_dirty(false);
|
||||
region.set_context(context);
|
||||
|
||||
read_only_range = region.get_min_max(read_only_range);
|
||||
return ®ion;
|
||||
|
@ -547,7 +505,7 @@ namespace vk
|
|||
const rsx::texture_upload_context context, std::vector<rsx_subresource_layout>& subresource_layout, const rsx::texture_dimension_extended type, const bool swizzled,
|
||||
std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
{
|
||||
auto section = create_new_texture(cmd, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, type,
|
||||
auto section = create_new_texture(cmd, rsx_address, pitch * height, width, height, depth, mipmaps, gcm_format, context, type,
|
||||
rsx::texture_create_flags::default_component_order, remap_vector);
|
||||
|
||||
auto image = section->get_raw_texture();
|
||||
|
|
|
@ -675,7 +675,7 @@ namespace rsx
|
|||
src_info.width = in_w;
|
||||
src_info.height = in_h;
|
||||
src_info.pitch = in_pitch;
|
||||
src_info.slice_h = clip_h;
|
||||
src_info.slice_h = slice_h;
|
||||
src_info.offset_x = (u16)in_x;
|
||||
src_info.offset_y = (u16)in_y;
|
||||
src_info.pixels = pixels_src;
|
||||
|
|
Loading…
Add table
Reference in a new issue