// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // 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 #include #include namespace D3D12MA { class Allocation; } class D3D12Device; class D3D12Texture final : public GPUTexture { friend D3D12Device; public: template using ComPtr = Microsoft::WRL::ComPtr; ~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 IsValid() const override { return static_cast(m_resource); } 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 resource, ComPtr 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 m_resource; ComPtr 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 D3D12Framebuffer final : public GPUFramebuffer { friend D3D12Device; public: ~D3D12Framebuffer() override; ALWAYS_INLINE const D3D12DescriptorHandle& GetRTV() const { return m_rtv; } ALWAYS_INLINE const D3D12DescriptorHandle& GetDSV() const { return m_dsv; } void SetDebugName(const std::string_view& name) override; private: D3D12Framebuffer(GPUTexture* rt, GPUTexture* ds, u32 width, u32 height, D3D12DescriptorHandle rtv, D3D12DescriptorHandle dsv); D3D12DescriptorHandle m_rtv; D3D12DescriptorHandle m_dsv; }; 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; };