Merge pull request #1840 from RPCS3/WIP

RSX improvements
This commit is contained in:
DHrpcs3 2016-06-28 14:22:12 +03:00 committed by GitHub
commit c7965405d3
19 changed files with 446 additions and 132 deletions

View File

@ -1207,7 +1207,7 @@ const std::string& fs::get_executable_dir()
return s_dir; return s_dir;
} }
void fs::remove_all(const std::string& path) void fs::remove_all(const std::string& path, bool remove_root)
{ {
for (const auto& entry : dir(path)) for (const auto& entry : dir(path))
{ {
@ -1227,7 +1227,10 @@ void fs::remove_all(const std::string& path)
} }
} }
remove_dir(path); if (remove_root)
{
remove_dir(path);
}
} }
u64 fs::get_dir_size(const std::string& path) u64 fs::get_dir_size(const std::string& path)

View File

@ -440,7 +440,7 @@ namespace fs
const std::string& get_executable_dir(); const std::string& get_executable_dir();
// Delete directory and all its contents recursively // Delete directory and all its contents recursively
void remove_all(const std::string& path); void remove_all(const std::string& path, bool remove_root = true);
// Get size of all files recursively // Get size of all files recursively
u64 get_dir_size(const std::string& path); u64 get_dir_size(const std::string& path);

4
bin/data/.gitignore vendored
View File

@ -1,4 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -1,4 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -120,7 +120,8 @@ u32 get_row_pitch_in_block(u16 width_in_block, size_t multiple_constraints_in_by
* Since rsx ignore unused dimensionnality some app set them to 0. * Since rsx ignore unused dimensionnality some app set them to 0.
* Use 1 value instead to be more general. * Use 1 value instead to be more general.
*/ */
std::tuple<u16, u16, u8> get_height_depth_layer(const rsx::texture &tex) template<typename RsxTextureType>
std::tuple<u16, u16, u8> get_height_depth_layer(const RsxTextureType &tex)
{ {
switch (tex.get_extended_texture_dimension()) switch (tex.get_extended_texture_dimension())
{ {
@ -133,7 +134,8 @@ std::tuple<u16, u16, u8> get_height_depth_layer(const rsx::texture &tex)
} }
} }
std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::texture &texture) template<typename RsxTextureType>
std::vector<rsx_subresource_layout> get_subresources_layout_impl(const RsxTextureType &texture)
{ {
u16 w = texture.width(); u16 w = texture.width();
u16 h; u16 h;
@ -184,6 +186,16 @@ std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::texture &
throw EXCEPTION("Wrong format 0x%x", format); throw EXCEPTION("Wrong format 0x%x", format);
} }
std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::texture &texture)
{
return get_subresources_layout_impl(texture);
}
std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::vertex_texture &texture)
{
return get_subresources_layout_impl(texture);
}
void upload_texture_subresource(gsl::span<gsl::byte> dst_buffer, const rsx_subresource_layout &src_layout, int format, bool is_swizzled, size_t dst_row_pitch_multiple_of) void upload_texture_subresource(gsl::span<gsl::byte> dst_buffer, const rsx_subresource_layout &src_layout, int format, bool is_swizzled, size_t dst_row_pitch_multiple_of)
{ {
u16 w = src_layout.width_in_block; u16 w = src_layout.width_in_block;
@ -339,36 +351,48 @@ u8 get_format_block_size_in_texel(int format)
} }
} }
static size_t get_placed_texture_storage_size(u16 width, u16 height, u32 depth, u8 format, u16 mipmap, bool cubemap, size_t row_pitch_alignement, size_t mipmap_alignment)
size_t get_placed_texture_storage_size(const rsx::texture &texture, size_t rowPitchAlignement, size_t mipmapAlignment)
{ {
size_t w = texture.width(), h = texture.height(), d = std::max<u16>(texture.depth(), 1); size_t w = width;
size_t h = std::max<u16>(height, 1);
size_t d = std::max<u16>(depth, 1);
int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); format &= ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
size_t blockEdge = get_format_block_size_in_texel(format); size_t block_edge = get_format_block_size_in_texel(format);
size_t blockSizeInByte = get_format_block_size_in_bytes(format); size_t block_size_in_byte = get_format_block_size_in_bytes(format);
size_t heightInBlocks = (h + blockEdge - 1) / blockEdge; size_t height_in_blocks = (h + block_edge - 1) / block_edge;
size_t widthInBlocks = (w + blockEdge - 1) / blockEdge; size_t width_in_blocks = (w + block_edge - 1) / block_edge;
size_t result = 0; size_t result = 0;
for (unsigned mipmap = 0; mipmap < texture.mipmap(); ++mipmap) for (u16 i = 0; i < mipmap; ++i)
{ {
size_t rowPitch = align(blockSizeInByte * widthInBlocks, rowPitchAlignement); size_t rowPitch = align(block_size_in_byte * width_in_blocks, row_pitch_alignement);
result += align(rowPitch * heightInBlocks * d, mipmapAlignment); result += align(rowPitch * height_in_blocks * d, mipmap_alignment);
heightInBlocks = std::max<size_t>(heightInBlocks / 2, 1); height_in_blocks = std::max<size_t>(height_in_blocks / 2, 1);
widthInBlocks = std::max<size_t>(widthInBlocks / 2, 1); width_in_blocks = std::max<size_t>(width_in_blocks / 2, 1);
} }
return result * (texture.cubemap() ? 6 : 1); return result * (cubemap ? 6 : 1);
}
size_t get_placed_texture_storage_size(const rsx::texture &texture, size_t row_pitch_alignement, size_t mipmap_alignment)
{
return get_placed_texture_storage_size(texture.width(), texture.height(), texture.depth(), texture.format(), texture.mipmap(), texture.cubemap(),
row_pitch_alignement, mipmap_alignment);
}
size_t get_placed_texture_storage_size(const rsx::vertex_texture &texture, size_t row_pitch_alignement, size_t mipmap_alignment)
{
return get_placed_texture_storage_size(texture.width(), texture.height(), texture.depth(), texture.format(), texture.mipmap(), texture.cubemap(),
row_pitch_alignement, mipmap_alignment);
} }
size_t get_texture_size(const rsx::texture &texture) static size_t get_texture_size(u32 w, u32 h, u8 format)
{ {
size_t w = texture.width(), h = texture.height(); format &= ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
// TODO: Take mipmaps into account // TODO: Take mipmaps into account
switch (format) switch (format)
{ {
@ -434,3 +458,13 @@ size_t get_texture_size(const rsx::texture &texture)
return 0; return 0;
} }
} }
size_t get_texture_size(const rsx::texture &texture)
{
return get_texture_size(texture.width(), texture.height(), texture.format());
}
size_t get_texture_size(const rsx::vertex_texture &texture)
{
return get_texture_size(texture.width(), texture.height(), texture.format());
}

