rsx: Fixups

This commit is contained in:
kd-11 2017-09-18 20:22:34 +03:00
parent 571dbfb7b1
commit 3836b40bf7
6 changed files with 252 additions and 192 deletions

View File

@ -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();
}

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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 &region;
@ -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();

View File

@ -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;