[GPU] Mostly generic, not square-only resolution scaling
This commit is contained in:
@@ -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 !=
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user