diff --git a/rpcs3/Emu/Cell/Modules/cellGame.cpp b/rpcs3/Emu/Cell/Modules/cellGame.cpp index 0d0c7977bc..7fd439d1ad 100644 --- a/rpcs3/Emu/Cell/Modules/cellGame.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGame.cpp @@ -684,27 +684,32 @@ s32 cellGameThemeInstallFromBuffer() s32 cellDiscGameGetBootDiscInfo() { - throw EXCEPTION(""); + UNIMPLEMENTED_FUNC(cellGame); + return CELL_OK; } s32 cellDiscGameRegisterDiscChangeCallback() { - throw EXCEPTION(""); + UNIMPLEMENTED_FUNC(cellGame); + return CELL_OK; } s32 cellDiscGameUnregisterDiscChangeCallback() { - throw EXCEPTION(""); + UNIMPLEMENTED_FUNC(cellGame); + return CELL_OK; } s32 cellGameRegisterDiscChangeCallback() { - throw EXCEPTION(""); + UNIMPLEMENTED_FUNC(cellGame); + return CELL_OK; } s32 cellGameUnregisterDiscChangeCallback() { - throw EXCEPTION(""); + UNIMPLEMENTED_FUNC(cellGame); + return CELL_OK; } diff --git a/rpcs3/Emu/Memory/vm_var.h b/rpcs3/Emu/Memory/vm_var.h index 9b49aaa87e..24fa149396 100644 --- a/rpcs3/Emu/Memory/vm_var.h +++ b/rpcs3/Emu/Memory/vm_var.h @@ -78,6 +78,7 @@ namespace vm _var_base(_var_base&& right) : pointer(right) + , m_size(right.m_size) { reinterpret_cast(static_cast(right)) = 0; } diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index f42f07fa04..82c583c876 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -515,28 +515,51 @@ enum CELL_GCM_SCULL_SFUNC_GEQUAL = 6, CELL_GCM_SCULL_SFUNC_ALWAYS = 7, - CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE = 1 << 0, - CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR = 1 << 1, - CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE = 1 << 2, - CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR = 1 << 3, - CELL_GCM_ATTRIB_OUTPUT_MASK_FOG = 1 << 4, - CELL_GCM_ATTRIB_OUTPUT_MASK_POINTSIZE = 1 << 5, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 = 1 << 6, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 = 1 << 7, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 = 1 << 8, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 = 1 << 9, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 = 1 << 10, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 = 1 << 11, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX8 = 1 << 12, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX9 = 1 << 13, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX0 = 1 << 14, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX1 = 1 << 15, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX2 = 1 << 16, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX3 = 1 << 17, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX4 = 1 << 18, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX5 = 1 << 19, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX6 = 1 << 20, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX7 = 1 << 21, + CELL_GCM_ATTRIB_OUTPUT_FRONTDIFFUSE = 0, + CELL_GCM_ATTRIB_OUTPUT_FRONTSPECULAR = 1, + CELL_GCM_ATTRIB_OUTPUT_BACKDIFFUSE = 2, + CELL_GCM_ATTRIB_OUTPUT_BACKSPECULAR = 3, + CELL_GCM_ATTRIB_OUTPUT_FOG = 4, + CELL_GCM_ATTRIB_OUTPUT_POINTSIZE = 5, + CELL_GCM_ATTRIB_OUTPUT_UC0 = 6, + CELL_GCM_ATTRIB_OUTPUT_UC1 = 7, + CELL_GCM_ATTRIB_OUTPUT_UC2 = 8, + CELL_GCM_ATTRIB_OUTPUT_UC3 = 9, + CELL_GCM_ATTRIB_OUTPUT_UC4 = 10, + CELL_GCM_ATTRIB_OUTPUT_UC5 = 11, + CELL_GCM_ATTRIB_OUTPUT_TEX8 = 12, + CELL_GCM_ATTRIB_OUTPUT_TEX9 = 13, + CELL_GCM_ATTRIB_OUTPUT_TEX0 = 14, + CELL_GCM_ATTRIB_OUTPUT_TEX1 = 15, + CELL_GCM_ATTRIB_OUTPUT_TEX2 = 16, + CELL_GCM_ATTRIB_OUTPUT_TEX3 = 17, + CELL_GCM_ATTRIB_OUTPUT_TEX4 = 18, + CELL_GCM_ATTRIB_OUTPUT_TEX5 = 19, + CELL_GCM_ATTRIB_OUTPUT_TEX6 = 20, + CELL_GCM_ATTRIB_OUTPUT_TEX7 = 21, + + CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE = 1 << CELL_GCM_ATTRIB_OUTPUT_FRONTDIFFUSE, + CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR = 1 << CELL_GCM_ATTRIB_OUTPUT_FRONTSPECULAR, + CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE = 1 << CELL_GCM_ATTRIB_OUTPUT_BACKDIFFUSE, + CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR = 1 << CELL_GCM_ATTRIB_OUTPUT_BACKSPECULAR, + CELL_GCM_ATTRIB_OUTPUT_MASK_FOG = 1 << CELL_GCM_ATTRIB_OUTPUT_FOG, + CELL_GCM_ATTRIB_OUTPUT_MASK_POINTSIZE = 1 << CELL_GCM_ATTRIB_OUTPUT_POINTSIZE, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC0, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC1, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC2, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC3, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC4, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC5, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX8 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX8, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX9 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX9, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX0 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX0, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX1 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX1, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX2 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX2, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX3 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX3, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX4 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX4, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX5 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX5, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX6 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX6, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX7 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX7, CELL_GCM_POLYGON_MODE_POINT = 0x1B00, CELL_GCM_POLYGON_MODE_LINE = 0x1B01, diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index d790e76a5f..56c4b4d9eb 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -64,12 +64,6 @@ void GLGSRender::begin() { rsx::thread::begin(); - if (!load_program()) - { - //no program - no drawing - return; - } - init_buffers(); std::chrono::time_point then = std::chrono::system_clock::now(); @@ -98,12 +92,6 @@ void GLGSRender::begin() __glcheck glDepthRange((f32&)rsx::method_registers[NV4097_SET_CLIP_MIN], (f32&)rsx::method_registers[NV4097_SET_CLIP_MAX]); __glcheck enable(rsx::method_registers[NV4097_SET_DITHER_ENABLE], GL_DITHER); - if (!!rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]) - { - //TODO: NV4097_SET_ALPHA_REF must be converted to f32 - //glcheck(glAlphaFunc(rsx::method_registers[NV4097_SET_ALPHA_FUNC], rsx::method_registers[NV4097_SET_ALPHA_REF])); - } - if (__glcheck enable(rsx::method_registers[NV4097_SET_BLEND_ENABLE], GL_BLEND)) { u32 sfactor = rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR]; @@ -207,6 +195,56 @@ void GLGSRender::begin() //NV4097_SET_FLAT_SHADE_OP //NV4097_SET_EDGE_FLAG + __glcheck enable(rsx::method_registers[NV4097_SET_POLY_OFFSET_FILL_ENABLE], GL_POLYGON_OFFSET_FILL); + + if (__glcheck enable(rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE], GL_CULL_FACE)) + { + __glcheck glCullFace(rsx::method_registers[NV4097_SET_CULL_FACE]); + } + + __glcheck glFrontFace(rsx::method_registers[NV4097_SET_FRONT_FACE] ^ 1); + + __glcheck enable(rsx::method_registers[NV4097_SET_POLY_SMOOTH_ENABLE], GL_POLYGON_SMOOTH); + + //NV4097_SET_COLOR_KEY_COLOR + //NV4097_SET_SHADER_CONTROL + //NV4097_SET_ZMIN_MAX_CONTROL + //NV4097_SET_ANTI_ALIASING_CONTROL + //NV4097_SET_CLIP_ID_TEST_ENABLE + + if (__glcheck enable(rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE], GL_PRIMITIVE_RESTART)) + { + __glcheck glPrimitiveRestartIndex(rsx::method_registers[NV4097_SET_RESTART_INDEX]); + } + + std::chrono::time_point now = std::chrono::system_clock::now(); + m_begin_time += (u32)std::chrono::duration_cast(now - then).count(); + m_draw_calls++; +} + +namespace +{ + GLenum get_gl_target_for_texture(const rsx::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() +{ + if (!draw_fbo || !load_program()) + { + rsx::thread::end(); + return; + } + u32 clip_plane_control = rsx::method_registers[NV4097_SET_USER_CLIP_PLANE_CONTROL]; u8 clip_plane_0 = clip_plane_control & 0xf; u8 clip_plane_1 = (clip_plane_control >> 4) & 0xf; @@ -252,56 +290,6 @@ void GLGSRender::begin() set_clip_plane_control(4, clip_plane_4); set_clip_plane_control(5, clip_plane_5); - __glcheck enable(rsx::method_registers[NV4097_SET_POLY_OFFSET_FILL_ENABLE], GL_POLYGON_OFFSET_FILL); - - if (__glcheck enable(rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE], GL_CULL_FACE)) - { - __glcheck glCullFace(rsx::method_registers[NV4097_SET_CULL_FACE]); - } - - __glcheck glFrontFace(rsx::method_registers[NV4097_SET_FRONT_FACE] ^ 1); - - __glcheck enable(rsx::method_registers[NV4097_SET_POLY_SMOOTH_ENABLE], GL_POLYGON_SMOOTH); - - //NV4097_SET_COLOR_KEY_COLOR - //NV4097_SET_SHADER_CONTROL - //NV4097_SET_ZMIN_MAX_CONTROL - //NV4097_SET_ANTI_ALIASING_CONTROL - //NV4097_SET_CLIP_ID_TEST_ENABLE - - if (__glcheck enable(rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE], GL_PRIMITIVE_RESTART)) - { - __glcheck glPrimitiveRestartIndex(rsx::method_registers[NV4097_SET_RESTART_INDEX]); - } - - std::chrono::time_point now = std::chrono::system_clock::now(); - m_begin_time += (u32)std::chrono::duration_cast(now - then).count(); - m_draw_calls++; -} - -namespace -{ - GLenum get_gl_target_for_texture(const rsx::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() -{ - if (!draw_fbo) - { - rsx::thread::end(); - return; - } - draw_fbo.bind(); m_program->use(); @@ -311,7 +299,7 @@ void GLGSRender::end() for (int i = 0; i < rsx::limits::textures_count; ++i) { int location; - if (m_program->uniforms.has_location("texture" + std::to_string(i), &location)) + if (m_program->uniforms.has_location("ftexture" + std::to_string(i), &location)) { if (!textures[i].enabled()) { @@ -330,7 +318,7 @@ void GLGSRender::end() //texture_index++; - if (m_program->uniforms.has_location("texture" + std::to_string(i) + "_cm", &location)) + if (m_program->uniforms.has_location("ftexture" + std::to_string(i) + "_cm", &location)) { if (textures[i].format() & CELL_GCM_TEXTURE_UN) { @@ -478,16 +466,24 @@ void GLGSRender::on_exit() programs_cache.clear(); if (draw_fbo) + { draw_fbo.remove(); + } if (m_flip_fbo) + { m_flip_fbo.remove(); + } if (m_flip_tex_color) + { m_flip_tex_color.remove(); + } if (m_vao) + { m_vao.remove(); + } for (gl::texture &tex : m_gl_attrib_buffers) { @@ -539,7 +535,7 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer) mask |= GLenum(gl::buffers::depth); } - if (surface_depth_format == rsx::surface_depth_format::z24s8 && arg & 0x2) + if (surface_depth_format == rsx::surface_depth_format::z24s8 && (arg & 0x2)) { u8 clear_stencil = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] & 0xff; @@ -607,6 +603,15 @@ struct alignas(4) glsl_fragment_constants_buffer float fc[2048][4]; }; +//binding 3 +struct alignas(4) glsl_fragment_state_buffer +{ + float fog_param0; + float fog_param1; + uint alpha_test; + float alpha_ref; +}; + static void fill_matrix_buffer(glsl_matrix_buffer *buffer) { rsx::fill_viewport_matrix(buffer->viewport_matrix, true); @@ -655,8 +660,25 @@ static void fill_matrix_buffer(glsl_matrix_buffer *buffer) rsx::fill_scale_offset_matrix(buffer->normalize_matrix, true, offset_x, offset_y, offset_z, scale_x, scale_y, scale_z); } +static void fill_fragment_state_buffer(glsl_fragment_state_buffer *buffer) +{ + std::memcpy(&buffer->fog_param0, rsx::method_registers + NV4097_SET_FOG_PARAMS, sizeof(float) * 2); + + buffer->alpha_test = rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]; + buffer->alpha_ref = rsx::method_registers[NV4097_SET_ALPHA_REF] / 255.f; +} + bool GLGSRender::load_program() { + if (0) + { + RSXVertexProgram vertex_program = get_current_vertex_program(); + RSXFragmentProgram fragment_program = get_current_fragment_program(); + + GLProgramBuffer prog_buffer; + __glcheck prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr); + } + rsx::program_info info = programs_cache.get(get_raw_program(), rsx::decompile_language::glsl); m_program = (gl::glsl::program*)info.program; m_program->use(); @@ -667,6 +689,7 @@ bool GLGSRender::load_program() u32 max_buffer_sz = align(sizeof(glsl_matrix_buffer), m_uniform_buffer_offset_align) + align(sizeof(glsl_vertex_constants_buffer), m_uniform_buffer_offset_align) + + align(sizeof(glsl_fragment_state_buffer), m_uniform_buffer_offset_align) + align(fragment_constants_size, m_uniform_buffer_offset_align); m_uniform_ring_buffer.reserve_and_map(max_buffer_sz); @@ -674,6 +697,7 @@ bool GLGSRender::load_program() u32 scale_offset_offset; u32 vertex_constants_offset; u32 fragment_constants_offset; + u32 fragment_state_offset; { auto mapping = m_uniform_ring_buffer.alloc_from_reserve(sizeof(glsl_matrix_buffer), m_uniform_buffer_offset_align); @@ -687,6 +711,12 @@ bool GLGSRender::load_program() vertex_constants_offset = mapping.second; } + { + auto mapping = m_uniform_ring_buffer.alloc_from_reserve(sizeof(glsl_fragment_state_buffer), m_uniform_buffer_offset_align); + fill_fragment_state_buffer((glsl_fragment_state_buffer *)mapping.first); + fragment_state_offset = mapping.second; + } + if (fragment_constants_size) { auto mapping = m_uniform_ring_buffer.alloc_from_reserve(fragment_constants_size, m_uniform_buffer_offset_align); @@ -710,12 +740,16 @@ bool GLGSRender::load_program() const __m128i &shuffled_vector = _mm_shuffle_epi8(vector, mask); _mm_stream_si128((__m128i*)dst, shuffled_vector); - float x = ((float*)dst)[0]; - float y = ((float*)dst)[1]; - float z = ((float*)dst)[2]; - float w = ((float*)dst)[3]; + if (0) + { + float x = ((float*)dst)[0]; + float y = ((float*)dst)[1]; + float z = ((float*)dst)[2]; + float w = ((float*)dst)[3]; + + LOG_WARNING(RSX, "fc%u = {%g, %g, %g, %g}", constant.id, x, y, z, w); + } - //LOG_WARNING(RSX, "fc%u = {%g, %g, %g, %g}", constant.id, x, y, z, w); ++dst; } } @@ -730,12 +764,13 @@ bool GLGSRender::load_program() m_uniform_ring_buffer.bind_range(2, fragment_constants_offset, fragment_constants_size); } + m_uniform_ring_buffer.bind_range(3, fragment_state_offset, sizeof(glsl_fragment_state_buffer)); + return true; } void GLGSRender::flip(int buffer) { - //LOG_NOTICE(Log::RSX, "flip(%d)", buffer); u32 buffer_width = gcm_buffers[buffer].width; u32 buffer_height = gcm_buffers[buffer].height; u32 buffer_pitch = gcm_buffers[buffer].pitch; @@ -744,33 +779,37 @@ void GLGSRender::flip(int buffer) glDisable(GL_SCISSOR_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); - - rsx::tiled_region buffer_region = get_tiled_address(gcm_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL); - bool skip_read = false; + rsx::tiled_region buffer_region = get_tiled_address(gcm_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL); + u32 absolute_address = buffer_region.address + buffer_region.base; + + if (0) + { + LOG_NOTICE(RSX, "flip(%d) -> 0x%x [0x%x]", buffer, absolute_address, rsx::get_address(gcm_buffers[1 - buffer].offset, CELL_GCM_LOCATION_LOCAL)); + } + + gl::texture *render_target_texture = m_rtts.get_texture_from_render_target_if_applicable(absolute_address); /** * Calling read_buffers will overwrite cached content */ - if (draw_fbo) + + __glcheck m_flip_fbo.recreate(); + m_flip_fbo.bind(); + + auto *flip_fbo = &m_flip_fbo; + + if (render_target_texture) { - skip_read = true; - /* - for (uint i = 0; i < rsx::limits::color_buffers_count; ++i) - { - u32 color_address = rsx::get_address(rsx::method_registers[mr_color_offset[i]], rsx::method_registers[mr_color_dma[i]]); - - if (color_address == buffer_address) - { - skip_read = true; - __glcheck draw_fbo.draw_buffer(draw_fbo.color[i]); - break; - } - } - */ + __glcheck m_flip_fbo.color = *render_target_texture; + __glcheck m_flip_fbo.read_buffer(m_flip_fbo.color); } - - if (!skip_read) + else if (draw_fbo) + { + //HACK! it's here, because textures cache isn't implemented correctly! + flip_fbo = &draw_fbo; + } + else { if (!m_flip_tex_color || m_flip_tex_color.size() != sizei{ (int)buffer_width, (int)buffer_height }) { @@ -782,15 +821,8 @@ void GLGSRender::flip(int buffer) .format(gl::texture::format::bgra); m_flip_tex_color.pixel_unpack_settings().aligment(1).row_length(buffer_pitch / 4); - - __glcheck m_flip_fbo.recreate(); - __glcheck m_flip_fbo.color = m_flip_tex_color; } - __glcheck m_flip_fbo.draw_buffer(m_flip_fbo.color); - - m_flip_fbo.bind(); - if (buffer_region.tile) { std::unique_ptr temp(new u8[buffer_height * buffer_pitch]); @@ -801,6 +833,9 @@ void GLGSRender::flip(int buffer) { __glcheck m_flip_tex_color.copy_from(buffer_region.ptr, gl::texture::format::bgra, gl::texture::type::uint_8_8_8_8); } + + m_flip_fbo.color = m_flip_tex_color; + __glcheck m_flip_fbo.read_buffer(m_flip_fbo.color); } areai screen_area = coordi({}, { (int)buffer_width, (int)buffer_height }); @@ -835,14 +870,7 @@ void GLGSRender::flip(int buffer) gl::screen.clear(gl::buffers::color_depth_stencil); - if (!skip_read) - { - __glcheck m_flip_fbo.blit(gl::screen, screen_area, areai(aspect_ratio).flipped_vertical()); - } - else - { - __glcheck draw_fbo.blit(gl::screen, screen_area, areai(aspect_ratio).flipped_vertical()); - } + __glcheck flip_fbo->blit(gl::screen, screen_area, areai(aspect_ratio).flipped_vertical()); m_frame->flip(m_context); diff --git a/rpcs3/Emu/RSX/GL/gl_render_targets.cpp b/rpcs3/Emu/RSX/GL/gl_render_targets.cpp index 346dd99038..8d568f0b17 100644 --- a/rpcs3/Emu/RSX/GL/gl_render_targets.cpp +++ b/rpcs3/Emu/RSX/GL/gl_render_targets.cpp @@ -83,57 +83,69 @@ void GLGSRender::init_buffers(bool skip_reading) u32 clip_horizontal = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL]; u32 clip_vertical = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL]; - set_viewport(); if (draw_fbo && !m_rtts_dirty) + { return; + } m_rtts_dirty = false; - m_rtts.prepare_render_target(nullptr, surface_format, clip_horizontal, clip_vertical, rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]), + if (0) + { + LOG_NOTICE(RSX, "render to -> 0x%x", get_color_surface_addresses()[0]); + } + + m_rtts.prepare_render_target(nullptr, surface_format, clip_horizontal, clip_vertical, + rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]), get_color_surface_addresses(), get_zeta_surface_address()); draw_fbo.recreate(); for (int i = 0; i < rsx::limits::color_buffers_count; ++i) { - if (std::get<0>(m_rtts.m_bound_render_targets[i]) != 0) + if (std::get<0>(m_rtts.m_bound_render_targets[i])) + { __glcheck draw_fbo.color[i] = *std::get<1>(m_rtts.m_bound_render_targets[i]); + } } - if (std::get<0>(m_rtts.m_bound_depth_stencil) != 0) + if (std::get<0>(m_rtts.m_bound_depth_stencil)) + { __glcheck draw_fbo.depth = *std::get<1>(m_rtts.m_bound_depth_stencil); + } __glcheck draw_fbo.check(); - __glcheck draw_fbo.read_buffer(draw_fbo.color[0]); - + //HACK: read_buffer shouldn't be there switch (rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) { case rsx::surface_target::none: break; case rsx::surface_target::surface_a: __glcheck draw_fbo.draw_buffer(draw_fbo.color[0]); + __glcheck draw_fbo.read_buffer(draw_fbo.color[0]); break; case rsx::surface_target::surface_b: - { __glcheck draw_fbo.draw_buffer(draw_fbo.color[1]); __glcheck draw_fbo.read_buffer(draw_fbo.color[1]); break; - } case rsx::surface_target::surfaces_a_b: __glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1] }); + __glcheck draw_fbo.read_buffer(draw_fbo.color[0]); break; case rsx::surface_target::surfaces_a_b_c: __glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1], draw_fbo.color[2] }); + __glcheck draw_fbo.read_buffer(draw_fbo.color[0]); break; case rsx::surface_target::surfaces_a_b_c_d: __glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1], draw_fbo.color[2], draw_fbo.color[3] }); + __glcheck draw_fbo.read_buffer(draw_fbo.color[0]); break; } } diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp b/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp index 8332195f6c..bced7df7fc 100644 --- a/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp +++ b/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp @@ -3,6 +3,162 @@ #include "gl_helpers.h" #include "../GCM.h" +static void insert_texture_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state) +{ + if (shader.textures.empty()) + { + return; + } + + dst += "vec4 texture_fetch(int index, vec4 coord)\n{\n"; + dst += "\tswitch (index)\n\t{\n"; + + for (auto &texture : shader.textures) + { + dst += "\tcase " + std::to_string(texture.id) + ": return "; + + switch (state.textures[texture.id]) + { + case rsx::texture_target::none: dst += "vec4(0.0)"; break; + case rsx::texture_target::_1: dst += "texture(" + texture.name + ", coord.x)"; break; + case rsx::texture_target::_2: dst += "texture(" + texture.name + ", coord.xy)"; break; + + case rsx::texture_target::cube: + case rsx::texture_target::_3: dst += "texture(" + texture.name + ", coord.xyz)"; break; + } + + dst += ";\n"; + } + + dst += "\t}\n"; + dst += "}\n"; +} + +static void insert_texture_bias_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state) +{ + if (shader.textures.empty()) + { + return; + } + + dst += "vec4 texture_bias_fetch(int index, vec4 coord, float bias)\n{\n"; + dst += "\tswitch (index)\n\t{\n"; + + for (auto &texture : shader.textures) + { + dst += "\tcase " + std::to_string(texture.id) + ": return "; + + switch (state.textures[texture.id]) + { + case rsx::texture_target::none: dst += "vec4(0.0)"; break; + case rsx::texture_target::_1: dst += "texture(" + texture.name + ", coord.x, bias)"; break; + case rsx::texture_target::_2: dst += "texture(" + texture.name + ", coord.xy, bias)"; break; + + case rsx::texture_target::cube: + case rsx::texture_target::_3: dst += "texture(" + texture.name + ", coord.xyz, bias)"; break; + } + + dst += ";\n"; + } + + dst += "\t}\n"; + dst += "}\n"; +} + +static void insert_texture_grad_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state) +{ + if (shader.textures.empty()) + { + return; + } + + dst += "vec4 texture_grad_fetch(int index, vec4 coord, vec4 dPdx, vec4 dPdy)\n{\n"; + dst += "\tswitch (index)\n\t{\n"; + + for (auto &texture : shader.textures) + { + dst += "\tcase " + std::to_string(texture.id) + ": return "; + + switch (state.textures[texture.id]) + { + case rsx::texture_target::none: dst += "vec4(0.0)"; break; + case rsx::texture_target::_1: dst += "textureGrad(" + texture.name + ", coord.x, dPdx.x, dPdy.x)"; break; + case rsx::texture_target::_2: dst += "textureGrad(" + texture.name + ", coord.xy, dPdx.xy, dPdy.xy)"; break; + + case rsx::texture_target::cube: + case rsx::texture_target::_3: dst += "textureGrad(" + texture.name + ", coord.xyz, dPdx.xyz, dPdy.xyz)"; break; + } + + dst += ";\n"; + } + + dst += "\t}\n"; + dst += "}\n"; +} + +static void insert_texture_lod_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state) +{ + if (shader.textures.empty()) + { + return; + } + + dst += "vec4 texture_lod_fetch(int index, vec4 coord, float lod)\n{\n"; + dst += "\tswitch (index)\n\t{\n"; + + for (auto &texture : shader.textures) + { + dst += "\tcase " + std::to_string(texture.id) + ": return "; + + switch (state.textures[texture.id]) + { + case rsx::texture_target::none: dst += "vec4(0.0)"; break; + case rsx::texture_target::_1: dst += "textureLod(" + texture.name + ", coord.x, lod)"; break; + case rsx::texture_target::_2: dst += "textureLod(" + texture.name + ", coord.xy, lod)"; break; + + case rsx::texture_target::cube: + case rsx::texture_target::_3: dst += "textureLod(" + texture.name + ", coord.xyz, lod)"; break; + } + + dst += ";\n"; + } + + dst += "\t}\n"; + 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()) + { + return; + } + + dst += "vec4 texture_proj_fetch(int index, vec4 coord, float bias)\n{\n"; + dst += "\tswitch (index)\n\t{\n"; + + for (auto &texture : shader.textures) + { + dst += "\tcase " + std::to_string(texture.id) + ": return "; + + switch (state.textures[texture.id]) + { + case rsx::texture_target::cube: + case rsx::texture_target::none: dst += "vec4(0.0)"; break; + case rsx::texture_target::_1: dst += "textureProj(" + texture.name + ", coord.xy, bias)"; break; + case rsx::texture_target::_2: dst += "textureProj(" + texture.name + ", coord.xyz, bias)"; break; + case rsx::texture_target::_3: dst += "textureProj(" + texture.name + ", coord, bias)"; break; + } + + dst += ";\n"; + } + + dst += "\t}\n"; + dst += "}\n"; +} + + rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, rsx::program_state state) { rsx::complete_shader result; @@ -17,6 +173,15 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, "\tmat4 normalize_matrix;\n" "};\n"; } + else if (shader.raw->type == rsx::program_type::fragment) + { + result.code += "layout(std140, binding = 3) uniform StateParameters\n{\n" + "\tfloat fog_param0;\n" + "\tfloat fog_param1;\n" + "\tuint alpha_test;\n" + "\tfloat alpha_ref;\n" + "};\n"; + } if (!shader.constants.empty()) { @@ -75,7 +240,21 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, for (const rsx::texture_info& texture : shader.textures) { result.code += "uniform vec4 " + texture.name + "_cm = vec4(1.0);\n"; - result.code += "uniform sampler2D " + texture.name + ";\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; @@ -85,6 +264,13 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, switch (shader.raw->type) { case rsx::program_type::fragment: + 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); + insert_texture_lod_fetch_function(result.code, shader, state); + insert_texture_proj_fetch_function(result.code, shader, state); + + result.code += "\n"; result.code += "layout(location = 0) out vec4 ocol;\n"; if (state.ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) @@ -153,6 +339,43 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, } } + { + if (~state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_FOG) + { + result.code += "vec4 fog = vec4(0.0);\n"; + } + + result.code += "vec4 fogc;\n"; + + std::string body; + switch ((rsx::fog_mode)state.fog_mode) + { + case rsx::fog_mode::linear: + body = "fog_param1 * fog.x + (fog_param0 - 1.0), fog_param1 * fog.x + (fog_param0 - 1.0)"; + break; + case rsx::fog_mode::exponential: + body = "11.084 * (fog_param1 * fog.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * fog.x + fog_param0 - 1.5))"; + break; + case rsx::fog_mode::exponential2: + body = "4.709 * (fog_param1 * fog.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * fog.x + fog_param0 - 1.5), 2.0))"; + break; + case rsx::fog_mode::linear_abs: + body = "fog_param1 * abs(fog.x) + (fog_param0 - 1.0), fog_param1 * abs(fog.x) + (fog_param0 - 1.0)"; + break; + case rsx::fog_mode::exponential_abs: + body = "11.084 * (fog_param1 * abs(fog.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs(fog.x) + fog_param0 - 1.5))"; + break; + case rsx::fog_mode::exponential2_abs: + body = "4.709 * (fog_param1 * abs(fog.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs(fog.x) + fog_param0 - 1.5), 2.0))"; + break; + + default: + body = "0.0, 0.0"; + } + + prepare += "\tfogc = clamp(vec4(" + body + ", 0.0, 0.0), 0.0, 1.0);\n"; + } + { u32 diffuse_color = state.output_attributes & (CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE); u32 specular_color = state.output_attributes & (CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR); @@ -240,10 +463,67 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, result.code += "in vec4 " + rsx::vertex_program::output_attrib_names[index] + ";\n"; } } + + { + auto make_comparsion_test = [](rsx::comparaison_function compare_func, const std::string &test, const std::string &a, const std::string &b) -> std::string + { + if (compare_func == rsx::comparaison_function::always) + { + return{}; + } + + if (compare_func == rsx::comparaison_function::never) + { + return "\tdiscard;\n"; + } + + std::string compare; + + switch (compare_func) + { + case rsx::comparaison_function::equal: + compare = "=="; + break; + + case rsx::comparaison_function::not_equal: + compare = "!="; + break; + + case rsx::comparaison_function::less_or_equal: + compare = "<="; + break; + + case rsx::comparaison_function::less: + compare = "<"; + break; + + case rsx::comparaison_function::greater: + compare = ">"; + break; + + case rsx::comparaison_function::greater_or_equal: + compare = ">="; + break; + } + + return "\tif (" + test + "!(" + a + " " + compare + " " + b + ")) discard;\n"; + }; + + for (u8 index = 0; index < 16; ++index) + { + if (state.textures_alpha_kill[index]) + { + std::string index_string = std::to_string(index); + std::string fetch_texture = "texture_fetch(" + index_string + ", tex" + index_string + " * ftexture" + index_string + "_cm).a"; + finalize += make_comparsion_test((rsx::comparaison_function)state.textures_zfunc[index], "", "0", fetch_texture); + } + } + + finalize += make_comparsion_test((rsx::comparaison_function)state.alpha_func, "alpha_test != 0 && ", "ocol.a", "alpha_ref"); + } break; case rsx::program_type::vertex: - result.code += "out vec4 wpos;\n"; // TODO @@ -266,9 +546,6 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, { if (shader.input_attributes & (1 << index)) { - // result.code += "in vec4 " + rsx::vertex_program::input_attrib_names[index] + ";\n"; - - // TODO: use actual information about vertex inputs const std::string &attrib_name = rsx::vertex_program::input_attrib_names[index]; result.code += "uniform "; @@ -290,11 +567,22 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, std::string vertex_id; - if (state.is_array & (1 << index)) + if (state.frequency[index] == 1) + { + if (state.divider_op & (1 << index)) + { + vertex_id += "0"; + } + else + { + vertex_id += "gl_VertexID"; + } + } + else { vertex_id = "gl_VertexID"; - if (state.frequency[index] > 1) + if (state.frequency[index]) { if (state.divider_op & (1 << index)) { @@ -308,10 +596,6 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, vertex_id += std::to_string(state.frequency[index]); } } - else - { - vertex_id = "0"; - } prepare += '\t' + attrib_name + " = texelFetch(" + attrib_name + "_buffer, " + vertex_id + ");\n"; } @@ -321,6 +605,12 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, } { + if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_FOG) + { + result.code += "out vec4 fog;\n"; + finalize += "\tfog = o5.xxxx;\n"; + } + auto map_register = [&](int to, int from) { if (shader.output_attributes & (1 << from)) @@ -332,11 +622,11 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, { result.code += "out vec4 " + rsx::vertex_program::output_attrib_names[to] + ";\n"; - if ((1 << to) == CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE && shader.output_attributes & (1 << 1)) + if (to == CELL_GCM_ATTRIB_OUTPUT_BACKDIFFUSE && shader.output_attributes & (1 << 1)) { finalize += "\t" + rsx::vertex_program::output_attrib_names[to] + " = o1;\n"; } - else if ((1 << to) == CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR && shader.output_attributes & (1 << 2)) + else if (to == CELL_GCM_ATTRIB_OUTPUT_BACKSPECULAR && shader.output_attributes & (1 << 2)) { finalize += "\t" + rsx::vertex_program::output_attrib_names[to] + " = o2;\n"; } @@ -347,19 +637,19 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, } }; - map_register(0, 1); - map_register(1, 2); - map_register(2, 3); - map_register(3, 4); - map_register(14, 7); - map_register(15, 8); - map_register(16, 9); - map_register(17, 10); - map_register(18, 11); - map_register(19, 12); - map_register(20, 13); - map_register(21, 14); - map_register(12, 15); + map_register(CELL_GCM_ATTRIB_OUTPUT_FRONTDIFFUSE, 1); + map_register(CELL_GCM_ATTRIB_OUTPUT_FRONTSPECULAR, 2); + map_register(CELL_GCM_ATTRIB_OUTPUT_BACKDIFFUSE, 3); + map_register(CELL_GCM_ATTRIB_OUTPUT_BACKSPECULAR, 4); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX0, 7); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX1, 8); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX2, 9); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX3, 10); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX4, 11); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX5, 12); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX6, 13); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX7, 14); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX8, 15); if (shader.output_attributes & (1 << 5)) { @@ -407,11 +697,6 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, finalize += "\tgl_ClipDistance[5] = uc_m5 * o6.w;\n"; } } - - if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_FOG) - { - //TODO - } } break; @@ -422,7 +707,7 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, result.code += "\n"; result.code += shader.code; - result.code += "void main()\n{\n" + prepare + "\t" + shader.entry_function + "();\n" + finalize + "}"; + result.code += "void main()\n{\n" + prepare + "\n\t" + shader.entry_function + "();\n\n" + finalize + "}"; return result; } @@ -446,7 +731,6 @@ void* glsl_make_program(const void *vertex_shader, const void *fragment_shader) result->attach(*(gl::glsl::shader*)fragment_shader); result->link(); - result->validate(); return result; } diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp b/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp index 141dca7bf7..ad2814693e 100644 --- a/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp +++ b/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp @@ -516,8 +516,6 @@ namespace rsx __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 glTexParameteri(m_target, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.zfunc()]); - __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)); diff --git a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp index a485b0d479..eaa958469a 100644 --- a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp +++ b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp @@ -176,12 +176,10 @@ u32 GLGSRender::set_vertex_buffer() for (u8 index = 0; index < rsx::limits::vertex_count; ++index) { - if (vertex_arrays_info[index].size == 0) + if (vertex_arrays_info[index].size || register_vertex_info[index].size) { - continue; + max_vertex_attrib_size += 16; } - - max_vertex_attrib_size += 16; } if (draw_command == rsx::draw_command::indexed) @@ -292,7 +290,7 @@ u32 GLGSRender::set_vertex_buffer() if (draw_command == rsx::draw_command::array || draw_command == rsx::draw_command::indexed) { u32 verts_allocated = std::max(vertex_draw_count, max_index + 1); - m_attrib_ring_buffer.reserve_and_map(verts_allocated * max_vertex_attrib_size); + __glcheck m_attrib_ring_buffer.reserve_and_map(verts_allocated * max_vertex_attrib_size); for (int index = 0; index < rsx::limits::vertex_count; ++index) { @@ -365,7 +363,6 @@ u32 GLGSRender::set_vertex_buffer() } else if (register_vertex_info[index].size > 0) { - //Untested! auto &vertex_data = register_vertex_data[index]; auto &vertex_info = register_vertex_info[index]; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index b68980724f..bb080f3818 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -342,18 +342,30 @@ namespace rsx void thread::begin() { + draw_inline_vertex_array = false; + inline_vertex_array.clear(); first_count_commands.clear(); + draw_command = rsx::draw_command::none; draw_mode = to_primitive_type(method_registers[NV4097_SET_BEGIN_END]); } void thread::end() { + 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) + { vertex_draw_count += first_count.second; + } + capture_frame("Draw " + std::to_string(vertex_draw_count)); vertex_draw_count = 0; } @@ -747,7 +759,7 @@ namespace rsx raw_program thread::get_raw_program() const { - raw_program result; + raw_program result{}; u32 fp_info = rsx::method_registers[NV4097_SET_SHADER_PROGRAM]; @@ -755,8 +767,8 @@ namespace rsx result.state.output_attributes = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK]; result.state.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL]; result.state.divider_op = rsx::method_registers[NV4097_SET_FREQUENCY_DIVIDER_OPERATION]; - - result.state.is_array = 0; + result.state.alpha_func = rsx::method_registers[NV4097_SET_ALPHA_FUNC]; + result.state.fog_mode = (u32)rsx::to_fog_mode(rsx::method_registers[NV4097_SET_FOG_MODE]); result.state.is_int = 0; for (u8 index = 0; index < rsx::limits::vertex_count; ++index) @@ -765,7 +777,6 @@ namespace rsx if (vertex_arrays_info[index].size > 0) { - result.state.is_array |= 1 << index; is_int = is_int_type(vertex_arrays_info[index].type); result.state.frequency[index] = vertex_arrays_info[index].frequency; } @@ -785,6 +796,32 @@ namespace rsx } } + for (u8 index = 0; index < rsx::limits::textures_count; ++index) + { + if (!textures[index].enabled()) + { + result.state.textures_alpha_kill[index] = 0; + result.state.textures_zfunc[index] = 0; + result.state.textures[index] = rsx::texture_target::none; + continue; + } + + result.state.textures_alpha_kill[index] = textures[index].alpha_kill_enabled() ? 1 : 0; + result.state.textures_zfunc[index] = textures[index].zfunc(); + + switch (textures[index].get_extended_texture_dimension()) + { + case rsx::texture_dimension_extended::texture_dimension_1d: result.state.textures[index] = rsx::texture_target::_1; break; + case rsx::texture_dimension_extended::texture_dimension_2d: result.state.textures[index] = rsx::texture_target::_2; break; + case rsx::texture_dimension_extended::texture_dimension_3d: result.state.textures[index] = rsx::texture_target::_3; break; + case rsx::texture_dimension_extended::texture_dimension_cubemap: result.state.textures[index] = rsx::texture_target::cube; break; + + default: + result.state.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 2ad12d998d..e25a8942f2 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -197,6 +197,7 @@ namespace rsx enum class draw_command { + none, array, inlined_array, indexed, diff --git a/rpcs3/Emu/RSX/rsx_cache.cpp b/rpcs3/Emu/RSX/rsx_cache.cpp index 86108992ea..61a5434684 100644 --- a/rpcs3/Emu/RSX/rsx_cache.cpp +++ b/rpcs3/Emu/RSX/rsx_cache.cpp @@ -92,7 +92,7 @@ namespace rsx program_info result; result.vertex_shader = m_vertex_shaders_cache.get(context, raw_program_.vertex_shader, raw_program_.state); - result.fragment_shader = m_vertex_shaders_cache.get(context, raw_program_.fragment_shader, raw_program_.state); + result.fragment_shader = m_fragment_shader_cache.get(context, raw_program_.fragment_shader, raw_program_.state); result.program = context.make_program(result.vertex_shader.complete->user_data, result.fragment_shader.complete->user_data); m_program_cache.insert({ raw_program_, result }); diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 96e8c224a0..a5d5f95259 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -90,7 +90,7 @@ namespace rsx //find begin of data size_t begin = id + index * element_size_in_words; - size_t position = 0;//entry.size(); + size_t position = entry.size(); entry.resize(position + element_size); memcpy(entry.data() + position, method_registers + begin, element_size); @@ -226,17 +226,47 @@ namespace rsx } }; - force_inline void set_begin_end(thread* rsx, u32 arg) + force_inline void set_begin_end(thread* rsxthr, u32 arg) { if (arg) { - rsx->draw_inline_vertex_array = false; - rsx->inline_vertex_array.clear(); - rsx->begin(); + rsxthr->begin(); return; } - rsx->end(); + u32 max_vertex_count = 0; + + for (u8 index = 0; index < rsx::limits::vertex_count; ++index) + { + auto &vertex_info = rsxthr->register_vertex_info[index]; + + if (vertex_info.size > 0) + { + auto &vertex_data = rsxthr->register_vertex_data[index]; + + u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size); + u32 element_count = vertex_data.size() / element_size; + + vertex_info.frequency = element_count; + rsx::method_registers[NV4097_SET_FREQUENCY_DIVIDER_OPERATION] |= 1 << index; + + if (rsxthr->draw_command == rsx::draw_command::none) + { + max_vertex_count = std::max(max_vertex_count, element_count); + } + } + } + + if (rsxthr->draw_command == rsx::draw_command::none && max_vertex_count) + { + rsxthr->draw_command = rsx::draw_command::array; + rsxthr->first_count_commands.push_back(std::make_pair(0, max_vertex_count)); + } + + if (!rsxthr->first_count_commands.empty()) + { + rsxthr->end(); + } } force_inline void get_report(thread* rsx, u32 arg) diff --git a/rsx_program_decompiler b/rsx_program_decompiler index 9f8814af57..aa6bcbc589 160000 --- a/rsx_program_decompiler +++ b/rsx_program_decompiler @@ -1 +1 @@ -Subproject commit 9f8814af57264c82b7e063c1df5d71dc32c7a951 +Subproject commit aa6bcbc58961356733ae1fc0742a37a0a6190f31