Skip to content

Commit

Permalink
sw_rasterizer: truncate depth operations to f24 precision
Browse files Browse the repository at this point in the history
  • Loading branch information
vitor-k committed Jan 16, 2024
1 parent 6a7841d commit 19c30fc
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 10 deletions.
14 changes: 13 additions & 1 deletion src/video_core/pica_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include <bit>
#include <cmath>
#include <cstring>
#include <boost/serialization/access.hpp>
Expand Down Expand Up @@ -31,6 +32,17 @@ struct Float {
return ret;
}

static constexpr Float<M, E> Trunc(float val) {
Float<M, E> ret;
u32 hex = std::bit_cast<u32>(val) & (0xffffffff ^ ((1 << (23 - M)) - 1));
ret.value = std::bit_cast<float>(hex);
return ret;
}

static constexpr Float<M, E> Trunc(const Float<M, E>& val) {
return Trunc(val.ToFloat32());
}

static constexpr Float<M, E> FromRaw(u32 hex) {
Float<M, E> res;

Expand All @@ -50,7 +62,7 @@ struct Float {
hex = sign;
}

std::memcpy(&res.value, &hex, sizeof(float));
res.value = std::bit_cast<float>(hex);

return res;
}
Expand Down
21 changes: 12 additions & 9 deletions src/video_core/renderer_software/sw_rasterizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

namespace SwRenderer {

using Pica::f20;
using Pica::f24;
using Pica::FramebufferRegs;
using Pica::RasterizerRegs;
Expand Down Expand Up @@ -331,18 +332,20 @@ void RasterizerSoftware::ProcessTriangle(const Vertex& v0, const Vertex& v1, con
f24::One() / Common::Dot(w_inverse, baricentric_coordinates);

// interpolated_z = z / w
const float interpolated_z_over_w =
(v0.screenpos[2].ToFloat32() * w0 + v1.screenpos[2].ToFloat32() * w1 +
v2.screenpos[2].ToFloat32() * w2) /
wsum;
const f24 interpolated_z_over_w =
f24::Trunc(f24::Trunc(f24::Trunc(v0.screenpos[2] * baricentric_coordinates[0]) +
f24::Trunc(v1.screenpos[2] * baricentric_coordinates[1]) +
f24::Trunc(v2.screenpos[2] * baricentric_coordinates[2]))
.ToFloat32() /
wsum);

// Not fully accurate. About 3 bits in precision are missing.
// Z-Buffer (z / w * scale + offset)
const float depth_scale =
f24::FromRaw(regs.rasterizer.viewport_depth_range).ToFloat32();
const float depth_offset =
f24::FromRaw(regs.rasterizer.viewport_depth_near_plane).ToFloat32();
float depth = interpolated_z_over_w * depth_scale + depth_offset;
const f24 depth_scale = f24::FromRaw(regs.rasterizer.viewport_depth_range);
const f24 depth_offset = f24::FromRaw(regs.rasterizer.viewport_depth_near_plane);
float depth =
f24::Trunc(f24::Trunc(interpolated_z_over_w * depth_scale) + depth_offset)
.ToFloat32();

// Potentially switch to W-Buffer
if (regs.rasterizer.depthmap_enable ==
Expand Down

0 comments on commit 19c30fc

Please sign in to comment.