Skip to content

Use correct scissor rects #1146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 40 additions & 13 deletions src/video_core/amdgpu/liverpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,13 @@ struct Liverpool {
}
};

struct ModeControl {
s32 msaa_enable : 1;
s32 vport_scissor_enable : 1;
s32 line_stripple_enable : 1;
s32 send_unlit_stiles_to_pkr : 1;
};

enum class ZOrder : u32 {
LateZ = 0,
EarlyZLateZ = 1,
Expand Down Expand Up @@ -559,29 +566,39 @@ 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));
}
};

struct WindowOffset {
s32 window_x_offset : 16;
s32 window_y_offset : 16;
};

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 {
Expand Down Expand Up @@ -953,10 +970,14 @@ struct Liverpool {
Scissor screen_scissor;
INSERT_PADDING_WORDS(0xA010 - 0xA00C - 2);
DepthBuffer depth_buffer;
INSERT_PADDING_WORDS(0xA08E - 0xA018);
INSERT_PADDING_WORDS(0xA080 - 0xA018);
WindowOffset window_offset;
ViewportScissor window_scissor;
INSERT_PADDING_WORDS(0xA08E - 0xA081 - 2);
ColorBufferMask color_target_mask;
ColorBufferMask color_shader_mask;
INSERT_PADDING_WORDS(0xA094 - 0xA08E - 2);
ViewportScissor generic_scissor;
INSERT_PADDING_WORDS(2);
std::array<ViewportScissor, NumViewports> viewport_scissors;
std::array<ViewportDepth, NumViewports> viewport_depths;
INSERT_PADDING_WORDS(0xA103 - 0xA0D4);
Expand Down Expand Up @@ -994,7 +1015,9 @@ struct Liverpool {
PolygonControl polygon_control;
ViewportControl viewport_control;
VsOutputControl vs_output_control;
INSERT_PADDING_WORDS(0xA29E - 0xA207 - 2);
INSERT_PADDING_WORDS(0xA292 - 0xA207 - 1);
ModeControl mode_control;
INSERT_PADDING_WORDS(0xA29D - 0xA292 - 1);
u32 index_size;
u32 max_index_size;
IndexBufferType index_buffer_type;
Expand Down Expand Up @@ -1206,8 +1229,11 @@ static_assert(GFX6_3D_REG_INDEX(depth_htile_data_base) == 0xA005);
static_assert(GFX6_3D_REG_INDEX(screen_scissor) == 0xA00C);
static_assert(GFX6_3D_REG_INDEX(depth_buffer.z_info) == 0xA010);
static_assert(GFX6_3D_REG_INDEX(depth_buffer.depth_slice) == 0xA017);
static_assert(GFX6_3D_REG_INDEX(window_offset) == 0xA080);
static_assert(GFX6_3D_REG_INDEX(window_scissor) == 0xA081);
static_assert(GFX6_3D_REG_INDEX(color_target_mask) == 0xA08E);
static_assert(GFX6_3D_REG_INDEX(color_shader_mask) == 0xA08F);
static_assert(GFX6_3D_REG_INDEX(generic_scissor) == 0xA090);
static_assert(GFX6_3D_REG_INDEX(viewport_scissors) == 0xA094);
static_assert(GFX6_3D_REG_INDEX(primitive_restart_index) == 0xA103);
static_assert(GFX6_3D_REG_INDEX(stencil_control) == 0xA10B);
Expand All @@ -1227,6 +1253,7 @@ static_assert(GFX6_3D_REG_INDEX(color_control) == 0xA202);
static_assert(GFX6_3D_REG_INDEX(clipper_control) == 0xA204);
static_assert(GFX6_3D_REG_INDEX(viewport_control) == 0xA206);
static_assert(GFX6_3D_REG_INDEX(vs_output_control) == 0xA207);
static_assert(GFX6_3D_REG_INDEX(mode_control) == 0xA292);
static_assert(GFX6_3D_REG_INDEX(index_size) == 0xA29D);
static_assert(GFX6_3D_REG_INDEX(index_buffer_type) == 0xA29F);
static_assert(GFX6_3D_REG_INDEX(enable_primitive_id) == 0xA2A1);
Expand Down
54 changes: 49 additions & 5 deletions src/video_core/renderer_vulkan/vk_rasterizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,11 +368,55 @@ void Rasterizer::UpdateViewportScissorState() {
.maxDepth = vp.zscale + vp.zoffset,
});
}
const auto& sc = regs.screen_scissor;
scissors.push_back({
.offset = {sc.top_left_x, sc.top_left_y},
.extent = {sc.GetWidth(), sc.GetHeight()},
});

const bool enable_offset = !regs.window_scissor.window_offset_disable.Value();
Liverpool::Scissor scsr{};
const auto combined_scissor_value_tl = [](s16 scr, s16 win, s16 gen, s16 win_offset) {
return std::max({scr, s16(win + win_offset), s16(gen + win_offset)});
};

scsr.top_left_x = combined_scissor_value_tl(
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 = combined_scissor_value_tl(
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);

const auto combined_scissor_value_br = [](s16 scr, s16 win, s16 gen, s16 win_offset) {
return std::min({scr, s16(win + win_offset), s16(gen + win_offset)});
};

scsr.bottom_right_x = combined_scissor_value_br(
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 = combined_scissor_value_br(
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 idx = 0; idx < Liverpool::NumViewports; idx++) {
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[idx].top_left_x.Value()));
vp_scsr.top_left_y =
std::max(vp_scsr.top_left_y, s16(regs.viewport_scissors[idx].top_left_y.Value()));
vp_scsr.bottom_right_x =
std::min(vp_scsr.bottom_right_x, regs.viewport_scissors[idx].bottom_right_x);
vp_scsr.bottom_right_y =
std::min(vp_scsr.bottom_right_y, regs.viewport_scissors[idx].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();
cmdbuf.setViewport(0, viewports);
cmdbuf.setScissor(0, scissors);
Expand Down
Loading