Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ set(GRAPHICS_DIRECTX12_SOURCES
src/Graphics/DirectX12/DirectX12Renderer.cpp
src/Graphics/DirectX12/DirectX12Shader.cpp
src/Graphics/DirectX12/DirectX12Texture.cpp
src/Graphics/DirectX12/DirectX12UploadContext.cpp
src/Graphics/DirectX12/DirectX12UploadRing.cpp
)

Expand Down
142 changes: 77 additions & 65 deletions include/private/Graphics/DirectX12/DirectX12Buffer.hpp
Original file line number Diff line number Diff line change
@@ -1,101 +1,113 @@
#ifndef DIRECTX12BUFFER_HPP_
#define DIRECTX12BUFFER_HPP_
#include "../Common/BufferBase.hpp"
#include <d3d12.h>
#include <wrl/client.h>

#include <cstdint>
#include <memory>
#include <vector>

#include "../Common/BufferBase.hpp"

namespace Sleak {
namespace RenderEngine {
class DirectX12UploadContext;

/// D3D12 buffer wrapper: default-heap resource plus an upload heap for CPU-to-GPU copies.
class DirectX12Buffer : public BufferBase {
public:
// Constructor for common buffer types
DirectX12Buffer(ID3D12Device* device, ID3D12CommandQueue* queue, size_t size, BufferType type);

// Constructor for custom buffer configuration
DirectX12Buffer(ID3D12Device* device, size_t size, D3D12_HEAP_TYPE heapType,
D3D12_RESOURCE_STATES resourceState);

// Prevent copying
DirectX12Buffer(const DirectX12Buffer&) = delete;
DirectX12Buffer& operator=(const DirectX12Buffer&) = delete;

// Allow moving
DirectX12Buffer(DirectX12Buffer&&) noexcept;
DirectX12Buffer& operator=(DirectX12Buffer&&) noexcept;

~DirectX12Buffer() override;
/// Creates the default-heap resource and uploads initial data via a staging buffer, if any.
bool Initialize(void* Data) override;
void Update() override;
void Cleanup() override;

/// Maps the buffer for CPU writes (upload-heap buffers only).
bool Map() override;
void Unmap() override;
/// Overwrites buffer contents via a fresh upload-heap copy.
void Update(void* data, size_t size) override;
/// Creates the buffer sized and pre-populated from a raw payload.
bool Initialize(const void* data, size_t size);

void* GetData() override;

// Getter for the underlying D3D buffer
ID3D12Resource* GetD3DBuffer() const { return m_buffer.Get(); }

// Get command list for execution
ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); }

// Check if command list is ready for execution
bool HasPendingCommands() const { return m_commandList != nullptr; }

/// Uploads go through the shared uploader when given, else they block.
DirectX12Buffer(ID3D12Device* device, ID3D12CommandQueue* queue, size_t size,
BufferType type, DirectX12UploadContext* uploader = nullptr);

// Constructor for custom buffer configuration
DirectX12Buffer(ID3D12Device* device, size_t size, D3D12_HEAP_TYPE heapType,
D3D12_RESOURCE_STATES resourceState);

// Prevent copying
DirectX12Buffer(const DirectX12Buffer&) = delete;
DirectX12Buffer& operator=(const DirectX12Buffer&) = delete;

// Allow moving
DirectX12Buffer(DirectX12Buffer&&) noexcept;
DirectX12Buffer& operator=(DirectX12Buffer&&) noexcept;

~DirectX12Buffer() override;
/// Creates the default-heap resource and uploads initial data via a staging
/// buffer, if any.
bool Initialize(void* Data) override;
void Update() override;
void Cleanup() override;

/// Maps the buffer for CPU writes (upload-heap buffers only).
bool Map() override;
void Unmap() override;
/// Overwrites buffer contents via a fresh upload-heap copy.
void Update(void* data, size_t size) override;
/// Creates the buffer sized and pre-populated from a raw payload.
bool Initialize(const void* data, size_t size);

void* GetData() override;

// Getter for the underlying D3D buffer
ID3D12Resource* GetD3DBuffer() const { return m_buffer.Get(); }

/// Latest constant buffer contents, copied into the upload ring on bind.
const void* GetConstantData() const {
return m_constantData.empty() ? nullptr : m_constantData.data();
}
size_t GetConstantDataSize() const { return m_constantData.size(); }

/// Ring address already holding the current contents for this frame, or 0.
D3D12_GPU_VIRTUAL_ADDRESS GetFrameAddress(uint64_t frame) const {
return m_frameSerial == frame ? m_frameAddress : 0;
}
/// Remembers where this frame's copy of the contents lives in the ring.
void SetFrameAddress(uint64_t frame, D3D12_GPU_VIRTUAL_ADDRESS address) {
m_frameSerial = frame;
m_frameAddress = address;
}

// Additional utility methods
bool IsValid() const { return m_buffer != nullptr; }
D3D12_HEAP_TYPE GetHeapType() const { return m_heapType; }
D3D12_RESOURCE_STATES GetResourceState() const { return m_resourceState; }

private:
// Helper method to set up buffer description
D3D12_RESOURCE_DESC CreateBufferDesc() const;

// Convert BufferType to DirectX configuration
void ConfigureFromBufferType(BufferType type);

// Create an upload buffer and copy data to the default buffer
bool CreateUploadBuffer(const void* data, size_t dataSize);

void SetAsVertexBuffer (ID3D12GraphicsCommandList* commandList, UINT slot, UINT stride, UINT offset = 0);
void SetAsIndexBuffer (ID3D12GraphicsCommandList* commandList, DXGI_FORMAT format, UINT offset = 0);
void SetAsConstantBuffer(ID3D12GraphicsCommandList* commandList, UINT rootParameterIndex);

// Wait for pending GPU upload to complete (for command list/allocator reuse)
void WaitForUploadComplete();

public:
// Release staging upload resources (call after GPU copy is guaranteed complete)
void ReleaseUploadResources();
/// Records a staged copy into the default-heap buffer.
bool UploadToDefaultHeap(const void* data, size_t dataSize);

// Deferred cleanup: queue buffers for deletion after GPU is done
static void DeferCleanup(Microsoft::WRL::ComPtr<ID3D12Resource> resource);
static void ProcessDeferredCleanup();

private:
public:
/// Queues a GPU object for release once the frame that used it is done.
static void DeferCleanup(Microsoft::WRL::ComPtr<ID3D12Pageable> object);
/// Stamps everything queued since the last call with its retire value.
static void TagDeferredCleanup(uint64_t fenceValue);
/// Releases every queued object whose fence value has completed.
static void ProcessDeferredCleanup(uint64_t completedValue);

private:
// Smart pointers for proper resource management
Microsoft::WRL::ComPtr<ID3D12Device> m_device;
ID3D12CommandQueue* m_commandQueue = nullptr; // non-owning, for upload execution
DirectX12UploadContext* m_uploader = nullptr; // non-owning
Microsoft::WRL::ComPtr<ID3D12Resource> m_buffer;
Microsoft::WRL::ComPtr<ID3D12Resource> m_uploadBuffer;
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> m_commandAllocator;
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> m_commandList;

D3D12_HEAP_TYPE m_heapType = D3D12_HEAP_TYPE_DEFAULT;
D3D12_RESOURCE_STATES m_resourceState = D3D12_RESOURCE_STATE_COMMON;
// Actual current GPU resource state (tracked for correct barriers on re-upload)
D3D12_RESOURCE_STATES m_currentState = D3D12_RESOURCE_STATE_COMMON;
void* m_mappedData = nullptr;

std::vector<uint8_t> m_constantData;
uint64_t m_frameSerial = 0;
D3D12_GPU_VIRTUAL_ADDRESS m_frameAddress = 0;
};
} // namespace RenderEngine
} // namespace Sleak
#endif // DIRECTX12BUFFER_HPP_
#endif // DIRECTX12BUFFER_HPP_
105 changes: 54 additions & 51 deletions include/private/Graphics/DirectX12/DirectX12CubemapTexture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,66 +14,69 @@

