Proper combination of scissors

This commit is contained in:
Vladislav Mikhalin 2024-09-29 13:12:15 +03:00
parent 24a03edfb7
commit fab50dcb00
2 changed files with 60 additions and 23 deletions

View file

@ -566,17 +566,22 @@ struct Liverpool {
s16 top_left_x;
s16 top_left_y;
};
union {
BitField<0, 15, u32> bottom_right_x;
BitField<16, 15, u32> bottom_right_y;
struct {
s16 bottom_right_x;
s16 bottom_right_y;
};
// From AMD spec: 'Negative numbers clamped to 0'
static s16 Clamp(s16 value) {
return std::max(s16(0), value);
}
u32 GetWidth() const {
return static_cast<u32>(bottom_right_x - top_left_x);
return static_cast<u32>(Clamp(bottom_right_x) - Clamp(top_left_x));
}
u32 GetHeight() const {
return static_cast<u32>(bottom_right_y - top_left_y);
return static_cast<u32>(Clamp(bottom_right_y) - Clamp(top_left_y));
}
};
@ -588,12 +593,12 @@ struct Liverpool {
struct ViewportScissor {
union {
BitField<0, 15, s32> top_left_x;
BitField<15, 15, s32> top_left_y;
BitField<30, 1, s32> window_offset_disable;
BitField<16, 15, s32> top_left_y;
BitField<31, 1, s32> window_offset_disable;
};
union {
BitField<0, 15, s32> bottom_right_x;
BitField<15, 15, s32> bottom_right_y;
struct {
s16 bottom_right_x;
s16 bottom_right_y;
};
u32 GetWidth() const {

View file

@ -342,6 +342,14 @@ void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) {
}
}
static s16 CombinedScissorValueTL(s16 scr, s16 win, s16 gen, s16 win_offset) {
return std::max({scr, s16(win + win_offset), s16(gen + win_offset)});
}
static s16 CombinedScissorValueBR(s16 scr, s16 win, s16 gen, s16 win_offset) {
return std::min({scr, s16(win + win_offset), s16(gen + win_offset)});
}
void Rasterizer::UpdateViewportScissorState() {
auto& regs = liverpool->regs;
@ -369,20 +377,44 @@ void Rasterizer::UpdateViewportScissorState() {
});
}
if (!regs.mode_control.vport_scissor_enable) {
const auto& sc = regs.screen_scissor;
scissors.push_back({
.offset = {sc.top_left_x, sc.top_left_y},
.extent = {sc.GetWidth(), sc.GetHeight()},
});
} else {
for (u32 i = 0; i < Liverpool::NumViewports; i++) {
const auto& scsrs = regs.viewport_scissors[i];
scissors.push_back({
.offset = {scsrs.top_left_x, scsrs.top_left_y},
.extent = {scsrs.GetWidth(), scsrs.GetHeight()},
});
const bool enable_offset = !regs.window_scissor.window_offset_disable.Value();
Liverpool::Scissor scsr;
scsr.top_left_x = CombinedScissorValueTL(
regs.screen_scissor.top_left_x, s16(regs.window_scissor.top_left_x.Value()),
s16(regs.generic_scissor.top_left_x.Value()),
enable_offset ? regs.window_offset.window_x_offset : 0);
scsr.top_left_y = CombinedScissorValueTL(
regs.screen_scissor.top_left_y, s16(regs.window_scissor.top_left_y.Value()),
s16(regs.generic_scissor.top_left_y.Value()),
enable_offset ? regs.window_offset.window_y_offset : 0);
scsr.bottom_right_x = CombinedScissorValueBR(
regs.screen_scissor.bottom_right_x, regs.window_scissor.bottom_right_x,
regs.generic_scissor.bottom_right_x,
enable_offset ? regs.window_offset.window_x_offset : 0);
scsr.bottom_right_y = CombinedScissorValueBR(
regs.screen_scissor.bottom_right_y, regs.window_scissor.bottom_right_y,
regs.generic_scissor.bottom_right_y,
enable_offset ? regs.window_offset.window_y_offset : 0);
for (u32 i = 0; i < Liverpool::NumViewports; i++) {
auto vp_scsr = scsr;
if (regs.mode_control.vport_scissor_enable) {
vp_scsr.top_left_x =
std::max(vp_scsr.top_left_x, s16(regs.viewport_scissors[i].top_left_x.Value()));
vp_scsr.top_left_y =
std::max(vp_scsr.top_left_y, s16(regs.viewport_scissors[i].top_left_y.Value()));
vp_scsr.bottom_right_x =
std::min(vp_scsr.bottom_right_x, regs.viewport_scissors[i].bottom_right_x);
vp_scsr.bottom_right_y =
std::min(vp_scsr.bottom_right_y, regs.viewport_scissors[i].bottom_right_y);
}
scissors.push_back({
.offset = {vp_scsr.top_left_x, vp_scsr.top_left_y},
.extent = {vp_scsr.GetWidth(), vp_scsr.GetHeight()},
});
}
const auto cmdbuf = scheduler.CommandBuffer();