[Render] Userclip for d12/vk/ogl (#2719)

This commit is contained in:
Jake 2017-04-25 05:32:39 -05:00 committed by raven02
parent 8b2473251d
commit 60ce85f840
9 changed files with 126 additions and 111 deletions

View File

@ -54,8 +54,8 @@ namespace
{
u32 element_size = rsx::get_vertex_type_size_on_host(info.type(), info.size());
D3D12_SHADER_RESOURCE_VIEW_DESC vertex_buffer_view = {
get_vertex_attribute_format(info.type(), info.size()), D3D12_SRV_DIMENSION_BUFFER,
get_component_mapping_from_vector_size(info.type(), info.size())};
get_vertex_attribute_format(info.type(), info.size()), D3D12_SRV_DIMENSION_BUFFER,
get_component_mapping_from_vector_size(info.type(), info.size())};
vertex_buffer_view.Buffer.FirstElement = offset_in_vertex_buffers_buffer / element_size;
vertex_buffer_view.Buffer.NumElements = buffer_size / element_size;
return vertex_buffer_view;
@ -65,7 +65,7 @@ namespace
{
u32 element_size = rsx::get_vertex_type_size_on_host(type, size);
D3D12_SHADER_RESOURCE_VIEW_DESC vertex_buffer_view = {get_vertex_attribute_format(type, size),
D3D12_SRV_DIMENSION_BUFFER, get_component_mapping_from_vector_size(type, size)};
D3D12_SRV_DIMENSION_BUFFER, get_component_mapping_from_vector_size(type, size)};
vertex_buffer_view.Buffer.FirstElement = offset_in_vertex_buffers_buffer / element_size;
vertex_buffer_view.Buffer.NumElements = buffer_size / element_size;
return vertex_buffer_view;
@ -87,8 +87,10 @@ void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex)
// Scale offset buffer
// Separate constant buffer
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + 512));
fill_scale_offset_data(mapped_buffer);
fill_fragment_state_buffer((char *)mapped_buffer + 64, m_fragment_program);
fill_scale_offset_data(mapped_buffer, true, false);
fill_user_clip_data((char*)mapped_buffer + 64);
fill_fragment_state_buffer((char *)mapped_buffer + 96, m_fragment_program);
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + 512));
D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = {

View File

@ -38,6 +38,7 @@ void D3D12FragmentDecompiler::insertHeader(std::stringstream & OS)
OS << "cbuffer SCALE_OFFSET : register(b0)" << std::endl;
OS << "{" << std::endl;
OS << " float4x4 scaleOffsetMat;" << std::endl;
OS << " int userClip[8];" << std::endl;
OS << " float fog_param0;\n";
OS << " float fog_param1;\n";
OS << " int isAlphaTested;" << std::endl;
@ -55,7 +56,7 @@ void D3D12FragmentDecompiler::insertIntputs(std::stringstream & OS)
OS << " float4 spec_color : COLOR1;" << std::endl;
OS << " float4 dst_reg3 : COLOR2;" << std::endl;
OS << " float4 dst_reg4 : COLOR3;" << std::endl;
OS << " float fogc : FOG;" << std::endl;
OS << " float4 fogc : FOG;" << std::endl;
OS << " float4 tc9 : TEXCOORD9;" << std::endl;
OS << " float4 tc0 : TEXCOORD0;" << std::endl;
OS << " float4 tc1 : TEXCOORD1;" << std::endl;
@ -66,6 +67,8 @@ void D3D12FragmentDecompiler::insertIntputs(std::stringstream & OS)
OS << " float4 tc6 : TEXCOORD6;" << std::endl;
OS << " float4 tc7 : TEXCOORD7;" << std::endl;
OS << " float4 tc8 : TEXCOORD8;" << std::endl;
OS << " float4 dst_userClip0 : SV_ClipDistance0;" << std::endl;
OS << " float4 dst_userClip1 : SV_ClipDistance1;" << std::endl;
OS << "};" << std::endl;
}
@ -154,22 +157,22 @@ namespace
switch (mode)
{
case rsx::fog_mode::linear:
OS << " float4 fogc = float4(fog_param1 * In.fogc + (fog_param0 - 1.), fog_param1 * In.fogc + (fog_param0 - 1.), 0., 0.);\n";
OS << " float4 fogc = float4(fog_param1 * In.fogc.x + (fog_param0 - 1.), fog_param1 * In.fogc.x + (fog_param0 - 1.), 0., 0.);\n";
break;
case rsx::fog_mode::exponential:
OS << " float4 fogc = float4(11.084 * (fog_param1 * In.fogc + fog_param0 - 1.5), exp(11.084 * (fog_param1 * In.fogc + fog_param0 - 1.5)), 0., 0.);\n";
OS << " float4 fogc = float4(11.084 * (fog_param1 * In.fogc.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * In.fogc.x + fog_param0 - 1.5)), 0., 0.);\n";
break;
case rsx::fog_mode::exponential2:
OS << " float4 fogc = float4(4.709 * (fog_param1 * In.fogc + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * In.fogc + fog_param0 - 1.5)), 2.)), 0., 0.);\n";
OS << " float4 fogc = float4(4.709 * (fog_param1 * In.fogc.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * In.fogc.x + fog_param0 - 1.5)), 2.)), 0., 0.);\n";
break;
case rsx::fog_mode::linear_abs:
OS << " float4 fogc = float4(fog_param1 * abs(In.fogc) + (fog_param0 - 1.), fog_param1 * abs(In.fogc) + (fog_param0 - 1.), 0., 0.);\n";
OS << " float4 fogc = float4(fog_param1 * abs(In.fogc.x) + (fog_param0 - 1.), fog_param1 * abs(In.fogc.x) + (fog_param0 - 1.), 0., 0.);\n";
break;
case rsx::fog_mode::exponential_abs:
OS << " float4 fogc = float4(11.084 * (fog_param1 * abs(In.fogc) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs(In.fogc) + fog_param0 - 1.5)), 0., 0.);\n";
OS << " float4 fogc = float4(11.084 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5)), 0., 0.);\n";
break;
case rsx::fog_mode::exponential2_abs:
OS << " float4 fogc = float4(4.709 * (fog_param1 * abs(In.fogc) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs(In.fogc) + fog_param0 - 1.5)), 2.)), 0., 0.);\n";
OS << " float4 fogc = float4(4.709 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5)), 2.)), 0., 0.);\n";
break;
default:
OS << " float4 fogc = float4(0., 0., 0., 0.);\n";

View File

@ -31,6 +31,7 @@ void D3D12VertexProgramDecompiler::insertHeader(std::stringstream &OS)
OS << "cbuffer SCALE_OFFSET : register(b0)" << std::endl;
OS << "{" << std::endl;
OS << " float4x4 scaleOffsetMat;" << std::endl;
OS << " float4 userClip[2];" << std::endl;
OS << " float fog_param0;" << std::endl;
OS << " float fog_param1;" << std::endl;
OS << " int isAlphaTested;" << std::endl;
@ -93,7 +94,7 @@ void D3D12VertexProgramDecompiler::insertOutputs(std::stringstream & OS, const s
OS << " float4 dst_reg2 : COLOR1;" << std::endl;
OS << " float4 dst_reg3 : COLOR2;" << std::endl;
OS << " float4 dst_reg4 : COLOR3;" << std::endl;
OS << " float dst_reg5 : FOG;" << std::endl;
OS << " float4 dst_reg5 : FOG;" << std::endl;
OS << " float4 dst_reg6 : TEXCOORD9;" << std::endl;
OS << " float4 dst_reg7 : TEXCOORD0;" << std::endl;
OS << " float4 dst_reg8 : TEXCOORD1;" << std::endl;
@ -104,6 +105,8 @@ void D3D12VertexProgramDecompiler::insertOutputs(std::stringstream & OS, const s
OS << " float4 dst_reg13 : TEXCOORD6;" << std::endl;
OS << " float4 dst_reg14 : TEXCOORD7;" << std::endl;
OS << " float4 dst_reg15 : TEXCOORD8;" << std::endl;
OS << " float4 dst_userClip0 : SV_ClipDistance0;" << std::endl;
OS << " float4 dst_userClip1 : SV_ClipDistance1;" << std::endl;
OS << "};" << std::endl;
}
@ -239,6 +242,20 @@ void D3D12VertexProgramDecompiler::insertMainEnd(std::stringstream & OS)
if (m_parr.HasParam(PF_PARAM_NONE, "float4", "dst_reg2"))
OS << " Out.dst_reg4 = dst_reg2;\n";
// user clip
if ((rsx_vertex_program.output_mask & (CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC2)) != 0)
{
OS << " Out.dst_userClip0.x = dst_reg5.y * userClip[0].x;\n";
OS << " Out.dst_userClip0.y = dst_reg5.z * userClip[0].y;\n";
OS << " Out.dst_userClip0.z = dst_reg5.w * userClip[0].z;\n";
}
if ((rsx_vertex_program.output_mask & (CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC5)) != 0)
{
OS << " Out.dst_userClip0.w = dst_reg6.y * userClip[0].w;\n";
OS << " Out.dst_userClip1.x = dst_reg6.z * userClip[1].x;\n";
OS << " Out.dst_userClip1.y = dst_reg6.w * userClip[1].y;\n";
}
OS << " Out.dst_reg0 = mul(Out.dst_reg0, scaleOffsetMat);" << std::endl;
OS << " return Out;" << std::endl;
OS << "}" << std::endl;

View File

@ -289,6 +289,13 @@ void GLGSRender::begin()
//NV4097_SET_ANTI_ALIASING_CONTROL
//NV4097_SET_CLIP_ID_TEST_ENABLE
__glcheck enable(true, GL_CLIP_DISTANCE0 + 0);
__glcheck enable(true, GL_CLIP_DISTANCE0 + 1);
__glcheck enable(true, GL_CLIP_DISTANCE0 + 2);
__glcheck enable(true, GL_CLIP_DISTANCE0 + 3);
__glcheck enable(true, GL_CLIP_DISTANCE0 + 4);
__glcheck enable(true, GL_CLIP_DISTANCE0 + 5);
std::chrono::time_point<steady_clock> now = steady_clock::now();
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
}
@ -336,48 +343,6 @@ void GLGSRender::end()
std::chrono::time_point<steady_clock> program_stop = steady_clock::now();
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(program_stop - program_start).count();
//Set active user clip planes
const rsx::user_clip_plane_op clip_plane_control[6] =
{
rsx::method_registers.clip_plane_0_enabled(),
rsx::method_registers.clip_plane_1_enabled(),
rsx::method_registers.clip_plane_2_enabled(),
rsx::method_registers.clip_plane_3_enabled(),
rsx::method_registers.clip_plane_4_enabled(),
rsx::method_registers.clip_plane_5_enabled(),
};
for (int index = 0; index < 6; ++index)
{
int value = 0;
int location;
if (m_program->uniforms.has_location("uc_m" + std::to_string(index), &location))
{
switch (clip_plane_control[index])
{
default:
LOG_ERROR(RSX, "bad clip plane control (0x%x)", (u8)clip_plane_control[index]);
case rsx::user_clip_plane_op::disable:
value = 0;
break;
case rsx::user_clip_plane_op::greater_or_equal:
value = 1;
break;
case rsx::user_clip_plane_op::less_than:
value = -1;
break;
}
__glcheck m_program->uniforms[location] = value;
}
__glcheck enable(value, GL_CLIP_DISTANCE0 + index);
};
if (manually_flush_ring_buffers)
{
//Use approximations to reseve space. This path is mostly for debug purposes anyway
@ -814,7 +779,8 @@ bool GLGSRender::load_program()
auto mapping = m_scale_offset_buffer->alloc_from_heap(512, m_uniform_buffer_offset_align);
buf = static_cast<u8*>(mapping.first);
scale_offset_offset = mapping.second;
fill_scale_offset_data(buf, false);
fill_scale_offset_data(buf, false, true);
fill_user_clip_data((char *)buf + 64);
if (m_transform_constants_dirty)
{

View File

@ -34,6 +34,7 @@ void GLVertexDecompilerThread::insertHeader(std::stringstream &OS)
OS << "layout(std140, binding = 0) uniform ScaleOffsetBuffer" << std::endl;
OS << "{" << std::endl;
OS << " mat4 scaleOffsetMat;" << std::endl;
OS << " vec4 userClip[2];" << std::endl;
OS << "};" << std::endl;
}
@ -124,13 +125,13 @@ static const reg_info reg_table[] =
{ "front_diff_color", true, "dst_reg3", "", false },
{ "front_spec_color", true, "dst_reg4", "", false },
{ "fog_c", true, "dst_reg5", ".xxxx", true },
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y * uc_m0", false },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z * uc_m1", false },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w * uc_m2", false },
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y * userClip[0].x", false },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z * userClip[0].y", false },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w * userClip[0].z", false },
{ "gl_PointSize", false, "dst_reg6", ".x", false },
{ "gl_ClipDistance[3]", false, "dst_reg6", ".y * uc_m3", false },
{ "gl_ClipDistance[4]", false, "dst_reg6", ".z * uc_m4", false },
{ "gl_ClipDistance[5]", false, "dst_reg6", ".w * uc_m5", false },
{ "gl_ClipDistance[3]", false, "dst_reg6", ".y * userClip[0].w", false },
{ "gl_ClipDistance[4]", false, "dst_reg6", ".z * userClip[1].x", false },
{ "gl_ClipDistance[5]", false, "dst_reg6", ".w * userClip[1].y", false },
{ "tc0", true, "dst_reg7", "", false },
{ "tc1", true, "dst_reg8", "", false },
{ "tc2", true, "dst_reg9", "", false },

