diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 4073a86080..46ed36bed1 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -441,7 +441,7 @@ void GLGSRender::end() int location; if (m_program->uniforms.has_location("tex" + std::to_string(i), &location)) { - __glcheck rsx::gl_texture::bind(m_texture_cache, textures[i]); + __glcheck rsx::gl_texture::bind(texture_cache, textures[i]); __glcheck glProgramUniform1i(m_program->id(), location, i); } } @@ -708,7 +708,7 @@ void GLGSRender::end() rsx::thread::end(); - m_texture_cache.update_protection(); + texture_cache.update_protection(); } void GLGSRender::set_viewport() @@ -829,7 +829,7 @@ void GLGSRender::on_exit() } } -void nv4097_clear_surface(u32 arg, GLGSRender* renderer) +bool nv4097_clear_surface(u32 arg, GLGSRender* renderer) { //LOG_NOTICE(RSX, "nv4097_clear_surface(0x%x)", arg); @@ -844,7 +844,7 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer) if ((arg & (depth_stencil | color_mask)) == 0) { //do nothing - return; + return true; } /* @@ -941,13 +941,22 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer) { __glcheck glClear(mask); } + + return true; } -using rsx_method_impl_t = void(*)(u32, GLGSRender*); +bool nv3089_image_in(u32 arg, GLGSRender* renderer) +{ + //TODO + return false; +} + +using rsx_method_impl_t = bool(*)(u32, GLGSRender*); static const std::unordered_map g_gl_method_tbl = { - { NV4097_CLEAR_SURFACE, nv4097_clear_surface } + { NV4097_CLEAR_SURFACE, nv4097_clear_surface }, + //{ NV3089_IMAGE_IN, nv3089_image_in }, }; bool GLGSRender::do_method(u32 cmd, u32 arg) @@ -959,8 +968,7 @@ bool GLGSRender::do_method(u32 cmd, u32 arg) return false; } - found->second(arg, this); - return true; + return found->second(arg, this); } bool GLGSRender::load_program() @@ -1205,7 +1213,7 @@ void GLGSRender::init_buffers(bool skip_reading) info.swizzled = swizzled; - cached_color_buffers[index] = &m_texture_cache.entry(info, skip_reading ? gl::cache_buffers::none : gl::cache_buffers::local); + cached_color_buffers[index] = &texture_cache.entry(info, skip_reading ? gl::cache_buffers::none : gl::cache_buffers::local); draw_fbo.color[index] = cached_color_buffers[index]->view(); }); @@ -1269,7 +1277,7 @@ void GLGSRender::init_buffers(bool skip_reading) info.format.remap = { GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO }; - __glcheck cached_depth_buffer = &m_texture_cache.entry(info, skip_reading ? gl::cache_buffers::none : gl::cache_buffers::local); + __glcheck cached_depth_buffer = &texture_cache.entry(info, skip_reading ? gl::cache_buffers::none : gl::cache_buffers::local); switch (m_surface.depth_format) { @@ -1333,7 +1341,7 @@ void GLGSRender::flip(int buffer) glDisable(GL_LOGIC_OP); glDisable(GL_CULL_FACE); - gl::cached_texture& texture = m_texture_cache.entry(surface_info(rsx::surface_color_format::a8r8g8b8, gcm_buffers[buffer].offset, + gl::cached_texture& texture = texture_cache.entry(surface_info(rsx::surface_color_format::a8r8g8b8, gcm_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL, buffer_width, buffer_height, buffer_pitch), gl::cache_buffers::local); //std::lock_guard lock(texture); @@ -1389,7 +1397,7 @@ u64 GLGSRender::timestamp() const bool GLGSRender::on_access_violation(u32 address, bool is_writing) { - if (auto region = m_texture_cache.find_region(address)) + if (auto region = texture_cache.find_region(address)) { //std::lock_guard lock(*region); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index cb512e0fe5..ebecc4c8de 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -28,9 +28,8 @@ private: texture_buffer_pair m_gl_attrib_buffers[rsx::limits::vertex_count]; - gl::texture_cache m_texture_cache; - public: + gl::texture_cache texture_cache; gl::fbo draw_fbo; private: diff --git a/rpcs3/Emu/RSX/GL/gl_helpers.cpp b/rpcs3/Emu/RSX/GL/gl_helpers.cpp index da61fb2d14..1692543da8 100644 --- a/rpcs3/Emu/RSX/GL/gl_helpers.cpp +++ b/rpcs3/Emu/RSX/GL/gl_helpers.cpp @@ -1,6 +1,42 @@ #include "stdafx.h" #include "gl_helpers.h" +#ifdef _WIN32 +#include +#pragma comment(lib, "Dbghelp.lib") +#endif + +//TODO: find proper place +void print_call_stack(int skip) +{ +#ifdef _WIN32 + HANDLE current_process = GetCurrentProcess(); + SymInitialize(current_process, nullptr, true); + + void* stack[61]; + u32 frames_count = CaptureStackBackTrace(skip + 1, 61 - skip, stack, nullptr); + + u32 max_sym_length = 255; + + std::unique_ptr sym_info + { + (SYMBOL_INFO*)std::calloc(sizeof(SYMBOL_INFO) + (max_sym_length + 1) * sizeof(char), 1), + std::free + }; + + sym_info->MaxNameLen = max_sym_length; + sym_info->SizeOfStruct = sizeof(SYMBOL_INFO); + + LOG_ERROR(GENERAL, "CALL STACK:"); + + for (s32 i = frames_count - 1; i > 0; --i) + { + SymFromAddr(current_process, (DWORD64)stack[i], 0, sym_info.get()); + LOG_ERROR(GENERAL, "%u: %s:%u - 0x%0X", i, sym_info->Name, sym_info->Index, sym_info->Address); + } +#endif +} + namespace gl { const fbo screen{}; diff --git a/rpcs3/Emu/RSX/GL/gl_helpers.h b/rpcs3/Emu/RSX/GL/gl_helpers.h index 2d210ee507..348cea5aa4 100644 --- a/rpcs3/Emu/RSX/GL/gl_helpers.h +++ b/rpcs3/Emu/RSX/GL/gl_helpers.h @@ -13,6 +13,8 @@ #include "OpenGL.h" #include "../GCM.h" +void print_call_stack(int skip); + namespace gl { #if 1//def _DEBUG @@ -44,6 +46,7 @@ namespace gl default: error = "unknown error"; break; } + print_call_stack(1); throw std::runtime_error(fmt::format("OpenGL error: %s. file '%s' function '%s' line %ld", error.c_str(), file, function, line)); } } diff --git a/rpcs3/Emu/RSX/GL/gl_texture_cache.cpp b/rpcs3/Emu/RSX/GL/gl_texture_cache.cpp index 8db95f5f27..1651f2ba7c 100644 --- a/rpcs3/Emu/RSX/GL/gl_texture_cache.cpp +++ b/rpcs3/Emu/RSX/GL/gl_texture_cache.cpp @@ -18,19 +18,19 @@ namespace gl void cached_texture::read() { cached_texture* found_texture = nullptr; - u32 texture_size = info->size(); + u32 texture_size = info.size(); - m_parent_region->for_each(info->start_address, texture_size, [&](cached_texture& texture) + m_parent_region->for_each(info.start_address, texture_size, [&](cached_texture& texture) { if ((texture.m_state & cache_entry_state::local_synchronized) == cache_entry_state::invalid) { return; } - if (texture.info->start_address != info->start_address || - texture.info->pitch != info->pitch || - texture.info->height < info->height || - texture.info->width < info->width) + if (texture.info.start_address != info.start_address || + texture.info.pitch != info.pitch || + texture.info.height < info.height || + texture.info.width < info.width) { return; } @@ -42,35 +42,35 @@ namespace gl { //read from local __glcheck glCopyImageSubData( - found_texture->gl_name, (GLenum)found_texture->info->target, 0, 0, 0, 0, - gl_name, (GLenum)info->target, 0, 0, 0, 0, - info->width, info->height, info->depth); + found_texture->gl_name, (GLenum)found_texture->info.target, 0, 0, 0, 0, + gl_name, (GLenum)info.target, 0, 0, 0, 0, + info.width, info.height, info.depth); } else { //read from host //flush all local textures at region - m_parent_region->for_each(info->start_address, texture_size, [](cached_texture& texture) + m_parent_region->for_each(info.start_address, texture_size, [](cached_texture& texture) { texture.sync(gl::cache_buffers::host); }); bind(); - if (info->format.format == gl::texture::format::depth || info->format.format == gl::texture::format::depth_stencil) + if (info.format.format == gl::texture::format::depth || info.format.format == gl::texture::format::depth_stencil) { gl::buffer pbo_depth; - __glcheck pbo_depth.create(info->size()); + __glcheck pbo_depth.create(info.size()); __glcheck pbo_depth.map([&](GLubyte* pixels) { - switch (info->format.bpp) + switch (info.format.bpp) { case 2: { u16 *dst = (u16*)pixels; - const be_t* src = (const be_t*)vm::base_priv(info->start_address); - for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i) + const be_t* src = (const be_t*)vm::base_priv(info.start_address); + for (u32 i = 0, end = info.pitch / info.format.bpp * info.height; i < end; ++i) { dst[i] = src[i]; } @@ -80,8 +80,8 @@ namespace gl case 4: { u32 *dst = (u32*)pixels; - const be_t* src = (const be_t*)vm::base_priv(info->start_address); - for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i) + const be_t* src = (const be_t*)vm::base_priv(info.start_address); + for (u32 i = 0, end = info.pitch / info.format.bpp * info.height; i < end; ++i) { dst[i] = src[i]; } @@ -94,47 +94,47 @@ namespace gl }, gl::buffer::access::write); gl::pixel_unpack_settings{} - .row_length(info->pitch / info->format.bpp) + .row_length(info.pitch / info.format.bpp) .aligment(1) - .swap_bytes((info->format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none) + //.swap_bytes((info.format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none) .apply(); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_depth.id()); - __glcheck glTexSubImage2D((GLenum)info->target, 0, 0, 0, info->width, info->height, - (GLenum)info->format.format, (GLenum)info->format.type, nullptr); + __glcheck glTexSubImage2D((GLenum)info.target, 0, 0, 0, info.width, info.height, + (GLenum)info.format.format, (GLenum)info.format.type, nullptr); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } - else if (info->compressed_size) + else if (info.compressed_size) { - __glcheck glCompressedTexSubImage2D((GLenum)info->target, 0, - 0, 0, info->width, info->height, - (GLenum)info->format.internal_format, - info->compressed_size, vm::base_priv(info->start_address)); + __glcheck glCompressedTexSubImage2D((GLenum)info.target, 0, + 0, 0, info.width, info.height, + (GLenum)info.format.internal_format, + info.compressed_size, vm::base_priv(info.start_address)); } else { - void *pixels = vm::base_priv(info->start_address); + void *pixels = vm::base_priv(info.start_address); std::unique_ptr linear_pixels; - if (info->swizzled && (info->format.flags & texture_flags::allow_swizzle) != texture_flags::none) + if (info.swizzled && (info.format.flags & texture_flags::allow_swizzle) != texture_flags::none) { - linear_pixels.reset(new u8[info->size()]); - switch (info->format.bpp) + linear_pixels.reset(new u8[info.size()]); + switch (info.format.bpp) { case 1: - rsx::convert_linear_swizzle(pixels, linear_pixels.get(), info->width, info->height, true); + rsx::convert_linear_swizzle(pixels, linear_pixels.get(), info.width, info.height, true); break; case 2: - rsx::convert_linear_swizzle(pixels, linear_pixels.get(), info->width, info->height, true); + rsx::convert_linear_swizzle(pixels, linear_pixels.get(), info.width, info.height, true); break; case 4: - rsx::convert_linear_swizzle(pixels, linear_pixels.get(), info->width, info->height, true); + rsx::convert_linear_swizzle(pixels, linear_pixels.get(), info.width, info.height, true); break; case 8: - rsx::convert_linear_swizzle(pixels, linear_pixels.get(), info->width, info->height, true); + rsx::convert_linear_swizzle(pixels, linear_pixels.get(), info.width, info.height, true); break; default: @@ -145,22 +145,22 @@ namespace gl } gl::pixel_unpack_settings{} - .row_length(info->pitch / info->format.bpp) + .row_length(info.pitch / info.format.bpp) .aligment(1) - .swap_bytes((info->format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none) + .swap_bytes((info.format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none) .apply(); - __glcheck glTexSubImage2D((GLenum)info->target, 0, 0, 0, info->width, info->height, - (GLenum)info->format.format, (GLenum)info->format.type, pixels); + __glcheck glTexSubImage2D((GLenum)info.target, 0, 0, 0, info.width, info.height, + (GLenum)info.format.format, (GLenum)info.format.type, pixels); } - if (info->mipmap > 1) + if (info.mipmap > 1) { - __glcheck glTexParameteri((GLenum)info->target, GL_TEXTURE_MIN_LOD, info->min_lod); - __glcheck glTexParameteri((GLenum)info->target, GL_TEXTURE_MAX_LOD, info->max_lod); - __glcheck glTexParameterf((GLenum)info->target, GL_TEXTURE_LOD_BIAS, info->lod_bias); + __glcheck glTexParameteri((GLenum)info.target, GL_TEXTURE_MIN_LOD, info.min_lod); + __glcheck glTexParameteri((GLenum)info.target, GL_TEXTURE_MAX_LOD, info.max_lod); + __glcheck glTexParameterf((GLenum)info.target, GL_TEXTURE_LOD_BIAS, info.lod_bias); - __glcheck glGenerateMipmap((GLenum)info->target); + __glcheck glGenerateMipmap((GLenum)info.target); } } @@ -171,33 +171,33 @@ namespace gl { bind(); - if (info->format.format == gl::texture::format::depth || info->format.format == gl::texture::format::depth_stencil) + if (info.format.format == gl::texture::format::depth || info.format.format == gl::texture::format::depth_stencil) { - //LOG_ERROR(RSX, "write depth color to host[0x%x]", info->start_address); + //LOG_ERROR(RSX, "write depth color to host[0x%x]", info.start_address); gl::buffer pbo_depth; - pbo_depth.create(info->size()); + pbo_depth.create(info.size()); gl::pixel_pack_settings{} - .row_length(info->pitch / info->format.bpp) + .row_length(info.pitch / info.format.bpp) .aligment(1) - //.swap_bytes((info->format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none) + //.swap_bytes((info.format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none) .apply(); __glcheck glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_depth.id()); - __glcheck glGetTexImage((GLenum)info->target, 0, (GLenum)info->format.format, (GLenum)info->format.type, nullptr); + __glcheck glGetTexImage((GLenum)info.target, 0, (GLenum)info.format.format, (GLenum)info.format.type, nullptr); __glcheck glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); __glcheck pbo_depth.map([&](GLubyte* pixels) { - switch (info->format.bpp) + switch (info.format.bpp) { case 2: { const u16 *src = (const u16*)pixels; - be_t* dst = (be_t*)vm::base_priv(info->start_address); - for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i) + be_t* dst = (be_t*)vm::base_priv(info.start_address); + for (u32 i = 0, end = info.pitch / info.format.bpp * info.height; i < end; ++i) { dst[i] = src[i]; } @@ -207,8 +207,8 @@ namespace gl case 4: { const u32 *src = (const u32*)pixels; - be_t* dst = (be_t*)vm::base_priv(info->start_address); - for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i) + be_t* dst = (be_t*)vm::base_priv(info.start_address); + for (u32 i = 0, end = info.pitch / info.format.bpp * info.height; i < end; ++i) { dst[i] = src[i]; } @@ -221,25 +221,25 @@ namespace gl }, gl::buffer::access::read); } - else if (info->compressed_size) + else if (info.compressed_size) { - LOG_ERROR(RSX, "writing compressed texture[0x%x] to host buffer", info->start_address); + LOG_ERROR(RSX, "writing compressed texture[0x%x] to host buffer", info.start_address); } else { - if (info->swizzled && (info->format.flags & texture_flags::allow_swizzle) != texture_flags::none) + if (info.swizzled && (info.format.flags & texture_flags::allow_swizzle) != texture_flags::none) { //TODO - LOG_ERROR(RSX, "writing swizzled texture[0x%x] to host buffer", info->start_address); + LOG_ERROR(RSX, "writing swizzled texture[0x%x] to host buffer", info.start_address); } gl::pixel_pack_settings{} - .row_length(info->pitch / info->format.bpp) + .row_length(info.pitch / info.format.bpp) .aligment(1) - .swap_bytes((info->format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none) + .swap_bytes((info.format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none) .apply(); - __glcheck glGetTexImage((GLenum)info->target, 0, (GLenum)info->format.format, (GLenum)info->format.type, vm::base_priv(info->start_address)); + __glcheck glGetTexImage((GLenum)info.target, 0, (GLenum)info.format.format, (GLenum)info.format.type, vm::base_priv(info.start_address)); } ignore(gl::cache_buffers::all); @@ -280,13 +280,13 @@ namespace gl if ((buffers & cache_buffers::host) != cache_buffers::none) { m_state &= ~cache_entry_state::host_synchronized; - m_parent_region->for_each(info->start_address, info->size(), [this](cached_texture& texture) + m_parent_region->for_each(info.start_address, info.size(), [this](cached_texture& texture) { if (std::addressof(texture) != this) { //LOG_WARNING(RSX, "cached_texture[0x%x,0x%x) invalidate cached_texture[0x%x, 0x%x)", - // info->start_address, info->start_address + info->size(), - // texture.info->start_address, texture.info->start_address + texture.info->size()); + // info.start_address, info.start_address + info.size(), + // texture.info.start_address, texture.info.start_address + texture.info.size()); texture.invalidate(cache_buffers::local); } }); @@ -368,7 +368,7 @@ namespace gl __glcheck glActiveTexture(GL_TEXTURE0 + index); } - __glcheck glBindTexture((GLenum)info->target, gl_name); + __glcheck glBindTexture((GLenum)info.target, gl_name); } void cached_texture::create() @@ -378,8 +378,8 @@ namespace gl glGenTextures(1, &gl_name); bind(); - __glcheck glTexStorage2D((GLenum)info->target, info->mipmap, (GLenum)info->format.internal_format, info->width, info->height); - //__glcheck glClearTexImage(gl_name, 0, (GLenum)info->format.format, (GLenum)info->format.type, nullptr); + __glcheck glTexStorage2D((GLenum)info.target, info.mipmap, (GLenum)info.format.internal_format, info.width, info.height); + //__glcheck glClearTexImage(gl_name, 0, (GLenum)info.format.format, (GLenum)info.format.type, nullptr); } void cached_texture::remove() @@ -528,7 +528,7 @@ namespace gl auto& texture_info = *result.first; - texture_info.second.info = &texture_info.first; + texture_info.second.info = texture_info.first; texture_info.second.parent(this); return texture_info.second; diff --git a/rpcs3/Emu/RSX/GL/gl_texture_cache.h b/rpcs3/Emu/RSX/GL/gl_texture_cache.h index 3932ba1a63..f1b69c08eb 100644 --- a/rpcs3/Emu/RSX/GL/gl_texture_cache.h +++ b/rpcs3/Emu/RSX/GL/gl_texture_cache.h @@ -80,7 +80,7 @@ namespace gl struct cached_texture { - const texture_info *info; + texture_info info; GLuint gl_name = 0; private: @@ -103,7 +103,7 @@ namespace gl gl::texture_view view() const { - return{ info->target, gl_name }; + return{ info.target, gl_name }; } cache_access requires_protection() const; diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 8432108997..fb6ae49a97 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -604,31 +604,45 @@ namespace rsx { force_inline void buffer_notify(u32 arg) { - const u32 inPitch = method_registers[NV0039_PITCH_IN]; - const u32 outPitch = method_registers[NV0039_PITCH_OUT]; - const u32 lineLength = method_registers[NV0039_LINE_LENGTH_IN]; - const u32 lineCount = method_registers[NV0039_LINE_COUNT]; - const u8 outFormat = method_registers[NV0039_FORMAT] >> 8; - const u8 inFormat = method_registers[NV0039_FORMAT]; + u32 in_pitch = method_registers[NV0039_PITCH_IN]; + u32 out_pitch = method_registers[NV0039_PITCH_OUT]; + const u32 line_length = method_registers[NV0039_LINE_LENGTH_IN]; + const u32 line_count = method_registers[NV0039_LINE_COUNT]; + const u8 out_format = method_registers[NV0039_FORMAT] >> 8; + const u8 in_format = method_registers[NV0039_FORMAT]; const u32 notify = arg; // The existing GCM commands use only the value 0x1 for inFormat and outFormat - if (inFormat != 0x01 || outFormat != 0x01) + if (in_format != 0x01 || out_format != 0x01) { - LOG_ERROR(RSX, "NV0039_OFFSET_IN: Unsupported format: inFormat=%d, outFormat=%d", inFormat, outFormat); + LOG_ERROR(RSX, "NV0039_OFFSET_IN: Unsupported format: inFormat=%d, outFormat=%d", in_format, out_format); } - if (lineCount == 1 && !inPitch && !outPitch && !notify) + if (!in_pitch) { - std::memcpy( - vm::base(get_address(method_registers[NV0039_OFFSET_OUT], method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_OUT])), - vm::base(get_address(method_registers[NV0039_OFFSET_IN], method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_IN])), - lineLength); + in_pitch = line_length; + } + + if (!out_pitch) + { + out_pitch = line_length; + } + + u8 *dst = (u8*)vm::base(get_address(method_registers[NV0039_OFFSET_OUT], method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_OUT])); + const u8 *src = (u8*)vm::base(get_address(method_registers[NV0039_OFFSET_IN], method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_IN])); + + if (in_pitch == out_pitch && out_pitch == line_length) + { + std::memcpy(dst, src, line_length * line_count); } else { - LOG_ERROR(RSX, "NV0039_OFFSET_IN: bad offset(in=0x%x, out=0x%x), pitch(in=0x%x, out=0x%x), line(len=0x%x, cnt=0x%x), fmt(in=0x%x, out=0x%x), notify=0x%x", - method_registers[NV0039_OFFSET_IN], method_registers[NV0039_OFFSET_OUT], inPitch, outPitch, lineLength, lineCount, inFormat, outFormat, notify); + for (u32 i = 0; i < line_count; ++i) + { + std::memcpy(dst, src, line_length); + dst += out_pitch; + src += in_pitch; + } } } }