View File

@ -18,13 +18,15 @@ struct rsx_subresource_layout
* Get size to store texture in a linear fashion. * Get size to store texture in a linear fashion.
* Storage is assumed to use a rowPitchAlignement boundary for every row of texture. * Storage is assumed to use a rowPitchAlignement boundary for every row of texture.
*/ */
size_t get_placed_texture_storage_size(const rsx::texture &texture, size_t rowPitchAlignement, size_t mipmapAlignment=512); size_t get_placed_texture_storage_size(const rsx::texture &texture, size_t row_pitch_alignement, size_t mipmap_alignment = 0x200);
size_t get_placed_texture_storage_size(const rsx::vertex_texture &texture, size_t row_pitch_alignement, size_t mipmap_alignment = 0x200);
/** /**
* get all rsx_subresource_layout for texture. * get all rsx_subresource_layout for texture.
* The subresources are ordered per layer then per mipmap level (as in rsx memory). * The subresources are ordered per layer then per mipmap level (as in rsx memory).
*/ */
std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::texture &texture); std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::texture &texture);
std::vector<rsx_subresource_layout> get_subresources_layout(const rsx::vertex_texture &texture);
void upload_texture_subresource(gsl::span<gsl::byte> dst_buffer, const rsx_subresource_layout &src_layout, int format, bool is_swizzled, size_t dst_row_pitch_multiple_of); void upload_texture_subresource(gsl::span<gsl::byte> dst_buffer, const rsx_subresource_layout &src_layout, int format, bool is_swizzled, size_t dst_row_pitch_multiple_of);
@ -35,3 +37,4 @@ u8 get_format_block_size_in_texel(int format);
* Get number of bytes occupied by texture in RSX mem * Get number of bytes occupied by texture in RSX mem
*/ */
size_t get_texture_size(const rsx::texture &texture); size_t get_texture_size(const rsx::texture &texture);
size_t get_texture_size(const rsx::vertex_texture &texture);

View File

