Merge pull request #2477 from kd-11/master

gl/vk/dx12: Implement forced channel remapping
This commit is contained in:
kd-11 2017-03-06 20:13:54 +03:00 committed by GitHub
commit 039e295e53
8 changed files with 146 additions and 38 deletions

View File

@ -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<INT, 4> 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)

View File

@ -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()));

View File

@ -178,6 +178,32 @@ namespace rsx
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
{
return float(f16((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff));

View File

@ -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<u8, 4>, std::array<u8, 4>> decoded_remap() const;
// Filter
float bias() const;
rsx::texture_minify_filter min_filter() const;

View File

@ -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
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;
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:
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);
}
return {mapping[remap_r], mapping[remap_g], mapping[remap_b], mapping[remap_a]};
return mapping;
}
}

View File

@ -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<VkComponentSwizzle, 4> get_component_mapping(u32 format);
VkPrimitiveTopology get_appropriate_topology(rsx::primitive_type& mode, bool &requires_modification);
}

View File

@ -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:

View File

@ -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,