dolphin/Source/Core/VideoBackends/D3D12/D3D12Gfx.h

181 lines
7.6 KiB
C++

// Copyright 2019 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <d3d12.h>
#include "VideoBackends/D3D12/DescriptorAllocator.h"
#include "VideoBackends/D3D12/DescriptorHeapManager.h"
#include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/Constants.h"
namespace DX12
{
class DXFramebuffer;
class DXTexture;
class DXShader;
class DXPipeline;
class SwapChain;
class Gfx final : public ::AbstractGfx
{
public:
Gfx(std::unique_ptr<SwapChain> swap_chain, float backbuffer_scale);
~Gfx() override;
static Gfx* GetInstance() { return static_cast<Gfx*>(g_gfx.get()); }
bool IsHeadless() const override;
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config,
std::string_view name) override;
std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
std::vector<AbstractTexture*> additional_color_attachments) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, std::string_view source,
std::string_view name) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length,
std::string_view name) override;
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data = nullptr,
size_t cache_data_length = 0) override;
void Flush() override;
void WaitForGPUIdle() override;
void ClearRegion(const MathUtil::Rectangle<int>& target_rc, bool color_enable, bool alpha_enable,
bool z_enable, u32 color, u32 z) override;
void SetPipeline(const AbstractPipeline* pipeline) override;
void SetFramebuffer(AbstractFramebuffer* framebuffer) override;
void SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer) override;
void SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, const ClearColor& color_value = {},
float depth_value = 0.0f) override;
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
void SetTexture(u32 index, const AbstractTexture* texture) override;
void SetSamplerState(u32 index, const SamplerState& state) override;
void SetComputeImageTexture(u32 index, AbstractTexture* texture, bool read, bool write) override;
void UnbindTexture(const AbstractTexture* texture) override;
void SetViewport(float x, float y, float width, float height, float near_depth,
float far_depth) override;
void Draw(u32 base_vertex, u32 num_vertices) override;
void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) override;
void DispatchComputeShader(const AbstractShader* shader, u32 groupsize_x, u32 groupsize_y,
u32 groupsize_z, u32 groups_x, u32 groups_y, u32 groups_z) override;
bool BindBackbuffer(const ClearColor& clear_color = {}) override;
void PresentBackbuffer() override;
SurfaceInfo GetSurfaceInfo() const override;
// Completes the current render pass, executes the command buffer, and restores state ready for
// next render. Use when you want to kick the current buffer to make room for new data.
void ExecuteCommandList(bool wait_for_completion);
// Setting constant buffer handles.
void SetConstantBuffer(u32 index, D3D12_GPU_VIRTUAL_ADDRESS address);
// Setting textures via descriptor handles. This is assumed to be in the shadow heap.
void SetTextureDescriptor(u32 index, D3D12_CPU_DESCRIPTOR_HANDLE handle);
// Pixel shader UAV.
void SetPixelShaderUAV(D3D12_CPU_DESCRIPTOR_HANDLE handle);
// Graphics vertex/index buffer binding.
void SetVertexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, D3D12_CPU_DESCRIPTOR_HANDLE srv,
u32 stride, u32 size);
void SetIndexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, u32 size, DXGI_FORMAT format);
// Binds all dirty state
bool ApplyState();
protected:
void OnConfigChanged(u32 bits) override;
private:
// Dirty bits
enum DirtyStates
{
DirtyState_Framebuffer = (1 << 0),
DirtyState_Pipeline = (1 << 1),
DirtyState_Textures = (1 << 2),
DirtyState_Samplers = (1 << 3),
DirtyState_Viewport = (1 << 4),
DirtyState_ScissorRect = (1 << 5),
DirtyState_ComputeImageTexture = (1 << 6),
DirtyState_PS_UAV = (1 << 7),
DirtyState_PS_CBV = (1 << 8),
DirtyState_VS_CBV = (1 << 9),
DirtyState_PS_CUS_CBV = (1 << 10),
DirtyState_GS_CBV = (1 << 11),
DirtyState_SRV_Descriptor = (1 << 12),
DirtyState_Sampler_Descriptor = (1 << 13),
DirtyState_UAV_Descriptor = (1 << 14),
DirtyState_VertexBuffer = (1 << 15),
DirtyState_IndexBuffer = (1 << 16),
DirtyState_PrimitiveTopology = (1 << 17),
DirtyState_RootSignature = (1 << 18),
DirtyState_ComputeRootSignature = (1 << 19),
DirtyState_DescriptorHeaps = (1 << 20),
DirtyState_VS_SRV = (1 << 21),
DirtyState_VS_SRV_Descriptor = (1 << 22),
DirtyState_All =
DirtyState_Framebuffer | DirtyState_Pipeline | DirtyState_Textures | DirtyState_Samplers |
DirtyState_Viewport | DirtyState_ScissorRect | DirtyState_ComputeImageTexture |
DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV | DirtyState_PS_CUS_CBV |
DirtyState_GS_CBV | DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor |
DirtyState_UAV_Descriptor | DirtyState_VertexBuffer | DirtyState_IndexBuffer |
DirtyState_PrimitiveTopology | DirtyState_RootSignature | DirtyState_ComputeRootSignature |
DirtyState_DescriptorHeaps | DirtyState_VS_SRV | DirtyState_VS_SRV_Descriptor
};
void CheckForSwapChainChanges();
void BindFramebuffer(DXFramebuffer* fb);
void SetRootSignatures();
void SetDescriptorHeaps();
void UpdateDescriptorTables();
bool UpdateSRVDescriptorTable();
bool UpdateUAVDescriptorTable();
bool UpdateVSSRVDescriptorTable();
bool UpdateComputeUAVDescriptorTable();
bool UpdateSamplerDescriptorTable();
float m_backbuffer_scale;
// Owned objects
std::unique_ptr<SwapChain> m_swap_chain;
// Current state
struct
{
ID3D12RootSignature* root_signature = nullptr;
DXShader* compute_shader = nullptr;
std::array<D3D12_GPU_VIRTUAL_ADDRESS, 4> constant_buffers = {};
std::array<D3D12_CPU_DESCRIPTOR_HANDLE, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> textures = {};
D3D12_CPU_DESCRIPTOR_HANDLE vs_srv = {};
D3D12_CPU_DESCRIPTOR_HANDLE ps_uav = {};
SamplerStateSet samplers = {};
const DXTexture* compute_image_texture = nullptr;
D3D12_VIEWPORT viewport = {};
D3D12_RECT scissor = {};
D3D12_GPU_DESCRIPTOR_HANDLE vertex_srv_descriptor_base = {};
D3D12_GPU_DESCRIPTOR_HANDLE srv_descriptor_base = {};
D3D12_GPU_DESCRIPTOR_HANDLE sampler_descriptor_base = {};
D3D12_GPU_DESCRIPTOR_HANDLE uav_descriptor_base = {};
D3D12_GPU_DESCRIPTOR_HANDLE compute_uav_descriptor_base = {};
D3D12_VERTEX_BUFFER_VIEW vertex_buffer = {};
D3D12_INDEX_BUFFER_VIEW index_buffer = {};
D3D12_PRIMITIVE_TOPOLOGY primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
bool using_integer_rtv = false;
} m_state;
u32 m_dirty_bits = DirtyState_All;
};
} // namespace DX12