[GPU] Rename PrimitiveTwoFaced to PrimitivePolygonal, add rects to it and ignore fill modes for non-polygons

This commit is contained in:
Triang3l 2020-11-19 23:55:49 +03:00
parent 3ff5965133
commit 44a3f200c3
6 changed files with 38 additions and 28 deletions

View File

@ -1876,14 +1876,14 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
!pixel_shader->memexport_stream_constants().empty(); !pixel_shader->memexport_stream_constants().empty();
bool memexport_used = memexport_used_vertex || memexport_used_pixel; bool memexport_used = memexport_used_vertex || memexport_used_pixel;
bool primitive_two_faced = bool primitive_polygonal =
xenos::IsPrimitiveTwoFaced(tessellated, primitive_type); xenos::IsPrimitivePolygonal(tessellated, primitive_type);
auto sq_program_cntl = regs.Get<reg::SQ_PROGRAM_CNTL>(); auto sq_program_cntl = regs.Get<reg::SQ_PROGRAM_CNTL>();
auto pa_su_sc_mode_cntl = regs.Get<reg::PA_SU_SC_MODE_CNTL>(); auto pa_su_sc_mode_cntl = regs.Get<reg::PA_SU_SC_MODE_CNTL>();
if (!memexport_used_vertex && if (!memexport_used_vertex &&
(sq_program_cntl.vs_export_mode == (sq_program_cntl.vs_export_mode ==
xenos::VertexShaderExportMode::kMultipass || xenos::VertexShaderExportMode::kMultipass ||
(primitive_two_faced && pa_su_sc_mode_cntl.cull_front && (primitive_polygonal && pa_su_sc_mode_cntl.cull_front &&
pa_su_sc_mode_cntl.cull_back))) { pa_su_sc_mode_cntl.cull_back))) {
// All faces are culled - can't be expressed in the pipeline. // All faces are culled - can't be expressed in the pipeline.
return true; return true;
@ -2027,11 +2027,11 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
scissor.height *= pixel_size_y; scissor.height *= pixel_size_y;
// Update viewport, scissor, blend factor and stencil reference. // Update viewport, scissor, blend factor and stencil reference.
UpdateFixedFunctionState(viewport_info, scissor, primitive_two_faced); UpdateFixedFunctionState(viewport_info, scissor, primitive_polygonal);
// Update system constants before uploading them. // Update system constants before uploading them.
UpdateSystemConstantValues( UpdateSystemConstantValues(
memexport_used, primitive_two_faced, line_loop_closing_index, memexport_used, primitive_polygonal, line_loop_closing_index,
indexed ? index_buffer_info->endianness : xenos::Endian::kNone, indexed ? index_buffer_info->endianness : xenos::Endian::kNone,
viewport_info, pixel_size_x, pixel_size_y, used_texture_mask, early_z, viewport_info, pixel_size_x, pixel_size_y, used_texture_mask, early_z,
GetCurrentColorMask(pixel_shader), pipeline_render_targets); GetCurrentColorMask(pixel_shader), pipeline_render_targets);
@ -2785,7 +2785,7 @@ void D3D12CommandProcessor::ClearCommandAllocatorCache() {
void D3D12CommandProcessor::UpdateFixedFunctionState( void D3D12CommandProcessor::UpdateFixedFunctionState(
const draw_util::ViewportInfo& viewport_info, const draw_util::ViewportInfo& viewport_info,
const draw_util::Scissor& scissor, bool primitive_two_faced) { const draw_util::Scissor& scissor, bool primitive_polygonal) {
#if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES #if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES
SCOPE_profile_cpu_f("gpu"); SCOPE_profile_cpu_f("gpu");
#endif // XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES #endif // XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES
@ -2851,7 +2851,7 @@ void D3D12CommandProcessor::UpdateFixedFunctionState(
// choose the back face one only if drawing only back faces. // choose the back face one only if drawing only back faces.
Register stencil_ref_mask_reg; Register stencil_ref_mask_reg;
auto pa_su_sc_mode_cntl = regs.Get<reg::PA_SU_SC_MODE_CNTL>(); auto pa_su_sc_mode_cntl = regs.Get<reg::PA_SU_SC_MODE_CNTL>();
if (primitive_two_faced && if (primitive_polygonal &&
regs.Get<reg::RB_DEPTHCONTROL>().backface_enable && regs.Get<reg::RB_DEPTHCONTROL>().backface_enable &&
pa_su_sc_mode_cntl.cull_front && !pa_su_sc_mode_cntl.cull_back) { pa_su_sc_mode_cntl.cull_front && !pa_su_sc_mode_cntl.cull_back) {
stencil_ref_mask_reg = XE_GPU_REG_RB_STENCILREFMASK_BF; stencil_ref_mask_reg = XE_GPU_REG_RB_STENCILREFMASK_BF;
@ -2870,7 +2870,7 @@ void D3D12CommandProcessor::UpdateFixedFunctionState(
} }
void D3D12CommandProcessor::UpdateSystemConstantValues( void D3D12CommandProcessor::UpdateSystemConstantValues(
bool shared_memory_is_uav, bool primitive_two_faced, bool shared_memory_is_uav, bool primitive_polygonal,
uint32_t line_loop_closing_index, xenos::Endian index_endian, uint32_t line_loop_closing_index, xenos::Endian index_endian,
const draw_util::ViewportInfo& viewport_info, uint32_t pixel_size_x, const draw_util::ViewportInfo& viewport_info, uint32_t pixel_size_x,
uint32_t pixel_size_y, uint32_t used_texture_mask, bool early_z, uint32_t pixel_size_y, uint32_t used_texture_mask, bool early_z,
@ -2983,9 +2983,9 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
flags |= (pa_cl_clip_cntl.value & 0b111111) flags |= (pa_cl_clip_cntl.value & 0b111111)
<< DxbcShaderTranslator::kSysFlag_UserClipPlane0_Shift; << DxbcShaderTranslator::kSysFlag_UserClipPlane0_Shift;
} }
// Whether SV_IsFrontFace matters. // Whether the primitive is polygonal and SV_IsFrontFace matters.
if (primitive_two_faced) { if (primitive_polygonal) {
flags |= DxbcShaderTranslator::kSysFlag_PrimitiveTwoFaced; flags |= DxbcShaderTranslator::kSysFlag_PrimitivePolygonal;
} }
// Primitive killing condition. // Primitive killing condition.
if (pa_cl_clip_cntl.vtx_kill_or) { if (pa_cl_clip_cntl.vtx_kill_or) {
@ -3082,7 +3082,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
// to do memexport. // to do memexport.
if (sq_program_cntl.vs_export_mode == if (sq_program_cntl.vs_export_mode ==
xenos::VertexShaderExportMode::kMultipass || xenos::VertexShaderExportMode::kMultipass ||
(primitive_two_faced && pa_su_sc_mode_cntl.cull_front && (primitive_polygonal && pa_su_sc_mode_cntl.cull_front &&
pa_su_sc_mode_cntl.cull_back)) { pa_su_sc_mode_cntl.cull_back)) {
float nan_value = std::nanf(""); float nan_value = std::nanf("");
for (uint32_t i = 0; i < 3; ++i) { for (uint32_t i = 0; i < 3; ++i) {
@ -3275,7 +3275,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
// are used. // are used.
float poly_offset_front_scale = 0.0f, poly_offset_front_offset = 0.0f; float poly_offset_front_scale = 0.0f, poly_offset_front_offset = 0.0f;
float poly_offset_back_scale = 0.0f, poly_offset_back_offset = 0.0f; float poly_offset_back_scale = 0.0f, poly_offset_back_offset = 0.0f;
if (primitive_two_faced) { if (primitive_polygonal) {
if (pa_su_sc_mode_cntl.poly_offset_front_enable) { if (pa_su_sc_mode_cntl.poly_offset_front_enable) {
poly_offset_front_scale = poly_offset_front_scale =
regs[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_SCALE].f32; regs[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_SCALE].f32;
@ -3338,7 +3338,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
system_constants_.edram_stencil_front_func_ops != stencil_func_ops; system_constants_.edram_stencil_front_func_ops != stencil_func_ops;
system_constants_.edram_stencil_front_func_ops = stencil_func_ops; system_constants_.edram_stencil_front_func_ops = stencil_func_ops;
if (primitive_two_faced && rb_depthcontrol.backface_enable) { if (primitive_polygonal && rb_depthcontrol.backface_enable) {
dirty |= system_constants_.edram_stencil_back_reference != dirty |= system_constants_.edram_stencil_back_reference !=
rb_stencilrefmask_bf.stencilref; rb_stencilrefmask_bf.stencilref;
system_constants_.edram_stencil_back_reference = system_constants_.edram_stencil_back_reference =

View File

@ -348,9 +348,9 @@ class D3D12CommandProcessor : public CommandProcessor {
void UpdateFixedFunctionState(const draw_util::ViewportInfo& viewport_info, void UpdateFixedFunctionState(const draw_util::ViewportInfo& viewport_info,
const draw_util::Scissor& scissor, const draw_util::Scissor& scissor,
bool primitive_two_faced); bool primitive_polygonal);
void UpdateSystemConstantValues( void UpdateSystemConstantValues(
bool shared_memory_is_uav, bool primitive_two_faced, bool shared_memory_is_uav, bool primitive_polygonal,
uint32_t line_loop_closing_index, xenos::Endian index_endian, uint32_t line_loop_closing_index, xenos::Endian index_endian,
const draw_util::ViewportInfo& viewport_info, uint32_t pixel_size_x, const draw_util::ViewportInfo& viewport_info, uint32_t pixel_size_x,
uint32_t pixel_size_y, uint32_t used_texture_mask, bool early_z, uint32_t pixel_size_y, uint32_t used_texture_mask, bool early_z,

View File

@ -1285,7 +1285,7 @@ bool PipelineCache::GetCurrentStateDescription(
uint32_t(regs.Get<reg::VGT_HOS_CNTL>().tess_mode); uint32_t(regs.Get<reg::VGT_HOS_CNTL>().tess_mode);
} }
bool primitive_two_faced = xenos::IsPrimitiveTwoFaced( bool primitive_polygonal = xenos::IsPrimitivePolygonal(
host_vertex_shader_type != Shader::HostVertexShaderType::kVertex, host_vertex_shader_type != Shader::HostVertexShaderType::kVertex,
primitive_type); primitive_type);
@ -1305,15 +1305,16 @@ bool PipelineCache::GetCurrentStateDescription(
// Here we also assume that only one side is culled - if two sides are culled, // Here we also assume that only one side is culled - if two sides are culled,
// the D3D12 command processor will drop such draw early. // the D3D12 command processor will drop such draw early.
bool cull_front, cull_back; bool cull_front, cull_back;
if (primitive_two_faced) { if (primitive_polygonal) {
cull_front = pa_su_sc_mode_cntl.cull_front != 0; cull_front = pa_su_sc_mode_cntl.cull_front != 0;
cull_back = pa_su_sc_mode_cntl.cull_back != 0; cull_back = pa_su_sc_mode_cntl.cull_back != 0;
} else { } else {
// Non-polygonal primitives are never culled.
cull_front = false; cull_front = false;
cull_back = false; cull_back = false;
} }
float poly_offset = 0.0f, poly_offset_scale = 0.0f; float poly_offset = 0.0f, poly_offset_scale = 0.0f;
if (primitive_two_faced) { if (primitive_polygonal) {
description_out.front_counter_clockwise = pa_su_sc_mode_cntl.face == 0; description_out.front_counter_clockwise = pa_su_sc_mode_cntl.face == 0;
if (cull_front) { if (cull_front) {
description_out.cull_mode = PipelineCullMode::kFront; description_out.cull_mode = PipelineCullMode::kFront;
@ -1327,8 +1328,8 @@ bool PipelineCache::GetCurrentStateDescription(
if (!cull_front) { if (!cull_front) {
// Front faces aren't culled. // Front faces aren't culled.
// Direct3D 12, unfortunately, doesn't support point fill mode. // Direct3D 12, unfortunately, doesn't support point fill mode.
if (pa_su_sc_mode_cntl.polymode_front_ptype != if (primitive_polygonal && pa_su_sc_mode_cntl.polymode_front_ptype !=
xenos::PolygonType::kTriangles) { xenos::PolygonType::kTriangles) {
description_out.fill_mode_wireframe = 1; description_out.fill_mode_wireframe = 1;
} }
if (!edram_rov_used_ && pa_su_sc_mode_cntl.poly_offset_front_enable) { if (!edram_rov_used_ && pa_su_sc_mode_cntl.poly_offset_front_enable) {
@ -1338,8 +1339,8 @@ bool PipelineCache::GetCurrentStateDescription(
} }
if (!cull_back) { if (!cull_back) {
// Back faces aren't culled. // Back faces aren't culled.
if (pa_su_sc_mode_cntl.polymode_back_ptype != if (primitive_polygonal && pa_su_sc_mode_cntl.polymode_back_ptype !=
xenos::PolygonType::kTriangles) { xenos::PolygonType::kTriangles) {
description_out.fill_mode_wireframe = 1; description_out.fill_mode_wireframe = 1;
} }
// Prefer front depth bias because in general, front faces are the ones // Prefer front depth bias because in general, front faces are the ones
@ -1413,7 +1414,7 @@ bool PipelineCache::GetCurrentStateDescription(
if (rb_depthcontrol.stencil_enable) { if (rb_depthcontrol.stencil_enable) {
description_out.stencil_enable = 1; description_out.stencil_enable = 1;
bool stencil_backface_enable = bool stencil_backface_enable =
primitive_two_faced && rb_depthcontrol.backface_enable; primitive_polygonal && rb_depthcontrol.backface_enable;
// Per-face masks not supported by Direct3D 12, choose the back face // Per-face masks not supported by Direct3D 12, choose the back face
// ones only if drawing only back faces. // ones only if drawing only back faces.
Register stencil_ref_mask_reg; Register stencil_ref_mask_reg;

View File

@ -770,7 +770,7 @@ void DxbcShaderTranslator::StartPixelShader() {
uint32_t(CbufferRegister::kSystemConstants), uint32_t(CbufferRegister::kSystemConstants),
kSysConst_Flags_Vec) kSysConst_Flags_Vec)
.Select(kSysConst_Flags_Comp), .Select(kSysConst_Flags_Comp),
DxbcSrc::LU(kSysFlag_PrimitiveTwoFaced)); DxbcSrc::LU(kSysFlag_PrimitivePolygonal));
DxbcOpIf(true, DxbcSrc::R(param_gen_temp, DxbcSrc::kZZZZ)); DxbcOpIf(true, DxbcSrc::R(param_gen_temp, DxbcSrc::kZZZZ));
{ {
// Negate modifier flips the sign bit even for 0 - set it to minus for // Negate modifier flips the sign bit even for 0 - set it to minus for

View File

@ -124,7 +124,7 @@ class DxbcShaderTranslator : public ShaderTranslator {
kSysFlag_UserClipPlane4_Shift, kSysFlag_UserClipPlane4_Shift,
kSysFlag_UserClipPlane5_Shift, kSysFlag_UserClipPlane5_Shift,
kSysFlag_KillIfAnyVertexKilled_Shift, kSysFlag_KillIfAnyVertexKilled_Shift,
kSysFlag_PrimitiveTwoFaced_Shift, kSysFlag_PrimitivePolygonal_Shift,
kSysFlag_AlphaPassIfLess_Shift, kSysFlag_AlphaPassIfLess_Shift,
kSysFlag_AlphaPassIfEqual_Shift, kSysFlag_AlphaPassIfEqual_Shift,
kSysFlag_AlphaPassIfGreater_Shift, kSysFlag_AlphaPassIfGreater_Shift,
@ -165,7 +165,7 @@ class DxbcShaderTranslator : public ShaderTranslator {
kSysFlag_UserClipPlane4 = 1u << kSysFlag_UserClipPlane4_Shift, kSysFlag_UserClipPlane4 = 1u << kSysFlag_UserClipPlane4_Shift,
kSysFlag_UserClipPlane5 = 1u << kSysFlag_UserClipPlane5_Shift, kSysFlag_UserClipPlane5 = 1u << kSysFlag_UserClipPlane5_Shift,
kSysFlag_KillIfAnyVertexKilled = 1u << kSysFlag_KillIfAnyVertexKilled_Shift, kSysFlag_KillIfAnyVertexKilled = 1u << kSysFlag_KillIfAnyVertexKilled_Shift,
kSysFlag_PrimitiveTwoFaced = 1u << kSysFlag_PrimitiveTwoFaced_Shift, kSysFlag_PrimitivePolygonal = 1u << kSysFlag_PrimitivePolygonal_Shift,
kSysFlag_AlphaPassIfLess = 1u << kSysFlag_AlphaPassIfLess_Shift, kSysFlag_AlphaPassIfLess = 1u << kSysFlag_AlphaPassIfLess_Shift,
kSysFlag_AlphaPassIfEqual = 1u << kSysFlag_AlphaPassIfEqual_Shift, kSysFlag_AlphaPassIfEqual = 1u << kSysFlag_AlphaPassIfEqual_Shift,
kSysFlag_AlphaPassIfGreater = 1u << kSysFlag_AlphaPassIfGreater_Shift, kSysFlag_AlphaPassIfGreater = 1u << kSysFlag_AlphaPassIfGreater_Shift,

View File

@ -64,7 +64,15 @@ enum class PrimitiveType : uint32_t {
kQuadPatch = 0x12, kQuadPatch = 0x12,
}; };
inline bool IsPrimitiveTwoFaced(bool tessellated, PrimitiveType type) { // Polygonal primitive types (not including points and lines) are rasterized as
// triangles, have front and back faces, and also support face culling and fill
// modes (polymode_front_ptype, polymode_back_ptype). Other primitive types are
// always "front" (but don't support front face and back face culling, according
// to OpenGL and Vulkan specifications - even if glCullFace is
// GL_FRONT_AND_BACK, points and lines are still drawn), and may in some cases
// use the "para" registers instead of "front" or "back" (for "parallelogram" -
// like poly_offset_para_enable).
constexpr bool IsPrimitivePolygonal(bool tessellated, PrimitiveType type) {
if (tessellated && (type == PrimitiveType::kTrianglePatch || if (tessellated && (type == PrimitiveType::kTrianglePatch ||
type == PrimitiveType::kQuadPatch)) { type == PrimitiveType::kQuadPatch)) {
return true; return true;
@ -74,6 +82,7 @@ inline bool IsPrimitiveTwoFaced(bool tessellated, PrimitiveType type) {
case PrimitiveType::kTriangleFan: case PrimitiveType::kTriangleFan:
case PrimitiveType::kTriangleStrip: case PrimitiveType::kTriangleStrip:
case PrimitiveType::kTriangleWithWFlags: case PrimitiveType::kTriangleWithWFlags:
case PrimitiveType::kRectangleList:
case PrimitiveType::kQuadList: case PrimitiveType::kQuadList:
case PrimitiveType::kQuadStrip: case PrimitiveType::kQuadStrip:
case PrimitiveType::kPolygon: case PrimitiveType::kPolygon: