fixed random crashes

improved nv0039::buffer_notify
added print_call_stack utility (TODO)
This commit is contained in:
DHrpcs3 2016-03-13 14:21:45 +03:00
commit 10ec26ace8
7 changed files with 159 additions and 99 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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