View File

@ -562,7 +562,7 @@ namespace rsx
return "rsx::thread";
}
void thread::fill_scale_offset_data(void *buffer, bool is_d3d) const
void thread::fill_scale_offset_data(void *buffer, bool flip_y, bool symmetrical_z) const
{
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
@ -574,12 +574,12 @@ namespace rsx
float scale_y = rsx::method_registers.viewport_scale_y() / (clip_h / 2.f);
float offset_y = (rsx::method_registers.viewport_offset_y() - (clip_h / 2.f));
offset_y /= clip_h / 2.f;
if (is_d3d) scale_y *= -1;
if (is_d3d) offset_y *= -1;
if (flip_y) scale_y *= -1;
if (flip_y) offset_y *= -1;
float scale_z = rsx::method_registers.viewport_scale_z();
float offset_z = rsx::method_registers.viewport_offset_z();
if (!is_d3d) offset_z -= .5;
if (symmetrical_z) offset_z -= .5;
float one = 1.f;
@ -589,6 +589,46 @@ namespace rsx
stream_vector((char*)buffer + 48, 0, 0, 0, (u32&)one);
}
void thread::fill_user_clip_data(void *buffer) const
{
const rsx::user_clip_plane_op clip_plane_control[6] =
{
rsx::method_registers.clip_plane_0_enabled(),
rsx::method_registers.clip_plane_1_enabled(),
rsx::method_registers.clip_plane_2_enabled(),
rsx::method_registers.clip_plane_3_enabled(),
rsx::method_registers.clip_plane_4_enabled(),
rsx::method_registers.clip_plane_5_enabled(),
};
std::array<f32, 8> tmp{};
for (int index = 0; index < 6; ++index)
{
f32 value = 0;
switch (clip_plane_control[index])
{
default:
LOG_ERROR(RSX, "bad clip plane control (0x%x)", (u8)clip_plane_control[index]);
case rsx::user_clip_plane_op::disable:
value = 0.f;
break;
case rsx::user_clip_plane_op::greater_or_equal:
value = 1.f;
break;
case rsx::user_clip_plane_op::less_than:
value = -1.f;
break;
}
tmp[index] = value;
}
stream_vector_from_memory((char*)buffer, tmp.data());
stream_vector_from_memory((char*)buffer + 16, &tmp[4]);
}
/**
* Fill buffer with vertex program constants.
* Buffer must be at least 512 float4 wide.
@ -624,12 +664,12 @@ namespace rsx
void thread::write_inline_array_to_buffer(void *dst_buffer)
{
u8* src =
reinterpret_cast<u8*>(rsx::method_registers.current_draw_clause.inline_vertex_array.data());
reinterpret_cast<u8*>(rsx::method_registers.current_draw_clause.inline_vertex_array.data());
u8* dst = (u8*)dst_buffer;
size_t bytes_written = 0;
while (bytes_written <
rsx::method_registers.current_draw_clause.inline_vertex_array.size() * sizeof(u32))
rsx::method_registers.current_draw_clause.inline_vertex_array.size() * sizeof(u32))
{
for (int index = 0; index < rsx::limits::vertex_count; ++index)
{
@ -730,7 +770,7 @@ namespace rsx
{
const rsx::data_array_format_info& info = state.vertex_arrays_info[index];
result.push_back(vertex_array_buffer{info.type(), info.size(), info.stride(),
get_raw_vertex_buffer(info, state.vertex_data_base_offset(), vertex_ranges), index});
get_raw_vertex_buffer(info, state.vertex_data_base_offset(), vertex_ranges), index});
continue;
}
@ -909,12 +949,12 @@ namespace rsx
if (rsx::method_registers.vertex_arrays_info[index].size() > 0)
{
result.rsx_vertex_inputs.push_back(
{index,
rsx::method_registers.vertex_arrays_info[index].size(),
rsx::method_registers.vertex_arrays_info[index].frequency(),
!!((modulo_mask >> index) & 0x1),
true,
is_int_type(rsx::method_registers.vertex_arrays_info[index].type()), 0});
{index,
rsx::method_registers.vertex_arrays_info[index].size(),
rsx::method_registers.vertex_arrays_info[index].frequency(),
!!((modulo_mask >> index) & 0x1),
true,
is_int_type(rsx::method_registers.vertex_arrays_info[index].type()), 0});
}
else if (vertex_push_buffers[index].vertex_count > 1)
{
@ -929,12 +969,12 @@ namespace rsx
else if (rsx::method_registers.register_vertex_info[index].size > 0)
{
result.rsx_vertex_inputs.push_back(
{index,
rsx::method_registers.register_vertex_info[index].size,
rsx::method_registers.register_vertex_info[index].frequency,
!!((modulo_mask >> index) & 0x1),
false,
is_int_type(rsx::method_registers.vertex_arrays_info[index].type()), 0});
{index,
rsx::method_registers.register_vertex_info[index].size,
rsx::method_registers.register_vertex_info[index].frequency,
!!((modulo_mask >> index) & 0x1),
false,
is_int_type(rsx::method_registers.vertex_arrays_info[index].type()), 0});
}
}
return result;

View File

@ -309,7 +309,13 @@ namespace rsx
* Vertex shader's position is to be multiplied by this matrix.
* if is_d3d is set, the matrix is modified to use d3d convention.
*/
void fill_scale_offset_data(void *buffer, bool is_d3d = true) const;
void fill_scale_offset_data(void *buffer, bool flip_y, bool symmetrical_z) const;
/**
* Fill buffer with user clip information
*/
void fill_user_clip_data(void *buffer) const;
/**
* Fill buffer with vertex program constants.

View File

@ -1180,33 +1180,12 @@ bool VKGSRender::load_program()
u8 *buf = (u8*)m_uniform_buffer_ring_info.map(scale_offset_offset, 256);
//TODO: Add case for this in RSXThread
/**
* NOTE: While VK's coord system resembles GLs, the clip volume is no longer symetrical in z
* Its like D3D without the flip in y (depending on how you build the spir-v)
*/
{
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
float scale_x = rsx::method_registers.viewport_scale_x() / (clip_w / 2.f);
float offset_x = rsx::method_registers.viewport_offset_x() - (clip_w / 2.f);
offset_x /= clip_w / 2.f;
float scale_y = rsx::method_registers.viewport_scale_y() / (clip_h / 2.f);
float offset_y = (rsx::method_registers.viewport_offset_y() - (clip_h / 2.f));
offset_y /= clip_h / 2.f;
float scale_z = rsx::method_registers.viewport_scale_z();
float offset_z = rsx::method_registers.viewport_offset_z();
float one = 1.f;
stream_vector(buf, (u32&)scale_x, 0, 0, (u32&)offset_x);
stream_vector((char*)buf + 16, 0, (u32&)scale_y, 0, (u32&)offset_y);
stream_vector((char*)buf + 32, 0, 0, (u32&)scale_z, (u32&)offset_z);
stream_vector((char*)buf + 48, 0, 0, 0, (u32&)one);
}
fill_scale_offset_data(buf, false, false);
fill_user_clip_data(buf + 64);
m_uniform_buffer_ring_info.unmap();

