From 3836b40bf7c25ceb5b36572a253828e69d1be61a Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 18 Sep 2017 20:22:34 +0300 Subject: [PATCH] rsx: Fixups --- rpcs3/Emu/RSX/Common/texture_cache.h | 255 ++++++++++++++++++++------- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 8 +- rpcs3/Emu/RSX/GL/GLTextureCache.h | 103 ++++------- rpcs3/Emu/RSX/RSXThread.cpp | 8 +- rpcs3/Emu/RSX/VK/VKTextureCache.h | 68 ++----- rpcs3/Emu/RSX/rsx_methods.cpp | 2 +- 6 files changed, 252 insertions(+), 192 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index be0ad061e1..eeb7b2372a 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -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 @@ -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>& remap_vector) = 0; + const rsx::texture_upload_context context, const rsx::texture_dimension_extended type, const texture_create_flags flags, std::pair, std::array>& 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& subresource_layout, const rsx::texture_dimension_extended type, const bool swizzled, std::pair, std::array>& 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 find_texture_from_range(u32 rsx_address, u32 range) { + std::vector 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(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(); } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 2436d8501c..f1c7eb1681 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -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) { diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 83735eb48d..07b7920d2e 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -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(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(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 @@ -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>& 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>& 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>& 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; } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index b1fc064d04..461439504c 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -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); } diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index d7be128f8c..89ce2217f5 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -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 uploaded_image_view; std::unique_ptr 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& 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>& 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>& 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& subresource_layout, const rsx::texture_dimension_extended type, const bool swizzled, std::pair, std::array>& 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(); diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 3c45b7b1fe..c65a8056d8 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -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;