[UI] Image post-processing and full presentation/window rework

[GPU] Add FXAA post-processing
[UI] Add FidelityFX FSR and CAS post-processing
[UI] Add blue noise dithering from 10bpc to 8bpc
[GPU] Apply the DC PWL gamma ramp closer to the spec, supporting fully white color
[UI] Allow the GPU CP thread to present on the host directly, bypassing the UI thread OS paint event
[UI] Allow variable refresh rate (or tearing)
[UI] Present the newest frame (restart) on DXGI
[UI] Replace GraphicsContext with a far more advanced Presenter with more coherent surface connection and UI overlay state management
[UI] Connect presentation to windows via the Surface class, not native window handles
[Vulkan] Switch to simpler Vulkan setup with no instance/device separation due to interdependencies and to pass fewer objects around
[Vulkan] Lower the minimum required Vulkan version to 1.0
[UI/GPU] Various cleanup, mainly ComPtr usage
[UI] Support per-monitor DPI awareness v2 on Windows
[UI] DPI-scale Dear ImGui
[UI] Replace the remaining non-detachable window delegates with unified window event and input listeners
[UI] Allow listeners to safely destroy or close the window, and to register/unregister listeners without use-after-free and the ABA problem
[UI] Explicit Z ordering of input listeners and UI overlays, top-down for input, bottom-up for drawing
[UI] Add explicit window lifecycle phases
[UI] Replace Window virtual functions with explicit desired state, its application, actual state, its feedback
[UI] GTK: Apply the initial size to the drawing area
[UI] Limit internal UI frame rate to that of the monitor
[UI] Hide the cursor using a timer instead of polling due to no repeated UI thread paints with GPU CP thread presentation, and only within the window
This commit is contained in:
Triang3l
2022-01-29 13:22:03 +03:00
parent 372bdd3ec9
commit fe3f0f26e4
428 changed files with 75942 additions and 18360 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -32,8 +32,8 @@
#include "xenia/gpu/dxbc_shader_translator.h"
#include "xenia/gpu/xenos.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/ui/d3d12/d3d12_context.h"
#include "xenia/ui/d3d12/d3d12_descriptor_heap_pool.h"
#include "xenia/ui/d3d12/d3d12_provider.h"
#include "xenia/ui/d3d12/d3d12_upload_buffer_pool.h"
#include "xenia/ui/d3d12/d3d12_util.h"
@@ -58,8 +58,9 @@ class D3D12CommandProcessor : public CommandProcessor {
void RestoreEdramSnapshot(const void* snapshot) override;
ui::d3d12::D3D12Context& GetD3D12Context() const {
return static_cast<ui::d3d12::D3D12Context&>(*context_);
ui::d3d12::D3D12Provider& GetD3D12Provider() const {
return *static_cast<ui::d3d12::D3D12Provider*>(
graphics_system_->provider());
}
// Returns the deferred drawing command list for the currently open
@@ -153,7 +154,7 @@ class D3D12CommandProcessor : public CommandProcessor {
kEdramR32G32UintUAV,
kEdramR32G32B32A32UintUAV,
kGammaRampNormalSRV,
kGammaRampTableSRV,
kGammaRampPWLSRV,
// Beyond this point, SRVs are accessible to shaders through an unbounded
@@ -210,16 +211,14 @@ class D3D12CommandProcessor : public CommandProcessor {
// Returns the text to display in the GPU backend name in the window title.
std::string GetWindowTitleText() const;
std::unique_ptr<xe::ui::RawImage> Capture();
protected:
bool SetupContext() override;
void ShutdownContext() override;
void WriteRegister(uint32_t index, uint32_t value) override;
void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) override;
void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) override;
void OnPrimaryBufferEnd() override;
@@ -321,8 +320,9 @@ class D3D12CommandProcessor : public CommandProcessor {
void CheckSubmissionFence(uint64_t await_submission);
// If is_guest_command is true, a new full frame - with full cleanup of
// resources and, if needed, starting capturing - is opened if pending (as
// opposed to simply resuming after mid-frame synchronization).
void BeginSubmission(bool is_guest_command);
// opposed to simply resuming after mid-frame synchronization). Returns
// whether a submission is open currently and the device is not removed.
bool BeginSubmission(bool is_guest_command);
// If is_swap is true, a full frame is closed - with, if needed, cache
// clearing and stopping capturing. Returns whether the submission was done
// successfully, if it has failed, leaves it open.
@@ -380,6 +380,8 @@ class D3D12CommandProcessor : public CommandProcessor {
void WriteGammaRampSRV(bool is_pwl, D3D12_CPU_DESCRIPTOR_HANDLE handle) const;
bool device_removed_ = false;
bool cache_clear_requested_ = false;
HANDLE fence_completion_event_ = nullptr;
@@ -497,42 +499,73 @@ class D3D12CommandProcessor : public CommandProcessor {
std::unique_ptr<TextureCache> texture_cache_;
// Mip 0 contains the normal gamma ramp (256 entries), mip 1 contains the PWL
// ramp (128 entries). DXGI_FORMAT_R10G10B10A2_UNORM 1D.
ID3D12Resource* gamma_ramp_texture_ = nullptr;
D3D12_RESOURCE_STATES gamma_ramp_texture_state_;
// Bytes 0x0...0x3FF - 256-entry R10G10B10X2 gamma ramp (red and blue must be
// read as swapped - 535107D4 has settings allowing separate configuration).
// Bytes 0x400...0x9FF - 128-entry PWL R16G16 gamma ramp (R - base, G - delta,
// low 6 bits of each are zero, 3 elements per entry).
// https://www.x.org/docs/AMD/old/42590_m76_rrg_1.01o.pdf
Microsoft::WRL::ComPtr<ID3D12Resource> gamma_ramp_buffer_;
D3D12_RESOURCE_STATES gamma_ramp_buffer_state_;
// Upload buffer for an image that is the same as gamma_ramp_, but with
// kQueueFrames array layers.
ID3D12Resource* gamma_ramp_upload_ = nullptr;
uint8_t* gamma_ramp_upload_mapping_ = nullptr;
D3D12_PLACED_SUBRESOURCE_FOOTPRINT gamma_ramp_footprints_[kQueueFrames * 2];
Microsoft::WRL::ComPtr<ID3D12Resource> gamma_ramp_upload_buffer_;
uint8_t* gamma_ramp_upload_buffer_mapping_ = nullptr;
static constexpr uint32_t kSwapTextureWidth = 1280;
static constexpr uint32_t kSwapTextureHeight = 720;
std::pair<uint32_t, uint32_t> GetSwapTextureSize() const {
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);
}
ID3D12Resource* swap_texture_ = nullptr;
D3D12_PLACED_SUBRESOURCE_FOOTPRINT swap_texture_copy_footprint_;
UINT64 swap_texture_copy_size_;
ID3D12DescriptorHeap* swap_texture_rtv_descriptor_heap_ = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE swap_texture_rtv_;
ID3D12DescriptorHeap* swap_texture_srv_descriptor_heap_ = nullptr;
struct ApplyGammaConstants {
uint32_t size[2];
};
enum class ApplyGammaRootParameter : UINT {
kConstants,
kDestination,
kSource,
kRamp,
kCount,
};
Microsoft::WRL::ComPtr<ID3D12RootSignature> apply_gamma_root_signature_;
Microsoft::WRL::ComPtr<ID3D12PipelineState> apply_gamma_table_pipeline_;
Microsoft::WRL::ComPtr<ID3D12PipelineState>
apply_gamma_table_fxaa_luma_pipeline_;
Microsoft::WRL::ComPtr<ID3D12PipelineState> apply_gamma_pwl_pipeline_;
Microsoft::WRL::ComPtr<ID3D12PipelineState>
apply_gamma_pwl_fxaa_luma_pipeline_;
struct FxaaConstants {
uint32_t size[2];
float size_inv[2];
};
enum class FxaaRootParameter : UINT {
kConstants,
kDestination,
kSource,
kCount,
};
Microsoft::WRL::ComPtr<ID3D12RootSignature> fxaa_root_signature_;
Microsoft::WRL::ComPtr<ID3D12PipelineState> fxaa_pipeline_;
Microsoft::WRL::ComPtr<ID3D12PipelineState> fxaa_extreme_pipeline_;
// PWL gamma ramp can result in values with more precision than 10bpc. Though
// those sub-10bpc bits don't have any noticeable visual effect, so normally
// R10G10B10A2_UNORM is enough. But what's the most important is that for the
// original FXAA shader, the luma needs to be written to the alpha channel.
// For simplicity (to avoid modifying the FXAA shader and adding more texture
// fetches into it), and for the highest quality (preserving all 13 bits that
// may be generated by applying the PWL gamma ramp with an increment of 2^3,
// and also leaving some space for the result of applying fractional weights
// to calculate the luma), using R16G16B16A16_UNORM instead of
// R10G10B10X2_UNORM with a separate alpha texture.
static constexpr DXGI_FORMAT kFxaaSourceTextureFormat =
DXGI_FORMAT_R16G16B16A16_UNORM;
// Kept in NON_PIXEL_SHADER_RESOURCE state.
Microsoft::WRL::ComPtr<ID3D12Resource> fxaa_source_texture_;
uint64_t fxaa_source_texture_submission_ = 0;
// Unsubmitted barrier batch.
std::vector<D3D12_RESOURCE_BARRIER> barriers_;
// <Resource, submission where requested>, sorted by the submission number.
std::deque<std::pair<ID3D12Resource*, uint64_t>> buffers_for_deletion_;
std::deque<std::pair<uint64_t, ID3D12Resource*>> resources_for_deletion_;
static constexpr uint32_t kScratchBufferSizeIncrement = 16 * 1024 * 1024;
ID3D12Resource* scratch_buffer_ = nullptr;

View File

@@ -22,13 +22,6 @@ namespace xe {
namespace gpu {
namespace d3d12 {
// Generated with `xb buildshaders`.
namespace shaders {
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_vs.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h"
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h"
} // namespace shaders
D3D12GraphicsSystem::D3D12GraphicsSystem() {}
D3D12GraphicsSystem::~D3D12GraphicsSystem() {}
@@ -48,198 +41,11 @@ std::string D3D12GraphicsSystem::name() const {
X_STATUS D3D12GraphicsSystem::Setup(cpu::Processor* processor,
kernel::KernelState* kernel_state,
ui::Window* target_window) {
ui::WindowedAppContext* app_context,
bool is_surface_required) {
provider_ = xe::ui::d3d12::D3D12Provider::Create();
auto d3d12_provider = static_cast<xe::ui::d3d12::D3D12Provider*>(provider());
auto device = d3d12_provider->GetDevice();
auto result = GraphicsSystem::Setup(processor, kernel_state, target_window);
if (result != X_STATUS_SUCCESS) {
return result;
}
if (target_window) {
display_context_ = reinterpret_cast<xe::ui::d3d12::D3D12Context*>(
target_window->context());
}
// Create the stretch pipeline root signature, with 1 parameter (source
// texture) for raw stretch and 3 parameters (source texture, gamma ramp LUT,
// inverse of the size of the gamma ramp LUT) for gamma-correcting stretch.
// Raw.
D3D12_ROOT_PARAMETER stretch_root_parameters[3];
stretch_root_parameters[0].ParameterType =
D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
stretch_root_parameters[0].DescriptorTable.NumDescriptorRanges = 1;
D3D12_DESCRIPTOR_RANGE stretch_root_texture_range;
stretch_root_texture_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
stretch_root_texture_range.NumDescriptors = 1;
stretch_root_texture_range.BaseShaderRegister = 0;
stretch_root_texture_range.RegisterSpace = 0;
stretch_root_texture_range.OffsetInDescriptorsFromTableStart = 0;
stretch_root_parameters[0].DescriptorTable.pDescriptorRanges =
&stretch_root_texture_range;
stretch_root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_STATIC_SAMPLER_DESC stretch_sampler_desc;
stretch_sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
stretch_sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
stretch_sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
stretch_sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
stretch_sampler_desc.MipLODBias = 0.0f;
stretch_sampler_desc.MaxAnisotropy = 1;
stretch_sampler_desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
stretch_sampler_desc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
stretch_sampler_desc.MinLOD = 0.0f;
stretch_sampler_desc.MaxLOD = 0.0f;
stretch_sampler_desc.ShaderRegister = 0;
stretch_sampler_desc.RegisterSpace = 0;
stretch_sampler_desc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_ROOT_SIGNATURE_DESC stretch_root_desc;
stretch_root_desc.NumParameters = 1;
stretch_root_desc.pParameters = stretch_root_parameters;
stretch_root_desc.NumStaticSamplers = 1;
stretch_root_desc.pStaticSamplers = &stretch_sampler_desc;
stretch_root_desc.Flags =
D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS;
stretch_root_signature_ =
ui::d3d12::util::CreateRootSignature(*d3d12_provider, stretch_root_desc);
if (stretch_root_signature_ == nullptr) {
XELOGE("Failed to create the front buffer stretch root signature");
return X_STATUS_UNSUCCESSFUL;
}
// Gamma.
stretch_root_parameters[1].ParameterType =
D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
stretch_root_parameters[1].DescriptorTable.NumDescriptorRanges = 1;
D3D12_DESCRIPTOR_RANGE stretch_root_gamma_ramp_range;
stretch_root_gamma_ramp_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
stretch_root_gamma_ramp_range.NumDescriptors = 1;
stretch_root_gamma_ramp_range.BaseShaderRegister = 1;
stretch_root_gamma_ramp_range.RegisterSpace = 0;
stretch_root_gamma_ramp_range.OffsetInDescriptorsFromTableStart = 0;
stretch_root_parameters[1].DescriptorTable.pDescriptorRanges =
&stretch_root_gamma_ramp_range;
stretch_root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
stretch_root_parameters[2].ParameterType =
D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
stretch_root_parameters[2].Constants.ShaderRegister = 0;
stretch_root_parameters[2].Constants.RegisterSpace = 0;
stretch_root_parameters[2].Constants.Num32BitValues = 1;
stretch_root_parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
stretch_root_desc.NumParameters = 3;
stretch_root_desc.pParameters = stretch_root_parameters;
stretch_gamma_root_signature_ =
ui::d3d12::util::CreateRootSignature(*d3d12_provider, stretch_root_desc);
if (stretch_gamma_root_signature_ == nullptr) {
XELOGE(
"Failed to create the gamma-correcting front buffer stretch root "
"signature");
stretch_root_signature_->Release();
stretch_root_signature_ = nullptr;
return X_STATUS_UNSUCCESSFUL;
}
// Create the stretch pipelines.
D3D12_GRAPHICS_PIPELINE_STATE_DESC stretch_pipeline_desc = {};
stretch_pipeline_desc.pRootSignature = stretch_root_signature_;
stretch_pipeline_desc.VS.pShaderBytecode = shaders::fullscreen_tc_vs;
stretch_pipeline_desc.VS.BytecodeLength = sizeof(shaders::fullscreen_tc_vs);
stretch_pipeline_desc.PS.pShaderBytecode = shaders::stretch_ps;
stretch_pipeline_desc.PS.BytecodeLength = sizeof(shaders::stretch_ps);
// The shader will set alpha to 1, don't use output-merger to preserve it.
stretch_pipeline_desc.BlendState.RenderTarget[0].RenderTargetWriteMask =
D3D12_COLOR_WRITE_ENABLE_ALL;
stretch_pipeline_desc.SampleMask = UINT_MAX;
stretch_pipeline_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
stretch_pipeline_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
stretch_pipeline_desc.RasterizerState.DepthClipEnable = TRUE;
stretch_pipeline_desc.PrimitiveTopologyType =
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
stretch_pipeline_desc.NumRenderTargets = 1;
stretch_pipeline_desc.RTVFormats[0] =
ui::d3d12::D3D12Context::kSwapChainFormat;
stretch_pipeline_desc.SampleDesc.Count = 1;
if (FAILED(device->CreateGraphicsPipelineState(
&stretch_pipeline_desc, IID_PPV_ARGS(&stretch_pipeline_)))) {
XELOGE("Failed to create the front buffer stretch pipeline");
stretch_gamma_root_signature_->Release();
stretch_gamma_root_signature_ = nullptr;
stretch_root_signature_->Release();
stretch_root_signature_ = nullptr;
return X_STATUS_UNSUCCESSFUL;
}
stretch_pipeline_desc.pRootSignature = stretch_gamma_root_signature_;
stretch_pipeline_desc.PS.pShaderBytecode = shaders::stretch_gamma_ps;
stretch_pipeline_desc.PS.BytecodeLength = sizeof(shaders::stretch_gamma_ps);
if (FAILED(device->CreateGraphicsPipelineState(
&stretch_pipeline_desc, IID_PPV_ARGS(&stretch_gamma_pipeline_)))) {
XELOGE(
"Failed to create the gamma-correcting front buffer stretch pipeline");
stretch_pipeline_->Release();
stretch_pipeline_ = nullptr;
stretch_gamma_root_signature_->Release();
stretch_gamma_root_signature_ = nullptr;
stretch_root_signature_->Release();
stretch_root_signature_ = nullptr;
return X_STATUS_UNSUCCESSFUL;
}
return X_STATUS_SUCCESS;
}
void D3D12GraphicsSystem::Shutdown() {
ui::d3d12::util::ReleaseAndNull(stretch_gamma_pipeline_);
ui::d3d12::util::ReleaseAndNull(stretch_pipeline_);
ui::d3d12::util::ReleaseAndNull(stretch_gamma_root_signature_);
ui::d3d12::util::ReleaseAndNull(stretch_root_signature_);
GraphicsSystem::Shutdown();
}
std::unique_ptr<xe::ui::RawImage> D3D12GraphicsSystem::Capture() {
auto d3d12_command_processor =
static_cast<D3D12CommandProcessor*>(command_processor());
if (!d3d12_command_processor) {
return nullptr;
}
return d3d12_command_processor->Capture();
}
void D3D12GraphicsSystem::StretchTextureToFrontBuffer(
D3D12_GPU_DESCRIPTOR_HANDLE handle,
D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size,
ID3D12GraphicsCommandList* command_list) {
if (gamma_ramp_handle != nullptr) {
command_list->SetPipelineState(stretch_gamma_pipeline_);
command_list->SetGraphicsRootSignature(stretch_gamma_root_signature_);
command_list->SetGraphicsRootDescriptorTable(1, *gamma_ramp_handle);
command_list->SetGraphicsRoot32BitConstants(2, 1, &gamma_ramp_inv_size, 0);
} else {
command_list->SetPipelineState(stretch_pipeline_);
command_list->SetGraphicsRootSignature(stretch_root_signature_);
}
command_list->SetGraphicsRootDescriptorTable(0, handle);
command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
command_list->DrawInstanced(3, 1, 0, 0);
}
void D3D12GraphicsSystem::StretchTextureToFrontBuffer(
D3D12_GPU_DESCRIPTOR_HANDLE handle,
D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size,
DeferredCommandList& command_list) {
if (gamma_ramp_handle != nullptr) {
command_list.D3DSetPipelineState(stretch_gamma_pipeline_);
command_list.D3DSetGraphicsRootSignature(stretch_gamma_root_signature_);
command_list.D3DSetGraphicsRootDescriptorTable(1, *gamma_ramp_handle);
command_list.D3DSetGraphicsRoot32BitConstants(2, 1, &gamma_ramp_inv_size,
0);
} else {
command_list.D3DSetPipelineState(stretch_pipeline_);
command_list.D3DSetGraphicsRootSignature(stretch_root_signature_);
}
command_list.D3DSetGraphicsRootDescriptorTable(0, handle);
command_list.D3DIASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
command_list.D3DDrawInstanced(3, 1, 0, 0);
return GraphicsSystem::Setup(processor, kernel_state, app_context,
is_surface_required);
}
std::unique_ptr<CommandProcessor>
@@ -248,69 +54,6 @@ D3D12GraphicsSystem::CreateCommandProcessor() {
new D3D12CommandProcessor(this, kernel_state_));
}
void D3D12GraphicsSystem::Swap(xe::ui::UIEvent* e) {
if (display_context_->WasLost()) {
// We're crashing. Cheese it.
return;
}
if (!command_processor_) {
return;
}
auto& swap_state = command_processor_->swap_state();
ID3D12DescriptorHeap* swap_srv_heap;
{
std::lock_guard<std::mutex> lock(swap_state.mutex);
swap_state.pending = false;
swap_srv_heap = reinterpret_cast<ID3D12DescriptorHeap*>(
swap_state.front_buffer_texture);
}
if (swap_srv_heap == nullptr) {
// Not ready yet.
return;
}
uint32_t window_width, window_height;
display_context_->GetSwapChainSize(window_width, window_height);
int32_t target_x, target_y;
uint32_t target_width, target_height;
draw_util::GetPresentArea(swap_state.width, swap_state.height, window_width,
window_height, target_x, target_y, target_width,
target_height);
// For safety.
target_x = clamp(target_x, int32_t(D3D12_VIEWPORT_BOUNDS_MIN),
int32_t(D3D12_VIEWPORT_BOUNDS_MAX));
target_y = clamp(target_y, int32_t(D3D12_VIEWPORT_BOUNDS_MIN),
int32_t(D3D12_VIEWPORT_BOUNDS_MAX));
target_width = std::min(
target_width, uint32_t(int32_t(D3D12_VIEWPORT_BOUNDS_MAX) - target_x));
target_height = std::min(
target_height, uint32_t(int32_t(D3D12_VIEWPORT_BOUNDS_MAX) - target_y));
auto command_list = display_context_->GetSwapCommandList();
// Assuming the window has already been cleared to the needed letterbox color.
D3D12_VIEWPORT viewport;
viewport.TopLeftX = float(target_x);
viewport.TopLeftY = float(target_y);
viewport.Width = float(target_width);
viewport.Height = float(target_height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 0.0f;
command_list->RSSetViewports(1, &viewport);
D3D12_RECT scissor;
scissor.left = 0;
scissor.top = 0;
scissor.right = window_width;
scissor.bottom = window_height;
command_list->RSSetScissorRects(1, &scissor);
command_list->SetDescriptorHeaps(1, &swap_srv_heap);
StretchTextureToFrontBuffer(
swap_srv_heap->GetGPUDescriptorHandleForHeapStart(), nullptr, 0.0f,
command_list);
}
} // namespace d3d12
} // namespace gpu
} // namespace xe

View File

@@ -15,7 +15,6 @@
#include "xenia/gpu/command_processor.h"
#include "xenia/gpu/d3d12/deferred_command_list.h"
#include "xenia/gpu/graphics_system.h"
#include "xenia/ui/d3d12/d3d12_context.h"
namespace xe {
namespace gpu {
@@ -31,37 +30,11 @@ class D3D12GraphicsSystem : public GraphicsSystem {
std::string name() const override;
X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state,
ui::Window* target_window) override;
void Shutdown() override;
std::unique_ptr<xe::ui::RawImage> Capture() override;
// Draws a texture covering the entire viewport to the render target currently
// bound on the specified command list (in D3D12Context::kSwapChainFormat).
// This changes the current pipeline, graphics root signature and primitive
// topology. The gamma ramp texture must be 1D if present at all, for linear
// space, pass nullptr as the gamma ramp.
void StretchTextureToFrontBuffer(
D3D12_GPU_DESCRIPTOR_HANDLE handle,
D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size,
ID3D12GraphicsCommandList* command_list);
void StretchTextureToFrontBuffer(
D3D12_GPU_DESCRIPTOR_HANDLE handle,
D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size,
DeferredCommandList& command_list);
ui::WindowedAppContext* app_context,
bool is_surface_required) override;
protected:
std::unique_ptr<CommandProcessor> CreateCommandProcessor() override;
void Swap(xe::ui::UIEvent* e) override;
private:
ui::d3d12::D3D12Context* display_context_ = nullptr;
ID3D12RootSignature* stretch_root_signature_ = nullptr;
ID3D12RootSignature* stretch_gamma_root_signature_ = nullptr;
ID3D12PipelineState* stretch_pipeline_ = nullptr;
ID3D12PipelineState* stretch_gamma_pipeline_ = nullptr;
};
} // namespace d3d12

View File

@@ -33,7 +33,7 @@ bool D3D12PrimitiveProcessor::Initialize() {
return false;
}
frame_index_buffer_pool_ = std::make_unique<ui::d3d12::D3D12UploadBufferPool>(
command_processor_.GetD3D12Context().GetD3D12Provider(),
command_processor_.GetD3D12Provider(),
std::max(size_t(kMinRequiredConvertedIndexBufferSize),
ui::GraphicsUploadBufferPool::kDefaultPageSize));
return true;
@@ -90,7 +90,7 @@ bool D3D12PrimitiveProcessor::InitializeBuiltin16BitIndexBuffer(
assert_null(builtin_index_buffer_upload_);
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
D3D12_RESOURCE_DESC resource_desc;

View File

@@ -215,7 +215,7 @@ D3D12RenderTargetCache::~D3D12RenderTargetCache() { Shutdown(true); }
bool D3D12RenderTargetCache::Initialize() {
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
if (cvars::render_target_path_d3d12 == "rtv") {
@@ -1298,7 +1298,7 @@ bool D3D12RenderTargetCache::Update(bool is_rasterization_done,
void D3D12RenderTargetCache::WriteEdramRawSRVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
@@ -1311,7 +1311,7 @@ void D3D12RenderTargetCache::WriteEdramRawSRVDescriptor(
void D3D12RenderTargetCache::WriteEdramRawUAVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
@@ -1339,7 +1339,7 @@ void D3D12RenderTargetCache::WriteEdramUintPow2SRVDescriptor(
return;
}
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
@@ -1366,7 +1366,7 @@ void D3D12RenderTargetCache::WriteEdramUintPow2UAVDescriptor(
return;
}
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
@@ -1668,8 +1668,9 @@ bool D3D12RenderTargetCache::InitializeTraceSubmitDownloads() {
ui::d3d12::util::FillBufferResourceDesc(edram_snapshot_download_buffer_desc,
xenos::kEdramSizeBytes,
D3D12_RESOURCE_FLAG_NONE);
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
if (FAILED(device->CreateCommittedResource(
&ui::d3d12::util::kHeapPropertiesReadback,
provider.GetHeapFlagCreateNotZeroed(),
@@ -1721,7 +1722,8 @@ void D3D12RenderTargetCache::RestoreEdramSnapshot(const void* snapshot) {
// Create the buffer - will be used for copying to either a 32-bit 1280x2048
// render target or the EDRAM buffer.
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
if (!edram_snapshot_restore_pool_) {
edram_snapshot_restore_pool_ =
std::make_unique<ui::d3d12::D3D12UploadBufferPool>(
@@ -1966,8 +1968,7 @@ DXGI_FORMAT D3D12RenderTargetCache::GetDepthSRVStencilDXGIFormat(
RenderTargetCache::RenderTarget* D3D12RenderTargetCache::CreateRenderTarget(
RenderTargetKey key) {
ID3D12Device* device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
D3D12_RESOURCE_DESC resource_desc;
resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
@@ -4345,8 +4346,7 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
// ***************************************************************************
ID3D12PipelineState* const* pipelines;
ID3D12Device* device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
D3D12_INPUT_ELEMENT_DESC pipeline_input_element_desc;
pipeline_input_element_desc.SemanticName = "POSITION";
pipeline_input_element_desc.SemanticIndex = 0;
@@ -4516,7 +4516,7 @@ void D3D12RenderTargetCache::PerformTransfersAndResolveClears(
assert_true(GetPath() == Path::kHostRenderTargets);
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
uint64_t current_submission = command_processor_.GetCurrentSubmission();
DeferredCommandList& command_list =
@@ -6476,8 +6476,8 @@ ID3D12PipelineState* D3D12RenderTargetCache::GetOrCreateDumpPipeline(
// Pipeline
// ***************************************************************************
ID3D12PipelineState* pipeline = ui::d3d12::util::CreateComputePipeline(
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(),
built_shader_.data(), built_shader_size_bytes,
command_processor_.GetD3D12Provider().GetDevice(), built_shader_.data(),
built_shader_size_bytes,
key.is_depth ? dump_root_signature_depth_ : dump_root_signature_color_);
const char* format_name =
key.is_depth
@@ -6561,7 +6561,7 @@ void D3D12RenderTargetCache::DumpRenderTargets(uint32_t dump_base,
// 32bpp and 64bpp.
size_t edram_uav_indices[2] = {SIZE_MAX, SIZE_MAX};
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
if (!bindless_resources_used_) {
if (any_sources_32bpp_64bpp[0]) {
edram_uav_indices[0] = current_temporary_descriptors_cpu_.size();

View File

@@ -43,7 +43,7 @@ bool D3D12SharedMemory::Initialize() {
InitializeCommon();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
D3D12_RESOURCE_DESC buffer_desc;
@@ -215,8 +215,9 @@ void D3D12SharedMemory::CommitUAVWritesAndTransitionBuffer(
void D3D12SharedMemory::WriteRawSRVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider.OffsetViewDescriptor(buffer_descriptor_heap_start_,
@@ -226,8 +227,9 @@ void D3D12SharedMemory::WriteRawSRVDescriptor(
void D3D12SharedMemory::WriteRawUAVDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider.OffsetViewDescriptor(buffer_descriptor_heap_start_,
@@ -252,8 +254,9 @@ void D3D12SharedMemory::WriteUintPow2SRVDescriptor(
assert_unhandled_case(element_size_bytes_pow2);
return;
}
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider.OffsetViewDescriptor(buffer_descriptor_heap_start_,
@@ -278,8 +281,9 @@ void D3D12SharedMemory::WriteUintPow2UAVDescriptor(
assert_unhandled_case(element_size_bytes_pow2);
return;
}
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
device->CopyDescriptorsSimple(
1, handle,
provider.OffsetViewDescriptor(buffer_descriptor_heap_start_,
@@ -298,8 +302,9 @@ bool D3D12SharedMemory::InitializeTraceSubmitDownloads() {
ui::d3d12::util::FillBufferResourceDesc(
download_buffer_desc, download_page_count << page_size_log2(),
D3D12_RESOURCE_FLAG_NONE);
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
if (FAILED(device->CreateCommittedResource(
&ui::d3d12::util::kHeapPropertiesReadback,
provider.GetHeapFlagCreateNotZeroed(), &download_buffer_desc,
@@ -365,7 +370,7 @@ bool D3D12SharedMemory::AllocateSparseHostGpuMemoryRange(
<< host_gpu_memory_sparse_granularity_log2();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Context().GetD3D12Provider();
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
ID3D12CommandQueue* direct_queue = provider.GetDirectQueue();

View File

@@ -87,7 +87,8 @@ PipelineCache::PipelineCache(D3D12CommandProcessor& command_processor,
register_file_(register_file),
render_target_cache_(render_target_cache),
bindless_resources_used_(bindless_resources_used) {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
bool edram_rov_used = render_target_cache.GetPath() ==
RenderTargetCache::Path::kPixelShaderInterlock;
@@ -109,7 +110,8 @@ PipelineCache::PipelineCache(D3D12CommandProcessor& command_processor,
PipelineCache::~PipelineCache() { Shutdown(); }
bool PipelineCache::Initialize() {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
// Initialize the command processor thread DXIL objects.
dxbc_converter_ = nullptr;
@@ -414,7 +416,8 @@ void PipelineCache::InitializeShaderStorage(
std::mutex shaders_failed_to_translate_mutex;
std::vector<D3D12Shader::D3D12Translation*> shaders_failed_to_translate;
auto shader_translation_thread_function = [&]() {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
StringBuffer ucode_disasm_buffer;
DxbcShaderTranslator translator(
provider.GetAdapterVendorID(), bindless_resources_used_,
@@ -1241,7 +1244,8 @@ bool PipelineCache::TranslateAnalyzedShader(
}
// Disassemble the shader for dumping.
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
if (cvars::d3d12_dxbc_disasm_dxilconv) {
translation.DisassembleDxbcAndDxil(provider, cvars::d3d12_dxbc_disasm,
dxbc_converter, dxc_utils, dxc_compiler);
@@ -2052,8 +2056,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
}
// Create the D3D12 pipeline state object.
auto device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
ID3D12PipelineState* state;
if (FAILED(device->CreateGraphicsPipelineState(&state_desc,
IID_PPV_ARGS(&state)))) {

View File

@@ -869,8 +869,9 @@ TextureCache::TextureCache(D3D12CommandProcessor& command_processor,
TextureCache::~TextureCache() { Shutdown(); }
bool TextureCache::Initialize() {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
if (IsDrawResolutionScaled()) {
// Buffers not used yet - no need aliasing barriers to change ownership of
@@ -1444,7 +1445,8 @@ void TextureCache::WriteActiveTextureBindfulSRV(
}
}
}
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
D3D12_CPU_DESCRIPTOR_HANDLE source_handle;
if (descriptor_index != UINT32_MAX) {
assert_not_null(texture);
@@ -1622,8 +1624,7 @@ void TextureCache::WriteSampler(SamplerParameters parameters,
desc.MinLOD = float(parameters.mip_min_level);
// Maximum mip level is in the texture resource itself.
desc.MaxLOD = FLT_MAX;
auto device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
device->CreateSampler(&desc, handle);
}
@@ -1712,8 +1713,9 @@ bool TextureCache::EnsureScaledResolveMemoryCommitted(
uint64_t last_scaled = uint64_t(start_unscaled + (length_unscaled - 1)) *
draw_resolution_scale_area;
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
// Ensure GPU virtual memory for buffers that may be used to access the range
// is allocated - buffers are created. Always creating both buffers for all
@@ -1943,8 +1945,8 @@ void TextureCache::CreateCurrentScaledResolveRangeUintPow2SRV(
scaled_resolve_2gb_buffers_[buffer_index];
assert_not_null(buffer);
ui::d3d12::util::CreateBufferTypedSRV(
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(),
handle, buffer->resource(),
command_processor_.GetD3D12Provider().GetDevice(), handle,
buffer->resource(),
ui::d3d12::util::GetUintPow2DXGIFormat(element_size_bytes_pow2),
uint32_t(scaled_resolve_current_range_length_scaled_ >>
element_size_bytes_pow2),
@@ -1961,8 +1963,8 @@ void TextureCache::CreateCurrentScaledResolveRangeUintPow2UAV(
scaled_resolve_2gb_buffers_[buffer_index];
assert_not_null(buffer);
ui::d3d12::util::CreateBufferTypedUAV(
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(),
handle, buffer->resource(),
command_processor_.GetD3D12Provider().GetDevice(), handle,
buffer->resource(),
ui::d3d12::util::GetUintPow2DXGIFormat(element_size_bytes_pow2),
uint32_t(scaled_resolve_current_range_length_scaled_ >>
element_size_bytes_pow2),
@@ -2254,8 +2256,9 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) {
// Untiling through a buffer instead of using unordered access because copying
// is not done that often.
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
auto device = provider.GetDevice();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
// Assuming untiling will be the next operation.
D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COPY_DEST;
ID3D12Resource* resource;
@@ -2317,9 +2320,9 @@ bool TextureCache::LoadTextureData(Texture* texture) {
return true;
}
auto& command_list = command_processor_.GetDeferredCommandList();
auto device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
DeferredCommandList& command_list =
command_processor_.GetDeferredCommandList();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
// Get the pipeline.
LoadMode load_mode = GetLoadMode(texture->key);
@@ -2875,8 +2878,7 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture,
host_swizzle |
D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES;
auto device =
command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice();
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
uint32_t descriptor_index;
if (bindless_resources_used_) {
descriptor_index =
@@ -2928,7 +2930,8 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture,
D3D12_CPU_DESCRIPTOR_HANDLE TextureCache::GetTextureDescriptorCPUHandle(
uint32_t descriptor_index) const {
auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider();
const ui::d3d12::D3D12Provider& provider =
command_processor_.GetD3D12Provider();
if (bindless_resources_used_) {
return provider.OffsetViewDescriptor(
command_processor_.GetViewBindlessHeapCPUStart(), descriptor_index);