From 1e71285de882e527c56df7af89beea2a874ba2d1 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 5 Mar 2017 14:58:53 +0300 Subject: [PATCH] gl/vk/dx12: Implement forced channel remapping gcc fix --- rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp | 58 ++++++++++++++++++---------- rpcs3/Emu/RSX/GL/GLTexture.cpp | 40 +++++++++++++++---- rpcs3/Emu/RSX/RSXTexture.cpp | 26 +++++++++++++ rpcs3/Emu/RSX/RSXTexture.h | 8 ++++ rpcs3/Emu/RSX/VK/VKFormats.cpp | 9 +---- rpcs3/Emu/RSX/VK/VKFormats.h | 2 +- rpcs3/Emu/RSX/VK/VKTextureCache.h | 30 +++++++++++++- rpcs3/Emu/RSX/gcm_enums.h | 9 +++++ 8 files changed, 144 insertions(+), 38 deletions(-) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp index fe7fa63dd6..a31cf85bc8 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp @@ -279,6 +279,9 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz D3D12_SHADER_RESOURCE_VIEW_DESC shared_resource_view_desc = get_srv_descriptor_with_dimensions(rsx::method_registers.fragment_textures[i]); shared_resource_view_desc.Format = get_texture_format(format); + bool requires_remap = false; + std::array channel_mapping = {}; + switch (format) { default: @@ -333,11 +336,8 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2 }; - shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( - RemapValue[remap_r], - RemapValue[remap_g], - RemapValue[remap_b], - RemapValue[remap_a]); + channel_mapping = { RemapValue[remap_r], RemapValue[remap_g], RemapValue[remap_b], RemapValue[remap_a] }; + requires_remap = true; } else { @@ -351,11 +351,8 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1 }; - shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( - RemapValue[remap_r], - RemapValue[remap_g], - RemapValue[remap_b], - RemapValue[remap_a]); + channel_mapping = { RemapValue[remap_r], RemapValue[remap_g], RemapValue[remap_b], RemapValue[remap_a] }; + requires_remap = true; } break; @@ -423,11 +420,8 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2 }; - shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( - RemapValue[remap_r], - RemapValue[remap_g], - RemapValue[remap_b], - RemapValue[remap_a]); + channel_mapping = { RemapValue[remap_r], RemapValue[remap_g], RemapValue[remap_b], RemapValue[remap_a] }; + requires_remap = true; } else if (is_depth_stencil_texture) { @@ -450,17 +444,41 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3 }; - shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( - RemapValue[remap_r], - RemapValue[remap_g], - RemapValue[remap_b], - RemapValue[remap_a]); + channel_mapping = { RemapValue[remap_r], RemapValue[remap_g], RemapValue[remap_b], RemapValue[remap_a] }; + requires_remap = true; } break; } } + if (requires_remap) + { + auto decoded_remap = rsx::method_registers.fragment_textures[i].decoded_remap(); + u8 remapped_inputs[] = { decoded_remap.second[1], decoded_remap.second[2], decoded_remap.second[3], decoded_remap.second[0] }; + + for (u8 channel = 0; channel < 4; channel++) + { + switch (remapped_inputs[channel]) + { + default: + case CELL_GCM_TEXTURE_REMAP_REMAP: + break; + case CELL_GCM_TEXTURE_REMAP_ONE: + channel_mapping[channel] = D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1; + break; + case CELL_GCM_TEXTURE_REMAP_ZERO: + channel_mapping[channel] = D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0; + } + } + + shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( + channel_mapping[0], + channel_mapping[1], + channel_mapping[2], + channel_mapping[3]); + } + m_device->CreateShaderResourceView(vram_texture, &shared_resource_view_desc, CD3DX12_CPU_DESCRIPTOR_HANDLE(m_current_texture_descriptors->GetCPUDescriptorHandleForHeapStart()) .Offset((UINT)i, m_descriptor_stride_srv_cbv_uav) diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index 5b5e953ad3..809c9dd3e7 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -493,15 +493,39 @@ namespace rsx glTexParameteri(m_target, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, tex.get_exact_mipmap_count() - 1); - 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; + auto decoded_remap = tex.decoded_remap(); - __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]); + //Remapping tables; format is A-R-G-B + //Remap input table. Contains channel index to read color from + const auto remap_inputs = decoded_remap.first; + + //Remap control table. Controls whether the remap value is used, or force either 0 or 1 + const auto remap_lookup = decoded_remap.second; + + GLenum remap_values[4]; + + for (u8 channel = 0; channel < 4; ++channel) + { + switch (remap_lookup[channel]) + { + default: + LOG_ERROR(RSX, "Unknown remap function 0x%X", remap_lookup[channel]); + case CELL_GCM_TEXTURE_REMAP_REMAP: + remap_values[channel] = glRemap[remap_inputs[channel]]; + break; + case CELL_GCM_TEXTURE_REMAP_ZERO: + remap_values[channel] = GL_ZERO; + break; + case CELL_GCM_TEXTURE_REMAP_ONE: + remap_values[channel] = GL_ONE; + break; + } + } + + __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, remap_values[0]); + __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, remap_values[1]); + __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, remap_values[2]); + __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, remap_values[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())); diff --git a/rpcs3/Emu/RSX/RSXTexture.cpp b/rpcs3/Emu/RSX/RSXTexture.cpp index 0643bd82d9..f871ef9da3 100644 --- a/rpcs3/Emu/RSX/RSXTexture.cpp +++ b/rpcs3/Emu/RSX/RSXTexture.cpp @@ -178,6 +178,32 @@ namespace rsx return (registers[NV4097_SET_TEXTURE_CONTROL1 + (m_index * 8)]); } + std::pair, std::array> fragment_texture::decoded_remap() const + { + const u32 remap_ctl = registers[NV4097_SET_TEXTURE_CONTROL1 + (m_index * 8)]; + + //Remapping tables; format is A-R-G-B + //Remap input table. Contains channel index to read color from + const std::array remap_inputs = + { + static_cast(remap_ctl & 0x3), + static_cast((remap_ctl >> 2) & 0x3), + static_cast((remap_ctl >> 4) & 0x3), + static_cast((remap_ctl >> 6) & 0x3), + }; + + //Remap control table. Controls whether the remap value is used, or force either 0 or 1 + const std::array remap_lookup = + { + static_cast((remap_ctl >> 8) & 0x3), + static_cast((remap_ctl >> 10) & 0x3), + static_cast((remap_ctl >> 12) & 0x3), + static_cast((remap_ctl >> 14) & 0x3), + }; + + return std::make_pair(remap_inputs, remap_lookup); + } + float fragment_texture::bias() const { return float(f16((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff)); diff --git a/rpcs3/Emu/RSX/RSXTexture.h b/rpcs3/Emu/RSX/RSXTexture.h index 3b8bcbb5c0..ac9f12b6ed 100644 --- a/rpcs3/Emu/RSX/RSXTexture.h +++ b/rpcs3/Emu/RSX/RSXTexture.h @@ -70,6 +70,14 @@ namespace rsx // Control1 u32 remap() const; + /** + * returns a pair of arrays + * First array is a redirection table into the channel indices + * Second array is a lookup reference deciding whether to use the redirection table or use constants 0 and 1 + * Both arrays have components in A-R-G-B format + */ + std::pair, std::array> decoded_remap() const; + // Filter float bias() const; rsx::texture_minify_filter min_filter() const; diff --git a/rpcs3/Emu/RSX/VK/VKFormats.cpp b/rpcs3/Emu/RSX/VK/VKFormats.cpp index 6163b89647..86f5f44d97 100644 --- a/rpcs3/Emu/RSX/VK/VKFormats.cpp +++ b/rpcs3/Emu/RSX/VK/VKFormats.cpp @@ -109,13 +109,8 @@ float max_aniso(rsx::texture_max_anisotropy gcm_aniso) } -VkComponentMapping get_component_mapping(u32 format, u8 swizzle_mask) +std::array get_component_mapping(u32 format) { - const u8 remap_a = swizzle_mask & 0x3; - const u8 remap_r = (swizzle_mask >> 2) & 0x3; - const u8 remap_g = (swizzle_mask >> 4) & 0x3; - const u8 remap_b = (swizzle_mask >> 6) & 0x3; - //Component map in ARGB format std::array mapping = {}; @@ -174,7 +169,7 @@ VkComponentMapping get_component_mapping(u32 format, u8 swizzle_mask) fmt::throw_exception("Invalid or unsupported component mapping for texture format (0x%x)" HERE, format); } - return {mapping[remap_r], mapping[remap_g], mapping[remap_b], mapping[remap_a]}; + return mapping; } } diff --git a/rpcs3/Emu/RSX/VK/VKFormats.h b/rpcs3/Emu/RSX/VK/VKFormats.h index 95197228c9..63bad8a610 100644 --- a/rpcs3/Emu/RSX/VK/VKFormats.h +++ b/rpcs3/Emu/RSX/VK/VKFormats.h @@ -22,6 +22,6 @@ namespace vk VkFilter get_mag_filter(rsx::texture_magnify_filter mag_filter); VkSamplerAddressMode vk_wrap_mode(rsx::texture_wrap_mode gcm_wrap); float max_aniso(rsx::texture_max_anisotropy gcm_aniso); - VkComponentMapping get_component_mapping(u32 format, u8 swizzle_mask); + std::array get_component_mapping(u32 format); VkPrimitiveTopology get_appropriate_topology(rsx::primitive_type& mode, bool &requires_modification); } diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index dda52c0416..30595a1eaa 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -143,12 +143,38 @@ namespace vk //Helpers VkComponentMapping get_component_map(rsx::fragment_texture &tex, u32 gcm_format) { - return vk::get_component_mapping(gcm_format, tex.remap()); + //Decoded remap returns 2 arrays; a redirection table and a lookup reference + auto decoded_remap = tex.decoded_remap(); + + //NOTE: Returns mapping in A-R-G-B + auto native_mapping = vk::get_component_mapping(gcm_format); + VkComponentSwizzle final_mapping[4] = {}; + + for (u8 channel = 0; channel < 4; ++channel) + { + switch (decoded_remap.second[channel]) + { + case CELL_GCM_TEXTURE_REMAP_ONE: + final_mapping[channel] = VK_COMPONENT_SWIZZLE_ONE; + break; + case CELL_GCM_TEXTURE_REMAP_ZERO: + final_mapping[channel] = VK_COMPONENT_SWIZZLE_ZERO; + break; + default: + LOG_ERROR(RSX, "Unknown remap lookup value %d", decoded_remap.second[channel]); + case CELL_GCM_TEXTURE_REMAP_REMAP: + final_mapping[channel] = native_mapping[decoded_remap.first[channel]]; + break; + } + } + + return { final_mapping[1], final_mapping[2], final_mapping[3], final_mapping[0] }; } 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)); + auto mapping = vk::get_component_mapping(gcm_format); + return { mapping[1], mapping[2], mapping[3], mapping[0] }; } public: diff --git a/rpcs3/Emu/RSX/gcm_enums.h b/rpcs3/Emu/RSX/gcm_enums.h index 27a43de158..6ef375d466 100644 --- a/rpcs3/Emu/RSX/gcm_enums.h +++ b/rpcs3/Emu/RSX/gcm_enums.h @@ -490,6 +490,15 @@ enum CELL_GCM_TEXTURE_SIGNED_REMAP_NORMAL = 0x0, CELL_GCM_TEXTURE_SIGNED_REMAP_CLAMPED = 0x3, + CELL_GCM_TEXTURE_REMAP_FROM_A = 0, + CELL_GCM_TEXTURE_REMAP_FROM_R = 1, + CELL_GCM_TEXTURE_REMAP_FROM_G = 2, + CELL_GCM_TEXTURE_REMAP_FROM_B = 3, + + CELL_GCM_TEXTURE_REMAP_ZERO = 0, + CELL_GCM_TEXTURE_REMAP_ONE = 1, + CELL_GCM_TEXTURE_REMAP_REMAP = 2, + CELL_GCM_TEXTURE_ZFUNC_NEVER = 0, CELL_GCM_TEXTURE_ZFUNC_LESS = 1, CELL_GCM_TEXTURE_ZFUNC_EQUAL = 2,