[GPU] Non-ROV f24 trunc/round, host shader modifications, cache dir
This commit is contained in:
@@ -167,7 +167,7 @@ void DxbcShaderTranslator::StartPixelShader_LoadROVParameters() {
|
||||
// bigger) to integer to system_temp_rov_params_.zw.
|
||||
// system_temp_rov_params_.z = X host pixel position as uint
|
||||
// system_temp_rov_params_.w = Y host pixel position as uint
|
||||
in_position_xy_used_ = true;
|
||||
in_position_used_ |= 0b0011;
|
||||
DxbcOpFToU(DxbcDest::R(system_temp_rov_params_, 0b1100),
|
||||
DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition), 0b01000000));
|
||||
// Revert the resolution scale to convert the position to guest pixels.
|
||||
@@ -315,7 +315,7 @@ void DxbcShaderTranslator::StartPixelShader_LoadROVParameters() {
|
||||
// Add host pixel offsets.
|
||||
// system_temp_rov_params_.y = scaled 32bpp depth/stencil address
|
||||
// system_temp_rov_params_.z = scaled 32bpp color offset if needed
|
||||
in_position_xy_used_ = true;
|
||||
in_position_used_ |= 0b0011;
|
||||
for (uint32_t i = 0; i < 2; ++i) {
|
||||
// Convert a position component to integer.
|
||||
DxbcOpFToU(DxbcDest::R(system_temp_rov_params_, 0b0001),
|
||||
@@ -417,23 +417,50 @@ void DxbcShaderTranslator::ROV_DepthStencilTest() {
|
||||
// With early depth/stencil, depth/stencil writing may be deferred to the
|
||||
// end of the shader to prevent writing in case something (like alpha test,
|
||||
// which is dynamic GPU state) discards the pixel. So, write directly to the
|
||||
// persistent register, system_temp_rov_depth_stencil_, instead of a local
|
||||
// persistent register, system_temp_depth_stencil_, instead of a local
|
||||
// temporary register.
|
||||
DxbcDest sample_depth_stencil_dest(
|
||||
depth_stencil_early
|
||||
? DxbcDest::R(system_temp_rov_depth_stencil_, 1 << i)
|
||||
: temp_x_dest);
|
||||
depth_stencil_early ? DxbcDest::R(system_temp_depth_stencil_, 1 << i)
|
||||
: temp_x_dest);
|
||||
DxbcSrc sample_depth_stencil_src(
|
||||
depth_stencil_early
|
||||
? DxbcSrc::R(system_temp_rov_depth_stencil_).Select(i)
|
||||
: temp_x_src);
|
||||
depth_stencil_early ? DxbcSrc::R(system_temp_depth_stencil_).Select(i)
|
||||
: temp_x_src);
|
||||
|
||||
if (!i) {
|
||||
if (writes_depth()) {
|
||||
// Clamp oDepth to the lower viewport depth bound (depth clamp happens
|
||||
// after the pixel shader in the pipeline, at least on Direct3D 11 and
|
||||
// Vulkan, thus applies to the shader's depth output too).
|
||||
system_constants_used_ |= 1ull << kSysConst_EdramDepthRange_Index;
|
||||
DxbcOpMax(DxbcDest::R(system_temp_depth_stencil_, 0b0001),
|
||||
DxbcSrc::R(system_temp_depth_stencil_, DxbcSrc::kXXXX),
|
||||
DxbcSrc::CB(cbuffer_index_system_constants_,
|
||||
uint32_t(CbufferRegister::kSystemConstants),
|
||||
kSysConst_EdramDepthRange_Vec)
|
||||
.Select(kSysConst_EdramDepthRangeOffset_Comp));
|
||||
// Calculate the upper Z range bound to temp.x for clamping after
|
||||
// biasing.
|
||||
// temp.x = viewport maximum depth
|
||||
system_constants_used_ |= 1ull << kSysConst_EdramDepthRange_Index;
|
||||
DxbcOpAdd(temp_x_dest,
|
||||
DxbcSrc::CB(cbuffer_index_system_constants_,
|
||||
uint32_t(CbufferRegister::kSystemConstants),
|
||||
kSysConst_EdramDepthRange_Vec)
|
||||
.Select(kSysConst_EdramDepthRangeOffset_Comp),
|
||||
DxbcSrc::CB(cbuffer_index_system_constants_,
|
||||
uint32_t(CbufferRegister::kSystemConstants),
|
||||
kSysConst_EdramDepthRange_Vec)
|
||||
.Select(kSysConst_EdramDepthRangeScale_Comp));
|
||||
// Clamp oDepth to the upper viewport depth bound (already not above 1,
|
||||
// but saturate for total safety).
|
||||
// temp.x = free
|
||||
DxbcOpMin(DxbcDest::R(system_temp_depth_stencil_, 0b0001),
|
||||
DxbcSrc::R(system_temp_depth_stencil_, DxbcSrc::kXXXX),
|
||||
temp_x_src, true);
|
||||
// Convert the shader-generated depth to 24-bit, using temp.x as
|
||||
// temporary.
|
||||
ROV_DepthTo24Bit(system_temp_rov_depth_stencil_, 0,
|
||||
system_temp_rov_depth_stencil_, 0, temp, 0);
|
||||
ROV_DepthTo24Bit(system_temp_depth_stencil_, 0,
|
||||
system_temp_depth_stencil_, 0, temp, 0);
|
||||
} else {
|
||||
// Load the first sample's Z*W and W to temp.xy - need this regardless
|
||||
// of coverage for polygon offset.
|
||||
@@ -529,14 +556,14 @@ void DxbcShaderTranslator::ROV_DepthStencilTest() {
|
||||
}
|
||||
|
||||
// Get if the current sample is covered to temp.w.
|
||||
// temp.x = first sample's viewport space Z or 24-bit oDepth
|
||||
// temp.x = first sample's viewport space Z if not writing to oDepth
|
||||
// temp.y = polygon offset if not writing to oDepth
|
||||
// temp.z = viewport maximum depth if not writing to oDepth
|
||||
// temp.w = coverage of the current sample
|
||||
DxbcOpAnd(temp_w_dest, DxbcSrc::R(system_temp_rov_params_, DxbcSrc::kXXXX),
|
||||
DxbcSrc::LU(1 << i));
|
||||
// Check if the current sample is covered. Release 1 VGPR.
|
||||
// temp.x = first sample's viewport space Z or 24-bit oDepth
|
||||
// temp.x = first sample's viewport space Z if not writing to oDepth
|
||||
// temp.y = polygon offset if not writing to oDepth
|
||||
// temp.z = viewport maximum depth if not writing to oDepth
|
||||
// temp.w = free
|
||||
@@ -546,7 +573,7 @@ void DxbcShaderTranslator::ROV_DepthStencilTest() {
|
||||
// Copy the 24-bit depth common to all samples to sample_depth_stencil.
|
||||
// temp.x = shader-generated 24-bit depth
|
||||
DxbcOpMov(sample_depth_stencil_dest,
|
||||
DxbcSrc::R(system_temp_rov_depth_stencil_, DxbcSrc::kXXXX));
|
||||
DxbcSrc::R(system_temp_depth_stencil_, DxbcSrc::kXXXX));
|
||||
} else {
|
||||
if (i) {
|
||||
// Sample's depth precalculated for sample 0 (for slope-scaled depth
|
||||
@@ -1720,7 +1747,7 @@ void DxbcShaderTranslator::CompletePixelShader_WriteToRTVs_AlphaToMask() {
|
||||
// Convert SSAA sample position to integer to temp.xy (not caring about the
|
||||
// resolution scale because it's not supported anywhere on the RTV output
|
||||
// path).
|
||||
in_position_xy_used_ = true;
|
||||
in_position_used_ |= 0b0011;
|
||||
DxbcOpFToU(DxbcDest::R(temp, 0b0011),
|
||||
DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition)));
|
||||
|
||||
@@ -1913,6 +1940,139 @@ void DxbcShaderTranslator::CompletePixelShader_WriteToRTVs() {
|
||||
PopSystemTemp(2);
|
||||
}
|
||||
|
||||
void DxbcShaderTranslator::CompletePixelShader_DSV_DepthTo24Bit() {
|
||||
if (!DSV_IsWritingFloat24Depth()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t temp;
|
||||
if (writes_depth()) {
|
||||
// The depth is already written to system_temp_depth_stencil_.x and clamped
|
||||
// to 0...1 with NaNs dropped (saturating in StoreResult); yzw are free.
|
||||
temp = system_temp_depth_stencil_;
|
||||
} else {
|
||||
// Need a temporary variable; copy the sample's depth input to it and
|
||||
// saturate it (in Direct3D 11, depth is clamped to the viewport bounds
|
||||
// after the pixel shader, and SV_Position.z contains the unclamped depth,
|
||||
// which may be outside the viewport's depth range if it's biased); though
|
||||
// it will be clamped to the viewport bounds anyway, but to be able to make
|
||||
// the assumption of it being clamped while working with the bit
|
||||
// representation.
|
||||
temp = PushSystemTemp();
|
||||
in_position_used_ |= 0b0100;
|
||||
DxbcOpMov(
|
||||
DxbcDest::R(temp, 0b0001),
|
||||
DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition), DxbcSrc::kZZZZ),
|
||||
true);
|
||||
}
|
||||
|
||||
DxbcDest temp_x_dest(DxbcDest::R(temp, 0b0001));
|
||||
DxbcSrc temp_x_src(DxbcSrc::R(temp, DxbcSrc::kXXXX));
|
||||
DxbcDest temp_y_dest(DxbcDest::R(temp, 0b0010));
|
||||
DxbcSrc temp_y_src(DxbcSrc::R(temp, DxbcSrc::kYYYY));
|
||||
|
||||
if (GetDxbcShaderModification().depth_stencil_mode ==
|
||||
Modification::DepthStencilMode::kFloat24Truncating) {
|
||||
// Simplified conversion, always less than or equal to the original value -
|
||||
// just drop the lower bits.
|
||||
// The float32 exponent bias is 127.
|
||||
// After saturating, the exponent range is -127...0.
|
||||
// The smallest normalized 20e4 exponent is -14 - should drop 3 mantissa
|
||||
// bits at -14 or above.
|
||||
// The smallest denormalized 20e4 number is -34 - should drop 23 mantissa
|
||||
// bits at -34.
|
||||
// Anything smaller than 2^-34 becomes 0.
|
||||
DxbcDest truncate_dest(writes_depth() ? DxbcDest::ODepth()
|
||||
: DxbcDest::ODepthLE());
|
||||
// Check if the number is representable as a float24 after truncation - the
|
||||
// exponent is at least -34.
|
||||
DxbcOpUGE(temp_y_dest, temp_x_src, DxbcSrc::LU(0x2E800000));
|
||||
DxbcOpIf(true, temp_y_src);
|
||||
{
|
||||
// Extract the biased float32 exponent to temp.y.
|
||||
// temp.y = 113+ at exponent -14+.
|
||||
// temp.y = 93 at exponent -34.
|
||||
DxbcOpUBFE(temp_y_dest, DxbcSrc::LU(8), DxbcSrc::LU(23), temp_x_src);
|
||||
// Convert exponent to the unclamped number of bits to truncate.
|
||||
// 116 - 113 = 3.
|
||||
// 116 - 93 = 23.
|
||||
// temp.y = 3+ at exponent -14+.
|
||||
// temp.y = 23 at exponent -34.
|
||||
DxbcOpIAdd(temp_y_dest, DxbcSrc::LI(116), -temp_y_src);
|
||||
// Clamp the truncated bit count to drop 3 bits of any normal number.
|
||||
// Exponents below -34 are handled separately.
|
||||
// temp.y = 3 at exponent -14.
|
||||
// temp.y = 23 at exponent -34.
|
||||
DxbcOpIMax(temp_y_dest, temp_y_src, DxbcSrc::LI(3));
|
||||
// Truncate the mantissa - fill the low bits with zeros.
|
||||
DxbcOpBFI(truncate_dest, temp_y_src, DxbcSrc::LU(0), DxbcSrc::LU(0),
|
||||
temp_x_src);
|
||||
}
|
||||
// The number is not representable as float24 after truncation - zero.
|
||||
DxbcOpElse();
|
||||
DxbcOpMov(truncate_dest, DxbcSrc::LF(0.0f));
|
||||
// Close the non-zero result check.
|
||||
DxbcOpEndIf();
|
||||
} else {
|
||||
// Properly convert to 20e4, with rounding to the nearest even.
|
||||
PreClampedDepthTo20e4(temp, 0, temp, 0, temp, 1);
|
||||
// Convert back to float32.
|
||||
// https://github.com/Microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexConvert.cpp
|
||||
// Unpack the exponent to temp.y.
|
||||
DxbcOpUShR(temp_y_dest, temp_x_src, DxbcSrc::LU(20));
|
||||
// Unpack the mantissa to temp.x.
|
||||
DxbcOpAnd(temp_x_dest, temp_x_src, DxbcSrc::LU(0xFFFFF));
|
||||
// Check if the number is denormalized.
|
||||
DxbcOpIf(false, temp_y_src);
|
||||
{
|
||||
// Check if the number is non-zero (if the mantissa isn't zero - the
|
||||
// exponent is known to be zero at this point).
|
||||
DxbcOpIf(true, temp_x_src);
|
||||
{
|
||||
// Normalize the mantissa.
|
||||
// Note that HLSL firstbithigh(x) is compiled to DXBC like:
|
||||
// `x ? 31 - firstbit_hi(x) : -1`
|
||||
// (returns the index from the LSB, not the MSB, but -1 for zero too).
|
||||
// temp.y = firstbit_hi(mantissa)
|
||||
DxbcOpFirstBitHi(temp_y_dest, temp_x_src);
|
||||
// temp.y = 20 - firstbithigh(mantissa)
|
||||
// Or:
|
||||
// temp.y = 20 - (31 - firstbit_hi(mantissa))
|
||||
DxbcOpIAdd(temp_y_dest, temp_y_src, DxbcSrc::LI(20 - 31));
|
||||
// mantissa = mantissa << (20 - firstbithigh(mantissa))
|
||||
// AND 0xFFFFF not needed after this - BFI will do it.
|
||||
DxbcOpIShL(temp_x_dest, temp_x_src, temp_y_src);
|
||||
// Get the normalized exponent.
|
||||
// exponent = 1 - (20 - firstbithigh(mantissa))
|
||||
DxbcOpIAdd(temp_y_dest, DxbcSrc::LI(1), -temp_y_src);
|
||||
}
|
||||
// The number is zero.
|
||||
DxbcOpElse();
|
||||
{
|
||||
// Set the unbiased exponent to -112 for zero - 112 will be added later,
|
||||
// resulting in zero float32.
|
||||
DxbcOpMov(temp_y_dest, DxbcSrc::LI(-112));
|
||||
}
|
||||
// Close the non-zero check.
|
||||
DxbcOpEndIf();
|
||||
}
|
||||
// Close the denormal check.
|
||||
DxbcOpEndIf();
|
||||
// Bias the exponent and move it to the correct location in float32 to
|
||||
// temp.y.
|
||||
DxbcOpIMAd(temp_y_dest, temp_y_src, DxbcSrc::LI(1 << 23),
|
||||
DxbcSrc::LI(112 << 23));
|
||||
// Combine the mantissa and the exponent into the result.
|
||||
DxbcOpBFI(DxbcDest::ODepth(), DxbcSrc::LU(20), DxbcSrc::LU(3), temp_x_src,
|
||||
temp_y_src);
|
||||
}
|
||||
|
||||
if (!writes_depth()) {
|
||||
// Release temp.
|
||||
PopSystemTemp();
|
||||
}
|
||||
}
|
||||
|
||||
void DxbcShaderTranslator::CompletePixelShader_ROV_AlphaToMaskSample(
|
||||
uint32_t sample_index, float threshold_base, DxbcSrc threshold_offset,
|
||||
float threshold_offset_scale, uint32_t temp, uint32_t temp_component) {
|
||||
@@ -1957,7 +2117,7 @@ void DxbcShaderTranslator::CompletePixelShader_ROV_AlphaToMask() {
|
||||
// floating-point. With resolution scaling, still using host pixels, to
|
||||
// preserve the idea of dithering.
|
||||
// temp.x = alpha to coverage offset as float 0.0...3.0.
|
||||
in_position_xy_used_ = true;
|
||||
in_position_used_ |= 0b0011;
|
||||
DxbcOpFToU(DxbcDest::R(temp, 0b0011),
|
||||
DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition)));
|
||||
DxbcOpAnd(DxbcDest::R(temp, 0b0010), DxbcSrc::R(temp, DxbcSrc::kYYYY),
|
||||
@@ -2067,7 +2227,7 @@ void DxbcShaderTranslator::CompletePixelShader_WriteToROV() {
|
||||
DxbcOpStoreUAVTyped(
|
||||
DxbcDest::U(uav_index_edram_, uint32_t(UAVRegister::kEdram)),
|
||||
DxbcSrc::R(system_temp_rov_params_, DxbcSrc::kYYYY), 1,
|
||||
DxbcSrc::R(system_temp_rov_depth_stencil_).Select(i));
|
||||
DxbcSrc::R(system_temp_depth_stencil_).Select(i));
|
||||
}
|
||||
// Close the write check.
|
||||
DxbcOpEndIf();
|
||||
@@ -3059,15 +3219,16 @@ void DxbcShaderTranslator::CompletePixelShader() {
|
||||
CompletePixelShader_WriteToROV();
|
||||
} else {
|
||||
CompletePixelShader_WriteToRTVs();
|
||||
CompletePixelShader_DSV_DepthTo24Bit();
|
||||
}
|
||||
}
|
||||
|
||||
void DxbcShaderTranslator::ROV_DepthTo24Bit(uint32_t d24_temp,
|
||||
uint32_t d24_temp_component,
|
||||
uint32_t d32_temp,
|
||||
uint32_t d32_temp_component,
|
||||
uint32_t temp_temp,
|
||||
uint32_t temp_temp_component) {
|
||||
void DxbcShaderTranslator::PreClampedDepthTo20e4(uint32_t d24_temp,
|
||||
uint32_t d24_temp_component,
|
||||
uint32_t d32_temp,
|
||||
uint32_t d32_temp_component,
|
||||
uint32_t temp_temp,
|
||||
uint32_t temp_temp_component) {
|
||||
assert_true(temp_temp != d24_temp ||
|
||||
temp_temp_component != d24_temp_component);
|
||||
assert_true(temp_temp != d32_temp ||
|
||||
@@ -3079,68 +3240,83 @@ void DxbcShaderTranslator::ROV_DepthTo24Bit(uint32_t d24_temp,
|
||||
DxbcDest temp_dest(DxbcDest::R(temp_temp, 1 << temp_temp_component));
|
||||
DxbcSrc temp_src(DxbcSrc::R(temp_temp).Select(temp_temp_component));
|
||||
|
||||
// CFloat24 from d3dref9.dll.
|
||||
// Assuming the depth is already clamped to [0, 2) (in all places, the depth
|
||||
// is written with the saturate flag set).
|
||||
|
||||
// Check if the number is too small to be represented as normalized 20e4.
|
||||
// temp = f32 < 2^-14
|
||||
DxbcOpULT(temp_dest, d32_src, DxbcSrc::LU(0x38800000));
|
||||
// Handle denormalized numbers separately.
|
||||
DxbcOpIf(true, temp_src);
|
||||
{
|
||||
// temp = f32 >> 23
|
||||
DxbcOpUShR(temp_dest, d32_src, DxbcSrc::LU(23));
|
||||
// temp = 113 - (f32 >> 23)
|
||||
DxbcOpIAdd(temp_dest, DxbcSrc::LI(113), -temp_src);
|
||||
// Don't allow the shift to overflow, since in DXBC the lower 5 bits of the
|
||||
// shift amount are used (otherwise 0 becomes 8).
|
||||
// temp = min(113 - (f32 >> 23), 24)
|
||||
DxbcOpUMin(temp_dest, temp_src, DxbcSrc::LU(24));
|
||||
// biased_f32 = (f32 & 0x7FFFFF) | 0x800000
|
||||
DxbcOpBFI(d24_dest, DxbcSrc::LU(9), DxbcSrc::LU(23), DxbcSrc::LU(1),
|
||||
d32_src);
|
||||
// biased_f32 = ((f32 & 0x7FFFFF) | 0x800000) >> min(113 - (f32 >> 23), 24)
|
||||
DxbcOpUShR(d24_dest, d24_src, temp_src);
|
||||
}
|
||||
// Not denormalized?
|
||||
DxbcOpElse();
|
||||
{
|
||||
// Bias the exponent.
|
||||
// biased_f32 = f32 + (-112 << 23)
|
||||
// (left shift of a negative value is undefined behavior)
|
||||
DxbcOpIAdd(d24_dest, d32_src, DxbcSrc::LU(0xC8000000u));
|
||||
}
|
||||
// Close the denormal check.
|
||||
DxbcOpEndIf();
|
||||
// Build the 20e4 number.
|
||||
// temp = (biased_f32 >> 3) & 1
|
||||
DxbcOpUBFE(temp_dest, DxbcSrc::LU(1), DxbcSrc::LU(3), d24_src);
|
||||
// f24 = biased_f32 + 3
|
||||
DxbcOpIAdd(d24_dest, d24_src, DxbcSrc::LU(3));
|
||||
// f24 = biased_f32 + 3 + ((biased_f32 >> 3) & 1)
|
||||
DxbcOpIAdd(d24_dest, d24_src, temp_src);
|
||||
// f24 = ((biased_f32 + 3 + ((biased_f32 >> 3) & 1)) >> 3) & 0xFFFFFF
|
||||
DxbcOpUBFE(d24_dest, DxbcSrc::LU(24), DxbcSrc::LU(3), d24_src);
|
||||
}
|
||||
|
||||
void DxbcShaderTranslator::ROV_DepthTo24Bit(uint32_t d24_temp,
|
||||
uint32_t d24_temp_component,
|
||||
uint32_t d32_temp,
|
||||
uint32_t d32_temp_component,
|
||||
uint32_t temp_temp,
|
||||
uint32_t temp_temp_component) {
|
||||
assert_true(temp_temp != d32_temp ||
|
||||
temp_temp_component != d32_temp_component);
|
||||
// Source and destination may be the same.
|
||||
|
||||
system_constants_used_ |= 1ull << kSysConst_Flags_Index;
|
||||
DxbcOpAnd(temp_dest,
|
||||
DxbcOpAnd(DxbcDest::R(temp_temp, 1 << temp_temp_component),
|
||||
DxbcSrc::CB(cbuffer_index_system_constants_,
|
||||
uint32_t(CbufferRegister::kSystemConstants),
|
||||
kSysConst_Flags_Vec)
|
||||
.Select(kSysConst_Flags_Comp),
|
||||
DxbcSrc::LU(kSysFlag_ROVDepthFloat24));
|
||||
// Convert according to the format.
|
||||
DxbcOpIf(true, temp_src);
|
||||
DxbcOpIf(true, DxbcSrc::R(temp_temp).Select(temp_temp_component));
|
||||
{
|
||||
// 20e4 conversion, using 1 VGPR.
|
||||
// CFloat24 from d3dref9.dll.
|
||||
// Assuming the depth is already clamped to [0, 2) (in all places, the depth
|
||||
// is written with the saturate flag set).
|
||||
|
||||
// Check if the number is too small to be represented as normalized 20e4.
|
||||
// temp = f32 < 2^-14
|
||||
DxbcOpULT(temp_dest, d32_src, DxbcSrc::LU(0x38800000));
|
||||
// Handle denormalized numbers separately.
|
||||
DxbcOpIf(true, temp_src);
|
||||
{
|
||||
// temp = f32 >> 23
|
||||
DxbcOpUShR(temp_dest, d32_src, DxbcSrc::LU(23));
|
||||
// temp = 113 - (f32 >> 23)
|
||||
DxbcOpIAdd(temp_dest, DxbcSrc::LI(113), -temp_src);
|
||||
// Don't allow the shift to overflow, since in DXBC the lower 5 bits of
|
||||
// the shift amount are used (otherwise 0 becomes 8).
|
||||
// temp = min(113 - (f32 >> 23), 24)
|
||||
DxbcOpUMin(temp_dest, temp_src, DxbcSrc::LU(24));
|
||||
// biased_f32 = (f32 & 0x7FFFFF) | 0x800000
|
||||
DxbcOpBFI(d24_dest, DxbcSrc::LU(9), DxbcSrc::LU(23), DxbcSrc::LU(1),
|
||||
d32_src);
|
||||
// biased_f32 =
|
||||
// ((f32 & 0x7FFFFF) | 0x800000) >> min(113 - (f32 >> 23), 24)
|
||||
DxbcOpUShR(d24_dest, d24_src, temp_src);
|
||||
}
|
||||
// Not denormalized?
|
||||
DxbcOpElse();
|
||||
{
|
||||
// Bias the exponent.
|
||||
// biased_f32 = f32 + (-112 << 23)
|
||||
// (left shift of a negative value is undefined behavior)
|
||||
DxbcOpIAdd(d24_dest, d32_src, DxbcSrc::LU(0xC8000000u));
|
||||
}
|
||||
// Close the denormal check.
|
||||
DxbcOpEndIf();
|
||||
// Build the 20e4 number.
|
||||
// temp = (biased_f32 >> 3) & 1
|
||||
DxbcOpUBFE(temp_dest, DxbcSrc::LU(1), DxbcSrc::LU(3), d24_src);
|
||||
// f24 = biased_f32 + 3
|
||||
DxbcOpIAdd(d24_dest, d24_src, DxbcSrc::LU(3));
|
||||
// f24 = biased_f32 + 3 + ((biased_f32 >> 3) & 1)
|
||||
DxbcOpIAdd(d24_dest, d24_src, temp_src);
|
||||
// f24 = ((biased_f32 + 3 + ((biased_f32 >> 3) & 1)) >> 3) & 0xFFFFFF
|
||||
DxbcOpUBFE(d24_dest, DxbcSrc::LU(24), DxbcSrc::LU(3), d24_src);
|
||||
// 20e4 conversion.
|
||||
PreClampedDepthTo20e4(d24_temp, d24_temp_component, d32_temp,
|
||||
d32_temp_component, temp_temp, temp_temp_component);
|
||||
}
|
||||
DxbcOpElse();
|
||||
{
|
||||
// Unorm24 conversion.
|
||||
|
||||
DxbcDest d24_dest(DxbcDest::R(d24_temp, 1 << d24_temp_component));
|
||||
DxbcSrc d24_src(DxbcSrc::R(d24_temp).Select(d24_temp_component));
|
||||
// Multiply by float(0xFFFFFF).
|
||||
DxbcOpMul(d24_dest, d32_src, DxbcSrc::LF(16777215.0f));
|
||||
DxbcOpMul(d24_dest, DxbcSrc::R(d32_temp).Select(d32_temp_component),
|
||||
DxbcSrc::LF(16777215.0f));
|
||||
// Round to the nearest even integer. This seems to be the correct way:
|
||||
// rounding towards zero gives 0xFF instead of 0x100 in clear shaders in,
|
||||
// for instance, Halo 3, but other clear shaders in it are also broken if
|
||||
|
||||
Reference in New Issue
Block a user