Merge remote-tracking branch 'xenia-master/master' into canary_experimental

This commit is contained in:
Herman S.
2026-03-06 14:10:00 +09:00
65 changed files with 1497 additions and 2231 deletions

View File

@@ -32,7 +32,7 @@ DECLARE_bool(depth_transfer_not_equal_test);
DECLARE_bool(depth_float24_round);
DECLARE_bool(depth_float24_convert_in_pixel_shader);
DECLARE_bool(draw_resolution_scaled_texture_offsets);
DECLARE_bool(gamma_render_target_as_srgb);
DECLARE_bool(gamma_render_target_as_unorm16);
DECLARE_bool(native_2x_msaa);
DECLARE_bool(native_stencil_value_output);
DECLARE_bool(snorm16_render_target_full_range);
@@ -72,12 +72,16 @@ class RenderTargetCache {
// - 16_16_FLOAT, k_16_16_16_16_FLOAT - the Xenos float16 doesn't have
// special values.
// Significant differences:
// - 8_8_8_8_GAMMA - the piecewise linear gamma curve is very different than
// sRGB, one possible path is conversion in shaders (resulting in
// incorrect blending, especially visible on decals in 4D5307E6), another
// is using sRGB render targets and either conversion on resolve or
// reading the resolved data as a true sRGB texture (incorrect when the
// game accesses the data directly, like 4541080F).
// - 8_8_8_8_GAMMA - the piecewise linear gamma precision distribution
// encoding is very different from sRGB. Linear space blending can be
// obtained by promoting to R16G16B16A16_UNORM, but for compact storage,
// conversion in pixel shader output may be done, though it results in
// incorrect blending, especially visible on decals in 4D5307E6. Emulating
// by replacing the encoding with sRGB for render target writes and
// resolved texture reads could work for some games, but certain games,
// such as 4541080F, perform piecewise gamma encoding calculations in
// their code, and that produces noticeably incorrect results if the
// encoding is changed in guest texture memory.
// - 2_10_10_10_FLOAT - ranges significantly different than in float16, much
// smaller RGB range, and alpha is fixed-point and has only 2 bits.
// - 16_16, 16_16_16_16 - has -32 to 32 range, not -1 to 1 - need either to
@@ -91,28 +95,6 @@ class RenderTargetCache {
kPixelShaderInterlock,
};
// Useful host-specific values.
// sRGB conversion from the Direct3D 11.3 functional specification.
static constexpr float kSrgbToLinearDenominator1 = 12.92f;
static constexpr float kSrgbToLinearDenominator2 = 1.055f;
static constexpr float kSrgbToLinearExponent = 2.4f;
static constexpr float kSrgbToLinearOffset = 0.055f;
static constexpr float kSrgbToLinearThreshold = 0.04045f;
static constexpr float SrgbToLinear(float srgb) {
// 0 and 1 must be exactly achievable, also convert NaN to 0.
if (!(srgb > 0.0f)) {
return 0.0f;
}
if (!(srgb < 1.0f)) {
return 1.0f;
}
if (srgb <= kSrgbToLinearThreshold) {
return srgb / kSrgbToLinearDenominator1;
}
return std::pow((srgb + kSrgbToLinearOffset) / kSrgbToLinearDenominator2,
kSrgbToLinearExponent);
}
// Pixel shader interlock implementation helpers.
// Appended to the format in the format constant via bitwise OR.
@@ -221,7 +203,6 @@ class RenderTargetCache {
// formats (resource formats, but if needed, with gamma taken into account) of
// each.
uint32_t GetLastUpdateBoundRenderTargets(
bool distinguish_gamma_formats,
uint32_t* depth_and_color_formats_out = nullptr) const;
protected:
@@ -238,6 +219,8 @@ class RenderTargetCache {
const RegisterFile& register_file() const { return register_file_; }
virtual bool IsGammaFormatHostStorageSeparate() const = 0;
// Call last in implementation-specific initialization (when things like path
// are initialized by the implementation).
void InitializeCommon();
@@ -274,7 +257,7 @@ class RenderTargetCache {
uint32_t pitch_tiles_at_32bpp : 8; // 19
xenos::MsaaSamples msaa_samples : xenos::kMsaaSamplesBits; // 21
uint32_t is_depth : 1; // 22
// Ignoring the blending precision and sRGB.
// Ignoring the blending precision.
uint32_t resource_format : xenos::kRenderTargetFormatBits; // 26
};
@@ -548,10 +531,6 @@ class RenderTargetCache {
assert_true(GetPath() == Path::kHostRenderTargets);
return last_update_accumulated_render_targets_;
}
uint32_t last_update_accumulated_color_targets_are_gamma() const {
assert_true(GetPath() == Path::kHostRenderTargets);
return last_update_accumulated_color_targets_are_gamma_;
}
const std::vector<Transfer>* last_update_transfers() const {
assert_true(GetPath() == Path::kHostRenderTargets);
@@ -697,11 +676,10 @@ class RenderTargetCache {
}
};
static constexpr xenos::ColorRenderTargetFormat GetColorResourceFormat(
xenos::ColorRenderTargetFormat format) {
// sRGB, if used on the host, is a view property or global state - linear
// and sRGB host render targets can share data directly without transfers.
if (format == xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA) {
xenos::ColorRenderTargetFormat GetColorResourceFormat(
xenos::ColorRenderTargetFormat format) const {
if (format == xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA &&
!IsGammaFormatHostStorageSeparate()) {
return xenos::ColorRenderTargetFormat::k_8_8_8_8;
}
return xenos::GetStorageColorFormat(format);
@@ -755,10 +733,6 @@ class RenderTargetCache {
RenderTarget*
last_update_accumulated_render_targets_[1 +
xenos::kMaxColorRenderTargets];
// Whether the color render targets (in bits 0...3) from the last successful
// update have k_8_8_8_8_GAMMA format, for sRGB emulation on the host if
// needed.
uint32_t last_update_accumulated_color_targets_are_gamma_;
// If false, the next update must copy last_update_used_render_targets_ to
// last_update_accumulated_render_targets_ - it's not beneficial or even
// incorrect to keep the previously bound render targets.