[GPU] Mostly generic, not square-only resolution scaling

This commit is contained in:
Triang3l
2021-12-11 21:55:33 +03:00
parent e2da8597e1
commit 38b4741c8f
254 changed files with 86052 additions and 344263 deletions

View File

@@ -778,11 +778,10 @@ std::string D3D12CommandProcessor::GetWindowTitleText() const {
default:
break;
}
uint32_t resolution_scale = render_target_cache_->GetResolutionScale();
if (resolution_scale > 1) {
title.put(' ');
title << resolution_scale;
title.put('x');
uint32_t resolution_scale_x = texture_cache_->GetDrawResolutionScaleX();
uint32_t resolution_scale_y = texture_cache_->GetDrawResolutionScaleY();
if (resolution_scale_x > 1 || resolution_scale_y > 1) {
title << ' ' << resolution_scale_x << 'x' << resolution_scale_y;
}
}
return title.str();
@@ -1203,7 +1202,8 @@ bool D3D12CommandProcessor::SetupContext() {
texture_cache_ = std::make_unique<TextureCache>(
*this, *register_file_, *shared_memory_, bindless_resources_used_,
render_target_cache_->GetResolutionScale());
render_target_cache_->GetResolutionScaleX(),
render_target_cache_->GetResolutionScaleY());
if (!texture_cache_->Initialize()) {
XELOGE("Failed to initialize the texture cache");
return false;
@@ -1791,10 +1791,11 @@ void D3D12CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
PushTransitionBarrier(swap_texture_, D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
// Don't care about graphics state because the frame is ending anyway.
auto swap_screen_size = GetSwapScreenSize();
{
std::lock_guard<std::mutex> lock(swap_state_.mutex);
swap_state_.width = swap_texture_size.first;
swap_state_.height = swap_texture_size.second;
swap_state_.width = swap_screen_size.first;
swap_state_.height = swap_screen_size.second;
swap_state_.front_buffer_texture =
reinterpret_cast<uintptr_t>(swap_texture_srv_descriptor_heap_);
}
@@ -1961,13 +1962,14 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
}
// Get dynamic rasterizer state.
uint32_t resolution_scale = texture_cache_->GetDrawResolutionScale();
uint32_t resolution_scale_x = texture_cache_->GetDrawResolutionScaleX();
uint32_t resolution_scale_y = texture_cache_->GetDrawResolutionScaleY();
RenderTargetCache::DepthFloat24Conversion depth_float24_conversion =
render_target_cache_->depth_float24_conversion();
draw_util::ViewportInfo viewport_info;
draw_util::GetHostViewportInfo(
regs, resolution_scale, true, D3D12_VIEWPORT_BOUNDS_MAX,
D3D12_VIEWPORT_BOUNDS_MAX, false,
regs, resolution_scale_x, resolution_scale_y, true,
D3D12_VIEWPORT_BOUNDS_MAX, D3D12_VIEWPORT_BOUNDS_MAX, false,
host_render_targets_used &&
(depth_float24_conversion ==
RenderTargetCache::DepthFloat24Conversion::kOnOutputTruncating ||
@@ -1977,10 +1979,10 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
viewport_info);
draw_util::Scissor scissor;
draw_util::GetScissor(regs, scissor);
scissor.offset[0] *= resolution_scale;
scissor.offset[1] *= resolution_scale;
scissor.extent[0] *= resolution_scale;
scissor.extent[1] *= resolution_scale;
scissor.offset[0] *= resolution_scale_x;
scissor.offset[1] *= resolution_scale_y;
scissor.extent[0] *= resolution_scale_x;
scissor.extent[1] *= resolution_scale_y;
// Update viewport, scissor, blend factor and stencil reference.
UpdateFixedFunctionState(viewport_info, scissor, primitive_polygonal);
@@ -2374,7 +2376,7 @@ bool D3D12CommandProcessor::IssueCopy() {
return false;
}
if (cvars::d3d12_readback_resolve &&
texture_cache_->GetDrawResolutionScale() <= 1 && written_length) {
!texture_cache_->IsDrawResolutionScaled() && written_length) {
// Read the resolved data on the CPU.
ID3D12Resource* readback_buffer = RequestReadbackBuffer(written_length);
if (readback_buffer != nullptr) {
@@ -2873,7 +2875,8 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
bool edram_rov_used = render_target_cache_->GetPath() ==
RenderTargetCache::Path::kPixelShaderInterlock;
uint32_t resolution_scale = texture_cache_->GetDrawResolutionScale();
uint32_t resolution_scale_x = texture_cache_->GetDrawResolutionScaleX();
uint32_t resolution_scale_y = texture_cache_->GetDrawResolutionScaleY();
// Get the color info register values for each render target. Also, for ROV,
// exclude components that don't exist in the format from the write mask.
@@ -3070,10 +3073,10 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
system_constants_.point_size_min = point_size_min;
system_constants_.point_size_max = point_size_max;
float point_screen_to_ndc_x =
(/* 0.5f * 2.0f * */ float(resolution_scale)) /
(/* 0.5f * 2.0f * */ float(resolution_scale_x)) /
std::max(viewport_info.xy_extent[0], uint32_t(1));
float point_screen_to_ndc_y =
(/* 0.5f * 2.0f * */ float(resolution_scale)) /
(/* 0.5f * 2.0f * */ float(resolution_scale_y)) /
std::max(viewport_info.xy_extent[1], uint32_t(1));
dirty |= system_constants_.point_screen_to_ndc[0] != point_screen_to_ndc_x;
dirty |= system_constants_.point_screen_to_ndc[1] != point_screen_to_ndc_y;
@@ -3142,15 +3145,22 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
dirty |= system_constants_.alpha_to_mask != alpha_to_mask;
system_constants_.alpha_to_mask = alpha_to_mask;
uint32_t edram_tile_dwords_scaled = xenos::kEdramTileWidthSamples *
xenos::kEdramTileHeightSamples *
(resolution_scale_x * resolution_scale_y);
// EDRAM pitch for ROV writing.
if (edram_rov_used) {
uint32_t edram_pitch_tiles =
// Align, then multiply by 32bpp tile size in dwords.
uint32_t edram_32bpp_tile_pitch_dwords_scaled =
((rb_surface_info.surface_pitch *
(rb_surface_info.msaa_samples >= xenos::MsaaSamples::k4X ? 2 : 1)) +
79) /
80;
dirty |= system_constants_.edram_pitch_tiles != edram_pitch_tiles;
system_constants_.edram_pitch_tiles = edram_pitch_tiles;
(xenos::kEdramTileWidthSamples - 1)) /
xenos::kEdramTileWidthSamples * edram_tile_dwords_scaled;
dirty |= system_constants_.edram_32bpp_tile_pitch_dwords_scaled !=
edram_32bpp_tile_pitch_dwords_scaled;
system_constants_.edram_32bpp_tile_pitch_dwords_scaled =
edram_32bpp_tile_pitch_dwords_scaled;
}
// Color exponent bias and output index mapping or ROV render target writing.
@@ -3184,7 +3194,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
if (rt_keep_masks[i][0] != UINT32_MAX ||
rt_keep_masks[i][1] != UINT32_MAX) {
uint32_t rt_base_dwords_scaled =
color_info.color_base * 1280 * resolution_scale * resolution_scale;
color_info.color_base * edram_tile_dwords_scaled;
dirty |= system_constants_.edram_rt_base_dwords_scaled[i] !=
rt_base_dwords_scaled;
system_constants_.edram_rt_base_dwords_scaled[i] =
@@ -3208,12 +3218,12 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
}
}
// Interpolator sampling pattern, resolution scale, depth/stencil testing and
// blend constant for ROV.
if (edram_rov_used) {
uint32_t depth_base_dwords = rb_depth_info.depth_base * 1280;
dirty |= system_constants_.edram_depth_base_dwords != depth_base_dwords;
system_constants_.edram_depth_base_dwords = depth_base_dwords;
uint32_t depth_base_dwords_scaled =
rb_depth_info.depth_base * edram_tile_dwords_scaled;
dirty |= system_constants_.edram_depth_base_dwords_scaled !=
depth_base_dwords_scaled;
system_constants_.edram_depth_base_dwords_scaled = depth_base_dwords_scaled;
// For non-polygons, front polygon offset is used, and it's enabled if
// POLY_OFFSET_PARA_ENABLED is set, for polygons, separate front and back
@@ -3243,8 +3253,13 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
poly_offset_back_offset = poly_offset_front_offset;
}
}
// With non-square resolution scaling, make sure the worst-case impact is
// reverted (slope only along the scaled axis), thus max. More bias is
// better than less bias, because less bias means Z fighting with the
// background is more likely.
float poly_offset_scale_factor =
xenos::kPolygonOffsetScaleSubpixelUnit * resolution_scale;
xenos::kPolygonOffsetScaleSubpixelUnit *
std::max(resolution_scale_x, resolution_scale_y);
poly_offset_front_scale *= poly_offset_scale_factor;
poly_offset_back_scale *= poly_offset_scale_factor;
dirty |= system_constants_.edram_poly_offset_front_scale !=

View File

@@ -10,6 +10,7 @@
#ifndef XENIA_GPU_D3D12_D3D12_COMMAND_PROCESSOR_H_
#define XENIA_GPU_D3D12_D3D12_COMMAND_PROCESSOR_H_
#include <algorithm>
#include <atomic>
#include <deque>
#include <memory>
@@ -509,7 +510,14 @@ class D3D12CommandProcessor : public CommandProcessor {
static constexpr uint32_t kSwapTextureWidth = 1280;
static constexpr uint32_t kSwapTextureHeight = 720;
std::pair<uint32_t, uint32_t> GetSwapTextureSize() const {
uint32_t resolution_scale = texture_cache_->GetDrawResolutionScale();
return std::make_pair(
kSwapTextureWidth * texture_cache_->GetDrawResolutionScaleX(),
kSwapTextureHeight * texture_cache_->GetDrawResolutionScaleY());
}
std::pair<uint32_t, uint32_t> GetSwapScreenSize() const {
uint32_t resolution_scale =
std::max(texture_cache_->GetDrawResolutionScaleX(),
texture_cache_->GetDrawResolutionScaleY());
return std::make_pair(kSwapTextureWidth * resolution_scale,
kSwapTextureHeight * resolution_scale);
}

File diff suppressed because it is too large Load Diff

View File

@@ -60,7 +60,8 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
Path GetPath() const override { return path_; }
uint32_t GetResolutionScale() const override { return resolution_scale_; }
uint32_t GetResolutionScaleX() const override { return resolution_scale_x_; }
uint32_t GetResolutionScaleY() const override { return resolution_scale_y_; }
bool Update(bool is_rasterization_done,
uint32_t shader_writes_color_targets) override;
@@ -249,7 +250,8 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
bool bindless_resources_used_;
Path path_ = Path::kHostRenderTargets;
uint32_t resolution_scale_ = 1;
uint32_t resolution_scale_x_ = 1;
uint32_t resolution_scale_y_ = 1;
// For host render targets, an EDRAM-sized scratch buffer for:
// - Guest render target data copied from host render targets during copying
@@ -290,7 +292,13 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
// Parameter 1 - destination (shared memory or a part of it).
// Parameter 2 - source (EDRAM).
ID3D12RootSignature* resolve_copy_root_signature_ = nullptr;
static const std::pair<const void*, size_t>
struct ResolveCopyShaderCode {
const void* unscaled;
size_t unscaled_size;
const void* scaled;
size_t scaled_size;
};
static const ResolveCopyShaderCode
kResolveCopyShaders[size_t(draw_util::ResolveCopyShaderIndex::kCount)];
ID3D12PipelineState* resolve_copy_pipelines_[size_t(
draw_util::ResolveCopyShaderIndex::kCount)] = {};
@@ -539,8 +547,8 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
uint32_t constant;
struct {
uint32_t pitch_tiles : xenos::kEdramPitchTilesBits;
// 1 to 3.
uint32_t resolution_scale : 2;
uint32_t resolution_scale_x : 2;
uint32_t resolution_scale_y : 2;
// Whether 2x MSAA is supported natively rather than through 4x.
uint32_t msaa_2x_supported : 1;
};
@@ -597,9 +605,7 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
union DumpOffsets {
uint32_t offsets;
struct {
// Absolute index of the first thread group's tile within the source
// texture.
uint32_t first_group_tile_source_relative : xenos::kEdramBaseTilesBits;
uint32_t dispatch_first_tile : xenos::kEdramBaseTilesBits;
uint32_t source_base_tiles : xenos::kEdramBaseTilesBits;
};
DumpOffsets() : offsets(0) { static_assert_size(*this, sizeof(offsets)); }
@@ -615,8 +621,8 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
uint32_t pitches;
struct {
// Both in tiles.
uint32_t source_pitch : xenos::kEdramPitchTilesBits;
uint32_t dest_pitch : xenos::kEdramPitchTilesBits;
uint32_t source_pitch : xenos::kEdramPitchTilesBits;
};
DumpPitches() : pitches(0) { static_assert_size(*this, sizeof(pitches)); }
bool operator==(const DumpPitches& other_pitches) const {
@@ -830,9 +836,6 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
// For rasterizer-ordered view (pixel shader interlock).
static const std::pair<const void*, size_t> kResolveROVClear32bppShaders[3];
static const std::pair<const void*, size_t> kResolveROVClear64bppShaders[3];
ID3D12RootSignature* resolve_rov_clear_root_signature_ = nullptr;
// Clearing 32bpp color or depth.
ID3D12PipelineState* resolve_rov_clear_32bpp_pipeline_ = nullptr;

View File

@@ -96,7 +96,8 @@ PipelineCache::PipelineCache(D3D12CommandProcessor& command_processor,
provider.GetAdapterVendorID(), bindless_resources_used_, edram_rov_used,
render_target_cache_.gamma_render_target_as_srgb(),
render_target_cache_.msaa_2x_supported(),
render_target_cache_.GetResolutionScale(),
render_target_cache_.GetResolutionScaleX(),
render_target_cache_.GetResolutionScaleY(),
provider.GetGraphicsAnalysis() != nullptr);
if (edram_rov_used) {
@@ -419,7 +420,8 @@ void PipelineCache::InitializeShaderStorage(
provider.GetAdapterVendorID(), bindless_resources_used_,
edram_rov_used, render_target_cache_.gamma_render_target_as_srgb(),
render_target_cache_.msaa_2x_supported(),
render_target_cache_.GetResolutionScale(),
render_target_cache_.GetResolutionScaleX(),
render_target_cache_.GetResolutionScaleY(),
provider.GetGraphicsAnalysis() != nullptr);
// If needed and possible, create objects needed for DXIL conversion and
// disassembly on this thread.
@@ -1879,9 +1881,14 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
description.front_counter_clockwise ? TRUE : FALSE;
state_desc.RasterizerState.DepthBias = description.depth_bias;
state_desc.RasterizerState.DepthBiasClamp = 0.0f;
// With non-square resolution scaling, make sure the worst-case impact is
// reverted (slope only along the scaled axis), thus max. More bias is better
// than less bias, because less bias means Z fighting with the background is
// more likely.
state_desc.RasterizerState.SlopeScaledDepthBias =
description.depth_bias_slope_scaled *
float(render_target_cache_.GetResolutionScale());
float(std::max(render_target_cache_.GetResolutionScaleX(),
render_target_cache_.GetResolutionScaleY()));
state_desc.RasterizerState.DepthClipEnable =
description.depth_clip ? TRUE : FALSE;
uint32_t msaa_sample_count = uint32_t(1)

View File

@@ -51,8 +51,8 @@ DEFINE_uint32(
"If texture_cache_memory_limit_soft, for instance, is 384, and this is 24, "
"it will be assumed that the game will be using roughly 24 MB of "
"render-to-texture (resolve) targets and 384 - 24 = 360 MB of regular "
"textures - so with 2x resolution scaling, the soft limit will be 360 + 96 "
"MB, and with 3x, it will be 360 + 216 MB.",
"textures - so with 2x2 resolution scaling, the soft limit will be 360 + "
"96 MB, and with 3x3, it will be 360 + 216 MB.",
"GPU");
namespace xe {
@@ -61,28 +61,21 @@ namespace d3d12 {
// Generated with `xb buildshaders`.
namespace shaders {
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h"
@@ -90,30 +83,22 @@ namespace shaders {
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_2x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_3x_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_scaled_cs.h"
} // namespace shaders
// For formats with less than 4 components, assuming the last component is
@@ -789,146 +774,96 @@ const char* const TextureCache::dimension_names_[4] = {"1D", "2D", "3D",
"cube"};
const TextureCache::LoadModeInfo TextureCache::load_mode_info_[] = {
{{{shaders::texture_load_8bpb_cs, sizeof(shaders::texture_load_8bpb_cs), 3,
4, 16},
{shaders::texture_load_8bpb_2x_cs,
sizeof(shaders::texture_load_8bpb_2x_cs), 4, 4, 16 * 2},
{shaders::texture_load_8bpb_3x_cs,
sizeof(shaders::texture_load_8bpb_3x_cs), 3, 3, 16 * 3}}},
{{{shaders::texture_load_16bpb_cs, sizeof(shaders::texture_load_16bpb_cs),
4, 4, 16},
{shaders::texture_load_16bpb_2x_cs,
sizeof(shaders::texture_load_16bpb_2x_cs), 4, 4, 16 * 2},
{shaders::texture_load_16bpb_3x_cs,
sizeof(shaders::texture_load_16bpb_3x_cs), 3, 3, 16 * 3}}},
{{{shaders::texture_load_32bpb_cs, sizeof(shaders::texture_load_32bpb_cs),
4, 4, 8},
{shaders::texture_load_32bpb_2x_cs,
sizeof(shaders::texture_load_32bpb_2x_cs), 4, 4, 8 * 2},
{shaders::texture_load_32bpb_3x_cs,
sizeof(shaders::texture_load_32bpb_3x_cs), 3, 3, 2 * 3}}},
{{{shaders::texture_load_64bpb_cs, sizeof(shaders::texture_load_64bpb_cs),
4, 4, 4},
{shaders::texture_load_64bpb_2x_cs,
sizeof(shaders::texture_load_64bpb_2x_cs), 4, 4, 4 * 2},
{shaders::texture_load_64bpb_3x_cs,
sizeof(shaders::texture_load_64bpb_3x_cs), 3, 3, 4 * 3}}},
{{{shaders::texture_load_128bpb_cs, sizeof(shaders::texture_load_128bpb_cs),
4, 4, 2},
{shaders::texture_load_128bpb_2x_cs,
sizeof(shaders::texture_load_128bpb_2x_cs), 4, 4, 2 * 2},
{shaders::texture_load_128bpb_3x_cs,
sizeof(shaders::texture_load_128bpb_3x_cs), 4, 4, 2 * 3}}},
{{{shaders::texture_load_r5g5b5a1_b5g5r5a1_cs,
sizeof(shaders::texture_load_r5g5b5a1_b5g5r5a1_cs), 4, 4, 16},
{shaders::texture_load_r5g5b5a1_b5g5r5a1_2x_cs,
sizeof(shaders::texture_load_r5g5b5a1_b5g5r5a1_2x_cs), 4, 4, 16 * 2},
{shaders::texture_load_r5g5b5a1_b5g5r5a1_3x_cs,
sizeof(shaders::texture_load_r5g5b5a1_b5g5r5a1_3x_cs), 3, 3, 16 * 3}}},
{{{shaders::texture_load_r5g6b5_b5g6r5_cs,
sizeof(shaders::texture_load_r5g6b5_b5g6r5_cs), 4, 4, 16},
{shaders::texture_load_r5g6b5_b5g6r5_2x_cs,
sizeof(shaders::texture_load_r5g6b5_b5g6r5_2x_cs), 4, 4, 16 * 2},
{shaders::texture_load_r5g6b5_b5g6r5_3x_cs,
sizeof(shaders::texture_load_r5g6b5_b5g6r5_3x_cs), 3, 3, 16 * 3}}},
{{{shaders::texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs,
sizeof(shaders::texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs), 4, 4, 16},
{shaders::texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs,
sizeof(shaders::texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs), 4, 4,
16 * 2},
{shaders::texture_load_r5g5b6_b5g6r5_swizzle_rbga_3x_cs,
sizeof(shaders::texture_load_r5g5b6_b5g6r5_swizzle_rbga_3x_cs), 3, 3,
16 * 3}}},
{{{shaders::texture_load_r4g4b4a4_b4g4r4a4_cs,
sizeof(shaders::texture_load_r4g4b4a4_b4g4r4a4_cs), 4, 4, 16},
{shaders::texture_load_r4g4b4a4_b4g4r4a4_2x_cs,
sizeof(shaders::texture_load_r4g4b4a4_b4g4r4a4_2x_cs), 4, 4, 16 * 2},
{shaders::texture_load_r4g4b4a4_b4g4r4a4_3x_cs,
sizeof(shaders::texture_load_r4g4b4a4_b4g4r4a4_3x_cs), 3, 3, 16 * 3}}},
{{{shaders::texture_load_r10g11b11_rgba16_cs,
sizeof(shaders::texture_load_r10g11b11_rgba16_cs), 4, 4, 8},
{shaders::texture_load_r10g11b11_rgba16_2x_cs,
sizeof(shaders::texture_load_r10g11b11_rgba16_2x_cs), 4, 4, 8 * 2},
{shaders::texture_load_r10g11b11_rgba16_3x_cs,
sizeof(shaders::texture_load_r10g11b11_rgba16_3x_cs), 3, 3, 2 * 3}}},
{{{shaders::texture_load_r10g11b11_rgba16_snorm_cs,
sizeof(shaders::texture_load_r10g11b11_rgba16_snorm_cs), 4, 4, 8},
{shaders::texture_load_r10g11b11_rgba16_snorm_2x_cs,
sizeof(shaders::texture_load_r10g11b11_rgba16_snorm_2x_cs), 4, 4, 8 * 2},
{shaders::texture_load_r10g11b11_rgba16_snorm_3x_cs,
sizeof(shaders::texture_load_r10g11b11_rgba16_snorm_3x_cs), 3, 3,
2 * 3}}},
{{{shaders::texture_load_r11g11b10_rgba16_cs,
sizeof(shaders::texture_load_r11g11b10_rgba16_cs), 4, 4, 8},
{shaders::texture_load_r11g11b10_rgba16_2x_cs,
sizeof(shaders::texture_load_r11g11b10_rgba16_2x_cs), 4, 4, 8 * 2},
{shaders::texture_load_r11g11b10_rgba16_3x_cs,
sizeof(shaders::texture_load_r11g11b10_rgba16_3x_cs), 3, 3, 2 * 3}}},
{{{shaders::texture_load_r11g11b10_rgba16_snorm_cs,
sizeof(shaders::texture_load_r11g11b10_rgba16_snorm_cs), 4, 4, 8},
{shaders::texture_load_r11g11b10_rgba16_snorm_2x_cs,
sizeof(shaders::texture_load_r11g11b10_rgba16_snorm_2x_cs), 4, 4, 8 * 2},
{shaders::texture_load_r11g11b10_rgba16_snorm_3x_cs,
sizeof(shaders::texture_load_r11g11b10_rgba16_snorm_3x_cs), 3, 3,
2 * 3}}},
{{{shaders::texture_load_dxt1_rgba8_cs,
sizeof(shaders::texture_load_dxt1_rgba8_cs), 4, 4, 4},
{},
{}}},
{{{shaders::texture_load_dxt3_rgba8_cs,
sizeof(shaders::texture_load_dxt3_rgba8_cs), 4, 4, 2},
{},
{}}},
{{{shaders::texture_load_dxt5_rgba8_cs,
sizeof(shaders::texture_load_dxt5_rgba8_cs), 4, 4, 2},
{},
{}}},
{{{shaders::texture_load_dxn_rg8_cs,
sizeof(shaders::texture_load_dxn_rg8_cs), 4, 4, 2},
{},
{}}},
{{{shaders::texture_load_dxt3a_cs, sizeof(shaders::texture_load_dxt3a_cs),
4, 4, 4},
{},
{}}},
{{{shaders::texture_load_dxt3aas1111_cs,
sizeof(shaders::texture_load_dxt3aas1111_cs), 4, 4, 4},
{},
{}}},
{{{shaders::texture_load_dxt5a_r8_cs,
sizeof(shaders::texture_load_dxt5a_r8_cs), 4, 4, 4},
{},
{}}},
{{{shaders::texture_load_ctx1_cs, sizeof(shaders::texture_load_ctx1_cs), 4,
4, 4},
{},
{}}},
{{{shaders::texture_load_depth_unorm_cs,
sizeof(shaders::texture_load_depth_unorm_cs), 4, 4, 8},
{shaders::texture_load_depth_unorm_2x_cs,
sizeof(shaders::texture_load_depth_unorm_2x_cs), 4, 4, 8 * 2},
{shaders::texture_load_depth_unorm_3x_cs,
sizeof(shaders::texture_load_depth_unorm_3x_cs), 3, 3, 2 * 3}}},
{{{shaders::texture_load_depth_float_cs,
sizeof(shaders::texture_load_depth_float_cs), 4, 4, 8},
{shaders::texture_load_depth_float_2x_cs,
sizeof(shaders::texture_load_depth_float_2x_cs), 4, 4, 8 * 2},
{shaders::texture_load_depth_float_3x_cs,
sizeof(shaders::texture_load_depth_float_3x_cs), 3, 3, 2 * 3}}},
{shaders::texture_load_8bpb_cs, sizeof(shaders::texture_load_8bpb_cs),
shaders::texture_load_8bpb_scaled_cs,
sizeof(shaders::texture_load_8bpb_scaled_cs), 3, 4, 16},
{shaders::texture_load_16bpb_cs, sizeof(shaders::texture_load_16bpb_cs),
shaders::texture_load_16bpb_scaled_cs,
sizeof(shaders::texture_load_16bpb_scaled_cs), 4, 4, 16},
{shaders::texture_load_32bpb_cs, sizeof(shaders::texture_load_32bpb_cs),
shaders::texture_load_32bpb_scaled_cs,
sizeof(shaders::texture_load_32bpb_scaled_cs), 4, 4, 8},
{shaders::texture_load_64bpb_cs, sizeof(shaders::texture_load_64bpb_cs),
shaders::texture_load_64bpb_scaled_cs,
sizeof(shaders::texture_load_64bpb_scaled_cs), 4, 4, 4},
{shaders::texture_load_128bpb_cs, sizeof(shaders::texture_load_128bpb_cs),
shaders::texture_load_128bpb_scaled_cs,
sizeof(shaders::texture_load_128bpb_scaled_cs), 4, 4, 2},
{shaders::texture_load_r5g5b5a1_b5g5r5a1_cs,
sizeof(shaders::texture_load_r5g5b5a1_b5g5r5a1_cs),
shaders::texture_load_r5g5b5a1_b5g5r5a1_scaled_cs,
sizeof(shaders::texture_load_r5g5b5a1_b5g5r5a1_scaled_cs), 4, 4, 16},
{shaders::texture_load_r5g6b5_b5g6r5_cs,
sizeof(shaders::texture_load_r5g6b5_b5g6r5_cs),
shaders::texture_load_r5g6b5_b5g6r5_scaled_cs,
sizeof(shaders::texture_load_r5g6b5_b5g6r5_scaled_cs), 4, 4, 16},
{shaders::texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs,
sizeof(shaders::texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs),
shaders::texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs,
sizeof(shaders::texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs), 4, 4,
16},
{shaders::texture_load_r4g4b4a4_b4g4r4a4_cs,
sizeof(shaders::texture_load_r4g4b4a4_b4g4r4a4_cs),
shaders::texture_load_r4g4b4a4_b4g4r4a4_scaled_cs,
sizeof(shaders::texture_load_r4g4b4a4_b4g4r4a4_scaled_cs), 4, 4, 16},
{shaders::texture_load_r10g11b11_rgba16_cs,
sizeof(shaders::texture_load_r10g11b11_rgba16_cs),
shaders::texture_load_r10g11b11_rgba16_scaled_cs,
sizeof(shaders::texture_load_r10g11b11_rgba16_scaled_cs), 4, 4, 8},
{shaders::texture_load_r10g11b11_rgba16_snorm_cs,
sizeof(shaders::texture_load_r10g11b11_rgba16_snorm_cs),
shaders::texture_load_r10g11b11_rgba16_snorm_scaled_cs,
sizeof(shaders::texture_load_r10g11b11_rgba16_snorm_scaled_cs), 4, 4, 8},
{shaders::texture_load_r11g11b10_rgba16_cs,
sizeof(shaders::texture_load_r11g11b10_rgba16_cs),
shaders::texture_load_r11g11b10_rgba16_scaled_cs,
sizeof(shaders::texture_load_r11g11b10_rgba16_scaled_cs), 4, 4, 8},
{shaders::texture_load_r11g11b10_rgba16_snorm_cs,
sizeof(shaders::texture_load_r11g11b10_rgba16_snorm_cs),
shaders::texture_load_r11g11b10_rgba16_snorm_scaled_cs,
sizeof(shaders::texture_load_r11g11b10_rgba16_snorm_scaled_cs), 4, 4, 8},
{shaders::texture_load_dxt1_rgba8_cs,
sizeof(shaders::texture_load_dxt1_rgba8_cs), nullptr, 0, 4, 4, 4},
{shaders::texture_load_dxt3_rgba8_cs,
sizeof(shaders::texture_load_dxt3_rgba8_cs), nullptr, 0, 4, 4, 2},
{shaders::texture_load_dxt5_rgba8_cs,
sizeof(shaders::texture_load_dxt5_rgba8_cs), nullptr, 0, 4, 4, 2},
{shaders::texture_load_dxn_rg8_cs, sizeof(shaders::texture_load_dxn_rg8_cs),
nullptr, 0, 4, 4, 2},
{shaders::texture_load_dxt3a_cs, sizeof(shaders::texture_load_dxt3a_cs),
nullptr, 0, 4, 4, 4},
{shaders::texture_load_dxt3aas1111_cs,
sizeof(shaders::texture_load_dxt3aas1111_cs), nullptr, 0, 4, 4, 4},
{shaders::texture_load_dxt5a_r8_cs,
sizeof(shaders::texture_load_dxt5a_r8_cs), nullptr, 0, 4, 4, 4},
{shaders::texture_load_ctx1_cs, sizeof(shaders::texture_load_ctx1_cs),
nullptr, 0, 4, 4, 4},
{shaders::texture_load_depth_unorm_cs,
sizeof(shaders::texture_load_depth_unorm_cs),
shaders::texture_load_depth_unorm_scaled_cs,
sizeof(shaders::texture_load_depth_unorm_scaled_cs), 4, 4, 8},
{shaders::texture_load_depth_float_cs,
sizeof(shaders::texture_load_depth_float_cs),
shaders::texture_load_depth_float_scaled_cs,
sizeof(shaders::texture_load_depth_float_scaled_cs), 4, 4, 8},
};
TextureCache::TextureCache(D3D12CommandProcessor& command_processor,
const RegisterFile& register_file,
D3D12SharedMemory& shared_memory,
bool bindless_resources_used,
uint32_t draw_resolution_scale)
uint32_t draw_resolution_scale_x,
uint32_t draw_resolution_scale_y)
: command_processor_(command_processor),
register_file_(register_file),
shared_memory_(shared_memory),
bindless_resources_used_(bindless_resources_used),
draw_resolution_scale_(draw_resolution_scale) {
assert_true(draw_resolution_scale >= 1);
assert_true(draw_resolution_scale <= 3);
draw_resolution_scale_x_(draw_resolution_scale_x),
draw_resolution_scale_y_(draw_resolution_scale_y) {
assert_true(draw_resolution_scale_x >= 1);
assert_true(draw_resolution_scale_x <= kMaxDrawResolutionScaleAlongAxis);
assert_true(draw_resolution_scale_y >= 1);
assert_true(draw_resolution_scale_y <= kMaxDrawResolutionScaleAlongAxis);
}
TextureCache::~TextureCache() { Shutdown(); }
@@ -937,8 +872,7 @@ bool TextureCache::Initialize() {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
if (draw_resolution_scale_ > 1) {
assert_true(draw_resolution_scale_ <= GetMaxDrawResolutionScale(provider));
if (IsDrawResolutionScaled()) {
// Buffers not used yet - no need aliasing barriers to change ownership of
// gigabytes between even and odd buffers.
std::memset(scaled_resolve_1gb_buffer_indices_, UINT8_MAX,
@@ -946,7 +880,7 @@ bool TextureCache::Initialize() {
assert_true(scaled_resolve_heaps_.empty());
uint64_t scaled_resolve_address_space_size =
uint64_t(SharedMemory::kBufferSize) *
(draw_resolution_scale_ * draw_resolution_scale_);
(draw_resolution_scale_x_ * draw_resolution_scale_y_);
scaled_resolve_heaps_.resize(size_t(scaled_resolve_address_space_size >>
kScaledResolveHeapSizeLog2));
constexpr uint32_t kScaledResolvePageDwordCount =
@@ -1006,9 +940,9 @@ bool TextureCache::Initialize() {
// Create the loading pipelines.
for (uint32_t i = 0; i < uint32_t(LoadMode::kCount); ++i) {
const LoadModeInfo& mode_info = load_mode_info_[i];
const LoadModeInfo& load_mode_info = load_mode_info_[i];
load_pipelines_[i] = ui::d3d12::util::CreateComputePipeline(
device, mode_info.shaders[0].shader, mode_info.shaders[0].shader_size,
device, load_mode_info.shader, load_mode_info.shader_size,
load_root_signature_);
if (load_pipelines_[i] == nullptr) {
XELOGE(
@@ -1018,21 +952,17 @@ bool TextureCache::Initialize() {
Shutdown();
return false;
}
if (draw_resolution_scale_ > 1) {
const LoadShaderInfo& scaled_load_shader_info =
mode_info.shaders[draw_resolution_scale_ - 1];
if (scaled_load_shader_info.shader) {
load_pipelines_scaled_[i] = ui::d3d12::util::CreateComputePipeline(
device, scaled_load_shader_info.shader,
scaled_load_shader_info.shader_size, load_root_signature_);
if (load_pipelines_scaled_[i] == nullptr) {
XELOGE(
"D3D12TextureCache: Failed to create the resolution-scaled "
"texture loading pipeline for mode {}",
i);
Shutdown();
return false;
}
if (IsDrawResolutionScaled() && load_mode_info.shader_scaled) {
load_pipelines_scaled_[i] = ui::d3d12::util::CreateComputePipeline(
device, load_mode_info.shader_scaled,
load_mode_info.shader_scaled_size, load_root_signature_);
if (load_pipelines_scaled_[i] == nullptr) {
XELOGE(
"D3D12TextureCache: Failed to create the resolution-scaled texture "
"loading pipeline for mode {}",
i);
Shutdown();
return false;
}
}
}
@@ -1096,7 +1026,7 @@ bool TextureCache::Initialize() {
provider.OffsetViewDescriptor(null_srv_descriptor_heap_start_,
uint32_t(NullSRVDescriptorIndex::kCube)));
if (draw_resolution_scale_ > 1) {
if (IsDrawResolutionScaled()) {
scaled_resolve_global_watch_handle_ = shared_memory_.RegisterGlobalWatch(
ScaledResolveGlobalWatchCallbackThunk, this);
}
@@ -1183,7 +1113,7 @@ void TextureCache::TextureFetchConstantWritten(uint32_t index) {
void TextureCache::BeginSubmission() {
// ExecuteCommandLists is a full UAV and aliasing barrier.
if (draw_resolution_scale_ > 1) {
if (IsDrawResolutionScaled()) {
size_t scaled_resolve_buffer_count = GetScaledResolveBufferCount();
for (size_t i = 0; i < scaled_resolve_buffer_count; ++i) {
ScaledResolveVirtualBuffer* scaled_resolve_buffer =
@@ -1215,7 +1145,7 @@ void TextureCache::BeginFrame() {
// so subtracting 1 from the scale.
uint32_t limit_scaled_resolve_add_mb =
cvars::texture_cache_memory_limit_render_to_texture *
(draw_resolution_scale_ * draw_resolution_scale_ - 1);
(draw_resolution_scale_x_ * draw_resolution_scale_y_ - 1);
uint32_t limit_soft_mb =
cvars::texture_cache_memory_limit_soft + limit_scaled_resolve_add_mb;
uint32_t limit_hard_mb =
@@ -1705,7 +1635,7 @@ void TextureCache::MarkRangeAsResolved(uint32_t start_unscaled,
start_unscaled &= 0x1FFFFFFF;
length_unscaled = std::min(length_unscaled, 0x20000000 - start_unscaled);
if (draw_resolution_scale_ > 1) {
if (IsDrawResolutionScaled()) {
uint32_t page_first = start_unscaled >> 12;
uint32_t page_last = (start_unscaled + length_unscaled - 1) >> 12;
uint32_t block_first = page_first >> 5;
@@ -1729,9 +1659,43 @@ void TextureCache::MarkRangeAsResolved(uint32_t start_unscaled,
shared_memory_.RangeWrittenByGpu(start_unscaled, length_unscaled, true);
}
void TextureCache::ClampDrawResolutionScaleToSupportedRange(
uint32_t& scale_x, uint32_t& scale_y,
const ui::d3d12::D3D12Provider& provider) {
if (provider.GetTiledResourcesTier() < D3D12_TILED_RESOURCES_TIER_1) {
scale_x = 1;
scale_y = 1;
return;
}
// Ensure it's not zero.
scale_x = std::max(scale_x, uint32_t(1));
scale_y = std::max(scale_y, uint32_t(1));
scale_x = std::min(scale_x, kMaxDrawResolutionScaleAlongAxis);
scale_y = std::min(scale_y, kMaxDrawResolutionScaleAlongAxis);
// Limit to the virtual address space available for a resource.
uint32_t virtual_address_bits_per_resource =
provider.GetVirtualAddressBitsPerResource();
while (scale_x > 1 || scale_y > 1) {
uint64_t highest_scaled_address =
uint64_t(SharedMemory::kBufferSize) * (scale_x * scale_y) - 1;
if (uint32_t(64) - xe::lzcnt(highest_scaled_address) <=
virtual_address_bits_per_resource) {
break;
}
// When reducing from a square size, prefer decreasing the horizontal
// resolution as vertical resolution difference is visible more clearly in
// perspective.
if (scale_x >= scale_y) {
--scale_x;
} else {
--scale_y;
}
}
}
bool TextureCache::EnsureScaledResolveMemoryCommitted(
uint32_t start_unscaled, uint32_t length_unscaled) {
assert_true(draw_resolution_scale_ > 1);
assert_true(IsDrawResolutionScaled());
if (length_unscaled == 0) {
return true;
@@ -1742,12 +1706,11 @@ bool TextureCache::EnsureScaledResolveMemoryCommitted(
return false;
}
uint32_t draw_resolution_scale_square =
draw_resolution_scale_ * draw_resolution_scale_;
uint64_t first_scaled =
uint64_t(start_unscaled) * draw_resolution_scale_square;
uint32_t draw_resolution_scale_area =
draw_resolution_scale_x_ * draw_resolution_scale_y_;
uint64_t first_scaled = uint64_t(start_unscaled) * draw_resolution_scale_area;
uint64_t last_scaled = uint64_t(start_unscaled + (length_unscaled - 1)) *
draw_resolution_scale_square;
draw_resolution_scale_area;
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
@@ -1773,7 +1736,7 @@ bool TextureCache::EnsureScaledResolveMemoryCommitted(
ui::d3d12::util::FillBufferResourceDesc(
scaled_resolve_buffer_desc,
std::min(uint64_t(1) << 31, uint64_t(SharedMemory::kBufferSize) *
draw_resolution_scale_square -
draw_resolution_scale_area -
(uint64_t(i) << 30)),
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
// The first access will be a resolve.
@@ -1855,7 +1818,7 @@ bool TextureCache::EnsureScaledResolveMemoryCommitted(
bool TextureCache::MakeScaledResolveRangeCurrent(uint32_t start_unscaled,
uint32_t length_unscaled) {
assert_true(draw_resolution_scale_ > 1);
assert_true(IsDrawResolutionScaled());
if (!length_unscaled || start_unscaled >= SharedMemory::kBufferSize ||
(SharedMemory::kBufferSize - start_unscaled) < length_unscaled) {
@@ -1864,12 +1827,11 @@ bool TextureCache::MakeScaledResolveRangeCurrent(uint32_t start_unscaled,
return false;
}
uint32_t draw_resolution_scale_square =
draw_resolution_scale_ * draw_resolution_scale_;
uint64_t start_scaled =
uint64_t(start_unscaled) * draw_resolution_scale_square;
uint32_t draw_resolution_scale_area =
draw_resolution_scale_x_ * draw_resolution_scale_y_;
uint64_t start_scaled = uint64_t(start_unscaled) * draw_resolution_scale_area;
uint64_t length_scaled =
uint64_t(length_unscaled) * draw_resolution_scale_square;
uint64_t(length_unscaled) * draw_resolution_scale_area;
uint64_t last_scaled = start_scaled + (length_scaled - 1);
// Get one or two buffers that can hold the whole range.
@@ -1967,7 +1929,7 @@ bool TextureCache::MakeScaledResolveRangeCurrent(uint32_t start_unscaled,
void TextureCache::TransitionCurrentScaledResolveRange(
D3D12_RESOURCE_STATES new_state) {
assert_true(draw_resolution_scale_ > 1);
assert_true(IsDrawResolutionScaled());
ScaledResolveVirtualBuffer& buffer = GetCurrentScaledResolveBuffer();
command_processor_.PushTransitionBarrier(
buffer.resource(), buffer.SetResourceState(new_state), new_state);
@@ -1975,7 +1937,7 @@ void TextureCache::TransitionCurrentScaledResolveRange(
void TextureCache::CreateCurrentScaledResolveRangeUintPow2SRV(
D3D12_CPU_DESCRIPTOR_HANDLE handle, uint32_t element_size_bytes_pow2) {
assert_true(draw_resolution_scale_ > 1);
assert_true(IsDrawResolutionScaled());
size_t buffer_index = GetCurrentScaledResolveBufferIndex();
const ScaledResolveVirtualBuffer* buffer =
scaled_resolve_2gb_buffers_[buffer_index];
@@ -1993,7 +1955,7 @@ void TextureCache::CreateCurrentScaledResolveRangeUintPow2SRV(
void TextureCache::CreateCurrentScaledResolveRangeUintPow2UAV(
D3D12_CPU_DESCRIPTOR_HANDLE handle, uint32_t element_size_bytes_pow2) {
assert_true(draw_resolution_scale_ > 1);
assert_true(IsDrawResolutionScaled());
size_t buffer_index = GetCurrentScaledResolveBufferIndex();
const ScaledResolveVirtualBuffer* buffer =
scaled_resolve_2gb_buffers_[buffer_index];
@@ -2218,7 +2180,7 @@ void TextureCache::LogTextureAction(const Texture* texture,
TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) {
// Check if the texture is a scaled resolve texture.
if (draw_resolution_scale_ > 1 && key.tiled) {
if (IsDrawResolutionScaled() && key.tiled) {
LoadMode load_mode = GetLoadMode(key);
if (load_mode != LoadMode::kUnknown &&
load_pipelines_scaled_[uint32_t(load_mode)] != nullptr) {
@@ -2242,8 +2204,8 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) {
uint32_t host_width = key.width;
uint32_t host_height = key.height;
if (key.scaled_resolve) {
host_width *= draw_resolution_scale_;
host_height *= draw_resolution_scale_;
host_width *= draw_resolution_scale_x_;
host_height *= draw_resolution_scale_y_;
}
// With 3x resolution scaling, a 2D texture may become bigger than the
// Direct3D 11 limit, and with 2x, a 3D one as well.
@@ -2359,17 +2321,14 @@ bool TextureCache::LoadTextureData(Texture* texture) {
if (load_mode == LoadMode::kUnknown) {
return false;
}
uint32_t texture_resolution_scale =
texture->key.scaled_resolve ? draw_resolution_scale_ : 1;
bool texture_resolution_scaled = texture->key.scaled_resolve;
ID3D12PipelineState* pipeline =
texture_resolution_scale > 1 ? load_pipelines_scaled_[uint32_t(load_mode)]
: load_pipelines_[uint32_t(load_mode)];
texture_resolution_scaled ? load_pipelines_scaled_[uint32_t(load_mode)]
: load_pipelines_[uint32_t(load_mode)];
if (pipeline == nullptr) {
return false;
}
const LoadModeInfo& load_mode_info = load_mode_info_[uint32_t(load_mode)];
const LoadShaderInfo& load_shader_info =
load_mode_info.shaders[texture_resolution_scale - 1];
// Request uploading of the texture data to the shared memory.
// This is also necessary when resolution scale is used - the texture cache
@@ -2382,7 +2341,7 @@ bool TextureCache::LoadTextureData(Texture* texture) {
if (!base_in_sync) {
if (!shared_memory_.RequestRange(
texture->key.base_page << 12, texture->GetGuestBaseSize(),
texture->key.scaled_resolve ? nullptr : &base_resolved)) {
texture_resolution_scaled ? nullptr : &base_resolved)) {
return false;
}
}
@@ -2390,11 +2349,11 @@ bool TextureCache::LoadTextureData(Texture* texture) {
if (!mips_in_sync) {
if (!shared_memory_.RequestRange(
texture->key.mip_page << 12, texture->GetGuestMipsSize(),
texture->key.scaled_resolve ? nullptr : &mips_resolved)) {
texture_resolution_scaled ? nullptr : &mips_resolved)) {
return false;
}
}
if (texture_resolution_scale > 1) {
if (texture_resolution_scaled) {
// Make sure all heaps are created.
if (!EnsureScaledResolveMemoryCommitted(texture->key.base_page << 12,
texture->GetGuestBaseSize())) {
@@ -2425,6 +2384,10 @@ bool TextureCache::LoadTextureData(Texture* texture) {
uint32_t level_packed = texture->guest_layout.packed_level;
uint32_t level_stored_first = std::min(level_first, level_packed);
uint32_t level_stored_last = std::min(level_last, level_packed);
uint32_t texture_resolution_scale_x =
texture_resolution_scaled ? draw_resolution_scale_x_ : 1;
uint32_t texture_resolution_scale_y =
texture_resolution_scaled ? draw_resolution_scale_y_ : 1;
// Get the host layout and the buffer.
UINT64 copy_buffer_size = 0;
@@ -2470,15 +2433,16 @@ bool TextureCache::LoadTextureData(Texture* texture) {
host_slice_layout_base.Footprint.Depth = depth;
}
host_slice_layout_base.Footprint.Width = xe::round_up(
host_slice_layout_base.Footprint.Width * texture_resolution_scale,
host_slice_layout_base.Footprint.Width * texture_resolution_scale_x,
UINT(host_block_width));
host_slice_layout_base.Footprint.Height = xe::round_up(
host_slice_layout_base.Footprint.Height * texture_resolution_scale,
host_slice_layout_base.Footprint.Height * texture_resolution_scale_y,
UINT(host_block_height));
host_slice_layout_base.Footprint.RowPitch =
xe::align(xe::round_up(host_slice_layout_base.Footprint.Width /
host_block_width,
load_shader_info.host_x_blocks_per_thread) *
load_mode_info.host_x_blocks_per_thread *
texture_resolution_scale_x) *
host_bytes_per_block,
uint32_t(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT));
host_slice_size_base = xe::align(
@@ -2515,15 +2479,16 @@ bool TextureCache::LoadTextureData(Texture* texture) {
std::max(depth >> level, uint32_t(1));
}
host_slice_layout_mip.Footprint.Width = xe::round_up(
host_slice_layout_mip.Footprint.Width * texture_resolution_scale,
host_slice_layout_mip.Footprint.Width * texture_resolution_scale_x,
UINT(host_block_width));
host_slice_layout_mip.Footprint.Height = xe::round_up(
host_slice_layout_mip.Footprint.Height * texture_resolution_scale,
host_slice_layout_mip.Footprint.Height * texture_resolution_scale_y,
UINT(host_block_height));
host_slice_layout_mip.Footprint.RowPitch =
xe::align(xe::round_up(host_slice_layout_mip.Footprint.Width /
host_block_width,
load_shader_info.host_x_blocks_per_thread) *
load_mode_info.host_x_blocks_per_thread *
texture_resolution_scale_x) *
host_bytes_per_block,
uint32_t(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT));
UINT64 host_slice_sizes_mip = xe::align(
@@ -2557,7 +2522,7 @@ bool TextureCache::LoadTextureData(Texture* texture) {
// descriptors for base and mips.
// Destination.
uint32_t descriptor_count = 1;
if (texture_resolution_scale > 1) {
if (texture_resolution_scaled) {
// Source - base and mips, one or both.
descriptor_count += (level_first == 0 && level_last != 0) ? 2 : 1;
} else {
@@ -2581,25 +2546,25 @@ bool TextureCache::LoadTextureData(Texture* texture) {
descriptors_allocated[descriptor_write_index++];
ui::d3d12::util::CreateBufferTypedUAV(
device, descriptor_dest.first, copy_buffer,
ui::d3d12::util::GetUintPow2DXGIFormat(load_shader_info.uav_bpe_log2),
uint32_t(copy_buffer_size) >> load_shader_info.uav_bpe_log2);
ui::d3d12::util::GetUintPow2DXGIFormat(load_mode_info.uav_bpe_log2),
uint32_t(copy_buffer_size) >> load_mode_info.uav_bpe_log2);
command_list.D3DSetComputeRootDescriptorTable(2, descriptor_dest.second);
// Set up the unscaled source descriptor (scaled needs two descriptors that
// depend on the buffer being current, so they will be set later - for mips,
// after loading the base is done).
if (texture_resolution_scale <= 1) {
if (!texture_resolution_scaled) {
shared_memory_.UseForReading();
ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_unscaled_source;
if (bindless_resources_used_) {
descriptor_unscaled_source =
command_processor_.GetSharedMemoryUintPow2BindlessSRVHandlePair(
load_shader_info.srv_bpe_log2);
load_mode_info.srv_bpe_log2);
} else {
assert_true(descriptor_write_index < descriptor_count);
descriptor_unscaled_source =
descriptors_allocated[descriptor_write_index++];
shared_memory_.WriteUintPow2SRVDescriptor(
descriptor_unscaled_source.first, load_shader_info.srv_bpe_log2);
descriptor_unscaled_source.first, load_mode_info.srv_bpe_log2);
}
command_list.D3DSetComputeRootDescriptorTable(
1, descriptor_unscaled_source.second);
@@ -2609,9 +2574,10 @@ bool TextureCache::LoadTextureData(Texture* texture) {
auto& cbuffer_pool = command_processor_.GetConstantBufferPool();
LoadConstants load_constants;
load_constants.is_tiled_3d_endian = uint32_t(texture->key.tiled) |
(uint32_t(is_3d) << 1) |
(uint32_t(texture->key.endianness) << 2);
load_constants.is_tiled_3d_endian_scale =
uint32_t(texture->key.tiled) | (uint32_t(is_3d) << 1) |
(uint32_t(texture->key.endianness) << 2) |
(texture_resolution_scale_x << 4) | (texture_resolution_scale_y << 6);
// The loop counter can mean two things depending on whether the packed mip
// tail is stored as mip 0, because in this case, it would be ambiguous since
@@ -2646,8 +2612,7 @@ bool TextureCache::LoadTextureData(Texture* texture) {
// Set up the base or mips source, also making it accessible if loading from
// scaled resolve memory.
if (texture_resolution_scale > 1 &&
(is_base || !scaled_mips_source_set_up)) {
if (texture_resolution_scaled && (is_base || !scaled_mips_source_set_up)) {
uint32_t guest_size_unscaled =
is_base ? texture->GetGuestBaseSize() : texture->GetGuestMipsSize();
if (!MakeScaledResolveRangeCurrent(guest_address, guest_size_unscaled)) {
@@ -2661,7 +2626,7 @@ bool TextureCache::LoadTextureData(Texture* texture) {
ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_scaled_source =
descriptors_allocated[descriptor_write_index++];
CreateCurrentScaledResolveRangeUintPow2SRV(descriptor_scaled_source.first,
load_shader_info.srv_bpe_log2);
load_mode_info.srv_bpe_log2);
command_list.D3DSetComputeRootDescriptorTable(
1, descriptor_scaled_source.second);
if (!is_base) {
@@ -2669,7 +2634,7 @@ bool TextureCache::LoadTextureData(Texture* texture) {
}
}
if (texture_resolution_scale > 1) {
if (texture_resolution_scaled) {
// Offset already applied in the buffer because more than 512 MB can't be
// directly addresses on Nvidia as R32.
load_constants.guest_offset = 0;
@@ -2678,7 +2643,8 @@ bool TextureCache::LoadTextureData(Texture* texture) {
}
if (!is_base) {
load_constants.guest_offset +=
texture->guest_layout.mip_offsets_bytes[level];
texture->guest_layout.mip_offsets_bytes[level] *
(texture_resolution_scale_x * texture_resolution_scale_y);
}
const texture_util::TextureGuestLayout::Level& level_guest_layout =
is_base ? texture->guest_layout.base
@@ -2709,14 +2675,15 @@ bool TextureCache::LoadTextureData(Texture* texture) {
level_height = std::max(height >> level, uint32_t(1));
level_depth = std::max(depth >> level, uint32_t(1));
}
load_constants.size_blocks[0] =
(level_width + (block_width - 1)) / block_width;
load_constants.size_blocks[1] =
(level_height + (block_height - 1)) / block_height;
load_constants.size_blocks[0] = (level_width + (block_width - 1)) /
block_width * texture_resolution_scale_x;
load_constants.size_blocks[1] = (level_height + (block_height - 1)) /
block_height * texture_resolution_scale_y;
load_constants.size_blocks[2] = level_depth;
load_constants.height_texels = level_height;
// Each thread group processes 32x32x1 guest blocks.
// Each thread group processes 32x32x1 source blocks (resolution-scaled, but
// still compressed if the host needs decompression).
uint32_t group_count_x = (load_constants.size_blocks[0] + 31) >> 5;
uint32_t group_count_y = (load_constants.size_blocks[1] + 31) >> 5;
@@ -2745,7 +2712,8 @@ bool TextureCache::LoadTextureData(Texture* texture) {
command_list.D3DDispatch(group_count_x, group_count_y,
load_constants.size_blocks[2]);
load_constants.guest_offset +=
level_guest_layout.array_slice_stride_bytes;
level_guest_layout.array_slice_stride_bytes *
(texture_resolution_scale_x * texture_resolution_scale_y);
load_constants.host_offset += host_slice_size;
}
}
@@ -3023,7 +2991,7 @@ void TextureCache::ClearBindings() {
bool TextureCache::IsRangeScaledResolved(uint32_t start_unscaled,
uint32_t length_unscaled) {
if (draw_resolution_scale_ <= 1) {
if (!IsDrawResolutionScaled()) {
return false;
}
@@ -3083,7 +3051,7 @@ void TextureCache::ScaledResolveGlobalWatchCallbackThunk(
void TextureCache::ScaledResolveGlobalWatchCallback(uint32_t address_first,
uint32_t address_last,
bool invalidated_by_gpu) {
assert_true(draw_resolution_scale_ > 1);
assert_true(IsDrawResolutionScaled());
if (invalidated_by_gpu) {
// Resolves themselves do exactly the opposite of what this should do.
return;

View File

@@ -84,7 +84,7 @@ class TextureCache {
// than an unsigned view of the same guest texture.
uint32_t signed_separate : 1; // 96
// Whether this texture is a 2x-scaled resolve target.
// Whether this texture is a resolution-scaled resolve target.
uint32_t scaled_resolve : 1; // 97
TextureKey() { MakeInvalid(); }
@@ -151,7 +151,8 @@ class TextureCache {
TextureCache(D3D12CommandProcessor& command_processor,
const RegisterFile& register_file,
D3D12SharedMemory& shared_memory, bool bindless_resources_used,
uint32_t draw_resolution_scale);
uint32_t draw_resolution_scale_x,
uint32_t draw_resolution_scale_y);
~TextureCache();
bool Initialize();
@@ -214,16 +215,20 @@ class TextureCache {
D3D12_CPU_DESCRIPTOR_HANDLE handle) const;
void MarkRangeAsResolved(uint32_t start_unscaled, uint32_t length_unscaled);
static uint32_t GetMaxDrawResolutionScale(
const ui::d3d12::D3D12Provider& provider) {
// 31 because 2 GB buffers are used.
if (provider.GetTiledResourcesTier() < D3D12_TILED_RESOURCES_TIER_1 ||
provider.GetVirtualAddressBitsPerResource() < 31) {
return 1;
}
return kMaxDrawResolutionScale;
// In textures, resolution scaling is done for 8-byte portions of memory for
// 8bpp textures, and for 16-byte portions for textures of higher bit depths
// (these are the sizes of regions where contiguous texels in memory are also
// contiguous in the texture along the horizontal axis, so 64-bit and 128-bit
// loads / stores, for 8bpp and 16bpp+ respectively, can be used for untiling
// regardless of the resolution scale).
static void ClampDrawResolutionScaleToSupportedRange(
uint32_t& scale_x, uint32_t& scale_y,
const ui::d3d12::D3D12Provider& provider);
uint32_t GetDrawResolutionScaleX() const { return draw_resolution_scale_x_; }
uint32_t GetDrawResolutionScaleY() const { return draw_resolution_scale_y_; }
bool IsDrawResolutionScaled() const {
return draw_resolution_scale_x_ > 1 || draw_resolution_scale_y_ > 1;
}
uint32_t GetDrawResolutionScale() const { return draw_resolution_scale_; }
// Ensures the tiles backing the range in the buffers are allocated.
bool EnsureScaledResolveMemoryCommitted(uint32_t start_unscaled,
uint32_t length_unscaled);
@@ -242,7 +247,7 @@ class TextureCache {
D3D12_CPU_DESCRIPTOR_HANDLE handle, uint32_t element_size_bytes_pow2);
void TransitionCurrentScaledResolveRange(D3D12_RESOURCE_STATES new_state);
void MarkCurrentScaledResolveRangeUAVWritesCommitNeeded() {
assert_true(draw_resolution_scale_ > 1);
assert_true(IsDrawResolutionScaled());
GetCurrentScaledResolveBuffer().SetUAVBarrierPending();
}
@@ -255,7 +260,11 @@ class TextureCache {
xenos::TextureFormat& format_out);
private:
static constexpr uint32_t kMaxDrawResolutionScale = 3;
// Hard limit, originating from the half-pixel offset (two-pixel offset is too
// much, the resolve shaders, being generic for different scales, only
// duplicate the second pixel into the first, not the third), and also due to
// the bit counts used for passing the scale to shaders.
static constexpr uint32_t kMaxDrawResolutionScaleAlongAxis = 3;
enum class LoadMode {
k8bpb,
@@ -287,7 +296,7 @@ class TextureCache {
kUnknown = kCount
};
struct LoadShaderInfo {
struct LoadModeInfo {
// Rules of data access in load shaders:
// - Source reading (from the shared memory or the scaled resolve buffer):
// - Guest data may be stored in a sparsely-allocated buffer, or, in
@@ -336,11 +345,13 @@ class TextureCache {
// - Resolution scaling enabled:
// - For simplicity, unlike in the shared memory, buffer tile boundaries
// are not aligned to powers of 2 the same way as guest addresses are.
// While for 2x resolution scaling it still happens to be the case
// because `host address = guest address << 1`, for 3x, it's not - a
// 64 KB host tile would represent 7281.777 guest bytes (though we
// scale texels, not bytes, but that's what it would be for k_8
// textures).
// While for 2x2 resolution scaling it still happens to be the case
// because `host scaling unit address = guest scaling unit
// address << 2` (similarly for 2x1 and 1x2), for 3x or x3, it's not -
// a 64 KB host tile would represent 7281.777 guest bytes with 3x3
// (disregarding that sequences of texels that are adjacent in memory
// alongside the horizontal axis, not individual bytes, are scaled,
// but even in that case it's not scaling by 2^n still).
// - The above would affect the `width > pitch` case for linear
// textures, requiring overestimating the width in calculation of the
// range of the tiles to map, while not doing this overestimation on
@@ -363,24 +374,26 @@ class TextureCache {
// - host_x_blocks_per_thread specifies how many pixels can be written
// without bounds checking within increments of that amount - the pitch
// of the destination buffer is manually overaligned if needed.
// Shader without resolution scaling.
const void* shader;
size_t shader_size;
// Shader with resolution scaling, if available. These shaders are separate
// so the majority of the textures are not affected by the code needed for
// resolution scale support, and also to check if the format allows
// resolution scaling.
const void* shader_scaled;
size_t shader_scaled_size;
// Log2 of the sizes, in bytes, of the source (guest) SRV and the
// destination (host) UAV accessed by the copying shader, since the shader
// may copy multiple blocks per one invocation.
uint32_t srv_bpe_log2;
uint32_t uav_bpe_log2;
// Number of guest blocks (or texels for uncompressed) along X axis written
// Number of host blocks (or texels for uncompressed) along X axis written
// by every compute shader thread - rows in the upload buffer are padded to
// at least this amount.
uint32_t host_x_blocks_per_thread;
};
struct LoadModeInfo {
// For different drawing resolution scales.
LoadShaderInfo shaders[kMaxDrawResolutionScale];
};
struct HostFormat {
// Format info for the regular case.
// DXGI format (typeless when different signedness or number representation
@@ -473,17 +486,18 @@ class TextureCache {
struct LoadConstants {
// vec4 0.
uint32_t is_tiled_3d_endian;
// Base offset in bytes.
uint32_t is_tiled_3d_endian_scale;
// Base offset in bytes, resolution-scaled.
uint32_t guest_offset;
// For tiled textures - row pitch in blocks, aligned to 32.
// For tiled textures - row pitch in blocks, aligned to 32, unscaled.
// For linear textures - row pitch in bytes.
uint32_t guest_pitch_aligned;
// For 3D textures only (ignored otherwise) - aligned to 32.
// For 3D textures only (ignored otherwise) - aligned to 32, unscaled.
uint32_t guest_z_stride_block_rows_aligned;
// vec4 1.
// If this is a packed mip tail, this is aligned to tile dimensions.
// Resolution-scaled.
uint32_t size_blocks[3];
// Base offset in bytes.
uint32_t host_offset;
@@ -671,7 +685,7 @@ class TextureCache {
void ClearBindings();
size_t GetScaledResolveBufferCount() const {
assert_true(draw_resolution_scale_ > 1);
assert_true(IsDrawResolutionScaled());
// Make sure any range up to 1 GB is accessible through 1 or 2 buffers.
// 2x2 scale buffers - just one 2 GB buffer for all 2 GB.
// 3x3 scale buffers - 4 buffers:
@@ -687,7 +701,7 @@ class TextureCache {
// three buffers.
uint64_t address_space_size =
uint64_t(SharedMemory::kBufferSize) *
(draw_resolution_scale_ * draw_resolution_scale_);
(draw_resolution_scale_x_ * draw_resolution_scale_y_);
return size_t((address_space_size - 1) >> 30);
}
// Returns indices of two scaled resolve virtual buffers that the location in
@@ -695,7 +709,7 @@ class TextureCache {
// the beginning or the end of the address represented only by one buffer.
std::array<size_t, 2> GetPossibleScaledResolveBufferIndices(
uint64_t address_scaled) const {
assert_true(draw_resolution_scale_ > 1);
assert_true(IsDrawResolutionScaled());
size_t address_gb = size_t(address_scaled >> 30);
size_t max_index = GetScaledResolveBufferCount() - 1;
// In different cases for 3x3:
@@ -788,11 +802,12 @@ class TextureCache {
};
uint8_t unsupported_format_features_used_[64];
uint32_t draw_resolution_scale_ = 1;
uint32_t draw_resolution_scale_x_ = 1;
uint32_t draw_resolution_scale_y_ = 1;
// The tiled buffer for resolved data with resolution scaling.
// Because on Direct3D 12 (at least on Windows 10 2004) typed SRV or UAV
// creation fails for offsets above 4 GB, a single tiled 4.5 GB buffer can't
// be used for 3x resolution scaling.
// be used for 3x3 resolution scaling.
// Instead, "sliding window" buffers allowing to access a single range of up
// to 1 GB (or up to 2 GB, depending on the low bits) at any moment are used.
// Parts of 4.5 GB address space can be accessed through 2 GB buffers as:
@@ -807,8 +822,8 @@ class TextureCache {
// Size is calculated the same as in GetScaledResolveBufferCount.
ScaledResolveVirtualBuffer*
scaled_resolve_2gb_buffers_[(uint64_t(SharedMemory::kBufferSize) *
(kMaxDrawResolutionScale *
kMaxDrawResolutionScale) -
(kMaxDrawResolutionScaleAlongAxis *
kMaxDrawResolutionScaleAlongAxis) -
1) >>
30] = {};
// Not very big heaps (16 MB) because they are needed pretty sparsely. One
@@ -838,8 +853,8 @@ class TextureCache {
// For aliasing barrier placement, last owning buffer index for each of 1 GB.
size_t
scaled_resolve_1gb_buffer_indices_[(uint64_t(SharedMemory::kBufferSize) *
kMaxDrawResolutionScale *
kMaxDrawResolutionScale +
kMaxDrawResolutionScaleAlongAxis *
kMaxDrawResolutionScaleAlongAxis +
((uint32_t(1) << 30) - 1)) >>
30];
// Range used in the last successful MakeScaledResolveRangeCurrent call.