[D3D12] Window output
This commit is contained in:
parent
ea1abdaa6e
commit
2e79eac976
|
@ -16,6 +16,7 @@
|
|||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/base/profiling.h"
|
||||
#include "xenia/gpu/d3d12/d3d12_graphics_system.h"
|
||||
#include "xenia/gpu/d3d12/d3d12_shader.h"
|
||||
#include "xenia/gpu/xenos.h"
|
||||
|
||||
|
@ -525,6 +526,69 @@ bool D3D12CommandProcessor::SetupContext() {
|
|||
return false;
|
||||
}
|
||||
|
||||
D3D12_HEAP_PROPERTIES swap_texture_heap_properties = {};
|
||||
swap_texture_heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
D3D12_RESOURCE_DESC swap_texture_desc;
|
||||
swap_texture_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
swap_texture_desc.Alignment = 0;
|
||||
swap_texture_desc.Width = kSwapTextureWidth;
|
||||
swap_texture_desc.Height = kSwapTextureHeight;
|
||||
swap_texture_desc.DepthOrArraySize = 1;
|
||||
swap_texture_desc.MipLevels = 1;
|
||||
swap_texture_desc.Format = ui::d3d12::D3D12Context::kSwapChainFormat;
|
||||
swap_texture_desc.SampleDesc.Count = 1;
|
||||
swap_texture_desc.SampleDesc.Quality = 0;
|
||||
swap_texture_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
swap_texture_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
// Can be sampled at any time, switch to render target when needed, then back.
|
||||
if (FAILED(device->CreateCommittedResource(
|
||||
&swap_texture_heap_properties, D3D12_HEAP_FLAG_NONE,
|
||||
&swap_texture_desc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
nullptr, IID_PPV_ARGS(&swap_texture_)))) {
|
||||
XELOGE("Failed to create the command processor front buffer");
|
||||
return false;
|
||||
}
|
||||
D3D12_DESCRIPTOR_HEAP_DESC swap_descriptor_heap_desc;
|
||||
swap_descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
swap_descriptor_heap_desc.NumDescriptors = 1;
|
||||
swap_descriptor_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
swap_descriptor_heap_desc.NodeMask = 0;
|
||||
if (FAILED(device->CreateDescriptorHeap(
|
||||
&swap_descriptor_heap_desc,
|
||||
IID_PPV_ARGS(&swap_texture_rtv_descriptor_heap_)))) {
|
||||
XELOGE("Failed to create the command processor front buffer RTV heap");
|
||||
return false;
|
||||
}
|
||||
swap_texture_rtv_ =
|
||||
swap_texture_rtv_descriptor_heap_->GetCPUDescriptorHandleForHeapStart();
|
||||
D3D12_RENDER_TARGET_VIEW_DESC swap_rtv_desc;
|
||||
swap_rtv_desc.Format = ui::d3d12::D3D12Context::kSwapChainFormat;
|
||||
swap_rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
swap_rtv_desc.Texture2D.MipSlice = 0;
|
||||
swap_rtv_desc.Texture2D.PlaneSlice = 0;
|
||||
device->CreateRenderTargetView(swap_texture_, &swap_rtv_desc,
|
||||
swap_texture_rtv_);
|
||||
swap_descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
swap_descriptor_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
if (FAILED(device->CreateDescriptorHeap(
|
||||
&swap_descriptor_heap_desc,
|
||||
IID_PPV_ARGS(&swap_texture_srv_descriptor_heap_)))) {
|
||||
XELOGE("Failed to create the command processor front buffer SRV heap");
|
||||
return false;
|
||||
}
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC swap_srv_desc;
|
||||
swap_srv_desc.Format = ui::d3d12::D3D12Context::kSwapChainFormat;
|
||||
swap_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
swap_srv_desc.Shader4ComponentMapping =
|
||||
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
swap_srv_desc.Texture2D.MostDetailedMip = 0;
|
||||
swap_srv_desc.Texture2D.MipLevels = 1;
|
||||
swap_srv_desc.Texture2D.PlaneSlice = 0;
|
||||
swap_srv_desc.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||
device->CreateShaderResourceView(
|
||||
swap_texture_, &swap_srv_desc,
|
||||
swap_texture_srv_descriptor_heap_->GetCPUDescriptorHandleForHeapStart());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -543,6 +607,26 @@ void D3D12CommandProcessor::ShutdownContext() {
|
|||
}
|
||||
buffers_for_deletion_.clear();
|
||||
|
||||
if (swap_texture_srv_descriptor_heap_ != nullptr) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(swap_state_.mutex);
|
||||
swap_state_.pending = false;
|
||||
swap_state_.front_buffer_texture = 0;
|
||||
}
|
||||
auto graphics_system = static_cast<D3D12GraphicsSystem*>(graphics_system_);
|
||||
graphics_system->AwaitFrontBufferUnused();
|
||||
swap_texture_srv_descriptor_heap_->Release();
|
||||
swap_texture_srv_descriptor_heap_ = nullptr;
|
||||
}
|
||||
if (swap_texture_rtv_descriptor_heap_ != nullptr) {
|
||||
swap_texture_rtv_descriptor_heap_->Release();
|
||||
swap_texture_rtv_descriptor_heap_ = nullptr;
|
||||
}
|
||||
if (swap_texture_ != nullptr) {
|
||||
swap_texture_->Release();
|
||||
swap_texture_ = nullptr;
|
||||
}
|
||||
|
||||
sampler_heap_pool_.reset();
|
||||
view_heap_pool_.reset();
|
||||
constant_buffer_pool_.reset();
|
||||
|
@ -593,6 +677,54 @@ void D3D12CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
|
|||
uint32_t frontbuffer_height) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
// In case the swap command is the only one in the frame.
|
||||
BeginFrame();
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE frontbuffer_cpu_handle;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE frontbuffer_gpu_handle;
|
||||
if (RequestViewDescriptors(0, 1, 1, frontbuffer_cpu_handle,
|
||||
frontbuffer_gpu_handle) != 0) {
|
||||
if (texture_cache_->RequestSwapTexture(frontbuffer_cpu_handle)) {
|
||||
auto command_list = GetCurrentCommandList();
|
||||
render_target_cache_->UnbindRenderTargets();
|
||||
// The swap texture is kept as an SRV because the graphics system may draw
|
||||
// with it at any time. It's switched to RTV and back when needed.
|
||||
PushTransitionBarrier(swap_texture_,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
SubmitBarriers();
|
||||
command_list->OMSetRenderTargets(1, &swap_texture_rtv_, TRUE, nullptr);
|
||||
D3D12_VIEWPORT viewport;
|
||||
viewport.TopLeftX = 0.0f;
|
||||
viewport.TopLeftY = 0.0f;
|
||||
viewport.Width = float(kSwapTextureWidth);
|
||||
viewport.Height = float(kSwapTextureHeight);
|
||||
viewport.MinDepth = 0.0f;
|
||||
viewport.MaxDepth = 0.0f;
|
||||
command_list->RSSetViewports(1, &viewport);
|
||||
D3D12_RECT scissor;
|
||||
scissor.left = 0;
|
||||
scissor.top = 0;
|
||||
scissor.right = kSwapTextureWidth;
|
||||
scissor.bottom = kSwapTextureHeight;
|
||||
command_list->RSSetScissorRects(1, &scissor);
|
||||
D3D12GraphicsSystem* graphics_system =
|
||||
static_cast<D3D12GraphicsSystem*>(graphics_system_);
|
||||
graphics_system->StretchTextureToFrontBuffer(frontbuffer_gpu_handle,
|
||||
command_list);
|
||||
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.
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(swap_state_.mutex);
|
||||
swap_state_.width = kSwapTextureWidth;
|
||||
swap_state_.height = kSwapTextureHeight;
|
||||
swap_state_.front_buffer_texture =
|
||||
reinterpret_cast<uintptr_t>(swap_texture_srv_descriptor_heap_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EndFrame();
|
||||
|
||||
if (cache_clear_requested_) {
|
||||
|
|
|
@ -185,6 +185,13 @@ class D3D12CommandProcessor : public CommandProcessor {
|
|||
std::unique_ptr<ui::d3d12::DescriptorHeapPool> view_heap_pool_ = nullptr;
|
||||
std::unique_ptr<ui::d3d12::DescriptorHeapPool> sampler_heap_pool_ = nullptr;
|
||||
|
||||
static constexpr uint32_t kSwapTextureWidth = 1280;
|
||||
static constexpr uint32_t kSwapTextureHeight = 720;
|
||||
ID3D12Resource* swap_texture_ = nullptr;
|
||||
ID3D12DescriptorHeap* swap_texture_rtv_descriptor_heap_ = nullptr;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE swap_texture_rtv_;
|
||||
ID3D12DescriptorHeap* swap_texture_srv_descriptor_heap_ = nullptr;
|
||||
|
||||
// Unsubmitted barrier batch.
|
||||
std::vector<D3D12_RESOURCE_BARRIER> barriers_;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "xenia/gpu/d3d12/d3d12_graphics_system.h"
|
||||
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
|
||||
#include "xenia/ui/d3d12/d3d12_provider.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
@ -17,6 +18,10 @@ namespace xe {
|
|||
namespace gpu {
|
||||
namespace d3d12 {
|
||||
|
||||
// Generated with `xb buildhlsl`.
|
||||
#include "xenia/gpu/d3d12/shaders/bin/fullscreen_vs.h"
|
||||
#include "xenia/gpu/d3d12/shaders/bin/stretch_ps.h"
|
||||
|
||||
D3D12GraphicsSystem::D3D12GraphicsSystem() {}
|
||||
|
||||
D3D12GraphicsSystem::~D3D12GraphicsSystem() {}
|
||||
|
@ -25,11 +30,138 @@ X_STATUS D3D12GraphicsSystem::Setup(cpu::Processor* processor,
|
|||
kernel::KernelState* kernel_state,
|
||||
ui::Window* target_window) {
|
||||
provider_ = xe::ui::d3d12::D3D12Provider::Create(target_window);
|
||||
auto device =
|
||||
static_cast<xe::ui::d3d12::D3D12Provider*>(provider())->GetDevice();
|
||||
|
||||
return GraphicsSystem::Setup(processor, kernel_state, target_window);
|
||||
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.
|
||||
D3D12_ROOT_PARAMETER stretch_root_parameter;
|
||||
stretch_root_parameter.ParameterType =
|
||||
D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
stretch_root_parameter.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_parameter.DescriptorTable.pDescriptorRanges =
|
||||
&stretch_root_texture_range;
|
||||
stretch_root_parameter.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_parameter;
|
||||
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;
|
||||
ID3DBlob* stretch_root_blob;
|
||||
ID3DBlob* stretch_root_error_blob = nullptr;
|
||||
if (FAILED(D3D12SerializeRootSignature(
|
||||
&stretch_root_desc, D3D_ROOT_SIGNATURE_VERSION_1, &stretch_root_blob,
|
||||
&stretch_root_error_blob))) {
|
||||
XELOGE("Failed to serialize the front buffer stretch root signature");
|
||||
if (stretch_root_error_blob != nullptr) {
|
||||
XELOGE("%s", reinterpret_cast<const char*>(
|
||||
stretch_root_error_blob->GetBufferPointer()));
|
||||
stretch_root_error_blob->Release();
|
||||
}
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
if (stretch_root_error_blob != nullptr) {
|
||||
stretch_root_error_blob->Release();
|
||||
}
|
||||
if (FAILED(device->CreateRootSignature(
|
||||
0, stretch_root_blob->GetBufferPointer(),
|
||||
stretch_root_blob->GetBufferSize(),
|
||||
IID_PPV_ARGS(&stretch_root_signature_)))) {
|
||||
XELOGE("Failed to create the front buffer stretch root signature");
|
||||
stretch_root_blob->Release();
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
stretch_root_blob->Release();
|
||||
|
||||
// Create the stretch pipeline.
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC stretch_pipeline_desc = {};
|
||||
stretch_pipeline_desc.pRootSignature = stretch_root_signature_;
|
||||
stretch_pipeline_desc.VS.pShaderBytecode = fullscreen_vs;
|
||||
stretch_pipeline_desc.VS.BytecodeLength = sizeof(fullscreen_vs);
|
||||
stretch_pipeline_desc.PS.pShaderBytecode = stretch_ps;
|
||||
stretch_pipeline_desc.PS.BytecodeLength = sizeof(stretch_ps);
|
||||
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 state");
|
||||
stretch_root_signature_->Release();
|
||||
stretch_root_signature_ = nullptr;
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void D3D12GraphicsSystem::Shutdown() { GraphicsSystem::Shutdown(); }
|
||||
void D3D12GraphicsSystem::Shutdown() {
|
||||
if (stretch_pipeline_ != nullptr) {
|
||||
stretch_pipeline_->Release();
|
||||
stretch_pipeline_ = nullptr;
|
||||
}
|
||||
if (stretch_root_signature_ != nullptr) {
|
||||
stretch_root_signature_->Release();
|
||||
stretch_root_signature_ = nullptr;
|
||||
}
|
||||
|
||||
GraphicsSystem::Shutdown();
|
||||
}
|
||||
|
||||
void D3D12GraphicsSystem::AwaitFrontBufferUnused() {
|
||||
if (display_context_ != nullptr) {
|
||||
display_context_->AwaitAllFramesCompletion();
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12GraphicsSystem::StretchTextureToFrontBuffer(
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE handle,
|
||||
ID3D12GraphicsCommandList* command_list) {
|
||||
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);
|
||||
}
|
||||
|
||||
std::unique_ptr<CommandProcessor>
|
||||
D3D12GraphicsSystem::CreateCommandProcessor() {
|
||||
|
@ -38,13 +170,48 @@ D3D12GraphicsSystem::CreateCommandProcessor() {
|
|||
}
|
||||
|
||||
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();
|
||||
std::lock_guard<std::mutex> lock(swap_state.mutex);
|
||||
swap_state.pending = false;
|
||||
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;
|
||||
}
|
||||
|
||||
auto command_list = display_context_->GetSwapCommandList();
|
||||
uint32_t swap_width, swap_height;
|
||||
display_context_->GetSwapChainSize(swap_width, swap_height);
|
||||
D3D12_VIEWPORT viewport;
|
||||
viewport.TopLeftX = 0.0f;
|
||||
viewport.TopLeftY = 0.0f;
|
||||
viewport.Width = float(swap_width);
|
||||
viewport.Height = float(swap_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 = swap_width;
|
||||
scissor.bottom = swap_height;
|
||||
command_list->RSSetScissorRects(1, &scissor);
|
||||
command_list->SetDescriptorHeaps(1, &swap_srv_heap);
|
||||
StretchTextureToFrontBuffer(
|
||||
swap_srv_heap->GetGPUDescriptorHandleForHeapStart(), command_list);
|
||||
}
|
||||
|
||||
} // namespace d3d12
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "xenia/gpu/command_processor.h"
|
||||
#include "xenia/gpu/graphics_system.h"
|
||||
#include "xenia/ui/d3d12/d3d12_context.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
@ -30,10 +31,24 @@ class D3D12GraphicsSystem : public GraphicsSystem {
|
|||
ui::Window* target_window) override;
|
||||
void Shutdown() override;
|
||||
|
||||
void AwaitFrontBufferUnused();
|
||||
|
||||
// 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.
|
||||
void StretchTextureToFrontBuffer(D3D12_GPU_DESCRIPTOR_HANDLE handle,
|
||||
ID3D12GraphicsCommandList* command_list);
|
||||
|
||||
private:
|
||||
std::unique_ptr<CommandProcessor> CreateCommandProcessor() override;
|
||||
|
||||
void Swap(xe::ui::UIEvent* e) override;
|
||||
|
||||
ui::d3d12::D3D12Context* display_context_ = nullptr;
|
||||
|
||||
ID3D12RootSignature* stretch_root_signature_ = nullptr;
|
||||
ID3D12PipelineState* stretch_pipeline_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace d3d12
|
||||
|
|
|
@ -1061,11 +1061,13 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
|
|||
return true;
|
||||
}
|
||||
|
||||
void RenderTargetCache::EndFrame() {
|
||||
void RenderTargetCache::UnbindRenderTargets() {
|
||||
StoreRenderTargetsToEDRAM();
|
||||
ClearBindings();
|
||||
}
|
||||
|
||||
void RenderTargetCache::EndFrame() { UnbindRenderTargets(); }
|
||||
|
||||
DXGI_FORMAT RenderTargetCache::GetColorDXGIFormat(
|
||||
ColorRenderTargetFormat format) {
|
||||
switch (format) {
|
||||
|
|
|
@ -220,6 +220,10 @@ class RenderTargetCache {
|
|||
// register values, and also clears the EDRAM buffer if needed. Must be in a
|
||||
// frame for calling.
|
||||
bool Resolve(SharedMemory* shared_memory, Memory* memory);
|
||||
// Flushes the render targets to EDRAM and unbinds them, for instance, when
|
||||
// the command processor takes over framebuffer bindings to draw something
|
||||
// special.
|
||||
void UnbindRenderTargets();
|
||||
void EndFrame();
|
||||
|
||||
static inline bool IsColorFormat64bpp(ColorRenderTargetFormat format) {
|
||||
|
|
|
@ -22,7 +22,7 @@ void main(uint3 xe_group_id : SV_GroupID,
|
|||
uint4 sample_info =
|
||||
(xe_edram_tile_sample_dest_info.xxxx >> uint4(15u, 14u, 17u, 16u)) & 1u;
|
||||
uint2 edram_tile_quarter =
|
||||
uint2(uint2(10u, 8u) <= xe_group_thread_id) * sample_info.xy;
|
||||
uint2(uint2(10u, 8u) <= xe_group_thread_id.xy) * sample_info.xy;
|
||||
uint edram_offset = XeEDRAMOffset(
|
||||
(xe_group_id.xy << sample_info.xy) + edram_tile_quarter,
|
||||
(xe_group_thread_id.xy - edram_tile_quarter * uint2(10u, 8u)) <<
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// A triangle covering the whole viewport.
|
||||
void main(uint xe_vertex_id : SV_VertexID, out float2 xe_texcoord : TEXCOORD,
|
||||
out float4 xe_position : SV_Position) {
|
||||
xe_texcoord = float2(uint2(xe_vertex_id, xe_vertex_id << 1u) & 2u);
|
||||
xe_position =
|
||||
float4(xe_texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
Texture2D<float4> xe_texture : register(t0);
|
||||
SamplerState xe_sampler : register(s0);
|
||||
float4 main(float2 xe_texcoord : TEXCOORD) : SV_Target {
|
||||
return xe_texture.SampleLevel(xe_sampler, xe_texcoord, 0.0f);
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include "xenia/memory.h"
|
||||
#include "xenia/ui/d3d12/d3d12_api.h"
|
||||
#include "xenia/ui/d3d12/d3d12_context.h"
|
||||
#include "xenia/ui/d3d12/pools.h"
|
||||
|
||||
namespace xe {
|
||||
|
|
|
@ -450,6 +450,39 @@ void TextureCache::WriteSampler(uint32_t fetch_constant,
|
|||
device->CreateSampler(&desc, handle);
|
||||
}
|
||||
|
||||
bool TextureCache::RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle) {
|
||||
auto group = reinterpret_cast<const xenos::xe_gpu_fetch_group_t*>(
|
||||
®ister_file_->values[XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0]);
|
||||
auto& fetch = group->texture_fetch;
|
||||
TextureKey key;
|
||||
uint32_t swizzle;
|
||||
TextureKeyFromFetchConstant(group->texture_fetch, key, swizzle);
|
||||
if (key.base_page == 0 || key.dimension != Dimension::k2D) {
|
||||
return false;
|
||||
}
|
||||
Texture* texture = FindOrCreateTexture(key);
|
||||
if (texture == nullptr || !LoadTextureData(texture)) {
|
||||
return false;
|
||||
}
|
||||
command_processor_->PushTransitionBarrier(
|
||||
texture->resource, texture->state,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
||||
srv_desc.Format = host_formats_[uint32_t(key.format)].dxgi_format;
|
||||
srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srv_desc.Shader4ComponentMapping =
|
||||
swizzle |
|
||||
D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES;
|
||||
srv_desc.Texture2D.MostDetailedMip = 0;
|
||||
srv_desc.Texture2D.MipLevels = 1;
|
||||
srv_desc.Texture2D.PlaneSlice = 0;
|
||||
srv_desc.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||
auto device =
|
||||
command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice();
|
||||
device->CreateShaderResourceView(texture->resource, &srv_desc, handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextureCache::TextureKeyFromFetchConstant(
|
||||
const xenos::xe_gpu_texture_fetch_t& fetch, TextureKey& key_out,
|
||||
uint32_t& swizzle_out) {
|
||||
|
|
|
@ -78,6 +78,8 @@ class TextureCache {
|
|||
void WriteSampler(uint32_t fetch_constant,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle);
|
||||
|
||||
bool RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle);
|
||||
|
||||
private:
|
||||
struct CopyModeInfo {
|
||||
const void* load_shader;
|
||||
|
|
|
@ -69,6 +69,10 @@ class D3D12Context : public GraphicsContext {
|
|||
D3D12_CPU_DESCRIPTOR_HANDLE GetSwapChainBackBufferRTV() const {
|
||||
return GetSwapChainBufferRTV(GetSwapChainBackBufferIndex());
|
||||
}
|
||||
void GetSwapChainSize(uint32_t& width, uint32_t& height) const {
|
||||
width = swap_chain_width_;
|
||||
height = swap_chain_height_;
|
||||
}
|
||||
ID3D12GraphicsCommandList* GetSwapCommandList() const {
|
||||
return swap_command_lists_[current_queue_frame_]->GetCommandList();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue