diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 54e4e41772..d790e76a5f 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -307,27 +307,38 @@ void GLGSRender::end() //setup textures { - int texture_index = 0; + //int texture_index = 0; for (int i = 0; i < rsx::limits::textures_count; ++i) { - if (!textures[i].enabled()) - { - continue; - } - int location; if (m_program->uniforms.has_location("texture" + std::to_string(i), &location)) { - __glcheck glProgramUniform1i(m_program->id(), location, texture_index); - __glcheck m_gl_textures[i].init(texture_index, textures[i]); + if (!textures[i].enabled()) + { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, 0); + glProgramUniform1i(m_program->id(), location, i); - texture_index++; + continue; + } + + 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("texture" + std::to_string(i) + "_cm", &location)) { if (textures[i].format() & CELL_GCM_TEXTURE_UN) { - //glProgramUniform4f(m_program->id(), location, textures[i].width(), textures[i].height(), textures[i].depth(), 1.0f); + 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); } } } @@ -349,8 +360,6 @@ void GLGSRender::end() */ } - __glcheck 0; - u32 offset_in_index_buffer = set_vertex_buffer(); m_vao.bind(); @@ -430,8 +439,6 @@ void GLGSRender::set_viewport() } glEnable(GL_SCISSOR_TEST); - - __glcheck 0; } void GLGSRender::on_init_thread() @@ -685,8 +692,6 @@ bool GLGSRender::load_program() auto mapping = m_uniform_ring_buffer.alloc_from_reserve(fragment_constants_size, m_uniform_buffer_offset_align); fragment_constants_offset = mapping.second; - u32 buffer_offset = 0; - static const __m128i mask = _mm_set_epi8( 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, @@ -695,20 +700,23 @@ bool GLGSRender::load_program() auto ucode = (const rsx::fragment_program::ucode_instr *)info.fragment_shader.decompiled->raw->ucode_ptr; + auto dst = (const rsx::fragment_program::ucode_instr *)mapping.first; + for (const auto& constant : info.fragment_shader.decompiled->constants) { - const void *data = ucode + u32(constant.id / sizeof(rsx::fragment_program::ucode_instr)); - const __m128i &vector = _mm_loadu_si128((const __m128i*)data); - const __m128i &shuffled_vector = _mm_shuffle_epi8(vector, mask); - _mm_stream_si128((__m128i*)((char*)mapping.first + buffer_offset), shuffled_vector); + const void *src = ucode + u32(constant.id / sizeof(*ucode)); - //float x = ((float*)((char*)mapping.first + buffer_offset))[0]; - //float y = ((float*)((char*)mapping.first + buffer_offset))[1]; - //float z = ((float*)((char*)mapping.first + buffer_offset))[2]; - //float w = ((float*)((char*)mapping.first + buffer_offset))[3]; + const __m128i &vector = _mm_loadu_si128((const __m128i*)src); + 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]; //LOG_WARNING(RSX, "fc%u = {%g, %g, %g, %g}", constant.id, x, y, z, w); - buffer_offset += 4 * sizeof(f32); + ++dst; } } diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp b/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp index aefc243bab..8332195f6c 100644 --- a/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp +++ b/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp @@ -259,17 +259,65 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, " gl_Position.w = o0.w;\n"; } - for (std::size_t index = 0; index < 16; ++index) { - if (shader.input_attributes & (1 << index)) - { - // result.code += "in vec4 " + rsx::vertex_program::input_attrib_names[index] + ";\n"; + std::string code_end; - // TODO: use actual information about vertex inputs - result.code += "layout(location=" + std::to_string(location++) + ") uniform samplerBuffer " + rsx::vertex_program::input_attrib_names[index] + "_buffer" + ";\n"; - result.code += "vec4 " + rsx::vertex_program::input_attrib_names[index] - + " = texelFetch(" + rsx::vertex_program::input_attrib_names[index] + "_buffer, gl_VertexID).rgba;\n"; + for (std::size_t index = 0; index < 16; ++index) + { + 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 "; + + if (state.is_int & (1 << index)) + { + result.code += "isamplerBuffer "; + code_end += "ivec4 "; + } + else + { + result.code += "samplerBuffer "; + code_end += "vec4 "; + } + + result.code += attrib_name + "_buffer" + ";\n"; + + code_end += attrib_name + ";\n"; + + std::string vertex_id; + + if (state.is_array & (1 << index)) + { + vertex_id = "gl_VertexID"; + + if (state.frequency[index] > 1) + { + if (state.divider_op & (1 << index)) + { + vertex_id += " % "; + } + else + { + vertex_id += " / "; + } + + vertex_id += std::to_string(state.frequency[index]); + } + } + else + { + vertex_id = "0"; + } + + prepare += '\t' + attrib_name + " = texelFetch(" + attrib_name + "_buffer, " + vertex_id + ");\n"; + } } + + result.code += code_end; } { diff --git a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp index 4b1208ee4b..a485b0d479 100644 --- a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp +++ b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp @@ -160,17 +160,9 @@ u32 GLGSRender::set_vertex_buffer() //initialize vertex attributes //merge all vertex arrays - std::chrono::time_point then = std::chrono::system_clock::now(); + static const u32 texture_index_offset = rsx::limits::textures_count + rsx::limits::vertex_textures_count; - const std::string reg_table[] = - { - "in_pos", "in_weight", "in_normal", - "in_diff_color", "in_spec_color", - "in_fog", - "in_point_size", "in_7", - "in_tc0", "in_tc1", "in_tc2", "in_tc3", - "in_tc4", "in_tc5", "in_tc6", "in_tc7" - }; + std::chrono::time_point then = std::chrono::system_clock::now(); u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK]; u32 min_index = 0, max_index = 0; @@ -185,7 +177,9 @@ u32 GLGSRender::set_vertex_buffer() for (u8 index = 0; index < rsx::limits::vertex_count; ++index) { if (vertex_arrays_info[index].size == 0) + { continue; + } max_vertex_attrib_size += 16; } @@ -240,9 +234,9 @@ u32 GLGSRender::set_vertex_buffer() if (!vertex_info.size) // disabled, bind a null sampler { - glActiveTexture(GL_TEXTURE0 + index + rsx::limits::textures_count); + glActiveTexture(GL_TEXTURE0 + index + texture_index_offset); glBindTexture(GL_TEXTURE_BUFFER, 0); - glProgramUniform1i(m_program->id(), location, index + rsx::limits::textures_count); + glProgramUniform1i(m_program->id(), location, index + texture_index_offset); continue; } @@ -279,7 +273,7 @@ u32 GLGSRender::set_vertex_buffer() texture.copy_from(m_attrib_ring_buffer, gl_type, mapping.second, data_size); //Link texture to uniform - m_program->uniforms.texture(location, index + rsx::limits::textures_count, texture); + m_program->uniforms.texture(location, index + texture_index_offset, texture); if (!is_primitive_native(draw_mode)) { std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw({ { 0, vertex_draw_count } }, draw_mode, m_index_ring_buffer); @@ -309,9 +303,9 @@ u32 GLGSRender::set_vertex_buffer() bool enabled = !!(input_mask & (1 << index)); if (!enabled) { - glActiveTexture(GL_TEXTURE0 + index + rsx::limits::textures_count); + glActiveTexture(GL_TEXTURE0 + index + texture_index_offset); glBindTexture(GL_TEXTURE_BUFFER, 0); - glProgramUniform1i(m_program->id(), location, index + rsx::limits::textures_count); + glProgramUniform1i(m_program->id(), location, index + texture_index_offset); continue; } @@ -367,7 +361,7 @@ u32 GLGSRender::set_vertex_buffer() texture.copy_from(m_attrib_ring_buffer, gl_type, buffer_offset, data_size); //Link texture to uniform - m_program->uniforms.texture(location, index + rsx::limits::textures_count, texture); + m_program->uniforms.texture(location, index + texture_index_offset, texture); } else if (register_vertex_info[index].size > 0) { @@ -392,7 +386,7 @@ u32 GLGSRender::set_vertex_buffer() texture.copy_from(m_attrib_ring_buffer, gl_type, mapping.second, data_size); //Link texture to uniform - m_program->uniforms.texture(location, index + rsx::limits::textures_count, texture); + m_program->uniforms.texture(location, index + texture_index_offset, texture); break; } default: @@ -402,9 +396,9 @@ u32 GLGSRender::set_vertex_buffer() } else { - glActiveTexture(GL_TEXTURE0 + index + rsx::limits::textures_count); + glActiveTexture(GL_TEXTURE0 + index + texture_index_offset); glBindTexture(GL_TEXTURE_BUFFER, 0); - glProgramUniform1i(m_program->id(), location, index + rsx::limits::textures_count); + glProgramUniform1i(m_program->id(), location, index + texture_index_offset); continue; } } diff --git a/rpcs3/Emu/RSX/RSXTexture.cpp b/rpcs3/Emu/RSX/RSXTexture.cpp index a8477b10cd..1cfc84acd1 100644 --- a/rpcs3/Emu/RSX/RSXTexture.cpp +++ b/rpcs3/Emu/RSX/RSXTexture.cpp @@ -72,6 +72,8 @@ namespace rsx 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); } } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 8a7ebf6677..b68980724f 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -751,8 +751,39 @@ namespace rsx u32 fp_info = rsx::method_registers[NV4097_SET_SHADER_PROGRAM]; + result.state.input_attributes = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK]; 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.is_int = 0; + + for (u8 index = 0; index < rsx::limits::vertex_count; ++index) + { + bool is_int = false; + + 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; + } + else if (register_vertex_info[index].size > 0) + { + is_int = is_int_type(register_vertex_info[index].type); + result.state.frequency[index] = register_vertex_info[index].frequency; + } + else + { + result.state.frequency[index] = 0; + } + + if (is_int) + { + result.state.is_int |= 1 << index; + } + } result.vertex_shader.ucode_ptr = transform_program; result.vertex_shader.offset = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START]; diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 94e84c7b2a..872134980b 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -67,10 +67,12 @@ $(SolutionDir)bin\ $(ProjectName)-dbg + $(SolutionDir)lib\Debug-$(Platform)\;$(LibraryPath) $(SolutionDir)bin\ $(ProjectName)-dbg + $(SolutionDir)lib\Debug-$(Platform)\;$(LibraryPath) $(SolutionDir)bin\ @@ -81,6 +83,7 @@ $(SolutionDir)bin\ false false + $(SolutionDir)lib\Release-$(Platform)\;$(LibraryPath) diff --git a/rsx_program_decompiler b/rsx_program_decompiler index e4d938c768..9f8814af57 160000 --- a/rsx_program_decompiler +++ b/rsx_program_decompiler @@ -1 +1 @@ -Subproject commit e4d938c76850549acd837326e2fe0890d5b4be03 +Subproject commit 9f8814af57264c82b7e063c1df5d71dc32c7a951