Skip to content

Commit

Permalink
Merge pull request #1177 from Triang3l/depthbias.
Browse files Browse the repository at this point in the history
[GPU] Depth bias support
  • Loading branch information
gibbed committed Jul 1, 2018
2 parents 15eb6ed + c6255af commit 94d1106
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 5 deletions.
94 changes: 89 additions & 5 deletions src/xenia/gpu/vulkan/pipeline_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,66 @@ bool PipelineCache::SetDynamicState(VkCommandBuffer command_buffer,
vkCmdSetViewport(command_buffer, 0, 1, &viewport_rect);
}

// VK_DYNAMIC_STATE_DEPTH_BIAS
// No separate front/back bias in Vulkan - using what's more expected to work.
// No need to reset to 0 if not enabled in the pipeline - recheck conditions.
float depth_bias_scales[2] = {0}, depth_bias_offsets[2] = {0};
auto cull_mode = regs.pa_su_sc_mode_cntl & 3;
if (cull_mode != 1) {
// Front faces are not culled.
depth_bias_scales[0] =
register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_SCALE].f32;
depth_bias_offsets[0] =
register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_OFFSET].f32;
}
if (cull_mode != 2) {
// Back faces are not culled.
depth_bias_scales[1] =
register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_SCALE].f32;
depth_bias_offsets[1] =
register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_OFFSET].f32;
}
if (depth_bias_scales[0] != 0.0f || depth_bias_scales[1] != 0.0f ||
depth_bias_offsets[0] != 0.0f || depth_bias_offsets[1] != 0.0f) {
float depth_bias_scale, depth_bias_offset;
// Prefer front if not culled and offset for both is enabled.
// However, if none are culled, and there's no front offset, use back offset
// (since there was an intention to enable depth offset at all).
// As SetRenderState sets for both sides, this should be very rare anyway.
// TODO(Triang3l): Verify the intentions if this happens in real games.
if (depth_bias_scales[0] != 0.0f || depth_bias_offsets[0] != 0.0f) {
depth_bias_scale = depth_bias_scales[0];
depth_bias_offset = depth_bias_offsets[0];
} else {
depth_bias_scale = depth_bias_scales[1];
depth_bias_offset = depth_bias_offsets[1];
}
// Convert to Vulkan units based on the values in Call of Duty 4:
// r_polygonOffsetScale is -1 there, but 32 in the register.
// r_polygonOffsetBias is -1 also, but passing 2/65536.
// 1/65536 and 2 scales are applied separately, however, and for shadow maps
// 0.5/65536 is passed (while sm_polygonOffsetBias is 0.5), and with 32768
// it would be 0.25, which seems too small. So using 65536, assuming it's a
// common scale value (which also looks less arbitrary than 32768).
// TODO(Triang3l): Investigate, also considering the depth format (kD24FS8).
// Possibly refer to:
// https://www.winehq.org/pipermail/wine-patches/2015-July/141200.html
float depth_bias_scale_vulkan = depth_bias_scale * (1.0f / 32.0f);
float depth_bias_offset_vulkan = depth_bias_offset * 65536.0f;
if (full_update ||
regs.pa_su_poly_offset_scale != depth_bias_scale_vulkan ||
regs.pa_su_poly_offset_offset != depth_bias_offset_vulkan) {
regs.pa_su_poly_offset_scale = depth_bias_scale_vulkan;
regs.pa_su_poly_offset_offset = depth_bias_offset_vulkan;
vkCmdSetDepthBias(command_buffer, depth_bias_offset_vulkan, 0.0f,
depth_bias_scale_vulkan);
}
} else if (full_update) {
regs.pa_su_poly_offset_scale = 0.0f;
regs.pa_su_poly_offset_offset = 0.0f;
vkCmdSetDepthBias(command_buffer, 0.0f, 0.0f, 0.0f);
}

