mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-08-05 15:49:20 +00:00
fixed random crashes
improved nv0039::buffer_notify added print_call_stack utility (TODO)
This commit is contained in:
parent
8aeac09741
commit
10ec26ace8
7 changed files with 159 additions and 99 deletions
|
@ -441,7 +441,7 @@ void GLGSRender::end()
|
||||||
int location;
|
int location;
|
||||||
if (m_program->uniforms.has_location("tex" + std::to_string(i), &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);
|
__glcheck glProgramUniform1i(m_program->id(), location, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -708,7 +708,7 @@ void GLGSRender::end()
|
||||||
|
|
||||||
rsx::thread::end();
|
rsx::thread::end();
|
||||||
|
|
||||||
m_texture_cache.update_protection();
|
texture_cache.update_protection();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGSRender::set_viewport()
|
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);
|
//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)
|
if ((arg & (depth_stencil | color_mask)) == 0)
|
||||||
{
|
{
|
||||||
//do nothing
|
//do nothing
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -941,13 +941,22 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer)
|
||||||
{
|
{
|
||||||
__glcheck glClear(mask);
|
__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<u32, rsx_method_impl_t> g_gl_method_tbl =
|
static const std::unordered_map<u32, rsx_method_impl_t> 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)
|
bool GLGSRender::do_method(u32 cmd, u32 arg)
|
||||||
|
@ -959,8 +968,7 @@ bool GLGSRender::do_method(u32 cmd, u32 arg)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
found->second(arg, this);
|
return found->second(arg, this);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGSRender::load_program()
|
bool GLGSRender::load_program()
|
||||||
|
@ -1205,7 +1213,7 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||||
|
|
||||||
info.swizzled = swizzled;
|
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();
|
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 };
|
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)
|
switch (m_surface.depth_format)
|
||||||
{
|
{
|
||||||
|
@ -1333,7 +1341,7 @@ void GLGSRender::flip(int buffer)
|
||||||
glDisable(GL_LOGIC_OP);
|
glDisable(GL_LOGIC_OP);
|
||||||
glDisable(GL_CULL_FACE);
|
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);
|
CELL_GCM_LOCATION_LOCAL, buffer_width, buffer_height, buffer_pitch), gl::cache_buffers::local);
|
||||||
|
|
||||||
//std::lock_guard<gl::cached_texture> lock(texture);
|
//std::lock_guard<gl::cached_texture> lock(texture);
|
||||||
|
@ -1389,7 +1397,7 @@ u64 GLGSRender::timestamp() const
|
||||||
|
|
||||||
bool GLGSRender::on_access_violation(u32 address, bool is_writing)
|
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<gl::protected_region> lock(*region);
|
//std::lock_guard<gl::protected_region> lock(*region);
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,8 @@ private:
|
||||||
|
|
||||||
texture_buffer_pair m_gl_attrib_buffers[rsx::limits::vertex_count];
|
texture_buffer_pair m_gl_attrib_buffers[rsx::limits::vertex_count];
|
||||||
|
|
||||||
gl::texture_cache m_texture_cache;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
gl::texture_cache texture_cache;
|
||||||
gl::fbo draw_fbo;
|
gl::fbo draw_fbo;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,6 +1,42 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "gl_helpers.h"
|
#include "gl_helpers.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <DbgHelp.h>
|
||||||
|
#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<SYMBOL_INFO, decltype(&std::free)> 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
|
namespace gl
|
||||||
{
|
{
|
||||||
const fbo screen{};
|
const fbo screen{};
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include "OpenGL.h"
|
#include "OpenGL.h"
|
||||||
#include "../GCM.h"
|
#include "../GCM.h"
|
||||||
|
|
||||||
|
void print_call_stack(int skip);
|
||||||
|
|
||||||
namespace gl
|
namespace gl
|
||||||
{
|
{
|
||||||
#if 1//def _DEBUG
|
#if 1//def _DEBUG
|
||||||
|
@ -44,6 +46,7 @@ namespace gl
|
||||||
default: error = "unknown error"; break;
|
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));
|
throw std::runtime_error(fmt::format("OpenGL error: %s. file '%s' function '%s' line %ld", error.c_str(), file, function, line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,19 +18,19 @@ namespace gl
|
||||||
void cached_texture::read()
|
void cached_texture::read()
|
||||||
{
|
{
|
||||||
cached_texture* found_texture = nullptr;
|
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)
|
if ((texture.m_state & cache_entry_state::local_synchronized) == cache_entry_state::invalid)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texture.info->start_address != info->start_address ||
|
if (texture.info.start_address != info.start_address ||
|
||||||
texture.info->pitch != info->pitch ||
|
texture.info.pitch != info.pitch ||
|
||||||
texture.info->height < info->height ||
|
texture.info.height < info.height ||
|
||||||
texture.info->width < info->width)
|
texture.info.width < info.width)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -42,35 +42,35 @@ namespace gl
|
||||||
{
|
{
|
||||||
//read from local
|
//read from local
|
||||||
__glcheck glCopyImageSubData(
|
__glcheck glCopyImageSubData(
|
||||||
found_texture->gl_name, (GLenum)found_texture->info->target, 0, 0, 0, 0,
|
found_texture->gl_name, (GLenum)found_texture->info.target, 0, 0, 0, 0,
|
||||||
gl_name, (GLenum)info->target, 0, 0, 0, 0,
|
gl_name, (GLenum)info.target, 0, 0, 0, 0,
|
||||||
info->width, info->height, info->depth);
|
info.width, info.height, info.depth);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//read from host
|
//read from host
|
||||||
//flush all local textures at region
|
//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);
|
texture.sync(gl::cache_buffers::host);
|
||||||
});
|
});
|
||||||
|
|
||||||
bind();
|
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;
|
gl::buffer pbo_depth;
|
||||||
|
|
||||||
__glcheck pbo_depth.create(info->size());
|
__glcheck pbo_depth.create(info.size());
|
||||||
__glcheck pbo_depth.map([&](GLubyte* pixels)
|
__glcheck pbo_depth.map([&](GLubyte* pixels)
|
||||||
{
|
{
|
||||||
switch (info->format.bpp)
|
switch (info.format.bpp)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
u16 *dst = (u16*)pixels;
|
u16 *dst = (u16*)pixels;
|
||||||
const be_t<u16>* src = (const be_t<u16>*)vm::base_priv(info->start_address);
|
const be_t<u16>* src = (const be_t<u16>*)vm::base_priv(info.start_address);
|
||||||
for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i)
|
for (u32 i = 0, end = info.pitch / info.format.bpp * info.height; i < end; ++i)
|
||||||
{
|
{
|
||||||
dst[i] = src[i];
|
dst[i] = src[i];
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,8 @@ namespace gl
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
u32 *dst = (u32*)pixels;
|
u32 *dst = (u32*)pixels;
|
||||||
const be_t<u32>* src = (const be_t<u32>*)vm::base_priv(info->start_address);
|
const be_t<u32>* src = (const be_t<u32>*)vm::base_priv(info.start_address);
|
||||||
for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i)
|
for (u32 i = 0, end = info.pitch / info.format.bpp * info.height; i < end; ++i)
|
||||||
{
|
{
|
||||||
dst[i] = src[i];
|
dst[i] = src[i];
|
||||||
}
|
}
|
||||||
|
@ -94,47 +94,47 @@ namespace gl
|
||||||
}, gl::buffer::access::write);
|
}, gl::buffer::access::write);
|
||||||
|
|
||||||
gl::pixel_unpack_settings{}
|
gl::pixel_unpack_settings{}
|
||||||
.row_length(info->pitch / info->format.bpp)
|
.row_length(info.pitch / info.format.bpp)
|
||||||
.aligment(1)
|
.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();
|
.apply();
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_depth.id());
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_depth.id());
|
||||||
|
|
||||||
__glcheck glTexSubImage2D((GLenum)info->target, 0, 0, 0, info->width, info->height,
|
__glcheck glTexSubImage2D((GLenum)info.target, 0, 0, 0, info.width, info.height,
|
||||||
(GLenum)info->format.format, (GLenum)info->format.type, nullptr);
|
(GLenum)info.format.format, (GLenum)info.format.type, nullptr);
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
}
|
}
|
||||||
else if (info->compressed_size)
|
else if (info.compressed_size)
|
||||||
{
|
{
|
||||||
__glcheck glCompressedTexSubImage2D((GLenum)info->target, 0,
|
__glcheck glCompressedTexSubImage2D((GLenum)info.target, 0,
|
||||||
0, 0, info->width, info->height,
|
0, 0, info.width, info.height,
|
||||||
(GLenum)info->format.internal_format,
|
(GLenum)info.format.internal_format,
|
||||||
info->compressed_size, vm::base_priv(info->start_address));
|
info.compressed_size, vm::base_priv(info.start_address));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
void *pixels = vm::base_priv(info->start_address);
|
void *pixels = vm::base_priv(info.start_address);
|
||||||
|
|
||||||
std::unique_ptr<u8[]> linear_pixels;
|
std::unique_ptr<u8[]> 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()]);
|
linear_pixels.reset(new u8[info.size()]);
|
||||||
switch (info->format.bpp)
|
switch (info.format.bpp)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
rsx::convert_linear_swizzle<u8>(pixels, linear_pixels.get(), info->width, info->height, true);
|
rsx::convert_linear_swizzle<u8>(pixels, linear_pixels.get(), info.width, info.height, true);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
rsx::convert_linear_swizzle<u16>(pixels, linear_pixels.get(), info->width, info->height, true);
|
rsx::convert_linear_swizzle<u16>(pixels, linear_pixels.get(), info.width, info.height, true);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
rsx::convert_linear_swizzle<u32>(pixels, linear_pixels.get(), info->width, info->height, true);
|
rsx::convert_linear_swizzle<u32>(pixels, linear_pixels.get(), info.width, info.height, true);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
rsx::convert_linear_swizzle<u64>(pixels, linear_pixels.get(), info->width, info->height, true);
|
rsx::convert_linear_swizzle<u64>(pixels, linear_pixels.get(), info.width, info.height, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -145,22 +145,22 @@ namespace gl
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::pixel_unpack_settings{}
|
gl::pixel_unpack_settings{}
|
||||||
.row_length(info->pitch / info->format.bpp)
|
.row_length(info.pitch / info.format.bpp)
|
||||||
.aligment(1)
|
.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();
|
.apply();
|
||||||
|
|
||||||
__glcheck glTexSubImage2D((GLenum)info->target, 0, 0, 0, info->width, info->height,
|
__glcheck glTexSubImage2D((GLenum)info.target, 0, 0, 0, info.width, info.height,
|
||||||
(GLenum)info->format.format, (GLenum)info->format.type, pixels);
|
(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_MIN_LOD, info.min_lod);
|
||||||
__glcheck glTexParameteri((GLenum)info->target, GL_TEXTURE_MAX_LOD, info->max_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 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();
|
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;
|
gl::buffer pbo_depth;
|
||||||
|
|
||||||
pbo_depth.create(info->size());
|
pbo_depth.create(info.size());
|
||||||
|
|
||||||
gl::pixel_pack_settings{}
|
gl::pixel_pack_settings{}
|
||||||
.row_length(info->pitch / info->format.bpp)
|
.row_length(info.pitch / info.format.bpp)
|
||||||
.aligment(1)
|
.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();
|
.apply();
|
||||||
|
|
||||||
__glcheck glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_depth.id());
|
__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 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
|
|
||||||
__glcheck pbo_depth.map([&](GLubyte* pixels)
|
__glcheck pbo_depth.map([&](GLubyte* pixels)
|
||||||
{
|
{
|
||||||
switch (info->format.bpp)
|
switch (info.format.bpp)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
const u16 *src = (const u16*)pixels;
|
const u16 *src = (const u16*)pixels;
|
||||||
be_t<u16>* dst = (be_t<u16>*)vm::base_priv(info->start_address);
|
be_t<u16>* dst = (be_t<u16>*)vm::base_priv(info.start_address);
|
||||||
for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i)
|
for (u32 i = 0, end = info.pitch / info.format.bpp * info.height; i < end; ++i)
|
||||||
{
|
{
|
||||||
dst[i] = src[i];
|
dst[i] = src[i];
|
||||||
}
|
}
|
||||||
|
@ -207,8 +207,8 @@ namespace gl
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
const u32 *src = (const u32*)pixels;
|
const u32 *src = (const u32*)pixels;
|
||||||
be_t<u32>* dst = (be_t<u32>*)vm::base_priv(info->start_address);
|
be_t<u32>* dst = (be_t<u32>*)vm::base_priv(info.start_address);
|
||||||
for (u32 i = 0, end = info->pitch / info->format.bpp * info->height; i < end; ++i)
|
for (u32 i = 0, end = info.pitch / info.format.bpp * info.height; i < end; ++i)
|
||||||
{
|
{
|
||||||
dst[i] = src[i];
|
dst[i] = src[i];
|
||||||
}
|
}
|
||||||
|
@ -221,25 +221,25 @@ namespace gl
|
||||||
|
|
||||||
}, gl::buffer::access::read);
|
}, 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
|
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
|
//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{}
|
gl::pixel_pack_settings{}
|
||||||
.row_length(info->pitch / info->format.bpp)
|
.row_length(info.pitch / info.format.bpp)
|
||||||
.aligment(1)
|
.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();
|
.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);
|
ignore(gl::cache_buffers::all);
|
||||||
|
@ -280,13 +280,13 @@ namespace gl
|
||||||
if ((buffers & cache_buffers::host) != cache_buffers::none)
|
if ((buffers & cache_buffers::host) != cache_buffers::none)
|
||||||
{
|
{
|
||||||
m_state &= ~cache_entry_state::host_synchronized;
|
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)
|
if (std::addressof(texture) != this)
|
||||||
{
|
{
|
||||||
//LOG_WARNING(RSX, "cached_texture[0x%x,0x%x) invalidate cached_texture[0x%x, 0x%x)",
|
//LOG_WARNING(RSX, "cached_texture[0x%x,0x%x) invalidate cached_texture[0x%x, 0x%x)",
|
||||||
// info->start_address, info->start_address + info->size(),
|
// info.start_address, info.start_address + info.size(),
|
||||||
// texture.info->start_address, texture.info->start_address + texture.info->size());
|
// texture.info.start_address, texture.info.start_address + texture.info.size());
|
||||||
texture.invalidate(cache_buffers::local);
|
texture.invalidate(cache_buffers::local);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -368,7 +368,7 @@ namespace gl
|
||||||
__glcheck glActiveTexture(GL_TEXTURE0 + index);
|
__glcheck glActiveTexture(GL_TEXTURE0 + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
__glcheck glBindTexture((GLenum)info->target, gl_name);
|
__glcheck glBindTexture((GLenum)info.target, gl_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cached_texture::create()
|
void cached_texture::create()
|
||||||
|
@ -378,8 +378,8 @@ namespace gl
|
||||||
glGenTextures(1, &gl_name);
|
glGenTextures(1, &gl_name);
|
||||||
|
|
||||||
bind();
|
bind();
|
||||||
__glcheck glTexStorage2D((GLenum)info->target, info->mipmap, (GLenum)info->format.internal_format, info->width, info->height);
|
__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 glClearTexImage(gl_name, 0, (GLenum)info.format.format, (GLenum)info.format.type, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cached_texture::remove()
|
void cached_texture::remove()
|
||||||
|
@ -528,7 +528,7 @@ namespace gl
|
||||||
|
|
||||||
auto& texture_info = *result.first;
|
auto& texture_info = *result.first;
|
||||||
|
|
||||||
texture_info.second.info = &texture_info.first;
|
texture_info.second.info = texture_info.first;
|
||||||
texture_info.second.parent(this);
|
texture_info.second.parent(this);
|
||||||
|
|
||||||
return texture_info.second;
|
return texture_info.second;
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace gl
|
||||||
|
|
||||||
struct cached_texture
|
struct cached_texture
|
||||||
{
|
{
|
||||||
const texture_info *info;
|
texture_info info;
|
||||||
GLuint gl_name = 0;
|
GLuint gl_name = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -103,7 +103,7 @@ namespace gl
|
||||||
|
|
||||||
gl::texture_view view() const
|
gl::texture_view view() const
|
||||||
{
|
{
|
||||||
return{ info->target, gl_name };
|
return{ info.target, gl_name };
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_access requires_protection() const;
|
cache_access requires_protection() const;
|
||||||
|
|
|
@ -604,31 +604,45 @@ namespace rsx
|
||||||
{
|
{
|
||||||
force_inline void buffer_notify(u32 arg)
|
force_inline void buffer_notify(u32 arg)
|
||||||
{
|
{
|
||||||
const u32 inPitch = method_registers[NV0039_PITCH_IN];
|
u32 in_pitch = method_registers[NV0039_PITCH_IN];
|
||||||
const u32 outPitch = method_registers[NV0039_PITCH_OUT];
|
u32 out_pitch = method_registers[NV0039_PITCH_OUT];
|
||||||
const u32 lineLength = method_registers[NV0039_LINE_LENGTH_IN];
|
const u32 line_length = method_registers[NV0039_LINE_LENGTH_IN];
|
||||||
const u32 lineCount = method_registers[NV0039_LINE_COUNT];
|
const u32 line_count = method_registers[NV0039_LINE_COUNT];
|
||||||
const u8 outFormat = method_registers[NV0039_FORMAT] >> 8;
|
const u8 out_format = method_registers[NV0039_FORMAT] >> 8;
|
||||||
const u8 inFormat = method_registers[NV0039_FORMAT];
|
const u8 in_format = method_registers[NV0039_FORMAT];
|
||||||
const u32 notify = arg;
|
const u32 notify = arg;
|
||||||
|
|
||||||
// The existing GCM commands use only the value 0x1 for inFormat and outFormat
|
// 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(
|
in_pitch = line_length;
|
||||||
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);
|
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
|
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",
|
for (u32 i = 0; i < line_count; ++i)
|
||||||
method_registers[NV0039_OFFSET_IN], method_registers[NV0039_OFFSET_OUT], inPitch, outPitch, lineLength, lineCount, inFormat, outFormat, notify);
|
{
|
||||||
|
std::memcpy(dst, src, line_length);
|
||||||
|
dst += out_pitch;
|
||||||
|
src += in_pitch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue