diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 3338d5d9b..8db6f1626 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -21,6 +21,7 @@ #include "xenia/gpu/d3d12/d3d12_command_processor.h" #include "xenia/gpu/d3d12/d3d12_graphics_system.h" #include "xenia/gpu/d3d12/d3d12_shader.h" +#include "xenia/gpu/draw_util.h" #include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/xenos.h" #include "xenia/ui/d3d12/d3d12_util.h" @@ -2846,34 +2847,20 @@ void D3D12CommandProcessor::UpdateFixedFunctionState(bool primitive_two_faced) { } // Scissor. - auto pa_sc_window_scissor_tl = regs.Get(); - auto pa_sc_window_scissor_br = regs.Get(); - D3D12_RECT scissor; - scissor.left = pa_sc_window_scissor_tl.tl_x; - scissor.top = pa_sc_window_scissor_tl.tl_y; - scissor.right = pa_sc_window_scissor_br.br_x; - scissor.bottom = pa_sc_window_scissor_br.br_y; - if (!pa_sc_window_scissor_tl.window_offset_disable) { - scissor.left = std::max( - LONG(scissor.left + pa_sc_window_offset.window_x_offset), LONG(0)); - scissor.top = std::max( - LONG(scissor.top + pa_sc_window_offset.window_y_offset), LONG(0)); - scissor.right = std::max( - LONG(scissor.right + pa_sc_window_offset.window_x_offset), LONG(0)); - scissor.bottom = std::max( - LONG(scissor.bottom + pa_sc_window_offset.window_y_offset), LONG(0)); - } - scissor.left *= pixel_size_x; - scissor.top *= pixel_size_y; - scissor.right *= pixel_size_x; - scissor.bottom *= pixel_size_y; - ff_scissor_update_needed_ |= ff_scissor_.left != scissor.left; - ff_scissor_update_needed_ |= ff_scissor_.top != scissor.top; - ff_scissor_update_needed_ |= ff_scissor_.right != scissor.right; - ff_scissor_update_needed_ |= ff_scissor_.bottom != scissor.bottom; + draw_util::Scissor scissor; + draw_util::GetScissor(regs, scissor); + D3D12_RECT scissor_rect; + scissor_rect.left = LONG(scissor.left * pixel_size_x); + scissor_rect.top = LONG(scissor.top * pixel_size_y); + scissor_rect.right = LONG((scissor.left + scissor.width) * pixel_size_x); + scissor_rect.bottom = LONG((scissor.top + scissor.height) * pixel_size_y); + ff_scissor_update_needed_ |= ff_scissor_.left != scissor_rect.left; + ff_scissor_update_needed_ |= ff_scissor_.top != scissor_rect.top; + ff_scissor_update_needed_ |= ff_scissor_.right != scissor_rect.right; + ff_scissor_update_needed_ |= ff_scissor_.bottom != scissor_rect.bottom; if (ff_scissor_update_needed_) { - ff_scissor_ = scissor; - deferred_command_list_.RSSetScissorRect(scissor); + ff_scissor_ = scissor_rect; + deferred_command_list_.RSSetScissorRect(scissor_rect); ff_scissor_update_needed_ = false; } diff --git a/src/xenia/gpu/draw_util.cc b/src/xenia/gpu/draw_util.cc index 6aaa1b856..202d34965 100644 --- a/src/xenia/gpu/draw_util.cc +++ b/src/xenia/gpu/draw_util.cc @@ -111,6 +111,34 @@ int32_t FloatToD3D11Fixed16p8(float f32) { return result.s; } +void GetScissor(const RegisterFile& regs, Scissor& scissor_out) { + // FIXME(Triang3l): Screen scissor isn't applied here, but it seems to be + // unused on Xbox 360 Direct3D 9. + auto pa_sc_window_scissor_tl = regs.Get(); + auto pa_sc_window_scissor_br = regs.Get(); + uint32_t tl_x = pa_sc_window_scissor_tl.tl_x; + uint32_t tl_y = pa_sc_window_scissor_tl.tl_y; + uint32_t br_x = pa_sc_window_scissor_br.br_x; + uint32_t br_y = pa_sc_window_scissor_br.br_y; + if (!pa_sc_window_scissor_tl.window_offset_disable) { + auto pa_sc_window_offset = regs.Get(); + tl_x = uint32_t(std::max( + int32_t(tl_x) + pa_sc_window_offset.window_x_offset, int32_t(0))); + tl_y = uint32_t(std::max( + int32_t(tl_y) + pa_sc_window_offset.window_y_offset, int32_t(0))); + br_x = uint32_t(std::max( + int32_t(br_x) + pa_sc_window_offset.window_x_offset, int32_t(0))); + br_y = uint32_t(std::max( + int32_t(br_y) + pa_sc_window_offset.window_y_offset, int32_t(0))); + } + br_x = std::max(br_x, tl_x); + br_y = std::max(br_y, tl_y); + scissor_out.left = tl_x; + scissor_out.top = tl_y; + scissor_out.width = br_x - tl_x; + scissor_out.height = br_y - tl_y; +} + xenos::CopySampleSelect SanitizeCopySampleSelect( xenos::CopySampleSelect copy_sample_select, xenos::MsaaSamples msaa_samples, bool is_depth) { diff --git a/src/xenia/gpu/draw_util.h b/src/xenia/gpu/draw_util.h index edb880ab0..7ef3186a0 100644 --- a/src/xenia/gpu/draw_util.h +++ b/src/xenia/gpu/draw_util.h @@ -33,6 +33,14 @@ namespace draw_util { // for use with the top-left rasterization rule later. int32_t FloatToD3D11Fixed16p8(float f32); +struct Scissor { + uint32_t left; + uint32_t top; + uint32_t width; + uint32_t height; +}; +void GetScissor(const RegisterFile& regs, Scissor& scissor_out); + // To avoid passing values that the shader won't understand (even though // Direct3D 9 shouldn't pass them anyway). xenos::CopySampleSelect SanitizeCopySampleSelect(