diff --git a/rpcs3/Emu/RSX/Common/ShaderParam.h b/rpcs3/Emu/RSX/Common/ShaderParam.h index 6ae251efb0..4adf78073a 100644 --- a/rpcs3/Emu/RSX/Common/ShaderParam.h +++ b/rpcs3/Emu/RSX/Common/ShaderParam.h @@ -33,6 +33,10 @@ enum class FUNCTION { FUNCTION_TEXTURE_SAMPLE3D_PROJ, FUNCTION_TEXTURE_SAMPLE3D_LOD, FUNCTION_TEXTURE_SAMPLE3D_GRAD, + FUNCTION_VERTEX_TEXTURE_FETCH1D, + FUNCTION_VERTEX_TEXTURE_FETCH2D, + FUNCTION_VERTEX_TEXTURE_FETCH3D, + FUNCTION_VERTEX_TEXTURE_FETCHCUBE, }; enum class COMPARE { diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index a5fb07d51b..554ea424af 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -178,11 +178,12 @@ std::vector get_subresources_layout_impl(const RsxTextur return get_subresources_layout_impl<1, u32>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: return get_subresources_layout_impl<1, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); + case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: + return get_subresources_layout_impl<1, u128>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); case CELL_GCM_TEXTURE_COMPRESSED_DXT1: return get_subresources_layout_impl<4, u64>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); case CELL_GCM_TEXTURE_COMPRESSED_DXT23: case CELL_GCM_TEXTURE_COMPRESSED_DXT45: - case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return get_subresources_layout_impl<4, u128>(pixels, w, h, depth, layer, texture.get_exact_mipmap_count(), texture.pitch(), !is_swizzled); } fmt::throw_exception("Wrong format 0x%x" HERE, format); @@ -264,6 +265,10 @@ void upload_texture_subresource(gsl::span dst_buffer, const rsx_subre copy_unmodified_block::copy_mipmap_level(as_span_workaround(dst_buffer), gsl::as_span>(src_layout.data), w, h, depth, get_row_pitch_in_block(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes); break; + case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: + copy_unmodified_block::copy_mipmap_level(as_span_workaround(dst_buffer), gsl::as_span>(src_layout.data), w, h, depth, get_row_pitch_in_block(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes); + break; + case CELL_GCM_TEXTURE_COMPRESSED_DXT1: copy_unmodified_block::copy_mipmap_level(as_span_workaround(dst_buffer), gsl::as_span(src_layout.data), w, h, depth, get_row_pitch_in_block(w, dst_row_pitch_multiple_of), src_layout.pitch_in_bytes); break; diff --git a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp index 0e26521469..4cf4b1d103 100644 --- a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp @@ -674,7 +674,7 @@ std::string VertexProgramDecompiler::Decompile() case RSX_VEC_OPCODE_SNE: SetDSTVec(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SNE, "$0", "$1") + ")"); break; case RSX_VEC_OPCODE_STR: SetDSTVec(getFunction(FUNCTION::FUNCTION_STR)); break; case RSX_VEC_OPCODE_SSG: SetDSTVec("sign($0)"); break; - case RSX_VEC_OPCODE_TXL: SetDSTVec("texture($t, $0.xy)"); break; + case RSX_VEC_OPCODE_TXL: SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D)); break; default: AddCode(fmt::format("//Unknown vp opcode 0x%x", u32{ d1.vec_opcode })); diff --git a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp index bd5ebb7fef..10a3bf8b0b 100644 --- a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp +++ b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp @@ -78,6 +78,8 @@ std::string getFunctionImpl(FUNCTION f) return "dFdx($0)"; case FUNCTION::FUNCTION_DFDY: return "dFdy($0)"; + case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D: + return "textureLod($t, $0.xy, 0)"; } } diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index 94922c881c..b8326498a3 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -347,6 +347,9 @@ void GLFragmentProgram::Compile() const char* str = shader.c_str(); const int strlen = ::narrow(shader.length()); + fs::create_path(fs::get_config_dir() + "/shaderlog"); + fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram" + std::to_string(id) + ".glsl", fs::rewrite).write(str); + glShaderSource(id, 1, &str, &strlen); glCompileShader(id); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 5bb50bc4a9..91303a2503 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -301,11 +301,6 @@ void GLGSRender::begin() //NV4097_SET_ANTI_ALIASING_CONTROL //NV4097_SET_CLIP_ID_TEST_ENABLE - if (__glcheck enable(rsx::method_registers.restart_index_enabled(), GL_PRIMITIVE_RESTART)) - { - __glcheck glPrimitiveRestartIndex(rsx::method_registers.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++; @@ -384,6 +379,28 @@ void GLGSRender::end() } } + //Vertex textures + for (int i = 0; i < rsx::limits::vertex_textures_count; ++i) + { + int texture_index = i + rsx::limits::fragment_textures_count; + int location; + if (m_program->uniforms.has_location("vtex" + std::to_string(i), &location)) + { + if (!rsx::method_registers.vertex_textures[i].enabled()) + { + glActiveTexture(GL_TEXTURE0 + texture_index); + glBindTexture(GL_TEXTURE_2D, 0); + glProgramUniform1i(m_program->id(), location, texture_index); + continue; + } + + m_gl_vertex_textures[i].set_target(get_gl_target_for_texture(rsx::method_registers.vertex_textures[i])); + + __glcheck m_gl_texture_cache.upload_texture(texture_index, rsx::method_registers.vertex_textures[i], m_gl_vertex_textures[i], m_rtts); + glProgramUniform1i(m_program->id(), location, texture_index); + } + } + u32 vertex_draw_count; std::optional > indexed_draw_info; std::tie(vertex_draw_count, indexed_draw_info) = set_vertex_buffer(); @@ -398,6 +415,12 @@ void GLGSRender::end() if (indexed_draw_info) { + if (__glcheck enable(rsx::method_registers.restart_index_enabled(), GL_PRIMITIVE_RESTART)) + { + GLenum index_type = std::get<0>(indexed_draw_info.value()); + __glcheck glPrimitiveRestartIndex((index_type == GL_UNSIGNED_SHORT)? 0xffff: 0xffffffff); + } + __glcheck glDrawElements(gl::draw_mode(rsx::method_registers.current_draw_clause.primitive), vertex_draw_count, std::get<0>(indexed_draw_info.value()), (GLvoid *)(std::ptrdiff_t)std::get<1>(indexed_draw_info.value())); } else diff --git a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h index 1f7ad871b2..4e5c0da30d 100644 --- a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h +++ b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h @@ -15,9 +15,6 @@ struct GLTraits { fragmentProgramData.Decompile(RSXFP); fragmentProgramData.Compile(); - //checkForGlError("m_fragment_prog.Compile"); - - fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram.glsl", fs::rewrite).write(fragmentProgramData.shader); } static @@ -25,9 +22,6 @@ struct GLTraits { vertexProgramData.Decompile(RSXVP); vertexProgramData.Compile(); - //checkForGlError("m_vertex_prog.Compile"); - - fs::file(fs::get_config_dir() + "shaderlog/VertexProgram.glsl", fs::rewrite).write(vertexProgramData.shader); } static diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index eb654e87e4..81c71f996b 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -133,7 +133,6 @@ namespace case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: case CELL_GCM_TEXTURE_DEPTH16: case CELL_GCM_TEXTURE_DEPTH16_FLOAT: - case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: case CELL_GCM_TEXTURE_COMPRESSED_DXT1: case CELL_GCM_TEXTURE_COMPRESSED_DXT23: case CELL_GCM_TEXTURE_COMPRESSED_DXT45: @@ -151,18 +150,19 @@ namespace return { GL_GREEN, GL_RED, GL_GREEN, GL_RED}; case CELL_GCM_TEXTURE_X16: - return { GL_RED, GL_ONE, GL_RED, GL_ONE }; + return { GL_RED, GL_RED, GL_RED, GL_RED }; case CELL_GCM_TEXTURE_Y16_X16: return { GL_RED, GL_GREEN, GL_RED, GL_GREEN}; case CELL_GCM_TEXTURE_X32_FLOAT: - return { GL_RED, GL_ONE, GL_ONE, GL_ONE }; + return { GL_RED, GL_RED, GL_RED, GL_RED }; case CELL_GCM_TEXTURE_Y16_X16_FLOAT: return { GL_GREEN, GL_RED, GL_GREEN, GL_RED }; case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: + case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return { GL_RED, GL_ALPHA, GL_BLUE, GL_GREEN }; case CELL_GCM_TEXTURE_D1R5G5B5: @@ -595,50 +595,18 @@ namespace rsx 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[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_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_REPEAT); + __glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_T, GL_REPEAT); + __glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_R, GL_REPEAT); - __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())); + __glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + __glcheck glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + __glcheck glTexParameterf(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); } void texture::bind() diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index 8990d552f5..b0072af52b 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -90,7 +90,18 @@ void GLVertexDecompilerThread::insertConstants(std::stringstream & OS, const std OS << "layout(std140, binding = 1) uniform VertexConstantsBuffer" << std::endl; OS << "{" << std::endl; OS << " vec4 vc[468];" << std::endl; - OS << "};" << std::endl; + OS << "};" << std::endl << std::endl; + + for (const ParamType &PT: constants) + { + for (const ParamItem &PI : PT.items) + { + if (PI.name == "vc[468]") + continue; + + OS << "uniform " << PT.type << " " << PI.name << ";" << std::endl; + } + } } struct reg_info @@ -201,6 +212,17 @@ void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS) for (const ParamItem &PI : PT.items) add_input(OS, PI, rsx_vertex_program.rsx_vertex_inputs); } + + for (const ParamType &PT : m_parr.params[PF_PARAM_UNIFORM]) + { + if (PT.type == "sampler2D") + { + for (const ParamItem &PI : PT.items) + { + OS << " vec2 " << PI.name << "_coord_scale = vec2(1.);" << std::endl; + } + } + } } void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS) @@ -247,6 +269,9 @@ void GLVertexProgram::Compile() const char* str = shader.c_str(); const int strlen = ::narrow(shader.length()); + fs::create_path(fs::get_config_dir() + "/shaderlog"); + fs::file(fs::get_config_dir() + "shaderlog/VertexProgram" + std::to_string(id) + ".glsl", fs::rewrite).write(str); + glShaderSource(id, 1, &str, &strlen); glCompileShader(id); diff --git a/rpcs3/Emu/RSX/VK/VKCommonDecompiler.cpp b/rpcs3/Emu/RSX/VK/VKCommonDecompiler.cpp index 1b7cf4c4ed..ca675132a6 100644 --- a/rpcs3/Emu/RSX/VK/VKCommonDecompiler.cpp +++ b/rpcs3/Emu/RSX/VK/VKCommonDecompiler.cpp @@ -73,6 +73,8 @@ namespace vk return "dFdx($0)"; case FUNCTION::FUNCTION_DFDY: return "dFdy($0)"; + case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D: + return "textureLod($t, $0.xy, 0)"; } } diff --git a/rpcs3/Emu/RSX/VK/VKFormats.cpp b/rpcs3/Emu/RSX/VK/VKFormats.cpp index f2a2fd2247..fcbcb3d0eb 100644 --- a/rpcs3/Emu/RSX/VK/VKFormats.cpp +++ b/rpcs3/Emu/RSX/VK/VKFormats.cpp @@ -126,7 +126,6 @@ VkComponentMapping get_component_mapping(u32 format, u8 swizzle_mask) case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: case CELL_GCM_TEXTURE_DEPTH16: case CELL_GCM_TEXTURE_DEPTH16_FLOAT: - case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: case CELL_GCM_TEXTURE_COMPRESSED_DXT1: case CELL_GCM_TEXTURE_COMPRESSED_DXT23: case CELL_GCM_TEXTURE_COMPRESSED_DXT45: @@ -144,7 +143,8 @@ VkComponentMapping get_component_mapping(u32 format, u8 swizzle_mask) } case CELL_GCM_TEXTURE_X16: - return { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R }; + case CELL_GCM_TEXTURE_X32_FLOAT: + return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }; case CELL_GCM_TEXTURE_Y16_X16: return { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R }; @@ -153,11 +153,9 @@ VkComponentMapping get_component_mapping(u32 format, u8 swizzle_mask) return { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G }; case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: + case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: return { VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R }; - case CELL_GCM_TEXTURE_X32_FLOAT: - return { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R }; - case CELL_GCM_TEXTURE_A4R4G4B4: { VkComponentSwizzle map_table[] = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index 29cd880657..f63c39c0b5 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -117,7 +117,7 @@ void VKFragmentDecompilerThread::insertOutputs(std::stringstream & OS) void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS) { - int location = 2; + int location = 0; for (const ParamType& PT : m_parr.params[PF_PARAM_UNIFORM]) { diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 9b459a3374..df5a8c1f12 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -364,7 +364,7 @@ namespace std::tuple get_shared_pipeline_layout(VkDevice dev) { - std::array bindings = {}; + std::array bindings = {}; size_t idx = 0; // Vertex buffer @@ -400,6 +400,15 @@ namespace idx++; } + for (int i = 0; i < 4; i++) + { + bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[idx].descriptorCount = 1; + bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + bindings[idx].binding = VERTEX_TEXTURES_FIRST_BIND_SLOT + i; + idx++; + } + bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; bindings[idx].descriptorCount = 1; bindings[idx].stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; @@ -677,6 +686,72 @@ void VKGSRender::end() } } + for (int i = 0; i < rsx::limits::fragment_textures_count; ++i) + { + if (m_program->has_uniform("tex" + std::to_string(i))) + { + if (!rsx::method_registers.fragment_textures[i].enabled()) + { + m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), descriptor_sets); + continue; + } + + vk::image_view *texture0 = m_texture_cache.upload_texture(m_command_buffer, rsx::method_registers.fragment_textures[i], m_rtts, m_memory_type_mapping, m_texture_upload_buffer_ring_info, m_texture_upload_buffer_ring_info.heap.get()); + + if (!texture0) + { + LOG_ERROR(RSX, "Texture upload failed to texture index %d. Binding null sampler.", i); + m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), descriptor_sets); + continue; + } + + VkFilter min_filter; + VkSamplerMipmapMode mip_mode; + std::tie(min_filter, mip_mode) = vk::get_min_filter_and_mip(rsx::method_registers.fragment_textures[i].min_filter()); + + m_sampler_to_clean.push_back(std::make_unique( + *m_device, + vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_s()), vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_t()), vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_r()), + !!(rsx::method_registers.fragment_textures[i].format() & CELL_GCM_TEXTURE_UN), + rsx::method_registers.fragment_textures[i].bias(), vk::max_aniso(rsx::method_registers.fragment_textures[i].max_aniso()), rsx::method_registers.fragment_textures[i].min_lod(), rsx::method_registers.fragment_textures[i].max_lod(), + min_filter, vk::get_mag_filter(rsx::method_registers.fragment_textures[i].mag_filter()), mip_mode, vk::get_border_color(rsx::method_registers.fragment_textures[i].border_color()) + )); + + m_program->bind_uniform({ m_sampler_to_clean.back()->value, texture0->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), descriptor_sets); + } + } + + for (int i = 0; i < rsx::limits::vertex_textures_count; ++i) + { + if (m_program->has_uniform("vtex" + std::to_string(i))) + { + if (!rsx::method_registers.vertex_textures[i].enabled()) + { + m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "vtex" + std::to_string(i), descriptor_sets); + continue; + } + + vk::image_view *texture0 = m_texture_cache.upload_texture(m_command_buffer, rsx::method_registers.vertex_textures[i], m_rtts, m_memory_type_mapping, m_texture_upload_buffer_ring_info, m_texture_upload_buffer_ring_info.heap.get()); + + if (!texture0) + { + LOG_ERROR(RSX, "Texture upload failed to vtexture index %d. Binding null sampler.", i); + m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "vtex" + std::to_string(i), descriptor_sets); + continue; + } + + m_sampler_to_clean.push_back(std::make_unique( + *m_device, + VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, + !!(rsx::method_registers.vertex_textures[i].format() & CELL_GCM_TEXTURE_UN), + 0, 1.f, rsx::method_registers.vertex_textures[i].min_lod(), rsx::method_registers.vertex_textures[i].max_lod(), + VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, vk::get_border_color(rsx::method_registers.vertex_textures[i].border_color()) + )); + + m_program->bind_uniform({ m_sampler_to_clean.back()->value, texture0->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "vtex" + std::to_string(i), descriptor_sets); + } + } + VkRenderPassBeginInfo rp_begin = {}; rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; rp_begin.renderPass = current_render_pass; @@ -884,11 +959,6 @@ bool VKGSRender::load_program() if (rsx::method_registers.restart_index_enabled()) { - if (rsx::method_registers.restart_index() != 0xFFFF && - rsx::method_registers.restart_index() != 0xFFFFFFFF) - { - LOG_ERROR(RSX, "Custom primitive restart index 0x%x should rewrite index buffer with proper value!", rsx::method_registers.restart_index()); - } properties.ia.primitiveRestartEnable = VK_TRUE; } else diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index 34c5554ca8..b9539fe5f8 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -15,6 +15,14 @@ #include "../Common/ring_buffer_helper.h" #define DESCRIPTOR_MAX_DRAW_CALLS 1024 + +#define VERTEX_BUFFERS_FIRST_BIND_SLOT 3 +#define FRAGMENT_CONSTANT_BUFFERS_BIND_SLOT 2 +#define VERTEX_CONSTANT_BUFFERS_BIND_SLOT 1 +#define SCALE_OFFSET_BIND_SLOT 0 +#define TEXTURES_FIRST_BIND_SLOT 19 +#define VERTEX_TEXTURES_FIRST_BIND_SLOT 35 //19+16 + extern cfg::bool_entry g_cfg_rsx_debug_output; namespace rsx @@ -1327,11 +1335,6 @@ namespace vk program& load_uniforms(program_domain domain, const std::vector& inputs); bool has_uniform(std::string uniform_name); -#define VERTEX_BUFFERS_FIRST_BIND_SLOT 3 -#define FRAGMENT_CONSTANT_BUFFERS_BIND_SLOT 2 -#define VERTEX_CONSTANT_BUFFERS_BIND_SLOT 1 -#define TEXTURES_FIRST_BIND_SLOT 19 -#define SCALE_OFFSET_BIND_SLOT 0 void bind_uniform(VkDescriptorImageInfo image_descriptor, std::string uniform_name, VkDescriptorSet &descriptor_set); void bind_uniform(VkDescriptorBufferInfo buffer_descriptor, uint32_t binding_point, VkDescriptorSet &descriptor_set); void bind_uniform(const VkBufferView &buffer_view, const std::string &binding_name, VkDescriptorSet &descriptor_set); diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 2789c427a5..740c8ab66c 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -151,6 +151,17 @@ namespace vk m_cache.resize(0); } + //Helpers + VkComponentMapping get_component_map(rsx::fragment_texture &tex, u32 gcm_format) + { + return vk::get_component_mapping(gcm_format, tex.remap()); + } + + VkComponentMapping get_component_map(rsx::vertex_texture &tex, u32 gcm_format) + { + return vk::get_component_mapping(gcm_format, (0 | 1 << 2 | 2 << 4 | 3 << 6)); + } + public: texture_cache() {} @@ -161,7 +172,8 @@ namespace vk purge_cache(); } - vk::image_view* upload_texture(command_buffer cmd, rsx::fragment_texture &tex, rsx::vk_render_targets &m_rtts, const vk::memory_type_mapping &memory_type_mapping, vk_data_heap& upload_heap, vk::buffer* upload_buffer) + template + vk::image_view* upload_texture(command_buffer cmd, RsxTextureType &tex, rsx::vk_render_targets &m_rtts, const vk::memory_type_mapping &memory_type_mapping, vk_data_heap& upload_heap, vk::buffer* upload_buffer) { const u32 texaddr = rsx::get_address(tex.offset(), tex.location()); const u32 range = (u32)get_texture_size(tex); @@ -193,7 +205,7 @@ namespace vk u32 raw_format = tex.format(); u32 format = raw_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); - VkComponentMapping mapping = vk::get_component_mapping(format, tex.remap()); + VkComponentMapping mapping = get_component_map(tex, format); VkFormat vk_format = get_compatible_sampler_format(format); VkImageType image_type; @@ -251,7 +263,7 @@ namespace vk change_image_layout(cmd, cto.uploaded_texture->value, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range); cto.uploaded_image_view = std::make_unique(*vk::get_current_renderer(), cto.uploaded_texture->value, image_view_type, vk_format, - vk::get_component_mapping(tex.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN), tex.remap()), + mapping, subresource_range); copy_mipmaped_image_using_buffer(cmd, cto.uploaded_texture->value, get_subresources_layout(tex), format, !(tex.format() & CELL_GCM_TEXTURE_LN), tex.get_exact_mipmap_count(), diff --git a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp index 876e01ac99..f4ffe5b399 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp @@ -106,7 +106,7 @@ void VKVertexDecompilerThread::insertConstants(std::stringstream & OS, const std OS << "layout(std140, set=0, binding = 1) uniform VertexConstantsBuffer" << std::endl; OS << "{" << std::endl; OS << " vec4 vc[468];" << std::endl; - OS << "};" << std::endl; + OS << "};" << std::endl << std::endl; vk::glsl::program_input in; in.location = 1; @@ -115,6 +115,33 @@ void VKVertexDecompilerThread::insertConstants(std::stringstream & OS, const std in.type = vk::glsl::input_type_uniform_buffer; inputs.push_back(in); + + //We offset this value by the index of the first fragment texture (19) below + //and allow 16 fragment textures to precede this slot + int location = 16; + + for (const ParamType &PT : constants) + { + for (const ParamItem &PI : PT.items) + { + if (PI.name == "vc[468]") + continue; + + if (PT.type == "sampler2D" || + PT.type == "samplerCube" || + PT.type == "sampler1D" || + PT.type == "sampler3D") + { + in.location = location; + in.name = PI.name; + in.type = vk::glsl::input_type_texture; + + inputs.push_back(in); + + OS << "layout(set = 0, binding=" << 19 + location++ << ") uniform " << PT.type << " " << PI.name << ";" << std::endl; + } + } + } } struct reg_info