vk/dx12: Enable/fix separate back and front lighting (#1927)

* vk: separate specular color

rsx: separate front color output from back color output

re-enable front-back diffuse lighting

vk: fix front face selection and actually enable face culling

* dx12: Hide constant-key blended visuals (by common use of factor, 1-factor)

* dx12: Fix 2 sided lighting when the shader does not compute both outputs

* vk/dx12: confirm that src register exists before copying for 2-sided lighting
This commit is contained in:
kd-11 2016-07-17 19:57:50 +03:00 committed by raven02
parent b2a7dac11b
commit 2337bf204c
9 changed files with 177 additions and 40 deletions

View File

@ -41,14 +41,14 @@ D3D12_BLEND get_blend_factor(rsx::blend_factor factor)
case rsx::blend_factor::constant_color:
case rsx::blend_factor::constant_alpha:
{
LOG_ERROR(RSX, "Constant blend factor not supported. Using ONE instead");
return D3D12_BLEND_ONE;
LOG_ERROR(RSX, "Constant blend factor not supported. Using ZERO instead");
return D3D12_BLEND_ZERO;
}
case rsx::blend_factor::one_minus_constant_color:
case rsx::blend_factor::one_minus_constant_alpha:
{
LOG_ERROR(RSX, "Inv Constant blend factor not supported. Using ZERO instead");
return D3D12_BLEND_ZERO;
LOG_ERROR(RSX, "Inv Constant blend factor not supported. Using ONE instead");
return D3D12_BLEND_ONE;
}
}
throw EXCEPTION("Invalid blend factor (0x%x)", factor);

View File

@ -210,12 +210,37 @@ void D3D12VertexProgramDecompiler::insertMainStart(std::stringstream & OS)
void D3D12VertexProgramDecompiler::insertMainEnd(std::stringstream & OS)
{
OS << " PixelInput Out = (PixelInput)0;" << std::endl;
bool insert_front_diffuse = (rsx_vertex_program.output_mask & 1);
bool insert_front_specular = (rsx_vertex_program.output_mask & 2);
bool insert_back_diffuse = (rsx_vertex_program.output_mask & 4);
bool insert_back_specular = (rsx_vertex_program.output_mask & 8);
// Declare inside main function
for (auto &i : reg_table)
{
if (m_parr.HasParam(PF_PARAM_NONE, "float4", i.src_reg))
{
if (i.name == "front_diff_color")
insert_front_diffuse = false;
if (i.name == "front_spec_color")
insert_front_specular = false;
OS << " Out." << i.src_reg << " = " << i.src_reg << ";" << std::endl;
}
}
//If 2 sided lighting is active and only back is written, copy the value to the front side (Outrun online arcade)
if (insert_front_diffuse && insert_back_diffuse)
if (m_parr.HasParam(PF_PARAM_NONE, "float4", "dst_reg1"))
OS << " Out.dst_reg3 = dst_reg1;\n";
if (insert_front_specular && insert_back_specular)
if (m_parr.HasParam(PF_PARAM_NONE, "float4", "dst_reg2"))
OS << " Out.dst_reg4 = dst_reg2;\n";
OS << " Out.dst_reg0 = mul(Out.dst_reg0, scaleOffsetMat);" << std::endl;
OS << " return Out;" << std::endl;
OS << "}" << std::endl;

View File

@ -225,6 +225,8 @@ struct RSXFragmentProgram
bool front_back_color_enabled : 1;
bool back_color_diffuse_output : 1;
bool back_color_specular_output : 1;
bool front_color_diffuse_output : 1;
bool front_color_specular_output : 1;
u32 texture_dimensions;
rsx::window_origin origin_mode;
rsx::window_pixel_center pixel_center_mode;

View File

@ -738,6 +738,8 @@ namespace rsx
result.front_back_color_enabled = !rsx::method_registers.two_side_light_en();
result.back_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE);
result.back_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
result.front_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE);
result.front_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR);
result.alpha_func = rsx::method_registers.alpha_func();
result.fog_equation = rsx::method_registers.fog_equation();
result.origin_mode = rsx::method_registers.shader_window_origin();