View File

@ -33,6 +33,7 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS)
OS << "layout(std140, set = 0, binding = 0) uniform ScaleOffsetBuffer" << std::endl;
OS << "{" << std::endl;
OS << " mat4 scaleOffsetMat;" << std::endl;
OS << " vec4 userClip[2];" << std::endl;
OS << "};" << std::endl;
vk::glsl::program_input in;
@ -158,16 +159,16 @@ static const reg_info reg_table[] =
{ "front_diff_color", true, "dst_reg3", "", false },
{ "front_spec_color", true, "dst_reg4", "", false },
{ "fog_c", true, "dst_reg5", ".xxxx", true },
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y", false },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z", false },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w", false },
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y * userClip[0].x", false },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z * userClip[0].y", false },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w * userClip[0].z", false },
{ "gl_PointSize", false, "dst_reg6", ".x", false },
//Disable user clip planes until they are properly handled
//{ "gl_ClipDistance[3]", false, "dst_reg6", ".y", false },
//{ "gl_ClipDistance[4]", false, "dst_reg6", ".z", false },
//{ "gl_ClipDistance[5]", false, "dst_reg6", ".w", false },
{ "gl_ClipDistance[3]", false, "dst_reg6", ".y * userClip[0].w", false },
{ "gl_ClipDistance[4]", false, "dst_reg6", ".z * userClip[1].x", false },
{ "gl_ClipDistance[5]", false, "dst_reg6", ".w * userClip[1].y", false },
{ "tc0", true, "dst_reg7", "", false },
{ "tc1", true, "dst_reg8", "", false },