// VK_DYNAMIC_STATE_BLEND_CONSTANTS
bool blend_constant_state_dirty = full_update;
blend_constant_state_dirty |=
Expand Down Expand Up @@ -864,9 +924,6 @@ bool PipelineCache::SetDynamicState(VkCommandBuffer command_buffer,
// VK_DYNAMIC_STATE_LINE_WIDTH
vkCmdSetLineWidth(command_buffer, 1.0f);

// VK_DYNAMIC_STATE_DEPTH_BIAS
vkCmdSetDepthBias(command_buffer, 0.0f, 0.0f, 0.0f);

// VK_DYNAMIC_STATE_DEPTH_BOUNDS
vkCmdSetDepthBounds(command_buffer, 0.0f, 1.0f);
}
Expand Down Expand Up @@ -1218,6 +1275,33 @@ PipelineCache::UpdateStatus PipelineCache::UpdateRasterizationState(
dirty |= SetShadowRegister(&regs.multi_prim_ib_reset_index,
XE_GPU_REG_VGT_MULTI_PRIM_IB_RESET_INDX);
regs.primitive_type = primitive_type;

// Vulkan doesn't support separate depth biases for different sides.
// SetRenderState also accepts only one argument, so they should be rare.
// The culling mode must match the one in SetDynamicState, so not applying
// the primitive type exceptions to this (very unlikely to happen anyway).
bool depth_bias_enable = false;
uint32_t cull_mode = regs.pa_su_sc_mode_cntl & 0x3;
if (cull_mode != 1) {
float depth_bias_scale =
register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_SCALE].f32;
float depth_bias_offset =
register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_OFFSET].f32;
depth_bias_enable = (depth_bias_scale != 0.0f && depth_bias_offset != 0.0f);
}
if (!depth_bias_enable && cull_mode != 2) {
float depth_bias_scale =
register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_SCALE].f32;
float depth_bias_offset =
register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_OFFSET].f32;
depth_bias_enable = (depth_bias_scale != 0.0f && depth_bias_offset != 0.0f);
}
if (regs.pa_su_poly_offset_enable !=
static_cast<uint32_t>(depth_bias_enable)) {
regs.pa_su_poly_offset_enable = static_cast<uint32_t>(depth_bias_enable);
dirty = true;
}

XXH64_update(&hash_state_, &regs, sizeof(regs));
if (!dirty) {
return UpdateStatus::kCompatible;
Expand Down Expand Up @@ -1252,7 +1336,7 @@ PipelineCache::UpdateStatus PipelineCache::UpdateRasterizationState(
state_info.polygonMode = VK_POLYGON_MODE_FILL;
}

switch (regs.pa_su_sc_mode_cntl & 0x3) {
switch (cull_mode) {
case 0:
state_info.cullMode = VK_CULL_MODE_NONE;
break;
Expand Down Expand Up @@ -1280,7 +1364,7 @@ PipelineCache::UpdateStatus PipelineCache::UpdateRasterizationState(
state_info.cullMode = VK_CULL_MODE_NONE;
}

state_info.depthBiasEnable = VK_FALSE;
state_info.depthBiasEnable = depth_bias_enable ? VK_TRUE : VK_FALSE;

// Ignored; set dynamically:
state_info.depthBiasConstantFactor = 0;
Expand Down
4 changes: 4 additions & 0 deletions src/xenia/gpu/vulkan/pipeline_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ class PipelineCache {
uint32_t pa_sc_screen_scissor_tl;
uint32_t pa_sc_screen_scissor_br;
uint32_t pa_sc_viz_query;
uint32_t pa_su_poly_offset_enable;
uint32_t multi_prim_ib_reset_index;

UpdateRasterizationStateRegisters() { Reset(); }
Expand Down Expand Up @@ -275,6 +276,9 @@ class PipelineCache {

uint32_t rb_surface_info;
uint32_t pa_su_sc_vtx_cntl;
// Bias is in Vulkan units because depth format may potentially effect it.
float pa_su_poly_offset_scale;
float pa_su_poly_offset_offset;
uint32_t pa_cl_vte_cntl;
float pa_cl_vport_xoffset;
float pa_cl_vport_yoffset;
Expand Down

2 comments on commit 94d1106

@Parovozik
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😋
bomberman

@Triang3l
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still some shadow acne there — random grey dots here and there. Will check what values it sends some time later.

Please sign in to comment.