[D3D12] Window output

This commit is contained in:
Triang3l 2018-08-23 19:50:11 +03:00
parent ea1abdaa6e
commit 2e79eac976
13 changed files with 384 additions and 7 deletions

View File

@ -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_) {

View File

@ -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_;

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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)) <<

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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*>(
&register_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) {

View File

@ -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;

View File

@ -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();
}