From 989f95443225c1866d6a6342c0d1687338f51bdb Mon Sep 17 00:00:00 2001 From: DH Date: Tue, 28 Jun 2016 12:58:44 +0300 Subject: [PATCH] Added WIP vertex textures support --- rpcs3/Emu/RSX/Common/TextureUtils.cpp | 72 +++++++++++++----- rpcs3/Emu/RSX/Common/TextureUtils.h | 5 +- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 52 +++++++++---- rpcs3/Emu/RSX/GL/gl_texture_cache.h | 5 +- rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp | 78 ++++++++++--------- rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp | 105 ++++++++++++++++++++++++++ rpcs3/Emu/RSX/GL/rsx_gl_texture.h | 2 + rpcs3/Emu/RSX/RSXTexture.cpp | 36 ++++++--- rpcs3/Emu/RSX/RSXTexture.h | 29 ++++--- rpcs3/Emu/RSX/RSXThread.cpp | 32 +++++++- rpcs3/Emu/RSX/RSXThread.h | 2 +- rsx_program_decompiler | 2 +- 12 files changed, 321 insertions(+), 99 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index 960512b5af..15769117be 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -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. * Use 1 value instead to be more general. */ -std::tuple get_height_depth_layer(const rsx::texture &tex) +template +std::tuple get_height_depth_layer(const RsxTextureType &tex) { switch (tex.get_extended_texture_dimension()) { @@ -133,7 +134,8 @@ std::tuple get_height_depth_layer(const rsx::texture &tex) } } -std::vector get_subresources_layout(const rsx::texture &texture) +template +std::vector get_subresources_layout_impl(const RsxTextureType &texture) { u16 w = texture.width(); u16 h; @@ -184,6 +186,16 @@ std::vector get_subresources_layout(const rsx::texture & throw EXCEPTION("Wrong format 0x%x", format); } +std::vector get_subresources_layout(const rsx::texture &texture) +{ + return get_subresources_layout_impl(texture); +} + +std::vector get_subresources_layout(const rsx::vertex_texture &texture) +{ + return get_subresources_layout_impl(texture); +} + void upload_texture_subresource(gsl::span 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; @@ -339,36 +351,48 @@ u8 get_format_block_size_in_texel(int format) } } - -size_t get_placed_texture_storage_size(const rsx::texture &texture, size_t rowPitchAlignement, size_t mipmapAlignment) +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 w = texture.width(), h = texture.height(), d = std::max(texture.depth(), 1); + size_t w = width; + size_t h = std::max(height, 1); + size_t d = std::max(depth, 1); - int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); - size_t blockEdge = get_format_block_size_in_texel(format); - size_t blockSizeInByte = get_format_block_size_in_bytes(format); + format &= ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); + size_t block_edge = get_format_block_size_in_texel(format); + size_t block_size_in_byte = get_format_block_size_in_bytes(format); - size_t heightInBlocks = (h + blockEdge - 1) / blockEdge; - size_t widthInBlocks = (w + blockEdge - 1) / blockEdge; + size_t height_in_blocks = (h + block_edge - 1) / block_edge; + size_t width_in_blocks = (w + block_edge - 1) / block_edge; 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); - result += align(rowPitch * heightInBlocks * d, mipmapAlignment); - heightInBlocks = std::max(heightInBlocks / 2, 1); - widthInBlocks = std::max(widthInBlocks / 2, 1); + size_t rowPitch = align(block_size_in_byte * width_in_blocks, row_pitch_alignement); + result += align(rowPitch * height_in_blocks * d, mipmap_alignment); + height_in_blocks = std::max(height_in_blocks / 2, 1); + width_in_blocks = std::max(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 switch (format) { @@ -434,3 +458,13 @@ size_t get_texture_size(const rsx::texture &texture) 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()); +} diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index c88a6a558a..c45c453841 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -18,13 +18,15 @@ struct rsx_subresource_layout * Get size to store texture in a linear fashion. * 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. * The subresources are ordered per layer then per mipmap level (as in rsx memory). */ std::vector get_subresources_layout(const rsx::texture &texture); +std::vector get_subresources_layout(const rsx::vertex_texture &texture); void upload_texture_subresource(gsl::span 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 */ size_t get_texture_size(const rsx::texture &texture); +size_t get_texture_size(const rsx::vertex_texture &texture); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 56c4b4d9eb..aeacddc532 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -235,6 +235,18 @@ namespace } 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() @@ -295,7 +307,6 @@ void GLGSRender::end() //setup textures { - //int texture_index = 0; for (int i = 0; i < rsx::limits::textures_count; ++i) { int location; @@ -311,12 +322,9 @@ void GLGSRender::end() } 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 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)) { @@ -331,21 +339,39 @@ void GLGSRender::end() } } } - /* + 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 (m_program->uniforms.has_location("vtexture" + std::to_string(i), &location)) + if (!textures[i].enabled()) { - glProgramUniform1i(m_program->id(), location, texture_index); - m_gl_vertex_textures[i].init(texture_index, vertex_textures[i]); - texture_index++; + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, 0); + 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(textures[i].width(), 1); + u32 height = std::max(textures[i].height(), 1); + u32 depth = std::max(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(); diff --git a/rpcs3/Emu/RSX/GL/gl_texture_cache.h b/rpcs3/Emu/RSX/GL/gl_texture_cache.h index ceedf7f19b..9a0fb0f44d 100644 --- a/rpcs3/Emu/RSX/GL/gl_texture_cache.h +++ b/rpcs3/Emu/RSX/GL/gl_texture_cache.h @@ -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 + 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 range = (u32)get_texture_size(tex); @@ -458,7 +459,7 @@ namespace gl if (texptr = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr)) { - texptr->bind(); + texptr->bind(); return; } diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp b/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp index bced7df7fc..2b237d7188 100644 --- a/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp +++ b/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp @@ -127,7 +127,6 @@ static void insert_texture_lod_fetch_function(std::string &dst, const rsx::decom dst += "}\n"; } - static void insert_texture_proj_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state) { if (shader.textures.empty()) @@ -237,26 +236,6 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, 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 finalize; int location = 1; @@ -264,6 +243,24 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, switch (shader.raw->type) { 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_bias_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; 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"; - - // TODO - if (0) - { - finalize += "\tgl_Position = o0;\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"; - } + + 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; diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp b/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp index ad2814693e..969717b0dd 100644 --- a/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp +++ b/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp @@ -536,6 +536,111 @@ namespace rsx __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 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& 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() { glBindTexture(m_target, m_id); diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_texture.h b/rpcs3/Emu/RSX/GL/rsx_gl_texture.h index 8198e583ba..dbdd21cdcc 100644 --- a/rpcs3/Emu/RSX/GL/rsx_gl_texture.h +++ b/rpcs3/Emu/RSX/GL/rsx_gl_texture.h @@ -3,6 +3,7 @@ namespace rsx { + class vertex_texture; class texture; namespace gl @@ -38,6 +39,7 @@ namespace rsx } 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 diff --git a/rpcs3/Emu/RSX/RSXTexture.cpp b/rpcs3/Emu/RSX/RSXTexture.cpp index 1cfc84acd1..2517ebd75d 100644 --- a/rpcs3/Emu/RSX/RSXTexture.cpp +++ b/rpcs3/Emu/RSX/RSXTexture.cpp @@ -299,9 +299,21 @@ namespace rsx 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 @@ -314,6 +326,12 @@ namespace rsx 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(floor(log2(std::max(width(), height()))) + 1); + return std::min(mipmap(), max_mipmap_count); + } + u8 vertex_texture::unsigned_remap() const { return ((method_registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 12) & 0xf); @@ -341,7 +359,7 @@ namespace rsx 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 @@ -354,9 +372,9 @@ namespace rsx 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 @@ -369,14 +387,14 @@ namespace rsx 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 diff --git a/rpcs3/Emu/RSX/RSXTexture.h b/rpcs3/Emu/RSX/RSXTexture.h index e776267b3d..9c258b75c9 100644 --- a/rpcs3/Emu/RSX/RSXTexture.h +++ b/rpcs3/Emu/RSX/RSXTexture.h @@ -84,9 +84,6 @@ namespace rsx u32 border_color() const; u16 depth() const; u32 pitch() const; - - //custom info - u8 index() const; }; class vertex_texture @@ -102,12 +99,12 @@ namespace rsx u32 offset() const; // Format - u8 location() const; + u8 location() const; bool cubemap() const; - u8 border_type() const; - u8 dimension() const; - u8 format() const; - u16 mipmap() const; + u8 border_type() const; + rsx::texture_dimension dimension() const; + u8 format() const; + u16 mipmap() const; // Address u8 unsigned_remap() const; @@ -118,16 +115,16 @@ namespace rsx // Control0 bool enabled() const; - u16 min_lod() const; - u16 max_lod() const; - u8 max_aniso() const; + u16 min_lod() const; + u16 max_lod() const; + rsx::texture_max_anisotropy max_aniso() const; bool alpha_kill_enabled() const; // Filter u16 bias() const; - u8 min_filter() const; - u8 mag_filter() const; - u8 convolution_filter() const; + rsx::texture_minify_filter min_filter() const; + rsx::texture_magnify_filter mag_filter() const; + u8 convolution_filter() const; bool a_signed() const; bool r_signed() const; bool g_signed() const; @@ -142,7 +139,7 @@ namespace rsx u16 depth() const; u32 pitch() const; - //custom info - u8 index() const; + rsx::texture_dimension_extended get_extended_texture_dimension() const; + u16 get_exact_mipmap_count() const; }; } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index bb080f3818..6393cea19d 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -351,14 +351,14 @@ namespace rsx void thread::end() { + transform_constants.clear(); + for (u8 index = 0; index < rsx::limits::vertex_count; ++index) { register_vertex_info[index].size = 0; register_vertex_data[index].clear(); } - transform_constants.clear(); - if (capture_current_frame) { 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 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; + if (capture_current_frame) + { frame_debug.command_queue.push_back(std::make_pair(reg, value)); + } if (auto method = methods[reg]) + { method(this, value); + } } 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.offset = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START]; diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index e25a8942f2..10488e37c8 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -268,7 +268,7 @@ namespace rsx u32 tiles_addr; u32 zculls_addr; - vm::ps3::ptr gcm_buffers; + vm::ps3::ptr gcm_buffers = vm::null; u32 gcm_buffers_count; u32 gcm_current_buffer; u32 ctxt_addr; diff --git a/rsx_program_decompiler b/rsx_program_decompiler index aa6bcbc589..3b1e7b0e50 160000 --- a/rsx_program_decompiler +++ b/rsx_program_decompiler @@ -1 +1 @@ -Subproject commit aa6bcbc58961356733ae1fc0742a37a0a6190f31 +Subproject commit 3b1e7b0e5080ec9cb43616422b0e286c61b88c87