@ -235,6 +235,18 @@ namespace
} }
throw EXCEPTION("Unknow texture target"); throw EXCEPTION("Unknow texture target");
} }
GLenum get_gl_target_for_texture(const rsx::vertex_texture& tex)
{
switch (tex.get_extended_texture_dimension())
{
case rsx::texture_dimension_extended::texture_dimension_1d: return GL_TEXTURE_1D;
case rsx::texture_dimension_extended::texture_dimension_2d: return GL_TEXTURE_2D;
case rsx::texture_dimension_extended::texture_dimension_cubemap: return GL_TEXTURE_CUBE_MAP;
case rsx::texture_dimension_extended::texture_dimension_3d: return GL_TEXTURE_3D;
}
throw EXCEPTION("Unknow texture target");
}
} }
void GLGSRender::end() void GLGSRender::end()
@ -295,7 +307,6 @@ void GLGSRender::end()
//setup textures //setup textures
{ {
//int texture_index = 0;
for (int i = 0; i < rsx::limits::textures_count; ++i) for (int i = 0; i < rsx::limits::textures_count; ++i)
{ {
int location; int location;
@ -311,12 +322,9 @@ void GLGSRender::end()
} }
m_gl_textures[i].set_target(get_gl_target_for_texture(textures[i])); m_gl_textures[i].set_target(get_gl_target_for_texture(textures[i]));
__glcheck m_gl_texture_cache.upload_texture(i, textures[i], m_gl_textures[i], m_rtts); __glcheck m_gl_texture_cache.upload_texture(i, textures[i], m_gl_textures[i], m_rtts);
__glcheck glProgramUniform1i(m_program->id(), location, i); __glcheck glProgramUniform1i(m_program->id(), location, i);
//__glcheck m_gl_textures[i].init(i, textures[i]);
//texture_index++;
if (m_program->uniforms.has_location("ftexture" + std::to_string(i) + "_cm", &location)) if (m_program->uniforms.has_location("ftexture" + std::to_string(i) + "_cm", &location))
{ {
@ -331,21 +339,39 @@ void GLGSRender::end()
} }
} }
} }
/*
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i) for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
{ {
if (vertex_textures[i].enabled()) int location;
if (m_program->uniforms.has_location("vtexture" + std::to_string(i), &location))
{ {
int location; if (!textures[i].enabled())
if (m_program->uniforms.has_location("vtexture" + std::to_string(i), &location))
{ {
glProgramUniform1i(m_program->id(), location, texture_index); glActiveTexture(GL_TEXTURE0 + i);
m_gl_vertex_textures[i].init(texture_index, vertex_textures[i]); glBindTexture(GL_TEXTURE_2D, 0);
texture_index++; glProgramUniform1i(m_program->id(), location, i);
continue;
}
m_gl_vertex_textures[i].set_target(get_gl_target_for_texture(vertex_textures[i]));
__glcheck m_gl_texture_cache.upload_texture(i, vertex_textures[i], m_gl_vertex_textures[i], m_rtts);
__glcheck glProgramUniform1i(m_program->id(), location, i);
if (m_program->uniforms.has_location("vtexture" + std::to_string(i) + "_cm", &location))
{
if (textures[i].format() & CELL_GCM_TEXTURE_UN)
{
u32 width = std::max<u32>(textures[i].width(), 1);
u32 height = std::max<u32>(textures[i].height(), 1);
u32 depth = std::max<u32>(textures[i].depth(), 1);
glProgramUniform4f(m_program->id(), location, 1.f / width, 1.f / height, 1.f / depth, 1.0f);
}
} }
} }
} }
*/
} }
u32 offset_in_index_buffer = set_vertex_buffer(); u32 offset_in_index_buffer = set_vertex_buffer();

View File

