mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-12-04 19:45:41 +00:00
149 lines
5.3 KiB
C++
149 lines
5.3 KiB
C++
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
|
|
|
#pragma once
|
|
|
|
#include "d3d12_descriptor_heap_manager.h"
|
|
#include "d3d12_stream_buffer.h"
|
|
#include "gpu_device.h"
|
|
#include "gpu_texture.h"
|
|
|
|
#include <d3d12.h>
|
|
#include <limits>
|
|
#include <memory>
|
|
|
|
namespace D3D12MA {
|
|
class Allocation;
|
|
}
|
|
|
|
class D3D12Device;
|
|
|
|
class D3D12Texture final : public GPUTexture
|
|
{
|
|
friend D3D12Device;
|
|
|
|
public:
|
|
template<typename T>
|
|
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
|
|
|
~D3D12Texture() override;
|
|
|
|
void Destroy(bool defer);
|
|
|
|
ALWAYS_INLINE const D3D12DescriptorHandle& GetSRVDescriptor() const { return m_srv_descriptor; }
|
|
ALWAYS_INLINE const D3D12DescriptorHandle& GetWriteDescriptor() const { return m_write_descriptor; }
|
|
ALWAYS_INLINE const D3D12DescriptorHandle& GetUAVDescriptor() const { return m_uav_descriptor; }
|
|
ALWAYS_INLINE D3D12_RESOURCE_STATES GetResourceState() const { return m_resource_state; }
|
|
ALWAYS_INLINE DXGI_FORMAT GetDXGIFormat() const { return m_dxgi_format; }
|
|
ALWAYS_INLINE ID3D12Resource* GetResource() const { return m_resource.Get(); }
|
|
|
|
bool Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer = 0, u32 level = 0) override;
|
|
bool Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer = 0, u32 level = 0) override;
|
|
void Unmap() override;
|
|
void MakeReadyForSampling() override;
|
|
|
|
void SetDebugName(const std::string_view& name) override;
|
|
|
|
void TransitionToState(D3D12_RESOURCE_STATES state);
|
|
void CommitClear();
|
|
void CommitClear(ID3D12GraphicsCommandList* cmdlist);
|
|
|
|
static u32 CalculateSubresource(u32 layer, u32 level, u32 num_levels);
|
|
u32 CalculateSubresource(u32 layer, u32 level) const;
|
|
|
|
void TransitionToState(ID3D12GraphicsCommandList* cmdlist, D3D12_RESOURCE_STATES state);
|
|
void TransitionSubresourceToState(ID3D12GraphicsCommandList* cmdlist, u32 layer, u32 level,
|
|
D3D12_RESOURCE_STATES before_state, D3D12_RESOURCE_STATES after_state) const;
|
|
void TransitionSubresourceToState(ID3D12GraphicsCommandList* cmdlist, u32 subresource,
|
|
D3D12_RESOURCE_STATES before_state, D3D12_RESOURCE_STATES after_state) const;
|
|
static void TransitionSubresourceToState(ID3D12GraphicsCommandList* cmdlist, ID3D12Resource* resource,
|
|
u32 subresource, D3D12_RESOURCE_STATES before_state,
|
|
D3D12_RESOURCE_STATES after_state);
|
|
|
|
// Call when the texture is bound to the pipeline, or read from in a copy.
|
|
ALWAYS_INLINE void SetUseFenceValue(u64 counter) { m_use_fence_counter = counter; }
|
|
|
|
private:
|
|
enum class WriteDescriptorType : u8
|
|
{
|
|
None,
|
|
RTV,
|
|
DSV
|
|
};
|
|
|
|
D3D12Texture(u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type, Format format,
|
|
DXGI_FORMAT dxgi_format, ComPtr<ID3D12Resource> resource, ComPtr<D3D12MA::Allocation> allocation,
|
|
const D3D12DescriptorHandle& srv_descriptor, const D3D12DescriptorHandle& write_descriptor,
|
|
const D3D12DescriptorHandle& uav_descriptor, WriteDescriptorType wdtype,
|
|
D3D12_RESOURCE_STATES resource_state);
|
|
|
|
ID3D12GraphicsCommandList4* GetCommandBufferForUpdate();
|
|
ID3D12Resource* AllocateUploadStagingBuffer(const void* data, u32 pitch, u32 upload_pitch, u32 width,
|
|
u32 height) const;
|
|
void CopyTextureDataForUpload(void* dst, const void* src, u32 width, u32 height, u32 pitch, u32 upload_pitch) const;
|
|
void ActuallyCommitClear(ID3D12GraphicsCommandList* cmdlist);
|
|
|
|
ComPtr<ID3D12Resource> m_resource;
|
|
ComPtr<D3D12MA::Allocation> m_allocation;
|
|
|
|
D3D12DescriptorHandle m_srv_descriptor = {};
|
|
D3D12DescriptorHandle m_write_descriptor = {};
|
|
D3D12DescriptorHandle m_uav_descriptor = {};
|
|
|
|
DXGI_FORMAT m_dxgi_format = DXGI_FORMAT_UNKNOWN;
|
|
D3D12_RESOURCE_STATES m_resource_state = D3D12_RESOURCE_STATE_COMMON;
|
|
WriteDescriptorType m_write_descriptor_type = WriteDescriptorType::None;
|
|
|
|
// Contains the fence counter when the texture was last used.
|
|
// When this matches the current fence counter, the texture was used this command buffer.
|
|
u64 m_use_fence_counter = 0;
|
|
|
|
u16 m_map_x = 0;
|
|
u16 m_map_y = 0;
|
|
u16 m_map_width = 0;
|
|
u16 m_map_height = 0;
|
|
u8 m_map_layer = 0;
|
|
u8 m_map_level = 0;
|
|
};
|
|
|
|
class D3D12Sampler final : public GPUSampler
|
|
{
|
|
friend D3D12Device;
|
|
|
|
public:
|
|
~D3D12Sampler() override;
|
|
|
|
ALWAYS_INLINE const D3D12DescriptorHandle& GetDescriptor() const { return m_descriptor; }
|
|
|
|
void SetDebugName(const std::string_view& name) override;
|
|
|
|
private:
|
|
D3D12Sampler(D3D12DescriptorHandle descriptor);
|
|
|
|
D3D12DescriptorHandle m_descriptor;
|
|
};
|
|
|
|
class D3D12TextureBuffer final : public GPUTextureBuffer
|
|
{
|
|
friend D3D12Device;
|
|
|
|
public:
|
|
D3D12TextureBuffer(Format format, u32 size_in_elements);
|
|
~D3D12TextureBuffer() override;
|
|
|
|
ALWAYS_INLINE const D3D12DescriptorHandle& GetDescriptor() const { return m_descriptor; }
|
|
|
|
bool Create(D3D12Device& dev);
|
|
void Destroy(bool defer);
|
|
|
|
// Inherited via GPUTextureBuffer
|
|
void* Map(u32 required_elements) override;
|
|
void Unmap(u32 used_elements) override;
|
|
|
|
void SetDebugName(const std::string_view& name) override;
|
|
|
|
private:
|
|
D3D12StreamBuffer m_buffer;
|
|
D3D12DescriptorHandle m_descriptor;
|
|
};
|