namespace Sleak {
namespace RenderEngine {
class DirectX12UploadContext;

/// D3D12 cubemap texture, loadable from six face images or a single equirectangular panorama.
class ENGINE_API DirectX12CubemapTexture : public ::Sleak::Texture {
public:
DirectX12CubemapTexture(ID3D12Device* device,
ID3D12CommandQueue* commandQueue);
~DirectX12CubemapTexture() override;

/// Loads and uploads 6 face images: +X, -X, +Y, -Y, +Z, -Z.
bool LoadCubemap(const std::array<std::string, 6>& facePaths);
/// Loads a single equirectangular panorama and resamples it into 6 cube faces.
bool LoadEquirectangular(const std::string& path, uint32_t faceSize = 512);

// Texture interface
/// Unused for cubemaps; load via LoadCubemap/LoadEquirectangular instead.
bool LoadFromMemory(const void* data, uint32_t width, uint32_t height,
TextureFormat format) override;
/// Unused for cubemaps; load via LoadCubemap/LoadEquirectangular instead.
bool LoadFromFile(const std::string& filePath) override;

void Bind(uint32_t slot = 0) const override;
void Unbind() const override;

void SetFilter(TextureFilter filter) override;
void SetWrapMode(TextureWrapMode wrapMode) override;

uint32_t GetWidth() const override { return m_width; }
uint32_t GetHeight() const override { return m_height; }
TextureFormat GetFormat() const override { return TextureFormat::RGBA8; }
TextureType GetType() const override { return TextureType::TextureCube; }

ID3D12Resource* GetResource() const { return m_texture.Get(); }

/// Binds this cubemap's SRV table at the given root parameter for a draw.
void BindToCommandList(ID3D12GraphicsCommandList* cmdList,
UINT rootParameterIndex) const;

// Set shared SRV heap slot (called by renderer during creation)
void SetSharedSrvGPUHandle(D3D12_GPU_DESCRIPTOR_HANDLE handle) { m_srvGpuHandle = handle; m_usesSharedHeap = true; }
/// Uploads go through the shared uploader when given, else they block.
DirectX12CubemapTexture(ID3D12Device* device, ID3D12CommandQueue* commandQueue,
DirectX12UploadContext* uploader = nullptr);
~DirectX12CubemapTexture() override;

/// Loads and uploads 6 face images: +X, -X, +Y, -Y, +Z, -Z.
bool LoadCubemap(const std::array<std::string, 6>& facePaths);
/// Loads a single equirectangular panorama and resamples it into 6 cube faces.
bool LoadEquirectangular(const std::string& path, uint32_t faceSize = 512);

// Texture interface
/// Unused for cubemaps; load via LoadCubemap/LoadEquirectangular instead.
bool LoadFromMemory(const void* data, uint32_t width, uint32_t height,
TextureFormat format) override;
/// Unused for cubemaps; load via LoadCubemap/LoadEquirectangular instead.
bool LoadFromFile(const std::string& filePath) override;

void Bind(uint32_t slot = 0) const override;
void Unbind() const override;

void SetFilter(TextureFilter filter) override;
void SetWrapMode(TextureWrapMode wrapMode) override;

uint32_t GetWidth() const override { return m_width; }
uint32_t GetHeight() const override { return m_height; }
TextureFormat GetFormat() const override { return TextureFormat::RGBA8; }
TextureType GetType() const override { return TextureType::TextureCube; }

ID3D12Resource* GetResource() const { return m_texture.Get(); }

/// Binds this cubemap's SRV table at the given root parameter for a draw.
void BindToCommandList(ID3D12GraphicsCommandList* cmdList,
UINT rootParameterIndex) const;

// Set shared SRV heap slot (called by renderer during creation)
void SetSharedSrvGPUHandle(D3D12_GPU_DESCRIPTOR_HANDLE handle) {
m_srvGpuHandle = handle;
m_usesSharedHeap = true;
}
// Create SRV directly into an externally-provided CPU handle (cube SRV)
void CreateSRVIntoHandle(D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle);

private:
/// Builds the cubemap texture array and shader resource view from decoded face pixels.
bool CreateCubemapFromFaces(const std::vector<unsigned char*>& faceData,
uint32_t faceSize);
/// Blocks until the upload-heap copy to the GPU-resident cubemap resource completes.
void WaitForUpload();

ID3D12Device* m_device = nullptr;
ID3D12CommandQueue* m_commandQueue = nullptr;

Microsoft::WRL::ComPtr<ID3D12Resource> m_texture;
Microsoft::WRL::ComPtr<ID3D12Resource> m_uploadBuffer;
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_srvHeap; // fallback
D3D12_GPU_DESCRIPTOR_HANDLE m_srvGpuHandle = {};
bool m_usesSharedHeap = false;

uint32_t m_width = 0;
uint32_t m_height = 0;
bool CreateCubemapFromFaces(const std::vector<unsigned char*>& faceData,
uint32_t faceSize);

ID3D12Device* m_device = nullptr;
ID3D12CommandQueue* m_commandQueue = nullptr;
DirectX12UploadContext* m_uploader = nullptr;

Microsoft::WRL::ComPtr<ID3D12Resource> m_texture;
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_srvHeap; // fallback
D3D12_GPU_DESCRIPTOR_HANDLE m_srvGpuHandle = {};
bool m_usesSharedHeap = false;

uint32_t m_width = 0;
uint32_t m_height = 0;
};

} // namespace RenderEngine
Expand Down
Loading
Loading