[DXBC] ROV: Force late Z write with kill instructions

This commit is contained in:
Triang3l 2020-12-10 12:36:37 +03:00
parent 9349cf4ff4
commit bc0c2040e2
2 changed files with 58 additions and 49 deletions

View File

@ -189,12 +189,12 @@ class DxbcShaderTranslator : public ShaderTranslator {
kSysFlag_ROVStencilTest_Shift, kSysFlag_ROVStencilTest_Shift,
// If the depth/stencil test has failed, but resulted in a stencil value // If the depth/stencil test has failed, but resulted in a stencil value
// that is different than the one currently in the depth buffer, write it // that is different than the one currently in the depth buffer, write it
// anyway and don't run the shader (to check if the sample may be discarded // anyway and don't run the rest of the shader (to check if the sample may
// some way). This, however, also results in depth/stencil testing done // be discarded some way) - use when alpha test and alpha to coverage are
// entirely early even when it passes to prevent writing in divergent places // disabled. Ignored by the shader if not applicable to it (like if it has
// in the shader. When the shader can kill, this must be set only for // kill instructions or writes the depth output).
// RB_DEPTHCONTROL EARLY_Z_ENABLE, not for alpha test/alpha to coverage // TODO(Triang3l): Replace with an alpha-to-mask flag, check if
// disabled. // (flags & (alpha test | alpha to mask)) == (always | disabled).
kSysFlag_ROVDepthStencilEarlyWrite_Shift, kSysFlag_ROVDepthStencilEarlyWrite_Shift,
kSysFlag_Count, kSysFlag_Count,

View File

@ -1024,6 +1024,14 @@ void DxbcShaderTranslator::ROV_DepthStencilTest() {
// temp.z = viewport maximum depth if not writing to oDepth // temp.z = viewport maximum depth if not writing to oDepth
// temp.w = whether depth/stencil has been modified // temp.w = whether depth/stencil has been modified
DxbcOpINE(temp_w_dest, sample_depth_stencil_src, temp_w_src); DxbcOpINE(temp_w_dest, sample_depth_stencil_src, temp_w_src);
if (depth_stencil_early && !CanWriteZEarly()) {
// Set the sample bit in bits 4:7 of system_temp_rov_params_.x - always
// need to write late in this shader, as it may do something like
// explicitly killing pixels.
DxbcOpBFI(DxbcDest::R(system_temp_rov_params_, 0b0001), DxbcSrc::LU(1),
DxbcSrc::LU(4 + i), temp_w_src,
DxbcSrc::R(system_temp_rov_params_, DxbcSrc::kXXXX));
} else {
// Check if need to write. // Check if need to write.
// temp.x? = resulting sample depth/stencil // temp.x? = resulting sample depth/stencil
// temp.y = polygon offset if not writing to oDepth // temp.y = polygon offset if not writing to oDepth
@ -1057,7 +1065,7 @@ void DxbcShaderTranslator::ROV_DepthStencilTest() {
// Need to still run the shader to know whether to write the // Need to still run the shader to know whether to write the
// depth/stencil value. // depth/stencil value.
DxbcOpElse(); DxbcOpElse();
// Set sample bit out of bits 4:7 of system_temp_rov_params_.x if need // Set the sample bit in bits 4:7 of system_temp_rov_params_.x if need
// to write later (after checking if the sample is not discarded by a // to write later (after checking if the sample is not discarded by a
// kill instruction, alphatest or alpha-to-coverage). // kill instruction, alphatest or alpha-to-coverage).
DxbcOpOr(DxbcDest::R(system_temp_rov_params_, 0b0001), DxbcOpOr(DxbcDest::R(system_temp_rov_params_, 0b0001),
@ -1069,6 +1077,7 @@ void DxbcShaderTranslator::ROV_DepthStencilTest() {
} }
// Close the write check. // Close the write check.
DxbcOpEndIf(); DxbcOpEndIf();
}
// Release sample_temp. // Release sample_temp.
PopSystemTemp(); PopSystemTemp();