View File

@ -231,20 +231,22 @@ namespace vk
static const varying_register_t varying_regs[] =
{
{ "diff_color", 0 },
{ "tc0", 1 },
{ "tc1", 2 },
{ "tc2", 3 },
{ "tc3", 4 },
{ "tc4", 5 },
{ "tc5", 6 },
{ "tc6", 7 },
{ "tc7", 8 },
{ "tc8", 9 },
{ "tc9", 10 },
{ "tc0", 0 },
{ "tc1", 1 },
{ "tc2", 2 },
{ "tc3", 3 },
{ "tc4", 4 },
{ "tc5", 5 },
{ "tc6", 6 },
{ "tc7", 7 },
{ "tc8", 8 },
{ "tc9", 9 },
{ "diff_color", 10 },
{ "back_diff_color", 10 },
{ "front_diff_color", 11 },
{ "front_spec_color", 12 },
{ "spec_color", 13 },
{ "spec_color", 12 },
{ "back_spec_color", 12 },
{ "front_spec_color", 13 },
{ "fog_c", 14 },
{ "fogc", 14 }
};

View File

@ -60,14 +60,38 @@ void VKFragmentDecompilerThread::insertIntputs(std::stringstream & OS)
if (PI.name == "ssa") continue;
const vk::varying_register_t &reg = vk::get_varying_register(PI.name);
std::string var_name = PI.name;
if (m_prog.front_back_color_enabled)
{
if (m_prog.back_color_diffuse_output && var_name == "diff_color")
var_name = "back_diff_color";
if (m_prog.back_color_specular_output && var_name == "spec_color")
var_name = "back_spec_color";
}
if (var_name == "fogc")
var_name = "fog_c";
OS << "layout(location=" << reg.reg_location << ") in " << PT.type << " " << var_name << ";" << std::endl;
}
}
if (m_prog.front_back_color_enabled)
{
if (m_prog.front_color_diffuse_output)
{
const vk::varying_register_t &reg = vk::get_varying_register("front_diff_color");
OS << "layout(location=" << reg.reg_location << ") in vec4 front_diff_color;" << std::endl;
}
if (m_prog.front_color_specular_output)
{
const vk::varying_register_t &reg = vk::get_varying_register("front_spec_color");
OS << "layout(location=" << reg.reg_location << ") in vec4 front_spec_color;" << std::endl;
}
}
}
void VKFragmentDecompilerThread::insertOutputs(std::stringstream & OS)
@ -202,6 +226,47 @@ void VKFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
{
for (const ParamItem& PI : PT.items)
{
if (m_prog.front_back_color_enabled)
{
if (PI.name == "spec_color")
{
if (m_prog.back_color_specular_output || m_prog.front_color_specular_output)
{
if (m_prog.back_color_specular_output && m_prog.front_color_specular_output)
{
OS << " vec4 spec_color = gl_FrontFacing ? front_spec_color : back_spec_color;\n";
}
else if (m_prog.back_color_specular_output)
{
OS << " vec4 spec_color = back_spec_color;\n";
}
else
OS << " vec4 spec_color = front_spec_color;\n";
}
continue;
}
else if (PI.name == "diff_color")
{
if (m_prog.back_color_diffuse_output || m_prog.front_color_diffuse_output)
{
if (m_prog.back_color_diffuse_output && m_prog.front_color_diffuse_output)
{
OS << " vec4 diff_color = gl_FrontFacing ? front_diff_color : back_diff_color;\n";
}
else if (m_prog.back_color_diffuse_output)
{
OS << " vec4 diff_color = back_diff_color;\n";
}
else
OS << " vec4 diff_color = front_diff_color;\n";
}
continue;
}
}
if (PI.name == "fogc")
{
vk::insert_fog_declaration(OS, m_prog.fog_equation);

View File

@ -262,12 +262,17 @@ namespace vk
}
}
VkFrontFace get_front_face_ccw(rsx::front_face ffv)
VkFrontFace get_front_face(rsx::front_face ffv)
{
u32 mask = 1;
if (rsx::to_window_origin((rsx::method_registers[NV4097_SET_SHADER_WINDOW] >> 12) & 0xf) == rsx::window_origin::bottom)
mask = 0;
switch (ffv)
{
case rsx::front_face::cw: return VK_FRONT_FACE_CLOCKWISE;
case rsx::front_face::ccw: return VK_FRONT_FACE_COUNTER_CLOCKWISE;
case rsx::front_face::cw: return (VkFrontFace)(VK_FRONT_FACE_CLOCKWISE ^ mask);
case rsx::front_face::ccw: return (VkFrontFace)(VK_FRONT_FACE_COUNTER_CLOCKWISE ^ mask);
default:
throw EXCEPTION("Unknown front face value: 0x%X", ffv);
}
@ -307,6 +312,7 @@ namespace
color_attachement_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
color_attachement_description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
color_attachement_description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
for (u32 i = 0; i < number_of_color_surface; ++i)
{
attachments.push_back(color_attachement_description);
@ -867,7 +873,6 @@ bool VKGSRender::load_program()
vk::pipeline_props properties = {};
properties.ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
bool unused;
properties.ia.topology = vk::get_appropriate_topology(draw_mode, unused);
@ -986,6 +991,12 @@ bool VKGSRender::load_program()
else
properties.ds.depthTestEnable = VK_FALSE;
properties.rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
properties.rs.polygonMode = VK_POLYGON_MODE_FILL;
properties.rs.depthClampEnable = VK_FALSE;
properties.rs.rasterizerDiscardEnable = VK_FALSE;
properties.rs.depthBiasEnable = VK_FALSE;
if (rsx::method_registers.cull_face_enabled())
{
switch (rsx::method_registers.cull_face_mode())
@ -1007,12 +1018,13 @@ bool VKGSRender::load_program()
else
properties.rs.cullMode = VK_CULL_MODE_NONE;
properties.rs.frontFace = vk::get_front_face_ccw(rsx::method_registers.front_face_mode());
properties.rs.frontFace = vk::get_front_face(rsx::method_registers.front_face_mode());
size_t idx = vk::get_render_pass_location(
vk::get_compatible_surface_format(rsx::method_registers.surface_color()).first,
vk::get_compatible_depth_surface_format(m_optimal_tiling_supported_formats, rsx::method_registers.surface_depth_fmt()),
(u8)vk::get_draw_buffers(rsx::method_registers.surface_color_target()).size());
properties.render_pass = m_render_passes[idx];
properties.num_targets = m_draw_buffers_count;

View File

@ -29,6 +29,7 @@ namespace vk
return false;
if (memcmp(&rs, &other.rs, sizeof(VkPipelineRasterizationStateCreateInfo)))
return false;
return num_targets == other.num_targets;
}
};
@ -55,6 +56,7 @@ namespace std
size_t seed = hash<unsigned>()(pipelineProperties.num_targets);
seed ^= hash_struct(pipelineProperties.ia);
seed ^= hash_struct(pipelineProperties.ds);
seed ^= hash_struct(pipelineProperties.rs);
seed ^= hash_struct(pipelineProperties.att_state[0]);
return hash<size_t>()(seed);
}
@ -125,21 +127,12 @@ struct VKTraits
cb.attachmentCount = 1;
cb.pAttachments = pipelineProperties.att_state;
VkPipelineRasterizationStateCreateInfo rs = {};
rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rs.polygonMode = VK_POLYGON_MODE_FILL;
rs.cullMode = VK_CULL_MODE_NONE;
rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rs.depthClampEnable = VK_FALSE;
rs.rasterizerDiscardEnable = VK_FALSE;
rs.depthBiasEnable = VK_FALSE;
VkPipeline pipeline;
VkGraphicsPipelineCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
info.pVertexInputState = &vi;
info.pInputAssemblyState = &pipelineProperties.ia;
info.pRasterizationState = &rs;
info.pRasterizationState = &pipelineProperties.rs;
info.pColorBlendState = &cb;
info.pMultisampleState = &ms;
info.pViewportState = &vp;

View File

@ -129,8 +129,8 @@ struct reg_info
static const reg_info reg_table[] =
{
{ "gl_Position", false, "dst_reg0", "", false },
{ "diff_color", true, "dst_reg1", "", false },
{ "spec_color", true, "dst_reg2", "", false },
{ "back_diff_color", true, "dst_reg1", "", false },
{ "back_spec_color", true, "dst_reg2", "", false },
{ "front_diff_color", true, "dst_reg3", "", false },
{ "front_spec_color", true, "dst_reg4", "", false },
{ "fog_c", true, "dst_reg5", ".xxxx", true },
@ -159,18 +159,32 @@ static const reg_info reg_table[] =
void VKVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std::vector<ParamType> & outputs)
{
bool insert_front_diffuse = (rsx_vertex_program.output_mask & 1);
bool insert_back_diffuse = (rsx_vertex_program.output_mask & 4);
bool insert_front_specular = (rsx_vertex_program.output_mask & 2);
bool insert_back_specular = (rsx_vertex_program.output_mask & 8);
for (auto &i : reg_table)
{
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", i.src_reg) && i.need_declare)
{
if (i.name == "front_diff_color")
insert_front_diffuse = false;
if (i.name == "front_spec_color")
insert_front_specular = false;
const vk::varying_register_t &reg = vk::get_varying_register(i.name);
// if (i.name == "fogc")
// OS << "layout(location=" << reg.reg_location << ") out vec4 fog_c;" << std::endl;
// else
OS << "layout(location=" << reg.reg_location << ") out vec4 " << i.name << ";" << std::endl;
OS << "layout(location=" << reg.reg_location << ") out vec4 " << i.name << ";" << std::endl;
}
}
if (insert_back_diffuse && insert_front_diffuse)
OS << "layout(location=" << vk::get_varying_register("front_diff_color").reg_location << ") out vec4 front_diff_color;" << std::endl;
if (insert_back_specular && insert_front_specular)
OS << "layout(location=" << vk::get_varying_register("front_spec_color").reg_location << ") out vec4 front_spec_color;" << std::endl;
}
namespace vk
@ -240,12 +254,34 @@ void VKVertexDecompilerThread::insertMainStart(std::stringstream & OS)
void VKVertexDecompilerThread::insertMainEnd(std::stringstream & OS)
{
bool insert_front_diffuse = (rsx_vertex_program.output_mask & 1);
bool insert_front_specular = (rsx_vertex_program.output_mask & 2);
bool insert_back_diffuse = (rsx_vertex_program.output_mask & 4);
bool insert_back_specular = (rsx_vertex_program.output_mask & 8);
for (auto &i : reg_table)
{
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", i.src_reg))
{
if (i.name == "front_spec_color")
insert_front_diffuse = false;
if (i.name == "front_spec_color")
insert_front_specular = false;
OS << " " << i.name << " = " << i.src_reg << i.src_reg_mask << ";" << std::endl;
}
}
if (insert_back_diffuse && insert_front_diffuse)
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", "dst_reg1"))
OS << " front_diff_color = dst_reg1;\n";
if (insert_back_specular && insert_front_specular)
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", "dst_reg2"))
OS << " front_spec_color = dst_reg2;\n";
OS << " gl_Position = gl_Position * scaleOffsetMat;" << std::endl;
OS << "}" << std::endl;
}