@ -424,7 +424,8 @@ namespace gl
} }
} }
void upload_texture(int index, rsx::texture &tex, rsx::gl::texture &gl_texture, gl_render_targets &m_rtts) template<typename RsxTextureType>
void upload_texture(int index, RsxTextureType &tex, rsx::gl::texture &gl_texture, gl_render_targets &m_rtts)
{ {
const u32 texaddr = rsx::get_address(tex.offset(), tex.location()); const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
const u32 range = (u32)get_texture_size(tex); const u32 range = (u32)get_texture_size(tex);
@ -458,7 +459,7 @@ namespace gl
if (texptr = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr)) if (texptr = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
{ {
texptr->bind(); texptr->bind();
return; return;
} }

View File

@ -127,7 +127,6 @@ static void insert_texture_lod_fetch_function(std::string &dst, const rsx::decom
dst += "}\n"; dst += "}\n";
} }
static void insert_texture_proj_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state) static void insert_texture_proj_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state)
{ {
if (shader.textures.empty()) if (shader.textures.empty())
@ -237,26 +236,6 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader,
result.code += "\n"; result.code += "\n";
for (const rsx::texture_info& texture : shader.textures)
{
result.code += "uniform vec4 " + texture.name + "_cm = vec4(1.0);\n";
rsx::texture_target target = state.textures[texture.id];
result.code += "uniform sampler";
switch (target)
{
default:
case rsx::texture_target::_1: result.code += "1D"; break;
case rsx::texture_target::_2: result.code += "2D"; break;
case rsx::texture_target::_3: result.code += "3D"; break;
case rsx::texture_target::cube: result.code += "Cube"; break;
}
result.code += " " + texture.name + ";\n";
}
std::string prepare; std::string prepare;
std::string finalize; std::string finalize;
int location = 1; int location = 1;
@ -264,6 +243,24 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader,
switch (shader.raw->type) switch (shader.raw->type)
{ {
case rsx::program_type::fragment: case rsx::program_type::fragment:
for (const rsx::texture_info& texture : shader.textures)
{
result.code += "uniform vec4 " + texture.name + "_cm = vec4(1.0);\n";
rsx::texture_target target = state.textures[texture.id];
result.code += "uniform sampler";
switch (target)
{
default:
case rsx::texture_target::_1: result.code += "1D"; break;
case rsx::texture_target::_2: result.code += "2D"; break;
case rsx::texture_target::_3: result.code += "3D"; break;
case rsx::texture_target::cube: result.code += "Cube"; break;
}
result.code += " " + texture.name + ";\n";
}
insert_texture_fetch_function(result.code, shader, state); insert_texture_fetch_function(result.code, shader, state);
insert_texture_bias_fetch_function(result.code, shader, state); insert_texture_bias_fetch_function(result.code, shader, state);
insert_texture_grad_fetch_function(result.code, shader, state); insert_texture_grad_fetch_function(result.code, shader, state);
@ -524,20 +521,33 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader,
break; break;
case rsx::program_type::vertex: case rsx::program_type::vertex:
for (const rsx::texture_info& texture : shader.textures)
{
result.code += "uniform vec4 " + texture.name + "_cm = vec4(1.0);\n";
rsx::texture_target target = state.vertex_textures[texture.id];
result.code += "uniform sampler";
switch (target)
{
default:
case rsx::texture_target::_1: result.code += "1D"; break;
case rsx::texture_target::_2: result.code += "2D"; break;
case rsx::texture_target::_3: result.code += "3D"; break;
case rsx::texture_target::cube: result.code += "Cube"; break;
}
result.code += " " + texture.name + ";\n";
}
insert_texture_lod_fetch_function(result.code, shader, state);
result.code += "out vec4 wpos;\n"; result.code += "out vec4 wpos;\n";
// TODO finalize +=
if (0) " wpos = window_matrix * viewport_matrix * vec4(o0.xyz, 1.0);\n"
{ " gl_Position = normalize_matrix * vec4(wpos.xyz, 1.0);\n"
finalize += "\tgl_Position = o0;\n"; " gl_Position.w = o0.w;\n";
}
else
{
finalize +=
" wpos = window_matrix * viewport_matrix * vec4(o0.xyz, 1.0);\n"
" gl_Position = normalize_matrix * vec4(wpos.xyz, 1.0);\n"
" gl_Position.w = o0.w;\n";
}
{ {
std::string code_end; std::string code_end;

View File

@ -536,6 +536,111 @@ namespace rsx
__glcheck glTexParameterf(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso())); __glcheck glTexParameterf(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso()));
} }
void texture::init(int index, rsx::vertex_texture& tex)
{
switch (tex.dimension())
{
case rsx::texture_dimension::dimension3d:
if (!tex.depth())
{
return;
}
case rsx::texture_dimension::dimension2d:
if (!tex.height())
{
return;
}
case rsx::texture_dimension::dimension1d:
if (!tex.width())
{
return;
}
break;
}
const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
//We can't re-use texture handles if using immutable storage
if (m_id)
{
__glcheck remove();
}
__glcheck create();
__glcheck glActiveTexture(GL_TEXTURE0 + index);
bind();
u32 full_format = tex.format();
u32 format = full_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
bool is_swizzled = !!(~full_format & CELL_GCM_TEXTURE_LN);
__glcheck::gl::pixel_pack_settings().apply();
__glcheck::gl::pixel_unpack_settings().apply();
u32 aligned_pitch = tex.pitch();
size_t texture_data_sz = get_placed_texture_storage_size(tex, 256);
std::vector<gsl::byte> data_upload_buf(texture_data_sz);
u32 block_sz = get_pitch_modifier(format);
__glcheck glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
__glcheck create_and_fill_texture(tex.get_extended_texture_dimension(), tex.get_exact_mipmap_count(), format, tex.width(), tex.height(), tex.depth(), get_subresources_layout(tex), is_swizzled, data_upload_buf);
const std::array<GLenum, 4>& glRemap = get_swizzle_remap(format);
glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, tex.get_exact_mipmap_count() - 1);
/*
if (format != CELL_GCM_TEXTURE_B8 && format != CELL_GCM_TEXTURE_X16 && format != CELL_GCM_TEXTURE_X32_FLOAT)
{
u8 remap_a = tex.remap() & 0x3;
u8 remap_r = (tex.remap() >> 2) & 0x3;
u8 remap_g = (tex.remap() >> 4) & 0x3;
u8 remap_b = (tex.remap() >> 6) & 0x3;
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]);
}
else
{
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
}
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_S, gl_wrap(tex.wrap_s()));
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t()));
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_R, gl_wrap(tex.wrap_r()));
*/
__glcheck glTexParameterf(m_target, GL_TEXTURE_LOD_BIAS, tex.bias());
__glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8));
__glcheck glTexParameteri(m_target, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8));
int min_filter = gl_tex_min_filter(tex.min_filter());
if (min_filter != GL_LINEAR && min_filter != GL_NEAREST)
{
if (tex.get_exact_mipmap_count() <= 1 || m_target == GL_TEXTURE_RECTANGLE)
{
LOG_WARNING(RSX, "Texture %d, target 0x%X, requesting mipmap filtering without any mipmaps set!", m_id, m_target);
min_filter = GL_LINEAR;
}
}
__glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, min_filter);
__glcheck glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, gl_tex_mag_filter(tex.mag_filter()));
__glcheck glTexParameterf(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso()));
}
void texture::bind() void texture::bind()
{ {
glBindTexture(m_target, m_id); glBindTexture(m_target, m_id);

View File

@ -3,6 +3,7 @@
namespace rsx namespace rsx
{ {
class vertex_texture;
class texture; class texture;
namespace gl namespace gl
@ -38,6 +39,7 @@ namespace rsx
} }
void init(int index, rsx::texture& tex); void init(int index, rsx::texture& tex);
void init(int index, rsx::vertex_texture& tex);
/** /**
* If a format is marked as mandating expansion, any request to have the data uploaded to the GPU shall require that the pixel data * If a format is marked as mandating expansion, any request to have the data uploaded to the GPU shall require that the pixel data

View File

@ -299,9 +299,21 @@ namespace rsx
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 3) & 0x1); return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 3) & 0x1);
} }
u8 vertex_texture::dimension() const rsx::texture_dimension vertex_texture::dimension() const
{ {
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 4) & 0xf); return rsx::to_texture_dimension((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 4) & 0xf);
}
rsx::texture_dimension_extended vertex_texture::get_extended_texture_dimension() const
{
switch (dimension())
{
case rsx::texture_dimension::dimension1d: return rsx::texture_dimension_extended::texture_dimension_1d;
case rsx::texture_dimension::dimension3d: return rsx::texture_dimension_extended::texture_dimension_2d;
case rsx::texture_dimension::dimension2d: return cubemap() ? rsx::texture_dimension_extended::texture_dimension_cubemap : rsx::texture_dimension_extended::texture_dimension_2d;
default: ASSUME(0);
}
} }
u8 vertex_texture::format() const u8 vertex_texture::format() const
@ -314,6 +326,12 @@ namespace rsx
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 16) & 0xffff); return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 16) & 0xffff);
} }
u16 vertex_texture::get_exact_mipmap_count() const
{
u16 max_mipmap_count = static_cast<u16>(floor(log2(std::max(width(), height()))) + 1);
return std::min(mipmap(), max_mipmap_count);
}
u8 vertex_texture::unsigned_remap() const u8 vertex_texture::unsigned_remap() const
{ {
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 12) & 0xf); return ((method_registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 12) & 0xf);
@ -341,7 +359,7 @@ namespace rsx
bool vertex_texture::enabled() const bool vertex_texture::enabled() const
{ {
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1); return location() <= 1 && ((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1);
} }
u16 vertex_texture::min_lod() const u16 vertex_texture::min_lod() const
@ -354,9 +372,9 @@ namespace rsx
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff); return ((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff);
} }
u8 vertex_texture::max_aniso() const rsx::texture_max_anisotropy vertex_texture::max_aniso() const
{ {
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 4) & 0x7); return rsx::to_texture_max_anisotropy((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 4) & 0x7);
} }
bool vertex_texture::alpha_kill_enabled() const bool vertex_texture::alpha_kill_enabled() const
@ -369,14 +387,14 @@ namespace rsx
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff); return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff);
} }
u8 vertex_texture::min_filter() const rsx::texture_minify_filter vertex_texture::min_filter() const
{ {
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 16) & 0x7); return rsx::to_texture_minify_filter((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 16) & 0x7);
} }
u8 vertex_texture::mag_filter() const rsx::texture_magnify_filter vertex_texture::mag_filter() const
{ {
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 24) & 0x7); return rsx::to_texture_magnify_filter((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 24) & 0x7);
} }
u8 vertex_texture::convolution_filter() const u8 vertex_texture::convolution_filter() const

View File

@ -84,9 +84,6 @@ namespace rsx
u32 border_color() const; u32 border_color() const;
u16 depth() const; u16 depth() const;
u32 pitch() const; u32 pitch() const;
//custom info
u8 index() const;
}; };
class vertex_texture class vertex_texture
@ -102,12 +99,12 @@ namespace rsx
u32 offset() const; u32 offset() const;
// Format // Format
u8 location() const; u8 location() const;
bool cubemap() const; bool cubemap() const;
u8 border_type() const; u8 border_type() const;
u8 dimension() const; rsx::texture_dimension dimension() const;
u8 format() const; u8 format() const;
u16 mipmap() const; u16 mipmap() const;
// Address // Address
u8 unsigned_remap() const; u8 unsigned_remap() const;
@ -118,16 +115,16 @@ namespace rsx
// Control0 // Control0
bool enabled() const; bool enabled() const;
u16 min_lod() const; u16 min_lod() const;
u16 max_lod() const; u16 max_lod() const;
u8 max_aniso() const; rsx::texture_max_anisotropy max_aniso() const;
bool alpha_kill_enabled() const; bool alpha_kill_enabled() const;
// Filter // Filter
u16 bias() const; u16 bias() const;
u8 min_filter() const; rsx::texture_minify_filter min_filter() const;
u8 mag_filter() const; rsx::texture_magnify_filter mag_filter() const;
u8 convolution_filter() const; u8 convolution_filter() const;
bool a_signed() const; bool a_signed() const;
bool r_signed() const; bool r_signed() const;
bool g_signed() const; bool g_signed() const;
@ -142,7 +139,7 @@ namespace rsx
u16 depth() const; u16 depth() const;
u32 pitch() const; u32 pitch() const;
//custom info rsx::texture_dimension_extended get_extended_texture_dimension() const;
u8 index() const; u16 get_exact_mipmap_count() const;
}; };
} }

View File

@ -351,14 +351,14 @@ namespace rsx
void thread::end() void thread::end()
{ {
transform_constants.clear();
for (u8 index = 0; index < rsx::limits::vertex_count; ++index) for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{ {
register_vertex_info[index].size = 0; register_vertex_info[index].size = 0;
register_vertex_data[index].clear(); register_vertex_data[index].clear();
} }
transform_constants.clear();
if (capture_current_frame) if (capture_current_frame)
{ {
for (const auto &first_count : first_count_commands) for (const auto &first_count : first_count_commands)
@ -468,14 +468,19 @@ namespace rsx
u32 reg = cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT ? first_cmd : first_cmd + i; u32 reg = cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT ? first_cmd : first_cmd + i;
u32 value = args[i]; u32 value = args[i];
LOG_TRACE(RSX, "%s(0x%x) = 0x%x", get_method_name(reg).c_str(), reg, value); //LOG_NOTICE(RSX, "%s(0x%x) = 0x%x", get_method_name(reg).c_str(), reg, value);
method_registers[reg] = value; method_registers[reg] = value;
if (capture_current_frame) if (capture_current_frame)
{
frame_debug.command_queue.push_back(std::make_pair(reg, value)); frame_debug.command_queue.push_back(std::make_pair(reg, value));
}
if (auto method = methods[reg]) if (auto method = methods[reg])
{
method(this, value); method(this, value);
}
} }
ctrl->get = get + (count + 1) * 4; ctrl->get = get + (count + 1) * 4;
@ -822,6 +827,27 @@ namespace rsx
} }
} }
for (u8 index = 0; index < rsx::limits::vertex_textures_count; ++index)
{
if (!textures[index].enabled())
{
result.state.vertex_textures[index] = rsx::texture_target::none;
continue;
}
switch (textures[index].get_extended_texture_dimension())
{
case rsx::texture_dimension_extended::texture_dimension_1d: result.state.vertex_textures[index] = rsx::texture_target::_1; break;
case rsx::texture_dimension_extended::texture_dimension_2d: result.state.vertex_textures[index] = rsx::texture_target::_2; break;
case rsx::texture_dimension_extended::texture_dimension_3d: result.state.vertex_textures[index] = rsx::texture_target::_3; break;
case rsx::texture_dimension_extended::texture_dimension_cubemap: result.state.vertex_textures[index] = rsx::texture_target::cube; break;
default:
result.state.vertex_textures[index] = rsx::texture_target::none;
break;
}
}
result.vertex_shader.ucode_ptr = transform_program; result.vertex_shader.ucode_ptr = transform_program;
result.vertex_shader.offset = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START]; result.vertex_shader.offset = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];

View File

@ -268,7 +268,7 @@ namespace rsx
u32 tiles_addr; u32 tiles_addr;
u32 zculls_addr; u32 zculls_addr;
vm::ps3::ptr<CellGcmDisplayInfo> gcm_buffers; vm::ps3::ptr<CellGcmDisplayInfo> gcm_buffers = vm::null;
u32 gcm_buffers_count; u32 gcm_buffers_count;
u32 gcm_current_buffer; u32 gcm_current_buffer;
u32 ctxt_addr; u32 ctxt_addr;

View File

@ -4,6 +4,11 @@
namespace rsx namespace rsx
{ {
void shaders_cache::path(const std::string &path_)
{
m_path = path_;
}
shader_info shaders_cache::get(const program_cache_context &ctxt, raw_shader &raw_shader, const program_state& state) shader_info shaders_cache::get(const program_cache_context &ctxt, raw_shader &raw_shader, const program_state& state)
{ {
auto found_entry = m_entries.find(raw_shader); auto found_entry = m_entries.find(raw_shader);
@ -11,8 +16,6 @@ namespace rsx
shader_info info; shader_info info;
entry_t *entry; entry_t *entry;
static const std::string &path = fs::get_executable_dir() + "data/cache/";
if (found_entry != m_entries.end()) if (found_entry != m_entries.end())
{ {
entry = &found_entry->second; entry = &found_entry->second;
@ -21,11 +24,19 @@ namespace rsx
{ {
//analyze_raw_shader(raw_shader); //analyze_raw_shader(raw_shader);
fs::file{ path + fmt::format("%016llx.", raw_shader.hash()) + (raw_shader.type == rsx::program_type::fragment ? "fp" : "vp") + ".ucode", fs::rewrite } std::string shader_name_base =
.write(raw_shader.ucode.data(), raw_shader.ucode.size()); fmt::format("%lld.%016llx", ++m_index, raw_shader.hash()) +
(raw_shader.type == rsx::program_type::fragment ? ".fp" : ".vp");
fs::file{ m_path + shader_name_base + ".ucode", fs::rewrite }
.write(raw_shader.ucode.data(), raw_shader.ucode.size());
rsx::decompiled_shader decompiled_shader = decompile(raw_shader, ctxt.lang); rsx::decompiled_shader decompiled_shader = decompile(raw_shader, ctxt.lang);
auto inserted = m_entries.insert({ raw_shader, entry_t{ decompiled_shader } }).first;
fs::file{ m_path + shader_name_base + (ctxt.lang == rsx::decompile_language::glsl ? ".glsl" : ".hlsl"), fs::rewrite }
.write(decompiled_shader.code);
auto inserted = m_entries.insert({ raw_shader, entry_t{ m_index, decompiled_shader } }).first;
inserted->second.decompiled.raw = &inserted->first; inserted->second.decompiled.raw = &inserted->first;
entry = &inserted->second; entry = &inserted->second;
} }
@ -45,7 +56,15 @@ namespace rsx
info.complete = &entry->complete.insert({ state, complete_shader }).first->second; info.complete = &entry->complete.insert({ state, complete_shader }).first->second;
info.complete->user_data = nullptr; info.complete->user_data = nullptr;
fs::file{ path + fmt::format("%016llx.", raw_shader.hash()) + (raw_shader.type == rsx::program_type::fragment ? "fp" : "vp") + "." + (ctxt.lang == rsx::decompile_language::glsl ? "glsl" : "hlsl"), fs::rewrite }.write(info.complete->code); const std::string hash_combination = fmt::format("%lld.%016llx.%016llx", entry->index, raw_shader.hash(), state.hash());
std::string shader_name =
hash_combination +
(raw_shader.type == rsx::program_type::fragment ? ".fp" : ".vp") +
(ctxt.lang == rsx::decompile_language::glsl ? ".glsl" : ".hlsl");
fs::file{ m_path + shader_name, fs::rewrite }.write(info.complete->code);
fs::file{ m_path + hash_combination + ".state", fs::rewrite }.write(state);
} }
if (info.complete->user_data == nullptr) if (info.complete->user_data == nullptr)
@ -69,6 +88,27 @@ namespace rsx
m_entries.clear(); m_entries.clear();
} }
programs_cache::programs_cache()
{
std::string path{ fs::get_executable_dir() + "data/cache/" };
std::string title = Emu.GetTitleID();
if (title.empty())
{
path += "temporary/";
fs::remove_all(path, false);
}
else
{
path += title + "/";
}
fs::create_path(path);
m_vertex_shaders_cache.path(path);
m_fragment_shader_cache.path(path);
}
programs_cache::~programs_cache() programs_cache::~programs_cache()
{ {
clear(); clear();

View File

@ -28,17 +28,22 @@ namespace rsx
void(*remove_shader)(void *ptr); void(*remove_shader)(void *ptr);
}; };
struct shaders_cache class shaders_cache
{ {
struct entry_t struct entry_t
{ {
std::int64_t index;
decompiled_shader decompiled; decompiled_shader decompiled;
std::unordered_map<program_state, complete_shader, hasher> complete; std::unordered_map<program_state, complete_shader, hasher> complete;
}; };
std::unordered_map<raw_shader, entry_t, hasher> m_entries; std::unordered_map<raw_shader, entry_t, hasher> m_entries;
std::string m_path;
std::int64_t m_index = -1;
public: public:
void path(const std::string &path_);
shader_info get(const program_cache_context &ctxt, raw_shader &raw_shader, const program_state& state); shader_info get(const program_cache_context &ctxt, raw_shader &raw_shader, const program_state& state);
void clear(const program_cache_context& context); void clear(const program_cache_context& context);
}; };
@ -53,6 +58,7 @@ namespace rsx
public: public:
program_cache_context context; program_cache_context context;
programs_cache();
~programs_cache(); ~programs_cache();
program_info get(raw_program raw_program_, decompile_language lang); program_info get(raw_program raw_program_, decompile_language lang);

View File

@ -433,6 +433,37 @@ namespace rsx
return; return;
} }
if (dst_dma == CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER)
{
//HACK: it's extension of the flip-hack. remove this when textures cache would be properly implemented
for (int i = 0; i < rsx::limits::color_buffers_count; ++i)
{
u32 begin = rsx->gcm_buffers[i].offset;
if (dst_offset < begin || !begin)
{
continue;
}
if (rsx->gcm_buffers[i].width < 720 || rsx->gcm_buffers[i].height < 480)
{
continue;
}
if (begin == dst_offset)
{
return;
}
u32 end = begin + rsx->gcm_buffers[i].height * rsx->gcm_buffers[i].pitch;
if (dst_offset < end)
{
return;
}
}
}
u32 in_bpp = src_color_format == CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 ? 2 : 4; // bytes per pixel u32 in_bpp = src_color_format == CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 ? 2 : 4; // bytes per pixel
u32 out_bpp = dst_color_format == CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5 ? 2 : 4; u32 out_bpp = dst_color_format == CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5 ? 2 : 4;
@ -645,31 +676,51 @@ 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;
}
u32 src_offset = method_registers[NV0039_OFFSET_IN];
u32 src_dma = method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_IN];
u32 dst_offset = method_registers[NV0039_OFFSET_OUT];
u32 dst_dma = method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_OUT];
u8 *dst = (u8*)vm::base(get_address(dst_offset, dst_dma));
const u8 *src = (u8*)vm::base(get_address(src_offset, src_dma));
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;
}
} }
} }
} }

@ -1 +1 @@
Subproject commit aa6bcbc58961356733ae1fc0742a37a0a6190f31 Subproject commit 05d1fc438948aaaf260d2244be9d75427ea9d3e9