mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-23 11:13:19 +01:00
Merge pull request #2477 from kd-11/master
gl/vk/dx12: Implement forced channel remapping
This commit is contained in:
commit
039e295e53
@ -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]);
|
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);
|
shared_resource_view_desc.Format = get_texture_format(format);
|
||||||
|
|
||||||
|
bool requires_remap = false;
|
||||||
|
std::array<INT, 4> channel_mapping = {};
|
||||||
|
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
@ -333,11 +336,8 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
|
|||||||
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2
|
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2
|
||||||
};
|
};
|
||||||
|
|
||||||
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
|
channel_mapping = { RemapValue[remap_r], RemapValue[remap_g], RemapValue[remap_b], RemapValue[remap_a] };
|
||||||
RemapValue[remap_r],
|
requires_remap = true;
|
||||||
RemapValue[remap_g],
|
|
||||||
RemapValue[remap_b],
|
|
||||||
RemapValue[remap_a]);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -351,11 +351,8 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
|
|||||||
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1
|
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1
|
||||||
};
|
};
|
||||||
|
|
||||||
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
|
channel_mapping = { RemapValue[remap_r], RemapValue[remap_g], RemapValue[remap_b], RemapValue[remap_a] };
|
||||||
RemapValue[remap_r],
|
requires_remap = true;
|
||||||
RemapValue[remap_g],
|
|
||||||
RemapValue[remap_b],
|
|
||||||
RemapValue[remap_a]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -423,11 +420,8 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
|
|||||||
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2
|
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2
|
||||||
};
|
};
|
||||||
|
|
||||||
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
|
channel_mapping = { RemapValue[remap_r], RemapValue[remap_g], RemapValue[remap_b], RemapValue[remap_a] };
|
||||||
RemapValue[remap_r],
|
requires_remap = true;
|
||||||
RemapValue[remap_g],
|
|
||||||
RemapValue[remap_b],
|
|
||||||
RemapValue[remap_a]);
|
|
||||||
}
|
}
|
||||||
else if (is_depth_stencil_texture)
|
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
|
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3
|
||||||
};
|
};
|
||||||
|
|
||||||
shared_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
|
channel_mapping = { RemapValue[remap_r], RemapValue[remap_g], RemapValue[remap_b], RemapValue[remap_a] };
|
||||||
RemapValue[remap_r],
|
requires_remap = true;
|
||||||
RemapValue[remap_g],
|
|
||||||
RemapValue[remap_b],
|
|
||||||
RemapValue[remap_a]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
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,
|
m_device->CreateShaderResourceView(vram_texture, &shared_resource_view_desc,
|
||||||
CD3DX12_CPU_DESCRIPTOR_HANDLE(m_current_texture_descriptors->GetCPUDescriptorHandleForHeapStart())
|
CD3DX12_CPU_DESCRIPTOR_HANDLE(m_current_texture_descriptors->GetCPUDescriptorHandleForHeapStart())
|
||||||
.Offset((UINT)i, m_descriptor_stride_srv_cbv_uav)
|
.Offset((UINT)i, m_descriptor_stride_srv_cbv_uav)
|
||||||
|
@ -493,15 +493,39 @@ namespace rsx
|
|||||||
glTexParameteri(m_target, GL_TEXTURE_BASE_LEVEL, 0);
|
glTexParameteri(m_target, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, tex.get_exact_mipmap_count() - 1);
|
glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, tex.get_exact_mipmap_count() - 1);
|
||||||
|
|
||||||
u8 remap_a = tex.remap() & 0x3;
|
auto decoded_remap = tex.decoded_remap();
|
||||||
u8 remap_r = (tex.remap() >> 2) & 0x3;
|
|
||||||
u8 remap_g = (tex.remap() >> 4) & 0x3;
|
|
||||||
u8 remap_b = (tex.remap() >> 6) & 0x3;
|
|
||||||
|
|
||||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]);
|
//Remapping tables; format is A-R-G-B
|
||||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]);
|
//Remap input table. Contains channel index to read color from
|
||||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]);
|
const auto remap_inputs = decoded_remap.first;
|
||||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]);
|
|
||||||
|
//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_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_T, gl_wrap(tex.wrap_t()));
|
||||||
|
@ -178,6 +178,32 @@ namespace rsx
|
|||||||
return (registers[NV4097_SET_TEXTURE_CONTROL1 + (m_index * 8)]);
|
return (registers[NV4097_SET_TEXTURE_CONTROL1 + (m_index * 8)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<std::array<u8, 4>, std::array<u8, 4>> 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<u8, 4> remap_inputs =
|
||||||
|
{
|
||||||
|
static_cast<u8>(remap_ctl & 0x3),
|
||||||
|
static_cast<u8>((remap_ctl >> 2) & 0x3),
|
||||||
|
static_cast<u8>((remap_ctl >> 4) & 0x3),
|
||||||
|
static_cast<u8>((remap_ctl >> 6) & 0x3),
|
||||||
|
};
|
||||||
|
|
||||||
|
//Remap control table. Controls whether the remap value is used, or force either 0 or 1
|
||||||
|
const std::array<u8, 4> remap_lookup =
|
||||||
|
{
|
||||||
|
static_cast<u8>((remap_ctl >> 8) & 0x3),
|
||||||
|
static_cast<u8>((remap_ctl >> 10) & 0x3),
|
||||||
|
static_cast<u8>((remap_ctl >> 12) & 0x3),
|
||||||
|
static_cast<u8>((remap_ctl >> 14) & 0x3),
|
||||||
|
};
|
||||||
|
|
||||||
|
return std::make_pair(remap_inputs, remap_lookup);
|
||||||
|
}
|
||||||
|
|
||||||
float fragment_texture::bias() const
|
float fragment_texture::bias() const
|
||||||
{
|
{
|
||||||
return float(f16((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff));
|
return float(f16((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff));
|
||||||
|
@ -70,6 +70,14 @@ namespace rsx
|
|||||||
// Control1
|
// Control1
|
||||||
u32 remap() const;
|
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<u8, 4>, std::array<u8, 4>> decoded_remap() const;
|
||||||
|
|
||||||
// Filter
|
// Filter
|
||||||
float bias() const;
|
float bias() const;
|
||||||
rsx::texture_minify_filter min_filter() const;
|
rsx::texture_minify_filter min_filter() const;
|
||||||
|
@ -109,13 +109,8 @@ float max_aniso(rsx::texture_max_anisotropy gcm_aniso)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkComponentMapping get_component_mapping(u32 format, u8 swizzle_mask)
|
std::array<VkComponentSwizzle, 4> 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
|
//Component map in ARGB format
|
||||||
std::array<VkComponentSwizzle, 4> mapping = {};
|
std::array<VkComponentSwizzle, 4> mapping = {};
|
||||||
|
|
||||||
@ -156,6 +151,8 @@ VkComponentMapping get_component_mapping(u32 format, u8 swizzle_mask)
|
|||||||
mapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G }; break;
|
mapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G }; break;
|
||||||
|
|
||||||
case CELL_GCM_TEXTURE_D8R8G8B8:
|
case CELL_GCM_TEXTURE_D8R8G8B8:
|
||||||
|
mapping = { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A }; break;
|
||||||
|
|
||||||
case CELL_GCM_TEXTURE_D1R5G5B5:
|
case CELL_GCM_TEXTURE_D1R5G5B5:
|
||||||
mapping = { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B }; break;
|
mapping = { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B }; break;
|
||||||
|
|
||||||
@ -174,7 +171,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);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,6 @@ namespace vk
|
|||||||
VkFilter get_mag_filter(rsx::texture_magnify_filter mag_filter);
|
VkFilter get_mag_filter(rsx::texture_magnify_filter mag_filter);
|
||||||
VkSamplerAddressMode vk_wrap_mode(rsx::texture_wrap_mode gcm_wrap);
|
VkSamplerAddressMode vk_wrap_mode(rsx::texture_wrap_mode gcm_wrap);
|
||||||
float max_aniso(rsx::texture_max_anisotropy gcm_aniso);
|
float max_aniso(rsx::texture_max_anisotropy gcm_aniso);
|
||||||
VkComponentMapping get_component_mapping(u32 format, u8 swizzle_mask);
|
std::array<VkComponentSwizzle, 4> get_component_mapping(u32 format);
|
||||||
VkPrimitiveTopology get_appropriate_topology(rsx::primitive_type& mode, bool &requires_modification);
|
VkPrimitiveTopology get_appropriate_topology(rsx::primitive_type& mode, bool &requires_modification);
|
||||||
}
|
}
|
||||||
|
@ -143,12 +143,38 @@ namespace vk
|
|||||||
//Helpers
|
//Helpers
|
||||||
VkComponentMapping get_component_map(rsx::fragment_texture &tex, u32 gcm_format)
|
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)
|
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:
|
public:
|
||||||
|
@ -490,6 +490,15 @@ enum
|
|||||||
CELL_GCM_TEXTURE_SIGNED_REMAP_NORMAL = 0x0,
|
CELL_GCM_TEXTURE_SIGNED_REMAP_NORMAL = 0x0,
|
||||||
CELL_GCM_TEXTURE_SIGNED_REMAP_CLAMPED = 0x3,
|
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_NEVER = 0,
|
||||||
CELL_GCM_TEXTURE_ZFUNC_LESS = 1,
|
CELL_GCM_TEXTURE_ZFUNC_LESS = 1,
|
||||||
CELL_GCM_TEXTURE_ZFUNC_EQUAL = 2,
|
CELL_GCM_TEXTURE_ZFUNC_EQUAL = 2,
|
||||||
|
Loading…
Reference in New Issue
Block a user