Compare commits

...

2 Commits

23 changed files with 627 additions and 288 deletions

86
AgentData/Imgui.md Normal file
View File

@@ -0,0 +1,86 @@
# ImGui Integration & Memory Debugger
## Task List
- [ ] **Preparation**
- [x] Fetch Dear ImGui Source Files (Verified existing submodule)
- [x] Create `External/imgui/Imgui.bff`
- [x] Update `fbuild.bff` to include `Imgui.bff`
- [x] Update `Juliet.bff` to link `ImGui` and include paths
- [x] Update `D3D12DescriptorHeap` to support ImGui (SRV for Font)
- [ ] **Memory Arena Debugging**
- [x] Modify `MemoryArena` struct to store allocation tags (Debug builds only)
- [x] Update `ArenaPush` signature to accept `const char* tag`
- [x] Update call sites (default parameter should minimize churn)
- [ ] **ImGui Core & TDD**
- [x] Create `Core/ImGui/ImGuiService.h/cpp` (Wrapper)
- [x] Create `Core/ImGui/ImGuiTests.cpp`
- [x] Implement `ImGui::SetAllocatorFunctions` using `EngineArena`
- [x] Test context creation and IO setup
- [ ] **Integration**
- [ ] Win32: Integrate `WndProc` in `Win32DisplayEvent.cpp`
- [x] DX12: Initialize/Shutdown in `D3D12GraphicsDevice` (Implemented in `ImGuiRenderer.cpp`)
- [x] DX12: Render Frame in `D3D12GraphicsDevice` (Fixed Buffer Crash)
- [ ] **Memory Debugger**
- [x] Create `Engine/Debug/MemoryDebugger.h/cpp`
- [x] Implement `DrawMemoryArena(const char* name, MemoryArena* arena)` with Allocation Tags
- [x] Implement Hex View for Arena Data (Allocations list implemented, Hex view pending/skipped)
- [x] Integrate into Main Loop (Toggle with 'Home' key)
- [ ] **Verification**
- [ ] Launch and verify ImGui renders
- [x] Verify Memory Debugger shows allocations and tags
---
## Implementation Plan
### Goal Description
Integrate Dear ImGui into the Juliet engine.
Implement a specialized Test Driven Development (TDD) approach.
Create a Memory Debugger panel to visualize `MemoryArena` state with allocation tags.
### Proposed Changes
#### Build System
**[NEW] [Imgui.bff](file:///w:/Classified/Juliet/External/imgui/Imgui.bff)**
- Defines the `ImGui` library configuration.
- Includes `imgui.cpp`, `imgui_draw.cpp`, `imgui_tables.cpp`, `imgui_widgets.cpp`, `imgui_demo.cpp`.
- Includes backends: `imgui_impl_win32.cpp`, `imgui_impl_dx12.cpp`.
**[MODIFY] [fbuild.bff](file:///w:/Classified/Juliet/fbuild.bff)**
- Include `External/imgui/Imgui.bff`.
**[MODIFY] [Juliet.bff](file:///w:/Classified/Juliet/Juliet/Juliet.bff)**
- Add `ImGui` to `Juliet` library dependencies.
- Add `External/imgui` and `External/imgui/backends` to include paths.
#### Core/Memory
**[MODIFY] [MemoryArena.h](file:///w:/Classified/Juliet/Juliet/include/Core/Memory/MemoryArena.h)**
**[MODIFY] [MemoryArena.cpp](file:///w:/Classified/Juliet/Juliet/src/Core/Memory/MemoryArena.cpp)**
- **Struct Change**: Add `AllocationTracking` vector (likely `std::vector` wrapped or fixed size array) in `JULIET_DEBUG`.
- **Function Change**: `ArenaPush(..., const char* tag = nullptr)`.
- **Logic**: Store offset + tag on push.
#### Core/ImGui
**[NEW] [ImGuiService.h](file:///w:/Classified/Juliet/Juliet/include/Core/ImGui/ImGuiService.h)**
**[NEW] [ImGuiService.cpp](file:///w:/Classified/Juliet/Juliet/src/Core/ImGui/ImGuiService.cpp)**
- Wrapper for ImGui lifecycle.
- Uses `EngineArena` for internal ImGui allocations.
**[NEW] [ImGuiTests.cpp](file:///w:/Classified/Juliet/Juliet/src/Core/ImGui/ImGuiTests.cpp)**
- TDD suite for ImGui service.
#### Graphics/D3D12
**[MODIFY] [D3D12GraphicsDevice.cpp](file:///w:/Classified/Juliet/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp)**
- ImGui backend initialization and rendering.
#### Engine/Debug
**[NEW] [MemoryDebugger.h](file:///w:/Classified/Juliet/Juliet/include/Engine/Debug/MemoryDebugger.h)**
**[NEW] [MemoryDebugger.cpp](file:///w:/Classified/Juliet/Juliet/src/Engine/Debug/MemoryDebugger.cpp)**
- Draw arena usage bar using tracked tags.
- Draw hex dump.

Binary file not shown.

View File

@@ -5,7 +5,12 @@ cbuffer RootConstants : register(b0, space0)
{ {
row_major float4x4 ViewProjection; row_major float4x4 ViewProjection;
uint BufferIndex; uint BufferIndex;
uint _Padding[3]; uint TextureIndex;
uint VertexOffset; // Base vertex for indexed drawing with bindless buffers
uint _Padding; // Padding for alignment
float2 Scale; // 2D scale factor
float2 Translate; // 2D translation
}; };
#endif // ROOT_CONSTANTS_HLSL #endif // ROOT_CONSTANTS_HLSL

View File

@@ -11,9 +11,8 @@ Output main(uint vertexIndex : SV_VertexID)
Output output; Output output;
// Retrieve the buffer using SM6.6 bindless syntax // Retrieve the buffer using SM6.6 bindless syntax
// We use index 0 as the sample app doesn't pass push constants yet. // Use BufferIndex from RootConstants (pushed via SetPushConstants)
uint bufferIndex = 0; ByteAddressBuffer buffer = ResourceDescriptorHeap[BufferIndex];
ByteAddressBuffer buffer = ResourceDescriptorHeap[bufferIndex];
// Read position from buffer (Index * stride) // Read position from buffer (Index * stride)
// Stride = 2 float (pos) + 4 float (color) = 6 * 4 = 24 bytes ? // Stride = 2 float (pos) + 4 float (color) = 6 * 4 = 24 bytes ?

View File

@@ -14,6 +14,10 @@
// For GET_X_LPARAM, GET_Y_LPARAM. // For GET_X_LPARAM, GET_Y_LPARAM.
#include <windowsx.h> #include <windowsx.h>
#include <imgui.h> // Need For IMGUI_IMPL_API
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
namespace Juliet::Win32 namespace Juliet::Win32
{ {
namespace namespace
@@ -147,8 +151,14 @@ namespace Juliet::Win32
LRESULT CALLBACK Win32MainWindowCallback(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK Win32MainWindowCallback(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{ {
if (ImGui_ImplWin32_WndProcHandler(handle, message, wParam, lParam))
{
return true;
}
LRESULT returnCode = -1; LRESULT returnCode = -1;
// Wait until the window state is created before doing anything // Wait until the window state is created before doing anything
auto* windowState = GetWindowStateFromHandle(handle); auto* windowState = GetWindowStateFromHandle(handle);
if (!windowState) if (!windowState)

View File

@@ -39,26 +39,15 @@ namespace Juliet
} }
} // namespace } // namespace
#if JULIET_DEBUG
namespace UnitTest
{
extern void TestMemoryArena();
}
#endif
void JulietInit(JulietInit_Flags flags) void JulietInit(JulietInit_Flags flags)
{ {
// Mandatory systems // Mandatory systems
MemoryArenasInit(); MemoryArenasInit();
#if JULIET_DEBUG
UnitTest::TestMemoryArena();
#endif
InitFilesystem(); InitFilesystem();
// Optional systems // Optional systems
if ((flags | JulietInit_Flags::Display) != JulietInit_Flags::None) if ((flags & JulietInit_Flags::Display) != JulietInit_Flags::None)
{ {
InitializeDisplaySystem(); InitializeDisplaySystem();
IncrementSystemRefCount(JulietInit_Flags::Display); IncrementSystemRefCount(JulietInit_Flags::Display);

View File

@@ -12,13 +12,6 @@ namespace Juliet::D3D12
{ {
namespace namespace
{ {
struct D3D12Buffer
{
Internal::D3D12Descriptor Descriptor;
ID3D12Resource* Handle;
D3D12_RESOURCE_STATES CurrentState;
};
enum class D3D12BufferType : uint8 enum class D3D12BufferType : uint8
{ {
Base, Base,
@@ -26,6 +19,30 @@ namespace Juliet::D3D12
TransferUpload, TransferUpload,
}; };
[[nodiscard]] const char* D3D12BufferTypeToString(D3D12BufferType type)
{
switch (type)
{
case D3D12BufferType::Base: return "Base";
case D3D12BufferType::TransferDownload: return "TransferDownload";
case D3D12BufferType::TransferUpload: return "TransferUpload";
}
return "Unknown";
}
[[nodiscard]] const char* BufferUsageToString(BufferUsage usage)
{
switch (usage)
{
case BufferUsage::None: return "None";
case BufferUsage::ConstantBuffer: return "ConstantBuffer";
case BufferUsage::StructuredBuffer: return "StructuredBuffer";
case BufferUsage::IndexBuffer: return "IndexBuffer";
case BufferUsage::VertexBuffer: return "VertexBuffer";
}
return "Unknown";
}
void DestroyBuffer(D3D12Buffer* buffer) void DestroyBuffer(D3D12Buffer* buffer)
{ {
if (!buffer) if (!buffer)
@@ -40,7 +57,7 @@ namespace Juliet::D3D12
if (buffer->Handle) if (buffer->Handle)
{ {
ID3D12Resource_Release(buffer->Handle); buffer->Handle->Release();
} }
Free(buffer); Free(buffer);
} }
@@ -78,6 +95,7 @@ namespace Juliet::D3D12
case BufferUsage::IndexBuffer: case BufferUsage::IndexBuffer:
case BufferUsage::StructuredBuffer: case BufferUsage::StructuredBuffer:
case BufferUsage::VertexBuffer:
{ {
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT; heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
@@ -99,8 +117,13 @@ namespace Juliet::D3D12
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
initialState = D3D12_RESOURCE_STATE_GENERIC_READ; initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
}
// heapFlags = D3D12_HEAP_FLAG_NONE; // Avoid overwriting if set above
if (heapProperties.Type == D3D12_HEAP_TYPE_GPU_UPLOAD)
{
heapFlags = D3D12_HEAP_FLAG_NONE; // Or appropriate flags
} }
heapFlags = D3D12_HEAP_FLAG_NONE;
break; break;
} }
} }
@@ -130,7 +153,7 @@ namespace Juliet::D3D12
D3D12_RESOURCE_DESC desc = {}; D3D12_RESOURCE_DESC desc = {};
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; desc.Alignment = 0;
desc.Width = size; desc.Width = size;
desc.Height = 1; desc.Height = 1;
desc.DepthOrArraySize = 1; desc.DepthOrArraySize = 1;
@@ -141,13 +164,22 @@ namespace Juliet::D3D12
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE; desc.Flags = D3D12_RESOURCE_FLAG_NONE;
Log(LogLevel::Message, LogCategory::Graphics, "CreateBuffer: Device=%p, Size=%zu, Type=%s Use=%s", (void*)d3d12Driver->D3D12Device, size, D3D12BufferTypeToString(type), BufferUsageToString(usage));
ID3D12Resource* handle = nullptr; ID3D12Resource* handle = nullptr;
HRESULT result = ID3D12Device_CreateCommittedResource(d3d12Driver->D3D12Device, &heapProperties, heapFlags, HRESULT result = d3d12Driver->D3D12Device->CreateCommittedResource(&heapProperties, heapFlags,
&desc, initialState, nullptr, IID_ID3D12Resource, &desc, initialState, nullptr,
reinterpret_cast<void**>(&handle)); IID_ID3D12Resource, reinterpret_cast<void**>(&handle));
if (FAILED(result)) if (FAILED(result))
{ {
LogError(d3d12Driver->D3D12Device, "Could not create buffer!", result); Log(LogLevel::Error, LogCategory::Graphics, "Could not create buffer! HRESULT=0x%08X", (uint32)result);
Log(LogLevel::Error, LogCategory::Graphics, "Failed Desc: Width=%llu Layout=%d HeapType=%d", (unsigned long long)desc.Width, (int)desc.Layout, (int)heapProperties.Type);
HRESULT removeReason = d3d12Driver->D3D12Device->GetDeviceRemovedReason();
if (FAILED(removeReason))
{
Log(LogLevel::Error, LogCategory::Graphics, "Device Removed Reason: 0x%08X", (uint32)removeReason);
}
DestroyBuffer(buffer); DestroyBuffer(buffer);
return nullptr; return nullptr;
} }
@@ -155,6 +187,7 @@ namespace Juliet::D3D12
buffer->Handle = handle; buffer->Handle = handle;
buffer->CurrentState = initialState; buffer->CurrentState = initialState;
buffer->Descriptor.Index = UINT32_MAX; buffer->Descriptor.Index = UINT32_MAX;
buffer->Size = size;
if (usage == BufferUsage::ConstantBuffer || usage == BufferUsage::StructuredBuffer) if (usage == BufferUsage::ConstantBuffer || usage == BufferUsage::StructuredBuffer)
{ {
@@ -169,25 +202,22 @@ namespace Juliet::D3D12
if (usage == BufferUsage::ConstantBuffer) if (usage == BufferUsage::ConstantBuffer)
{ {
cbvDesc.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(handle); cbvDesc.BufferLocation = handle->GetGPUVirtualAddress();
cbvDesc.SizeInBytes = static_cast<uint32>(size); cbvDesc.SizeInBytes = static_cast<uint32>(size);
ID3D12Device_CreateConstantBufferView(d3d12Driver->D3D12Device, &cbvDesc, cpuHandle); d3d12Driver->D3D12Device->CreateConstantBufferView(&cbvDesc, cpuHandle);
} }
else if (usage == BufferUsage::StructuredBuffer) else if (usage == BufferUsage::StructuredBuffer)
{ {
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Buffer.FirstElement = 0; srvDesc.Buffer.FirstElement = 0;
srvDesc.Buffer.NumElements = static_cast<uint32>( srvDesc.Buffer.NumElements = static_cast<uint32>(size / 4);
size / 4); // Assuming 4 bytes stride for raw access or similar. Ideally should be provided. srvDesc.Buffer.StructureByteStride = 0;
srvDesc.Buffer.StructureByteStride = 0; // Raw buffer for simplicity, or 4 if typed? srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
// If it's a Structured Buffer, we typically need stride. For now let's assume raw ByteAddressBuffer (R32_TYPELESS) or similar if stride is 0. d3d12Driver->D3D12Device->CreateShaderResourceView(handle, &srvDesc, cpuHandle);
// Actually, let's treat it as a ByteAddressBuffer (Raw) for most flexibility in bindless. Log(LogLevel::Message, LogCategory::Graphics, " -> SRV DescriptorIndex=%u", descriptor.Index);
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
ID3D12Device_CreateShaderResourceView(d3d12Driver->D3D12Device, handle, &srvDesc, cpuHandle);
} }
} }
else else
@@ -230,7 +260,7 @@ namespace Juliet::D3D12
void* ptr = nullptr; void* ptr = nullptr;
// 0-0 range means we don't intend to read anything. // 0-0 range means we don't intend to read anything.
D3D12_RANGE readRange = { 0, 0 }; D3D12_RANGE readRange = { 0, 0 };
if (FAILED(ID3D12Resource_Map(d3d12Buffer->Handle, 0, &readRange, &ptr))) if (FAILED(d3d12Buffer->Handle->Map(0, &readRange, &ptr)))
{ {
return nullptr; return nullptr;
} }
@@ -240,7 +270,7 @@ namespace Juliet::D3D12
void UnmapBuffer(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsTransferBuffer> buffer) void UnmapBuffer(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsTransferBuffer> buffer)
{ {
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get()); auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
ID3D12Resource_Unmap(d3d12Buffer->Handle, 0, nullptr); d3d12Buffer->Handle->Unmap(0, nullptr);
} }
uint32 GetDescriptorIndex(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer) uint32 GetDescriptorIndex(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer)
@@ -267,7 +297,7 @@ namespace Juliet::D3D12
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
ID3D12GraphicsCommandList_ResourceBarrier(d3d12CmdList->GraphicsCommandList.CommandList, 1, &barrier); d3d12CmdList->GraphicsCommandList.CommandList->ResourceBarrier(1, &barrier);
d3d12Dst->CurrentState = D3D12_RESOURCE_STATE_COPY_DEST; d3d12Dst->CurrentState = D3D12_RESOURCE_STATE_COPY_DEST;
} }
@@ -275,7 +305,7 @@ namespace Juliet::D3D12
// We assume Upload buffers are always in state GENERIC_READ or similar suitable for CopySrc. // We assume Upload buffers are always in state GENERIC_READ or similar suitable for CopySrc.
// D3D12 Upload heaps start in GENERIC_READ and cannot transition. // D3D12 Upload heaps start in GENERIC_READ and cannot transition.
ID3D12GraphicsCommandList_CopyBufferRegion(d3d12CmdList->GraphicsCommandList.CommandList, d3d12Dst->Handle, d3d12CmdList->GraphicsCommandList.CommandList->CopyBufferRegion(d3d12Dst->Handle,
dstOffset, d3d12Src->Handle, srcOffset, size); dstOffset, d3d12Src->Handle, srcOffset, size);
} }
@@ -296,7 +326,7 @@ namespace Juliet::D3D12
barrier.Transition.StateAfter = neededState; barrier.Transition.StateAfter = neededState;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
ID3D12GraphicsCommandList_ResourceBarrier(d3d12CmdList->GraphicsCommandList.CommandList, 1, &barrier); d3d12CmdList->GraphicsCommandList.CommandList->ResourceBarrier(1, &barrier);
d3d12Buffer->CurrentState = neededState; d3d12Buffer->CurrentState = neededState;
} }
} }

View File

@@ -1,7 +1,9 @@
#pragma once #pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/NonNullPtr.h> #include <Core/Common/NonNullPtr.h>
#include <Graphics/GraphicsBuffer.h> #include <Graphics/GraphicsBuffer.h>
#include <Graphics/D3D12/D3D12DescriptorHeap.h>
namespace Juliet namespace Juliet
{ {
@@ -10,6 +12,14 @@ namespace Juliet
} // namespace Juliet } // namespace Juliet
namespace Juliet::D3D12 namespace Juliet::D3D12
{ {
struct D3D12Buffer
{
Internal::D3D12Descriptor Descriptor;
ID3D12Resource* Handle;
D3D12_RESOURCE_STATES CurrentState;
size_t Size;
};
extern GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage); extern GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage);
extern void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer); extern void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer);

View File

@@ -1,5 +1,7 @@
#include <Core/Memory/Allocator.h> #include <Core/Memory/Allocator.h>
#include <Graphics/D3D12/D3D12CommandList.h> #include <Graphics/D3D12/D3D12CommandList.h>
#include <Graphics/D3D12/D3D12CommandList.h>
#include <Graphics/D3D12/D3D12Buffer.h>
#include <Graphics/D3D12/D3D12GraphicsDevice.h> #include <Graphics/D3D12/D3D12GraphicsDevice.h>
#include <Graphics/D3D12/D3D12Synchronization.h> #include <Graphics/D3D12/D3D12Synchronization.h>
#include <Graphics/D3D12/D3D12Utils.h> #include <Graphics/D3D12/D3D12Utils.h>
@@ -26,15 +28,14 @@ namespace Juliet::D3D12
bool CreateAllocator(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandListBaseData> baseData, bool CreateAllocator(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandListBaseData> baseData,
D3D12_COMMAND_QUEUE_DESC queueDesc) D3D12_COMMAND_QUEUE_DESC queueDesc)
{ {
HRESULT result = ID3D12Device5_CreateCommandAllocator(driver->D3D12Device, queueDesc.Type, IID_ID3D12CommandAllocator, HRESULT result = driver->D3D12Device->CreateCommandAllocator(queueDesc.Type, IID_ID3D12CommandAllocator, reinterpret_cast<void**>(&baseData->Allocator));
reinterpret_cast<void**>(&baseData->Allocator));
if (FAILED(result)) if (FAILED(result))
{ {
AssertHR(result, "Cannot create ID3D12CommandAllocator"); AssertHR(result, "Cannot create ID3D12CommandAllocator");
return false; return false;
} }
ID3D12CommandAllocator_Reset(baseData->Allocator); baseData->Allocator->Reset();
return true; return true;
} }
@@ -54,7 +55,7 @@ namespace Juliet::D3D12
CreateAllocator(driver, &commandList->GraphicsCommandList, queueDesc); CreateAllocator(driver, &commandList->GraphicsCommandList, queueDesc);
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr; ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
HRESULT result = HRESULT result =
ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type, driver->D3D12Device->CreateCommandList1(queueDesc.NodeMask, queueDesc.Type,
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6, D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
reinterpret_cast<void**>(&d3d12GraphicsCommandList)); reinterpret_cast<void**>(&d3d12GraphicsCommandList));
if (FAILED(result)) if (FAILED(result))
@@ -65,8 +66,8 @@ namespace Juliet::D3D12
} }
commandList->GraphicsCommandList.CommandList = d3d12GraphicsCommandList; commandList->GraphicsCommandList.CommandList = d3d12GraphicsCommandList;
ID3D12GraphicsCommandList6_SetName(d3d12GraphicsCommandList, wide_str.c_str()); d3d12GraphicsCommandList->SetName(wide_str.c_str());
ID3D12GraphicsCommandList6_Reset(d3d12GraphicsCommandList, commandList->GraphicsCommandList.Allocator, nullptr); d3d12GraphicsCommandList->Reset(commandList->GraphicsCommandList.Allocator, nullptr);
return true; return true;
} }
@@ -75,7 +76,7 @@ namespace Juliet::D3D12
CreateAllocator(driver, &commandList->ComputeCommandList, queueDesc); CreateAllocator(driver, &commandList->ComputeCommandList, queueDesc);
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr; ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
HRESULT result = HRESULT result =
ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type, driver->D3D12Device->CreateCommandList1(queueDesc.NodeMask, queueDesc.Type,
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6, D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
reinterpret_cast<void**>(&d3d12GraphicsCommandList)); reinterpret_cast<void**>(&d3d12GraphicsCommandList));
if (FAILED(result)) if (FAILED(result))
@@ -86,8 +87,8 @@ namespace Juliet::D3D12
} }
commandList->ComputeCommandList.CommandList = d3d12GraphicsCommandList; commandList->ComputeCommandList.CommandList = d3d12GraphicsCommandList;
ID3D12GraphicsCommandList6_SetName(d3d12GraphicsCommandList, wide_str.c_str()); d3d12GraphicsCommandList->SetName(wide_str.c_str());
ID3D12GraphicsCommandList6_Reset(d3d12GraphicsCommandList, commandList->ComputeCommandList.Allocator, nullptr); d3d12GraphicsCommandList->Reset(commandList->ComputeCommandList.Allocator, nullptr);
return true; return true;
} }
@@ -95,9 +96,8 @@ namespace Juliet::D3D12
{ {
CreateAllocator(driver, &commandList->CopyCommandList, queueDesc); CreateAllocator(driver, &commandList->CopyCommandList, queueDesc);
ID3D12GraphicsCommandList* d3d12CopyCommandList = nullptr; ID3D12GraphicsCommandList* d3d12CopyCommandList = nullptr;
HRESULT result = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type, HRESULT result = driver->D3D12Device->CreateCommandList1(queueDesc.NodeMask, queueDesc.Type,
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList, D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList, reinterpret_cast<void**>(&d3d12CopyCommandList));
reinterpret_cast<void**>(&d3d12CopyCommandList));
if (FAILED(result)) if (FAILED(result))
{ {
@@ -105,8 +105,8 @@ namespace Juliet::D3D12
return false; return false;
} }
commandList->CopyCommandList.CommandList = d3d12CopyCommandList; commandList->CopyCommandList.CommandList = d3d12CopyCommandList;
ID3D12GraphicsCommandList_SetName(d3d12CopyCommandList, wide_str.c_str()); d3d12CopyCommandList->SetName(wide_str.c_str());
ID3D12GraphicsCommandList_Reset(d3d12CopyCommandList, commandList->CopyCommandList.Allocator, nullptr); d3d12CopyCommandList->Reset(commandList->CopyCommandList.Allocator, nullptr);
return true; return true;
} }
@@ -227,30 +227,21 @@ namespace Juliet::D3D12
barrierDesc.Transition.pResource = subresource->Parent->Resource; barrierDesc.Transition.pResource = subresource->Parent->Resource;
barrierDesc.Transition.Subresource = subresource->Index; barrierDesc.Transition.Subresource = subresource->Index;
ID3D12GraphicsCommandList_ResourceBarrier(d3d12CommandList->GraphicsCommandList.CommandList, 1, &barrierDesc); d3d12CommandList->GraphicsCommandList.CommandList->ResourceBarrier(1, &barrierDesc);
} }
// Notify the command buffer that we have completed recording // Notify the command buffer that we have completed recording
HRESULT result = ID3D12GraphicsCommandList_Close(d3d12CommandList->GraphicsCommandList.CommandList); HRESULT result = d3d12CommandList->GraphicsCommandList.CommandList->Close();
if (FAILED(result)) if (FAILED(result))
{ {
LogError(d3d12Driver->D3D12Device, "Failed to close command list!", result); LogError(d3d12Driver->D3D12Device, "Failed to close command list!", result);
return false; return false;
} }
ID3D12CommandList* commandLists[1]; ID3D12CommandList* ppCommandLists[] = { d3d12CommandList->GraphicsCommandList.CommandList };
result = ID3D12GraphicsCommandList_QueryInterface(d3d12CommandList->GraphicsCommandList.CommandList,
IID_ID3D12CommandList, reinterpret_cast<void**>(&commandLists[0]));
if (FAILED(result))
{
LogError(d3d12Driver->D3D12Device, "Failed to convert command list!", result);
return false;
}
// Submit the command list to the queue // Submit the command list to the queue
ID3D12CommandQueue_ExecuteCommandLists(d3d12Driver->GraphicsQueue, 1, commandLists); d3d12Driver->GraphicsQueue->ExecuteCommandLists(1, ppCommandLists);
ID3D12CommandList_Release(commandLists[0]);
// Acquire a fence and set it to the in-flight fence // Acquire a fence and set it to the in-flight fence
d3d12CommandList->InFlightFence = Internal::AcquireFence(d3d12Driver); d3d12CommandList->InFlightFence = Internal::AcquireFence(d3d12Driver);
@@ -260,7 +251,7 @@ namespace Juliet::D3D12
} }
// Mark that a fence should be signaled after command list execution // Mark that a fence should be signaled after command list execution
result = ID3D12CommandQueue_Signal(d3d12Driver->GraphicsQueue, d3d12CommandList->InFlightFence->Handle, D3D12_FENCE_SIGNAL_VALUE); result = d3d12Driver->GraphicsQueue->Signal(d3d12CommandList->InFlightFence->Handle, D3D12_FENCE_SIGNAL_VALUE);
if (FAILED(result)) if (FAILED(result))
{ {
LogError(d3d12Driver->D3D12Device, "Failed to enqueue fence signal!", result); LogError(d3d12Driver->D3D12Device, "Failed to enqueue fence signal!", result);
@@ -299,14 +290,13 @@ namespace Juliet::D3D12
presentFlags = DXGI_PRESENT_ALLOW_TEARING; presentFlags = DXGI_PRESENT_ALLOW_TEARING;
} }
result = IDXGISwapChain_Present(windowData->SwapChain, syncInterval, presentFlags); result = windowData->SwapChain->Present(syncInterval, presentFlags);
if (FAILED(result)) if (FAILED(result))
{ {
success = false; success = false;
} }
ID3D12Resource_Release( windowData->SwapChainTextureContainers[presentData->SwapChainImageIndex].ActiveTexture->Resource->Release();
windowData->SwapChainTextureContainers[presentData->SwapChainImageIndex].ActiveTexture->Resource);
windowData->InFlightFences[windowData->WindowFrameCounter] = reinterpret_cast<Fence*>(d3d12CommandList->InFlightFence); windowData->InFlightFences[windowData->WindowFrameCounter] = reinterpret_cast<Fence*>(d3d12CommandList->InFlightFence);
d3d12CommandList->InFlightFence->ReferenceCount += 1; d3d12CommandList->InFlightFence->ReferenceCount += 1;
@@ -317,7 +307,7 @@ namespace Juliet::D3D12
// Check for cleanups // Check for cleanups
for (int32 i = d3d12Driver->SubmittedCommandListCount - 1; i >= 0; i -= 1) for (int32 i = d3d12Driver->SubmittedCommandListCount - 1; i >= 0; i -= 1)
{ {
uint64 fenceValue = ID3D12Fence_GetCompletedValue(d3d12Driver->SubmittedCommandLists[i]->InFlightFence->Handle); uint64 fenceValue = d3d12Driver->SubmittedCommandLists[i]->InFlightFence->Handle->GetCompletedValue();
if (fenceValue == D3D12_FENCE_SIGNAL_VALUE) if (fenceValue == D3D12_FENCE_SIGNAL_VALUE)
{ {
success &= Internal::CleanCommandList(d3d12Driver, d3d12Driver->SubmittedCommandLists[i], false); success &= Internal::CleanCommandList(d3d12Driver, d3d12Driver->SubmittedCommandLists[i], false);
@@ -342,7 +332,7 @@ namespace Juliet::D3D12
d3d12Viewport.Height = viewPort.Height; d3d12Viewport.Height = viewPort.Height;
d3d12Viewport.MinDepth = viewPort.MinDepth; d3d12Viewport.MinDepth = viewPort.MinDepth;
d3d12Viewport.MaxDepth = viewPort.MaxDepth; d3d12Viewport.MaxDepth = viewPort.MaxDepth;
ID3D12GraphicsCommandList_RSSetViewports(d3d12CommandList->GraphicsCommandList.CommandList, 1, &d3d12Viewport); d3d12CommandList->GraphicsCommandList.CommandList->RSSetViewports(1, &d3d12Viewport);
} }
void SetScissorRect(NonNullPtr<CommandList> commandList, const Rectangle& rectangle) void SetScissorRect(NonNullPtr<CommandList> commandList, const Rectangle& rectangle)
@@ -353,20 +343,48 @@ namespace Juliet::D3D12
scissorRect.top = rectangle.Y; scissorRect.top = rectangle.Y;
scissorRect.right = rectangle.X + rectangle.Width; scissorRect.right = rectangle.X + rectangle.Width;
scissorRect.bottom = rectangle.Y + rectangle.Height; scissorRect.bottom = rectangle.Y + rectangle.Height;
ID3D12GraphicsCommandList_RSSetScissorRects(d3d12CommandList->GraphicsCommandList.CommandList, 1, &scissorRect); d3d12CommandList->GraphicsCommandList.CommandList->RSSetScissorRects(1, &scissorRect);
} }
void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants) void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants)
{ {
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get()); auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
FLOAT blendFactor[4] = { blendConstants.R, blendConstants.G, blendConstants.B, blendConstants.A }; FLOAT blendFactor[4] = { blendConstants.R, blendConstants.G, blendConstants.B, blendConstants.A };
ID3D12GraphicsCommandList_OMSetBlendFactor(d3d12CommandList->GraphicsCommandList.CommandList, blendFactor); d3d12CommandList->GraphicsCommandList.CommandList->OMSetBlendFactor(blendFactor);
} }
void SetStencilReference(NonNullPtr<CommandList> commandList, uint8 reference) void SetStencilReference(NonNullPtr<CommandList> commandList, uint8 reference)
{ {
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get()); auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
ID3D12GraphicsCommandList_OMSetStencilRef(d3d12CommandList->GraphicsCommandList.CommandList, reference); d3d12CommandList->GraphicsCommandList.CommandList->OMSetStencilRef(reference);
}
void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format)
{
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
auto* d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
// Transition to INDEX_BUFFER state if needed
if (d3d12Buffer->CurrentState != D3D12_RESOURCE_STATE_INDEX_BUFFER)
{
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = d3d12Buffer->Handle;
barrier.Transition.StateBefore = d3d12Buffer->CurrentState;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_INDEX_BUFFER;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
d3d12CommandList->GraphicsCommandList.CommandList->ResourceBarrier(1, &barrier);
d3d12Buffer->CurrentState = D3D12_RESOURCE_STATE_INDEX_BUFFER;
}
D3D12_INDEX_BUFFER_VIEW ibView;
ibView.BufferLocation = d3d12Buffer->Handle->GetGPUVirtualAddress();
ibView.SizeInBytes = static_cast<UINT>(d3d12Buffer->Size);
ibView.Format = (format == IndexFormat::UInt16) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
d3d12CommandList->GraphicsCommandList.CommandList->IASetIndexBuffer(&ibView);
} }
void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage /*stage*/, uint32 rootParameterIndex, void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage /*stage*/, uint32 rootParameterIndex,
@@ -374,7 +392,7 @@ namespace Juliet::D3D12
{ {
auto d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get()); auto d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
// For now we assume Graphics Root Signature. Compute support would need a check or separate function. // For now we assume Graphics Root Signature. Compute support would need a check or separate function.
ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(d3d12CommandList->GraphicsCommandList.CommandList, d3d12CommandList->GraphicsCommandList.CommandList->SetGraphicsRoot32BitConstants(
rootParameterIndex, numConstants, constants, 0); rootParameterIndex, numConstants, constants, 0);
} }
@@ -396,7 +414,7 @@ namespace Juliet::D3D12
heaps[0] = viewHeap->Handle; heaps[0] = viewHeap->Handle;
heaps[1] = samplerHeap->Handle; heaps[1] = samplerHeap->Handle;
ID3D12GraphicsCommandList_SetDescriptorHeaps(commandList->GraphicsCommandList.CommandList, 2, heaps); commandList->GraphicsCommandList.CommandList->SetDescriptorHeaps(2, heaps);
} }
void DestroyCommandList(NonNullPtr<D3D12CommandList> commandList) void DestroyCommandList(NonNullPtr<D3D12CommandList> commandList)
@@ -404,10 +422,10 @@ namespace Juliet::D3D12
// TODO : Handle other kind of command list (copy compute) // TODO : Handle other kind of command list (copy compute)
if (commandList->GraphicsCommandList.CommandList) if (commandList->GraphicsCommandList.CommandList)
{ {
ID3D12GraphicsCommandList_Release(commandList->GraphicsCommandList.CommandList); commandList->GraphicsCommandList.CommandList->Release();
} }
ID3D12CommandAllocator_Release(commandList->GraphicsCommandList.Allocator); commandList->GraphicsCommandList.Allocator->Release();
SafeFree(commandList->PresentDatas); SafeFree(commandList->PresentDatas);
SafeFree(commandList->UsedTextures); SafeFree(commandList->UsedTextures);
@@ -420,14 +438,14 @@ namespace Juliet::D3D12
// No more presentation data // No more presentation data
commandList->PresentDataCount = 0; commandList->PresentDataCount = 0;
HRESULT result = ID3D12CommandAllocator_Reset(commandList->GraphicsCommandList.Allocator); HRESULT result = commandList->GraphicsCommandList.Allocator->Reset();
if (FAILED(result)) if (FAILED(result))
{ {
LogError(driver->D3D12Device, "Could not reset command allocator", result); LogError(driver->D3D12Device, "Could not reset command allocator", result);
return false; return false;
} }
result = ID3D12GraphicsCommandList_Reset(commandList->GraphicsCommandList.CommandList, result = commandList->GraphicsCommandList.CommandList->Reset(
commandList->GraphicsCommandList.Allocator, nullptr); commandList->GraphicsCommandList.Allocator, nullptr);
if (FAILED(result)) if (FAILED(result))
{ {

View File

@@ -96,6 +96,7 @@ namespace Juliet::D3D12
extern void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants); extern void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants);
extern void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants); extern void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants);
extern void SetStencilReference(NonNullPtr<CommandList> commandList, uint8 reference); extern void SetStencilReference(NonNullPtr<CommandList> commandList, uint8 reference);
extern void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format);
extern void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex, uint32 numConstants, const void* constants); extern void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex, uint32 numConstants, const void* constants);
namespace Internal namespace Internal

View File

@@ -28,7 +28,7 @@ namespace Juliet::D3D12::Internal
heapDesc.NodeMask = 0; heapDesc.NodeMask = 0;
HRESULT result = HRESULT result =
ID3D12Device_CreateDescriptorHeap(driver->D3D12Device, &heapDesc, IID_ID3D12DescriptorHeap, (void**)&handle); driver->D3D12Device->CreateDescriptorHeap(&heapDesc, IID_ID3D12DescriptorHeap, (void**)&handle);
if (FAILED(result)) if (FAILED(result))
{ {
LogError(driver->D3D12Device, "Failed to create descriptor heap!", result); LogError(driver->D3D12Device, "Failed to create descriptor heap!", result);
@@ -40,11 +40,11 @@ namespace Juliet::D3D12::Internal
heap->HeapType = type; heap->HeapType = type;
heap->MaxDescriptors = count; heap->MaxDescriptors = count;
heap->Staging = isStaging; heap->Staging = isStaging;
heap->DescriptorSize = ID3D12Device_GetDescriptorHandleIncrementSize(driver->D3D12Device, type); heap->DescriptorSize = driver->D3D12Device->GetDescriptorHandleIncrementSize(type);
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(handle, &heap->DescriptorHeapCPUStart); heap->DescriptorHeapCPUStart = handle->GetCPUDescriptorHandleForHeapStart();
if (!isStaging) if (!isStaging)
{ {
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(handle, &heap->DescriptorHeapGPUStart); heap->DescriptorHeapGPUStart = handle->GetGPUDescriptorHandleForHeapStart();
} }
return heap; return heap;
@@ -54,7 +54,7 @@ namespace Juliet::D3D12::Internal
{ {
if (heap->Handle) if (heap->Handle)
{ {
ID3D12DescriptorHeap_Release(heap->Handle); heap->Handle->Release();
} }
SafeFree(heap->FreeIndices); SafeFree(heap->FreeIndices);
Free(heap.Get()); Free(heap.Get());

View File

@@ -46,8 +46,8 @@ namespace Juliet::D3D12
bool CheckResourceTypeTier(ID3D12Device5* device) bool CheckResourceTypeTier(ID3D12Device5* device)
{ {
D3D12_FEATURE_DATA_D3D12_OPTIONS options = {}; D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
HRESULT result = ID3D12Device5_CheckFeatureSupport(device, D3D12_FEATURE_D3D12_OPTIONS, &options, HRESULT result =
sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS)); device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS));
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
if (options.ResourceBindingTier < D3D12_RESOURCE_BINDING_TIER_3) if (options.ResourceBindingTier < D3D12_RESOURCE_BINDING_TIER_3)
@@ -83,8 +83,8 @@ namespace Juliet::D3D12
for (auto allModelVersion : allModelVersions) for (auto allModelVersion : allModelVersions)
{ {
shaderModel.HighestShaderModel = allModelVersion; shaderModel.HighestShaderModel = allModelVersion;
HRESULT result = ID3D12Device5_CheckFeatureSupport(device, D3D12_FEATURE_SHADER_MODEL, &shaderModel, HRESULT result = device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shaderModel,
sizeof(D3D12_FEATURE_DATA_SHADER_MODEL)); sizeof(D3D12_FEATURE_DATA_SHADER_MODEL));
if (result != E_INVALIDARG) if (result != E_INVALIDARG)
{ {
if (FAILED(result)) if (FAILED(result))
@@ -142,40 +142,40 @@ namespace Juliet::D3D12
// Can query the 1.4 factory ? // Can query the 1.4 factory ?
IDXGIFactory4* factory4 = nullptr; IDXGIFactory4* factory4 = nullptr;
result = IDXGIFactory1_QueryInterface(factory1, IID_IDXGIFactory4, reinterpret_cast<void**>(&factory4)); result = factory1->QueryInterface(IID_IDXGIFactory4, reinterpret_cast<void**>(&factory4));
if (FAILED(result)) if (FAILED(result))
{ {
IDXGIFactory1_Release(factory1); factory1->Release();
Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Failed to query DXGI1.4."); Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Failed to query DXGI1.4.");
return false; return false;
} }
IDXGIFactory4_Release(factory4); factory4->Release();
// Check for 1.6. (It's not mandatory). // Check for 1.6. (It's not mandatory).
IDXGIAdapter1* adapter = nullptr; IDXGIAdapter1* adapter = nullptr;
IDXGIFactory6* factory6 = nullptr; IDXGIFactory6* factory6 = nullptr;
result = IDXGIFactory1_QueryInterface(factory1, IID_IDXGIFactory6, reinterpret_cast<void**>(&factory6)); result = factory1->QueryInterface(IID_IDXGIFactory6, reinterpret_cast<void**>(&factory6));
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
result = IDXGIFactory6_EnumAdapterByGpuPreference(factory6, 0, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, result = factory6->EnumAdapterByGpuPreference(0, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
IID_IDXGIAdapter1, reinterpret_cast<void**>(&adapter)); IID_IDXGIAdapter1, reinterpret_cast<void**>(&adapter));
IDXGIFactory6_Release(factory6); factory6->Release();
} }
else else
{ {
result = IDXGIFactory1_EnumAdapters1(factory1, 0, &adapter); result = factory1->EnumAdapters1(0, &adapter);
} }
if (FAILED(result)) if (FAILED(result))
{ {
Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Failed to find an adapter for D3D12."); Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Failed to find an adapter for D3D12.");
IDXGIFactory1_Release(factory1); factory1->Release();
return false; return false;
} }
ID3D12Device5* device = nullptr; ID3D12Device5* device = nullptr;
result = D3D12CreateDeviceFuncPtr(reinterpret_cast<IUnknown*>(adapter), kD3DFeatureLevel, IID_ID3D12Device5, result = D3D12CreateDeviceFuncPtr(static_cast<IUnknown*>(adapter), kD3DFeatureLevel, IID_ID3D12Device5,
reinterpret_cast<void**>(&device)); reinterpret_cast<void**>(&device));
bool driverIsValid = true; bool driverIsValid = true;
@@ -184,7 +184,7 @@ namespace Juliet::D3D12
driverIsValid &= CheckShaderModel(device); driverIsValid &= CheckShaderModel(device);
driverIsValid &= CheckResourceTypeTier(device); driverIsValid &= CheckResourceTypeTier(device);
ID3D12Device5_Release(device); device->Release();
} }
else else
{ {
@@ -192,8 +192,8 @@ namespace Juliet::D3D12
"DX12: Failed to create a D3D12Device with feature level %s.", kD3DFeatureLevelStr); "DX12: Failed to create a D3D12Device with feature level %s.", kD3DFeatureLevelStr);
driverIsValid = false; driverIsValid = false;
} }
IDXGIAdapter1_Release(adapter); adapter->Release();
IDXGIFactory1_Release(factory1); factory1->Release();
return driverIsValid; return driverIsValid;
} }
@@ -206,7 +206,7 @@ namespace Juliet::D3D12
} }
if (rootSignature->Handle) if (rootSignature->Handle)
{ {
ID3D12RootSignature_Release(rootSignature->Handle); rootSignature->Handle->Release();
} }
Free(rootSignature); Free(rootSignature);
} }
@@ -272,9 +272,10 @@ namespace Juliet::D3D12
{ {
if (errorBlob) if (errorBlob)
{ {
auto errorBuffer = ID3D10Blob_GetBufferPointer(errorBlob); auto errorBuffer = errorBlob->GetBufferPointer();
LogError(LogCategory::Graphics, "Failed to serialize RootSignature: %s", errorBuffer); LogError(LogCategory::Graphics, "Failed to serialize RootSignature: %s", errorBuffer);
ID3D10Blob_Release(errorBlob);
errorBlob->Release();
} }
DestroyGraphicsRootSignature(d3d12GraphicsRootSignature); DestroyGraphicsRootSignature(d3d12GraphicsRootSignature);
return nullptr; return nullptr;
@@ -282,16 +283,16 @@ namespace Juliet::D3D12
// Create the root signature // Create the root signature
ID3D12RootSignature* rootSignature; ID3D12RootSignature* rootSignature;
res = ID3D12Device_CreateRootSignature(d3d12Driver->D3D12Device, 0, ID3D10Blob_GetBufferPointer(serializedRootSignature), res = d3d12Driver->D3D12Device->CreateRootSignature(0, serializedRootSignature->GetBufferPointer(),
ID3D10Blob_GetBufferSize(serializedRootSignature), serializedRootSignature->GetBufferSize(), IID_ID3D12RootSignature,
IID_ID3D12RootSignature, reinterpret_cast<void**>(&rootSignature)); reinterpret_cast<void**>(&rootSignature));
if (FAILED(res)) if (FAILED(res))
{ {
if (errorBlob) if (errorBlob)
{ {
LogError(LogCategory::Graphics, "Failed to create RootSignature: %s", LogError(LogCategory::Graphics, "Failed to create RootSignature: %s",
(const char*)ID3D10Blob_GetBufferPointer(errorBlob)); (const char*)errorBlob->GetBufferPointer());
ID3D10Blob_Release(errorBlob); errorBlob->Release();
} }
DestroyGraphicsRootSignature(d3d12GraphicsRootSignature); DestroyGraphicsRootSignature(d3d12GraphicsRootSignature);
return nullptr; return nullptr;
@@ -332,12 +333,9 @@ namespace Juliet::D3D12
} }
else else
{ {
IDXGIInfoQueue_SetBreakOnSeverity(driver->DXGIInfoQueue, DXGI_DEBUG_ALL, driver->DXGIInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE); driver->DXGIInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
IDXGIInfoQueue_SetBreakOnSeverity(driver->DXGIInfoQueue, DXGI_DEBUG_ALL, driver->DXGIInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING, TRUE);
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
IDXGIInfoQueue_SetBreakOnSeverity(driver->DXGIInfoQueue, DXGI_DEBUG_ALL,
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING, TRUE);
} }
} }
} }
@@ -346,9 +344,9 @@ namespace Juliet::D3D12
{ {
if (driver->DXGIDebug) if (driver->DXGIDebug)
{ {
IDXGIDebug_ReportLiveObjects(driver->DXGIDebug, DXGI_DEBUG_ALL, driver->DXGIDebug->ReportLiveObjects(DXGI_DEBUG_ALL, static_cast<DXGI_DEBUG_RLO_FLAGS>(
static_cast<DXGI_DEBUG_RLO_FLAGS>(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL)); DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL));
IDXGIDebug_Release(driver->DXGIDebug); driver->DXGIDebug->Release();
driver->DXGIDebug = nullptr; driver->DXGIDebug = nullptr;
} }
@@ -380,7 +378,7 @@ namespace Juliet::D3D12
return; return;
} }
ID3D12Debug1_EnableDebugLayer(driver->D3D12Debug); driver->D3D12Debug->EnableDebugLayer();
} }
bool InitializeD3D12DebugInfoQueue(NonNullPtr<D3D12Driver> driver) bool InitializeD3D12DebugInfoQueue(NonNullPtr<D3D12Driver> driver)
@@ -388,8 +386,7 @@ namespace Juliet::D3D12
ID3D12InfoQueue* infoQueue = nullptr; ID3D12InfoQueue* infoQueue = nullptr;
D3D12_MESSAGE_SEVERITY severities[] = { D3D12_MESSAGE_SEVERITY_INFO }; D3D12_MESSAGE_SEVERITY severities[] = { D3D12_MESSAGE_SEVERITY_INFO };
HRESULT result = HRESULT result = driver->D3D12Device->QueryInterface(IID_ID3D12InfoQueue, reinterpret_cast<void**>(&infoQueue));
ID3D12Device_QueryInterface(driver->D3D12Device, IID_ID3D12InfoQueue, reinterpret_cast<void**>(&infoQueue));
if (FAILED(result)) if (FAILED(result))
{ {
LogError(driver->D3D12Device, "Failed to convert ID3D12Device to ID3D12InfoQueue", result); LogError(driver->D3D12Device, "Failed to convert ID3D12Device to ID3D12InfoQueue", result);
@@ -399,14 +396,13 @@ namespace Juliet::D3D12
D3D12_INFO_QUEUE_FILTER filter = {}; D3D12_INFO_QUEUE_FILTER filter = {};
filter.DenyList.NumSeverities = 1; filter.DenyList.NumSeverities = 1;
filter.DenyList.pSeverityList = severities; filter.DenyList.pSeverityList = severities;
ID3D12InfoQueue_PushStorageFilter(infoQueue, &filter); infoQueue->PushStorageFilter(&filter);
ID3D12InfoQueue_SetBreakOnSeverity(infoQueue, D3D12_MESSAGE_SEVERITY_CORRUPTION, true); // infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true);
ID3D12InfoQueue_Release(infoQueue); infoQueue->Release();
return true; return true;
} }
#ifdef ID3D12InfoQueue1_SUPPORTED
void WINAPI OnD3D12DebugInfoMsg(D3D12_MESSAGE_CATEGORY category, D3D12_MESSAGE_SEVERITY severity, void WINAPI OnD3D12DebugInfoMsg(D3D12_MESSAGE_CATEGORY category, D3D12_MESSAGE_SEVERITY severity,
D3D12_MESSAGE_ID id, LPCSTR description, void* /*context*/) D3D12_MESSAGE_ID id, LPCSTR description, void* /*context*/)
{ {
@@ -451,19 +447,16 @@ namespace Juliet::D3D12
{ {
// Only supported on Win 11 apparently // Only supported on Win 11 apparently
ID3D12InfoQueue1* infoQueue = nullptr; ID3D12InfoQueue1* infoQueue = nullptr;
HRESULT result = HRESULT result = driver->D3D12Device->QueryInterface(IID_ID3D12InfoQueue1, reinterpret_cast<void**>(&infoQueue));
ID3D12Device5_QueryInterface(driver->D3D12Device, IID_ID3D12InfoQueue1, reinterpret_cast<void**>(&infoQueue));
if (FAILED(result)) if (FAILED(result))
{ {
return; return;
} }
ID3D12InfoQueue1_RegisterMessageCallback(infoQueue, OnD3D12DebugInfoMsg, D3D12_MESSAGE_CALLBACK_FLAG_NONE, infoQueue->RegisterMessageCallback(OnD3D12DebugInfoMsg, D3D12_MESSAGE_CALLBACK_FLAG_NONE, nullptr, nullptr);
nullptr, nullptr); infoQueue->Release();
ID3D12InfoQueue1_Release(infoQueue); Log(LogLevel::Message, LogCategory::Graphics, "DX12: Debug Info Logger Initialized");
} }
#endif
#endif #endif
void DestroyDriver_Internal(NonNullPtr<D3D12Driver> driver) void DestroyDriver_Internal(NonNullPtr<D3D12Driver> driver)
@@ -520,6 +513,7 @@ namespace Juliet::D3D12
Internal::DestroyDescriptorHeap(driver->BindlessDescriptorHeap); Internal::DestroyDescriptorHeap(driver->BindlessDescriptorHeap);
// Clean allocations // Clean allocations
SafeFree(driver->AvailableCommandLists); SafeFree(driver->AvailableCommandLists);
SafeFree(driver->SubmittedCommandLists); SafeFree(driver->SubmittedCommandLists);
SafeFree(driver->GraphicsPipelinesToDispose); SafeFree(driver->GraphicsPipelinesToDispose);
@@ -528,41 +522,40 @@ namespace Juliet::D3D12
if (driver->IndirectDrawCommandSignature) if (driver->IndirectDrawCommandSignature)
{ {
ID3D12CommandSignature_Release(driver->IndirectDrawCommandSignature); driver->IndirectDrawCommandSignature->Release();
driver->IndirectDrawCommandSignature = nullptr;
} }
if (driver->IndirectIndexedDrawCommandSignature) if (driver->IndirectIndexedDrawCommandSignature)
{ {
ID3D12CommandSignature_Release(driver->IndirectIndexedDrawCommandSignature); driver->IndirectIndexedDrawCommandSignature->Release();
driver->IndirectIndexedDrawCommandSignature = nullptr; driver->IndirectIndexedDrawCommandSignature = nullptr;
} }
if (driver->IndirectDispatchCommandSignature) if (driver->IndirectDispatchCommandSignature)
{ {
ID3D12CommandSignature_Release(driver->IndirectDispatchCommandSignature); driver->IndirectDispatchCommandSignature->Release();
driver->IndirectDispatchCommandSignature = nullptr; driver->IndirectDispatchCommandSignature = nullptr;
} }
if (driver->GraphicsQueue) if (driver->GraphicsQueue)
{ {
ID3D12CommandQueue_Release(driver->GraphicsQueue); driver->GraphicsQueue->Release();
driver->GraphicsQueue = nullptr; driver->GraphicsQueue = nullptr;
} }
if (driver->D3D12Device) if (driver->D3D12Device)
{ {
ID3D12Device5_Release(driver->D3D12Device); driver->D3D12Device->Release();
driver->D3D12Device = nullptr; driver->D3D12Device = nullptr;
} }
if (driver->DXGIAdapter) if (driver->DXGIAdapter)
{ {
IDXGIAdapter1_Release(driver->DXGIAdapter); driver->DXGIAdapter->Release();
driver->DXGIAdapter = nullptr; driver->DXGIAdapter = nullptr;
} }
if (driver->DXGIFactory) if (driver->DXGIFactory)
{ {
IDXGIFactory4_Release(driver->DXGIFactory); driver->DXGIFactory->Release();
driver->DXGIFactory = nullptr; driver->DXGIFactory = nullptr;
} }
@@ -598,6 +591,7 @@ namespace Juliet::D3D12
Log(LogLevel::Error, LogCategory::Graphics, "OOM: D3D12WindowData"); Log(LogLevel::Error, LogCategory::Graphics, "OOM: D3D12WindowData");
return false; return false;
} }
d3d12Driver->WindowData = windowData;
windowData->Window = window; windowData->Window = window;
@@ -609,7 +603,6 @@ namespace Juliet::D3D12
} }
d3d12Driver->WindowData = windowData; d3d12Driver->WindowData = windowData;
// TODO : React to resize. Need event system.
return true; return true;
} }
@@ -645,12 +638,116 @@ namespace Juliet::D3D12
Free(device.Get()); Free(device.Get());
} }
// Note: SetViewPort, SetScissorRect, SetBlendConstants, SetStencilReference
// are defined in D3D12CommandList.cpp and used directly via D3D12:: namespace
// BindGraphicsPipeline is now assigned directly from D3D12:: namespace
// DrawPrimitives is now assigned directly from D3D12:: namespace
void DrawIndexedPrimitives(NonNullPtr<CommandList> commandList, uint32 numIndices, uint32 numInstances,
uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance)
{
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
d3d12CommandList->GraphicsCommandList.CommandList->DrawIndexedInstanced(numIndices, numInstances, firstIndex,
static_cast<INT>(vertexOffset), firstInstance);
}
// WaitUntilGPUIsIdle, SetPushConstants are now assigned directly from D3D12:: namespace
// QueryFence, ReleaseFence, CreateShader, DestroyShader are now assigned directly from D3D12:: namespace
// CreateGraphicsPipeline is assigned directly from D3D12:: namespace
void DestroyGraphicsPipeline(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> pipeline)
{
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
d3d12Driver->GraphicsPipelinesToDispose[d3d12Driver->GraphicsPipelinesToDisposeCount] =
reinterpret_cast<D3D12GraphicsPipeline*>(pipeline.Get());
d3d12Driver->GraphicsPipelinesToDisposeCount += 1;
if (d3d12Driver->GraphicsPipelinesToDisposeCount >= d3d12Driver->GraphicsPipelinesToDisposeCapacity)
{
Internal::ReleaseGraphicsPipeline(reinterpret_cast<D3D12GraphicsPipeline*>(pipeline.Get()));
}
}
// Buffer functions are assigned directly from D3D12:: namespace
void CopyBufferToTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Texture> dst, NonNullPtr<GraphicsTransferBuffer> src)
{
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
auto* d3d12TextureContainer = reinterpret_cast<D3D12TextureContainer*>(dst.Get());
auto* d3d12Texture = d3d12TextureContainer->ActiveTexture;
Internal::TextureTransitionFromDefaultUsage(d3d12CommandList, d3d12Texture, D3D12_RESOURCE_STATE_COPY_DEST);
// Get resource desc using C++ API
D3D12_RESOURCE_DESC desc = d3d12Texture->Resource->GetDesc();
D3D12_TEXTURE_COPY_LOCATION dstLoc = {};
dstLoc.pResource = d3d12Texture->Resource;
dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
dstLoc.SubresourceIndex = 0;
// Get buffer resource - D3D12Buffer is anonymous, access Handle directly
// The GraphicsTransferBuffer IS a D3D12Buffer internally
struct D3D12TransferBuffer
{
Internal::D3D12Descriptor Descriptor;
ID3D12Resource* Handle;
D3D12_RESOURCE_STATES CurrentState;
};
auto* d3d12BufferSrc = reinterpret_cast<D3D12TransferBuffer*>(src.Get());
D3D12_TEXTURE_COPY_LOCATION srcLoc = {};
srcLoc.pResource = d3d12BufferSrc->Handle;
srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
srcLoc.PlacedFootprint.Offset = 0;
srcLoc.PlacedFootprint.Footprint.Format = desc.Format;
srcLoc.PlacedFootprint.Footprint.Width = (UINT)desc.Width;
srcLoc.PlacedFootprint.Footprint.Height = desc.Height;
srcLoc.PlacedFootprint.Footprint.Depth = 1;
uint32 rowPitch = (uint32)desc.Width * 4;
rowPitch = (rowPitch + 255u) & ~255u;
srcLoc.PlacedFootprint.Footprint.RowPitch = rowPitch;
d3d12CommandList->GraphicsCommandList.CommandList->CopyTextureRegion(&dstLoc, 0, 0, 0, &srcLoc, nullptr);
Internal::TextureTransitionToDefaultUsage(d3d12CommandList, d3d12Texture, D3D12_RESOURCE_STATE_COPY_DEST);
}
// GetDescriptorIndex wrapper needed to adapt signature from GPUDriver* to GraphicsDevice*
uint32 GetDescriptorIndex(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
{
auto* driver = static_cast<D3D12Driver*>(device->Driver);
return D3D12::GetDescriptorIndex(driver, buffer);
}
// GetDescriptorIndexTexture provides custom logic to get SRV handle index
uint32 GetDescriptorIndexTexture(NonNullPtr<GraphicsDevice> /*device*/, NonNullPtr<Texture> texture)
{
auto* textureContainer = reinterpret_cast<D3D12TextureContainer*>(texture.Get());
return textureContainer->ActiveTexture->SRVHandle.CpuHandleIndex;
}
#if ALLOW_SHADER_HOT_RELOAD
bool UpdateGraphicsPipelineShaders(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsPipeline> /*graphicsPipeline*/,
Shader* /*optional_vertexShader*/, Shader* /*optional_fragmentShader*/)
{
// Missing implementation, skipping for now
return false;
}
#endif
GraphicsDevice* CreateGraphicsDevice(bool enableDebug) GraphicsDevice* CreateGraphicsDevice(bool enableDebug)
{ {
#if JULIET_DEBUG #if JULIET_DEBUG
// Unit Tests for D3D12 Logic // Unit Tests for D3D12 Logic
UnitTest::TestDescriptorHeapPool(); UnitTest::TestDescriptorHeapPool();
#endif #endif
auto driver = static_cast<D3D12Driver*>(Calloc(1, sizeof(D3D12Driver))); auto driver = static_cast<D3D12Driver*>(Calloc(1, sizeof(D3D12Driver)));
@@ -671,7 +768,7 @@ namespace Juliet::D3D12
return nullptr; return nullptr;
} }
result = IDXGIFactory1_QueryInterface(factory1, IID_IDXGIFactory4, reinterpret_cast<void**>(&driver->DXGIFactory)); result = factory1->QueryInterface(IID_IDXGIFactory4, reinterpret_cast<void**>(&driver->DXGIFactory));
if (FAILED(result)) if (FAILED(result))
{ {
DestroyDriver_Internal(driver); DestroyDriver_Internal(driver);
@@ -679,43 +776,40 @@ namespace Juliet::D3D12
"checked in CheckDriver"); "checked in CheckDriver");
return nullptr; return nullptr;
} }
IDXGIFactory1_Release(factory1); factory1->Release();
// Query DXGI1.5 and check for monitor Tearing support // Query DXGI1.5 and check for monitor Tearing support
IDXGIFactory5* factory5 = nullptr; IDXGIFactory5* factory5 = nullptr;
result = IDXGIFactory4_QueryInterface(driver->DXGIFactory, IID_IDXGIFactory5, reinterpret_cast<void**>(&factory5)); result = driver->DXGIFactory->QueryInterface(IID_IDXGIFactory5, reinterpret_cast<void**>(&factory5));
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
bool isTearingSupported = false; bool isTearingSupported = false;
result = IDXGIFactory5_CheckFeatureSupport(factory5, DXGI_FEATURE_PRESENT_ALLOW_TEARING, result = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &isTearingSupported,
&isTearingSupported, sizeof(isTearingSupported)); sizeof(isTearingSupported));
driver->IsTearingSupported = isTearingSupported; driver->IsTearingSupported = isTearingSupported;
if (FAILED(result)) if (FAILED(result))
{ {
driver->IsTearingSupported = false; driver->IsTearingSupported = false;
} }
IDXGIFactory5_Release(factory5); factory5->Release();
} }
// If available use DXGI1.6 to fetch the good graphics card. // If available use DXGI1.6 to fetch the good graphics card.
// 1.6 should be available on most Win10 PC if they didnt their windows update. // 1.6 should be available on most Win10 PC if they didnt their windows update.
// Lets support not having it for now... // Lets support not having it for now...
IDXGIFactory6* factory6 = nullptr; IDXGIFactory6* factory6 = nullptr;
result = IDXGIFactory4_QueryInterface(driver->DXGIFactory, IID_IDXGIFactory6, reinterpret_cast<void**>(&factory6)); result = driver->DXGIFactory->QueryInterface(IID_IDXGIFactory6, reinterpret_cast<void**>(&factory6));
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
// TODO: Put into the config // TODO: Put into the config
static constexpr bool useLowPower = false; static constexpr bool useLowPower = false;
result = IDXGIFactory6_EnumAdapterByGpuPreference(factory6, 0, result = factory6->EnumAdapterByGpuPreference(0, useLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER : DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
useLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER IID_IDXGIAdapter1, reinterpret_cast<void**>(&driver->DXGIAdapter));
: DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, factory6->Release();
IID_IDXGIAdapter1,
reinterpret_cast<void**>(&driver->DXGIAdapter));
IDXGIFactory6_Release(factory6);
} }
else else
{ {
result = IDXGIFactory4_EnumAdapters1(driver->DXGIFactory, 0, &driver->DXGIAdapter); result = driver->DXGIFactory->EnumAdapters1(0, &driver->DXGIAdapter);
} }
if (FAILED(result)) if (FAILED(result))
@@ -727,7 +821,7 @@ namespace Juliet::D3D12
// Adapter is setup, get all the relevant info in the descriptor // Adapter is setup, get all the relevant info in the descriptor
DXGI_ADAPTER_DESC1 adapterDesc; DXGI_ADAPTER_DESC1 adapterDesc;
result = IDXGIAdapter1_GetDesc1(driver->DXGIAdapter, &adapterDesc); result = driver->DXGIAdapter->GetDesc1(&adapterDesc);
if (FAILED(result)) if (FAILED(result))
{ {
DestroyDriver_Internal(driver); DestroyDriver_Internal(driver);
@@ -737,7 +831,7 @@ namespace Juliet::D3D12
// Driver version // Driver version
LARGE_INTEGER umdVersion; LARGE_INTEGER umdVersion;
result = IDXGIAdapter1_CheckInterfaceSupport(driver->DXGIAdapter, IID_IDXGIDevice, &umdVersion); result = driver->DXGIAdapter->CheckInterfaceSupport(IID_IDXGIDevice, &umdVersion);
if (FAILED(result)) if (FAILED(result))
{ {
DestroyDriver_Internal(driver); DestroyDriver_Internal(driver);
@@ -784,7 +878,7 @@ namespace Juliet::D3D12
} }
#endif #endif
result = D3D12CreateDeviceFuncPtr(reinterpret_cast<IUnknown*>(driver->DXGIAdapter), kD3DFeatureLevel, result = D3D12CreateDeviceFuncPtr(static_cast<IUnknown*>(driver->DXGIAdapter), kD3DFeatureLevel,
IID_ID3D12Device5, reinterpret_cast<void**>(&driver->D3D12Device)); IID_ID3D12Device5, reinterpret_cast<void**>(&driver->D3D12Device));
if (FAILED(result)) if (FAILED(result))
{ {
@@ -793,6 +887,8 @@ namespace Juliet::D3D12
return nullptr; return nullptr;
} }
Log(LogLevel::Message, LogCategory::Graphics, "DX12: D3D12Device Created: %p", (void*)driver->D3D12Device);
#if JULIET_DEBUG #if JULIET_DEBUG
if (enableDebug) if (enableDebug)
{ {
@@ -800,17 +896,15 @@ namespace Juliet::D3D12
{ {
return nullptr; return nullptr;
} }
#ifdef ID3D12InfoQueue1_SUPPORTED
InitializeD3D12DebugInfoLogger(driver); InitializeD3D12DebugInfoLogger(driver);
#endif
} }
#endif #endif
// Check if UMA (unified memory architecture) is available. Used on APU i think ?? // Check if UMA (unified memory architecture) is available. Used on APU i think ??
D3D12_FEATURE_DATA_ARCHITECTURE architecture; D3D12_FEATURE_DATA_ARCHITECTURE architecture;
architecture.NodeIndex = 0; architecture.NodeIndex = 0;
result = ID3D12Device5_CheckFeatureSupport(driver->D3D12Device, D3D12_FEATURE_ARCHITECTURE, &architecture, result = driver->D3D12Device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &architecture,
sizeof(D3D12_FEATURE_DATA_ARCHITECTURE)); sizeof(D3D12_FEATURE_DATA_ARCHITECTURE));
if (FAILED(result)) if (FAILED(result))
{ {
DestroyDriver_Internal(driver); DestroyDriver_Internal(driver);
@@ -823,8 +917,7 @@ namespace Juliet::D3D12
// Check "GPU Upload Heap" support (for fast uniform buffers. Not supported on my 5700xt // Check "GPU Upload Heap" support (for fast uniform buffers. Not supported on my 5700xt
D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16; D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16;
driver->GPUUploadHeapSupported = false; driver->GPUUploadHeapSupported = false;
result = ID3D12Device5_CheckFeatureSupport(driver->D3D12Device, D3D12_FEATURE_D3D12_OPTIONS16, &options16, result = driver->D3D12Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS16, &options16, sizeof(options16));
sizeof(options16));
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
driver->GPUUploadHeapSupported = options16.GPUUploadHeapSupported; driver->GPUUploadHeapSupported = options16.GPUUploadHeapSupported;
@@ -840,17 +933,23 @@ namespace Juliet::D3D12
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
queueDesc.NodeMask = 0; queueDesc.NodeMask = 0;
queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
result = ID3D12Device5_CreateCommandQueue(driver->D3D12Device, &queueDesc, IID_ID3D12CommandQueue, result = driver->D3D12Device->CreateCommandQueue(&queueDesc, IID_ID3D12CommandQueue,
reinterpret_cast<void**>(&driver->GraphicsQueue)); reinterpret_cast<void**>(&driver->GraphicsQueue));
if (FAILED(result)) if (FAILED(result))
{ {
DestroyDriver_Internal(driver); DestroyDriver_Internal(driver);
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create D3D12CommandQueue: Graphics"); Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create D3D12CommandQueue: Graphics");
return nullptr; return nullptr;
} }
ID3D12CommandQueue_SetName(driver->GraphicsQueue, L"GRAPHICS_QUEUE"); driver->GraphicsQueue->SetName(L"GRAPHICS_QUEUE");
driver->QueueDesc[ToUnderlying(QueueType::Graphics)] = queueDesc; driver->QueueDesc[ToUnderlying(QueueType::Graphics)] = queueDesc;
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE;
driver->QueueDesc[ToUnderlying(QueueType::Compute)] = queueDesc;
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_COPY;
driver->QueueDesc[ToUnderlying(QueueType::Copy)] = queueDesc;
// Indirect Commands // Indirect Commands
D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc; D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc;
D3D12_INDIRECT_ARGUMENT_DESC indirectArgumentDesc; D3D12_INDIRECT_ARGUMENT_DESC indirectArgumentDesc;
@@ -861,8 +960,8 @@ namespace Juliet::D3D12
commandSignatureDesc.ByteStride = sizeof(IndirectDrawCommand); commandSignatureDesc.ByteStride = sizeof(IndirectDrawCommand);
commandSignatureDesc.NumArgumentDescs = 1; commandSignatureDesc.NumArgumentDescs = 1;
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc; commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
result = ID3D12Device5_CreateCommandSignature(driver->D3D12Device, &commandSignatureDesc, nullptr, IID_ID3D12CommandSignature, result = driver->D3D12Device->CreateCommandSignature(&commandSignatureDesc, nullptr, IID_ID3D12CommandSignature,
reinterpret_cast<void**>(&driver->IndirectDrawCommandSignature)); reinterpret_cast<void**>(&driver->IndirectDrawCommandSignature));
if (FAILED(result)) if (FAILED(result))
{ {
DestroyDriver_Internal(driver); DestroyDriver_Internal(driver);
@@ -874,8 +973,8 @@ namespace Juliet::D3D12
commandSignatureDesc.ByteStride = sizeof(IndexedIndirectDrawCommand); commandSignatureDesc.ByteStride = sizeof(IndexedIndirectDrawCommand);
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc; commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
result = ID3D12Device5_CreateCommandSignature(driver->D3D12Device, &commandSignatureDesc, nullptr, IID_ID3D12CommandSignature, result = driver->D3D12Device->CreateCommandSignature(&commandSignatureDesc, nullptr, IID_ID3D12CommandSignature,
reinterpret_cast<void**>(&driver->IndirectIndexedDrawCommandSignature)); reinterpret_cast<void**>(&driver->IndirectIndexedDrawCommandSignature));
if (FAILED(result)) if (FAILED(result))
{ {
@@ -888,8 +987,8 @@ namespace Juliet::D3D12
commandSignatureDesc.ByteStride = sizeof(IndirectDispatchCommand); commandSignatureDesc.ByteStride = sizeof(IndirectDispatchCommand);
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc; commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
result = ID3D12Device5_CreateCommandSignature(driver->D3D12Device, &commandSignatureDesc, nullptr, IID_ID3D12CommandSignature, result = driver->D3D12Device->CreateCommandSignature(&commandSignatureDesc, nullptr, IID_ID3D12CommandSignature,
reinterpret_cast<void**>(&driver->IndirectDispatchCommandSignature)); reinterpret_cast<void**>(&driver->IndirectDispatchCommandSignature));
if (FAILED(result)) if (FAILED(result))
{ {
DestroyDriver_Internal(driver); DestroyDriver_Internal(driver);
@@ -984,35 +1083,42 @@ namespace Juliet::D3D12
device->AcquireSwapChainTexture = AcquireSwapChainTexture; device->AcquireSwapChainTexture = AcquireSwapChainTexture;
device->WaitAndAcquireSwapChainTexture = WaitAndAcquireSwapChainTexture; device->WaitAndAcquireSwapChainTexture = WaitAndAcquireSwapChainTexture;
device->GetSwapChainTextureFormat = GetSwapChainTextureFormat; device->GetSwapChainTextureFormat = GetSwapChainTextureFormat;
device->AcquireCommandList = AcquireCommandList; device->AcquireCommandList = D3D12::AcquireCommandList;
device->SubmitCommandLists = SubmitCommandLists; device->SubmitCommandLists = D3D12::SubmitCommandLists;
device->BeginRenderPass = BeginRenderPass;
device->EndRenderPass = EndRenderPass; device->BeginRenderPass = D3D12::BeginRenderPass;
device->SetViewPort = SetViewPort; device->EndRenderPass = D3D12::EndRenderPass;
device->SetScissorRect = SetScissorRect; device->SetViewPort = D3D12::SetViewPort;
device->SetBlendConstants = SetBlendConstants; device->SetScissorRect = D3D12::SetScissorRect;
device->SetStencilReference = SetStencilReference; device->SetBlendConstants = D3D12::SetBlendConstants;
device->BindGraphicsPipeline = BindGraphicsPipeline; device->SetStencilReference = D3D12::SetStencilReference;
device->DrawPrimitives = DrawPrimitives; device->BindGraphicsPipeline = D3D12::BindGraphicsPipeline;
device->WaitUntilGPUIsIdle = WaitUntilGPUIsIdle; device->DrawPrimitives = D3D12::DrawPrimitives;
device->SetPushConstants = SetPushConstants; device->DrawIndexedPrimitives = DrawIndexedPrimitives;
device->QueryFence = QueryFence; device->SetIndexBuffer = D3D12::SetIndexBuffer;
device->ReleaseFence = ReleaseFence; device->WaitUntilGPUIsIdle = D3D12::WaitUntilGPUIsIdle;
device->CreateShader = CreateShader;
device->DestroyShader = DestroyShader; device->SetPushConstants = D3D12::SetPushConstants;
device->CreateGraphicsPipeline = CreateGraphicsPipeline; device->QueryFence = D3D12::QueryFence;
device->DestroyGraphicsPipeline = DestroyGraphicsPipeline; device->ReleaseFence = D3D12::ReleaseFence;
device->CreateGraphicsBuffer = CreateGraphicsBuffer; device->CreateShader = D3D12::CreateShader;
device->DestroyGraphicsBuffer = DestroyGraphicsBuffer; device->DestroyShader = D3D12::DestroyShader;
device->CreateGraphicsTransferBuffer = CreateGraphicsTransferBuffer; device->CreateGraphicsPipeline = D3D12::CreateGraphicsPipeline;
device->DestroyGraphicsTransferBuffer = DestroyGraphicsTransferBuffer; device->DestroyGraphicsPipeline = DestroyGraphicsPipeline;
device->MapGraphicsTransferBuffer = MapBuffer; device->CreateGraphicsBuffer = D3D12::CreateGraphicsBuffer;
device->UnmapGraphicsTransferBuffer = UnmapBuffer; device->DestroyGraphicsBuffer = D3D12::DestroyGraphicsBuffer;
device->CopyBuffer = CopyBuffer; device->CreateGraphicsTransferBuffer = D3D12::CreateGraphicsTransferBuffer;
device->TransitionBufferToReadable = TransitionBufferToReadable; device->DestroyGraphicsTransferBuffer = D3D12::DestroyGraphicsTransferBuffer;
device->GetDescriptorIndex = GetDescriptorIndex; device->MapGraphicsTransferBuffer = D3D12::MapBuffer;
device->CreateTexture = CreateTexture; device->UnmapGraphicsTransferBuffer = D3D12::UnmapBuffer;
device->DestroyTexture = DestroyTexture; device->CopyBuffer = CopyBuffer;
device->CopyBufferToTexture = CopyBufferToTexture;
device->TransitionBufferToReadable = D3D12::TransitionBufferToReadable;
device->GetDescriptorIndex = GetDescriptorIndex;
device->GetDescriptorIndexTexture = GetDescriptorIndexTexture;
device->CreateTexture = D3D12::CreateTexture;
device->DestroyTexture = D3D12::DestroyTexture;
#if ALLOW_SHADER_HOT_RELOAD #if ALLOW_SHADER_HOT_RELOAD
device->UpdateGraphicsPipelineShaders = UpdateGraphicsPipelineShaders; device->UpdateGraphicsPipelineShaders = UpdateGraphicsPipelineShaders;
@@ -1024,7 +1130,8 @@ namespace Juliet::D3D12
driver->GraphicsDevice = device; driver->GraphicsDevice = device;
// Create Global Bindless Heap that stays alive for the driver whole lifetime // Create Global Bindless Heap that stays alive for the driver whole lifetime
driver->BindlessDescriptorHeap = Internal::CreateDescriptorHeap(driver, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, GPUDriver::kCBV_SRV_UAV_HeapDescriptorCount, false); driver->BindlessDescriptorHeap = Internal::CreateDescriptorHeap(driver, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
GPUDriver::kCBV_SRV_UAV_HeapDescriptorCount, false);
return device; return device;
} }

View File

@@ -53,7 +53,7 @@ namespace Juliet::D3D12
ID3D12Device5* D3D12Device; ID3D12Device5* D3D12Device;
PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE D3D12SerializeVersionedRootSignatureFct; PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE D3D12SerializeVersionedRootSignatureFct;
ID3D12CommandQueue* GraphicsQueue; ID3D12CommandQueue* GraphicsQueue;
D3D12_COMMAND_QUEUE_DESC QueueDesc[ToUnderlying(QueueType::Copy)]; D3D12_COMMAND_QUEUE_DESC QueueDesc[ToUnderlying(QueueType::Count)];
#if JULIET_DEBUG #if JULIET_DEBUG
ID3D12Debug1* D3D12Debug; ID3D12Debug1* D3D12Debug;
#endif #endif
@@ -112,6 +112,7 @@ namespace Juliet::D3D12
bool GPUUploadHeapSupported : 1; bool GPUUploadHeapSupported : 1;
}; };
namespace Internal namespace Internal
{ {
void DisposePendingResourcces(NonNullPtr<D3D12Driver> driver); void DisposePendingResourcces(NonNullPtr<D3D12Driver> driver);

View File

@@ -406,7 +406,7 @@ namespace Juliet::D3D12
psoDesc.pRootSignature = d3d12Driver->BindlessRootSignature->Handle; psoDesc.pRootSignature = d3d12Driver->BindlessRootSignature->Handle;
ID3D12PipelineState* pipelineState; ID3D12PipelineState* pipelineState;
HRESULT res = ID3D12Device_CreateGraphicsPipelineState(d3d12Driver->D3D12Device, &psoDesc, IID_ID3D12PipelineState, HRESULT res = d3d12Driver->D3D12Device->CreateGraphicsPipelineState(&psoDesc, IID_ID3D12PipelineState,
reinterpret_cast<void**>(&pipelineState)); reinterpret_cast<void**>(&pipelineState));
if (FAILED(res)) if (FAILED(res))
{ {
@@ -499,7 +499,7 @@ namespace Juliet::D3D12
psoDesc.pRootSignature = d3d12Driver->BindlessRootSignature->Handle; psoDesc.pRootSignature = d3d12Driver->BindlessRootSignature->Handle;
ID3D12PipelineState* pipelineState; ID3D12PipelineState* pipelineState;
HRESULT res = ID3D12Device_CreateGraphicsPipelineState(d3d12Driver->D3D12Device, &psoDesc, IID_ID3D12PipelineState, HRESULT res = d3d12Driver->D3D12Device->CreateGraphicsPipelineState(&psoDesc, IID_ID3D12PipelineState,
reinterpret_cast<void**>(&pipelineState)); reinterpret_cast<void**>(&pipelineState));
if (FAILED(res)) if (FAILED(res))
{ {
@@ -520,7 +520,7 @@ namespace Juliet::D3D12
// If everything worked, we patch the graphics pipeline and destroy everything irrelevant // If everything worked, we patch the graphics pipeline and destroy everything irrelevant
if (d3d12GraphicsPipeline->PipelineState) if (d3d12GraphicsPipeline->PipelineState)
{ {
ID3D12PipelineState_Release(d3d12GraphicsPipeline->PipelineState); d3d12GraphicsPipeline->PipelineState->Release();
} }
d3d12GraphicsPipeline->PipelineState = pipelineState; d3d12GraphicsPipeline->PipelineState = pipelineState;
@@ -543,7 +543,7 @@ namespace Juliet::D3D12
{ {
if (d3d12GraphicsPipeline->PipelineState) if (d3d12GraphicsPipeline->PipelineState)
{ {
ID3D12PipelineState_Release(d3d12GraphicsPipeline->PipelineState); d3d12GraphicsPipeline->PipelineState->Release();
} }
#if ALLOW_SHADER_HOT_RELOAD #if ALLOW_SHADER_HOT_RELOAD

View File

@@ -8,30 +8,22 @@
// Because Microsoft respects nothing // Because Microsoft respects nothing
// TODO: Create an external dependency with its one fbuild.bff // TODO: Create an external dependency with its one fbuild.bff
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreserved-macro-identifier" #pragma clang diagnostic ignored "-Wreserved-macro-identifier"
#pragma clang diagnostic ignored "-Wreserved-identifier" #pragma clang diagnostic ignored "-Wreserved-identifier"
#pragma clang diagnostic ignored "-Wnonportable-system-include-path" #pragma clang diagnostic ignored "-Wnonportable-system-include-path"
#pragma clang diagnostic ignored "-Wmicrosoft-enum-value" #pragma clang diagnostic ignored "-Wmicrosoft-enum-value"
#pragma clang diagnostic ignored "-Wnested-anon-types" #pragma clang diagnostic ignored "-Wnested-anon-types"
#pragma clang diagnostic ignored "-Wnon-virtual-dtor" #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#endif #endif
// We will use the C interface of DX12.
// Those define disable the C++ API.
// It also prevents using d3dx12 because it only supports C++ :(
#define COBJMACROS
#define CINTERFACE
#include <Graphics/D3D12/AgilitySDK/d3d12.h>
#include <dxgi1_6.h> #include <dxgi1_6.h>
#include <Graphics/D3D12/AgilitySDK/d3d12.h>
#if JULIET_DEBUG #if JULIET_DEBUG
#include <dxgidebug.h> #include <dxgidebug.h>
#endif #endif
//#include <dxgi.h>
#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__ #ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
#define IDXGIINFOQUEUE_SUPPORTED #define IDXGIINFOQUEUE_SUPPORTED
#endif #endif
@@ -44,5 +36,5 @@
#undef max #undef max
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif

View File

@@ -136,6 +136,9 @@ namespace Juliet::D3D12::UnitTest
// Note: heap2 is heap1. // Note: heap2 is heap1.
// Pool array in driver leaked for test scope, acceptable. // Pool array in driver leaked for test scope, acceptable.
printf("DescriptorHeapPool tests passed.\n");
} }
} }
#endif #endif

View File

@@ -67,7 +67,7 @@ namespace Juliet::D3D12
// TODO: Check if texture has stencil // TODO: Check if texture has stencil
// if (HasStencil(container->Header.CreateInfo.Format)) clearFlags |= D3D12_CLEAR_FLAG_STENCIL; // if (HasStencil(container->Header.CreateInfo.Format)) clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
ID3D12GraphicsCommandList_ClearDepthStencilView(d3d12CommandList->GraphicsCommandList.CommandList, DSV, d3d12CommandList->GraphicsCommandList.CommandList->ClearDepthStencilView(DSV,
clearFlags, depthStencilTargetInfo->ClearDepth, clearFlags, depthStencilTargetInfo->ClearDepth,
depthStencilTargetInfo->ClearStencil, 0, nullptr); depthStencilTargetInfo->ClearStencil, 0, nullptr);
} }
@@ -93,7 +93,7 @@ namespace Juliet::D3D12
clearColor[2] = colorTargetInfos[idx].ClearColor.B; clearColor[2] = colorTargetInfos[idx].ClearColor.B;
clearColor[3] = colorTargetInfos[idx].ClearColor.A; clearColor[3] = colorTargetInfos[idx].ClearColor.A;
ID3D12GraphicsCommandList6_ClearRenderTargetView(d3d12CommandList->GraphicsCommandList.CommandList, rtv, d3d12CommandList->GraphicsCommandList.CommandList->ClearRenderTargetView(rtv,
clearColor, 0, nullptr); clearColor, 0, nullptr);
} }
@@ -119,7 +119,7 @@ namespace Juliet::D3D12
} }
} }
ID3D12GraphicsCommandList_OMSetRenderTargets(d3d12CommandList->GraphicsCommandList.CommandList, d3d12CommandList->GraphicsCommandList.CommandList->OMSetRenderTargets(
colorTargetInfoCount, RTVs, false, hasDSV ? &DSV : nullptr); colorTargetInfoCount, RTVs, false, hasDSV ? &DSV : nullptr);
// Set defaults graphics states // Set defaults graphics states
@@ -163,8 +163,7 @@ namespace Juliet::D3D12
Internal::TextureSubresourceBarrier(d3d12CommandList, D3D12_RESOURCE_STATE_RENDER_TARGET, Internal::TextureSubresourceBarrier(d3d12CommandList, D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_RESOLVE_SOURCE, D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
d3d12CommandList->ColorTargetSubresources[idx]); d3d12CommandList->ColorTargetSubresources[idx]);
ID3D12GraphicsCommandList_ResolveSubresource( d3d12CommandList->GraphicsCommandList.CommandList->ResolveSubresource(
d3d12CommandList->GraphicsCommandList.CommandList,
d3d12CommandList->ColorResolveSubresources[idx]->Parent->Resource, d3d12CommandList->ColorResolveSubresources[idx]->Parent->Resource,
d3d12CommandList->ColorResolveSubresources[idx]->Index, d3d12CommandList->ColorResolveSubresources[idx]->Index,
d3d12CommandList->ColorTargetSubresources[idx]->Parent->Resource, d3d12CommandList->ColorTargetSubresources[idx]->Parent->Resource,
@@ -199,7 +198,7 @@ namespace Juliet::D3D12
} }
d3d12CommandList->CurrentGraphicsPipeline = nullptr; d3d12CommandList->CurrentGraphicsPipeline = nullptr;
ID3D12GraphicsCommandList_OMSetRenderTargets(d3d12CommandList->GraphicsCommandList.CommandList, 0, nullptr, false, nullptr); d3d12CommandList->GraphicsCommandList.CommandList->OMSetRenderTargets(0, nullptr, false, nullptr);
// Reset bind states // Reset bind states
ZeroArray(d3d12CommandList->ColorTargetSubresources); ZeroArray(d3d12CommandList->ColorTargetSubresources);
@@ -236,10 +235,10 @@ namespace Juliet::D3D12
Internal::SetDescriptorHeaps(d3d12CommandList); Internal::SetDescriptorHeaps(d3d12CommandList);
// Set the pipeline state // Set the pipeline state
ID3D12GraphicsCommandList_SetPipelineState(d3d12CommandList->GraphicsCommandList.CommandList, pipeline->PipelineState); d3d12CommandList->GraphicsCommandList.CommandList->SetPipelineState(pipeline->PipelineState);
ID3D12GraphicsCommandList_SetGraphicsRootSignature(d3d12CommandList->GraphicsCommandList.CommandList, d3d12CommandList->GraphicsCommandList.CommandList->SetGraphicsRootSignature(
pipeline->RootSignature->Handle); pipeline->RootSignature->Handle);
ID3D12GraphicsCommandList_IASetPrimitiveTopology(d3d12CommandList->GraphicsCommandList.CommandList, d3d12CommandList->GraphicsCommandList.CommandList->IASetPrimitiveTopology(
JulietToD3D12_PrimitiveType[ToUnderlying(pipeline->PrimitiveType)]); JulietToD3D12_PrimitiveType[ToUnderlying(pipeline->PrimitiveType)]);
// Mark that bindings are needed // Mark that bindings are needed
@@ -281,7 +280,7 @@ namespace Juliet::D3D12
// TODO : Last missing piece // TODO : Last missing piece
// D3D12_INTERNAL_BindGraphicsResources(d3d12CommandBuffer); // D3D12_INTERNAL_BindGraphicsResources(d3d12CommandBuffer);
ID3D12GraphicsCommandList_DrawInstanced(d3d12CommandList->GraphicsCommandList.CommandList, numVertices, d3d12CommandList->GraphicsCommandList.CommandList->DrawInstanced(numVertices,
numInstances, firstVertex, firstInstance); numInstances, firstVertex, firstInstance);
} }
} // namespace Juliet::D3D12 } // namespace Juliet::D3D12

View File

@@ -42,7 +42,7 @@ namespace Juliet::D3D12
{ {
ID3D12Resource* swapChainTexture = nullptr; ID3D12Resource* swapChainTexture = nullptr;
HRESULT result = HRESULT result =
IDXGISwapChain_GetBuffer(swapChain, index, IID_ID3D12Resource, reinterpret_cast<void**>(&swapChainTexture)); swapChain->GetBuffer(index, IID_ID3D12Resource, reinterpret_cast<void**>(&swapChainTexture));
if (FAILED(result)) if (FAILED(result))
{ {
LogError(driver->D3D12Device, "Cannot get buffer from SwapChain", result); LogError(driver->D3D12Device, "Cannot get buffer from SwapChain", result);
@@ -53,7 +53,7 @@ namespace Juliet::D3D12
if (!texture) if (!texture)
{ {
LogError(driver->D3D12Device, "Cannot allocate D3D12Texture (out of memory)", result); LogError(driver->D3D12Device, "Cannot allocate D3D12Texture (out of memory)", result);
ID3D12Resource_Release(swapChainTexture); swapChainTexture->Release();
return false; return false;
} }
@@ -64,7 +64,7 @@ namespace Juliet::D3D12
{ {
LogError(driver->D3D12Device, "Cannot allocate D3D12TextureSubresource (out of memory)", result); LogError(driver->D3D12Device, "Cannot allocate D3D12TextureSubresource (out of memory)", result);
Free(texture); Free(texture);
ID3D12Resource_Release(swapChainTexture); swapChainTexture->Release();
return false; return false;
} }
texture->Subresources[0].RTVHandles = texture->Subresources[0].RTVHandles =
@@ -77,8 +77,7 @@ namespace Juliet::D3D12
texture->Subresources[0].Depth = 1; texture->Subresources[0].Depth = 1;
texture->Subresources[0].Level = 0; texture->Subresources[0].Level = 0;
D3D12_RESOURCE_DESC textureDesc; D3D12_RESOURCE_DESC textureDesc = swapChainTexture->GetDesc();
ID3D12Resource_GetDesc(swapChainTexture, &textureDesc);
textureContainer->Header.CreateInfo.Width = static_cast<uint32>(textureDesc.Width); textureContainer->Header.CreateInfo.Width = static_cast<uint32>(textureDesc.Width);
textureContainer->Header.CreateInfo.Height = static_cast<uint32>(textureDesc.Height); textureContainer->Header.CreateInfo.Height = static_cast<uint32>(textureDesc.Height);
textureContainer->Header.CreateInfo.LayerCount = 1; textureContainer->Header.CreateInfo.LayerCount = 1;
@@ -93,7 +92,7 @@ namespace Juliet::D3D12
{ {
Free(texture->Subresources); Free(texture->Subresources);
Free(texture); Free(texture);
ID3D12Resource_Release(swapChainTexture); swapChainTexture->Release();
return false; return false;
} }
@@ -115,10 +114,10 @@ namespace Juliet::D3D12
rtvDesc.Texture2D.MipSlice = 0; rtvDesc.Texture2D.MipSlice = 0;
rtvDesc.Texture2D.PlaneSlice = 0; rtvDesc.Texture2D.PlaneSlice = 0;
ID3D12Device_CreateRenderTargetView(driver->D3D12Device, swapChainTexture, &rtvDesc, driver->D3D12Device->CreateRenderTargetView(swapChainTexture, &rtvDesc,
texture->Subresources[0].RTVHandles[0].CpuHandle); texture->Subresources[0].RTVHandles[0].CpuHandle);
ID3D12Resource_Release(swapChainTexture); swapChainTexture->Release();
return true; return true;
} }
@@ -161,11 +160,9 @@ namespace Juliet::D3D12
windowData->InFlightFences[windowData->WindowFrameCounter] = nullptr; windowData->InFlightFences[windowData->WindowFrameCounter] = nullptr;
} }
uint32 swapchainIndex = IDXGISwapChain3_GetCurrentBackBufferIndex(windowData->SwapChain); uint32 swapchainIndex = windowData->SwapChain->GetCurrentBackBufferIndex();
HRESULT result = HRESULT result =
IDXGISwapChain_GetBuffer(windowData->SwapChain, swapchainIndex, IID_ID3D12Resource, windowData->SwapChain->GetBuffer(swapchainIndex, IID_ID3D12Resource, reinterpret_cast<void**>(&windowData->SwapChainTextureContainers[swapchainIndex].ActiveTexture->Resource));
reinterpret_cast<void**>(
&windowData->SwapChainTextureContainers[swapchainIndex].ActiveTexture->Resource));
if (FAILED(result)) if (FAILED(result))
{ {
LogError(driver->D3D12Device, "Could not acquire swapchain", result); LogError(driver->D3D12Device, "Could not acquire swapchain", result);
@@ -192,7 +189,7 @@ namespace Juliet::D3D12
barrierDesc.Transition.pResource = windowData->SwapChainTextureContainers[swapchainIndex].ActiveTexture->Resource; barrierDesc.Transition.pResource = windowData->SwapChainTextureContainers[swapchainIndex].ActiveTexture->Resource;
barrierDesc.Transition.Subresource = 0; barrierDesc.Transition.Subresource = 0;
ID3D12GraphicsCommandList_ResourceBarrier(d3d12CommandList->GraphicsCommandList.CommandList, 1, &barrierDesc); d3d12CommandList->GraphicsCommandList.CommandList->ResourceBarrier(1, &barrierDesc);
*swapchainTexture = reinterpret_cast<Texture*>(&windowData->SwapChainTextureContainers[swapchainIndex]); *swapchainTexture = reinterpret_cast<Texture*>(&windowData->SwapChainTextureContainers[swapchainIndex]);
@@ -294,7 +291,7 @@ namespace Juliet::D3D12
IDXGISwapChain1* swapChain = nullptr; IDXGISwapChain1* swapChain = nullptr;
HRESULT result = HRESULT result =
IDXGIFactory4_CreateSwapChainForHwnd(driver->DXGIFactory, reinterpret_cast<IUnknown*>(driver->GraphicsQueue), driver->DXGIFactory->CreateSwapChainForHwnd(static_cast<IUnknown*>(driver->GraphicsQueue),
windowHandle, &swapChainDesc, &swapChainFullscreenDesc, nullptr, &swapChain); windowHandle, &swapChainDesc, &swapChainFullscreenDesc, nullptr, &swapChain);
if (FAILED(result)) if (FAILED(result))
{ {
@@ -303,8 +300,8 @@ namespace Juliet::D3D12
} }
IDXGISwapChain3* swapChain3 = nullptr; IDXGISwapChain3* swapChain3 = nullptr;
result = IDXGISwapChain1_QueryInterface(swapChain, IID_IDXGISwapChain3, reinterpret_cast<void**>(&swapChain3)); result = swapChain->QueryInterface(IID_IDXGISwapChain3, reinterpret_cast<void**>(&swapChain3));
IDXGISwapChain1_Release(swapChain); swapChain->Release();
if (FAILED(result)) if (FAILED(result))
{ {
LogError(driver->D3D12Device, "Could not query IDXGISwapChain3 interface", result); LogError(driver->D3D12Device, "Could not query IDXGISwapChain3 interface", result);
@@ -313,11 +310,11 @@ namespace Juliet::D3D12
if (composition != SwapChainComposition::SDR) if (composition != SwapChainComposition::SDR)
{ {
IDXGISwapChain3_SetColorSpace1(swapChain3, SwapchainCompositionToColorSpace[ToUnderlying(composition)]); swapChain3->SetColorSpace1(SwapchainCompositionToColorSpace[ToUnderlying(composition)]);
} }
IDXGIFactory1* parentFactory = nullptr; IDXGIFactory1* parentFactory = nullptr;
result = IDXGISwapChain3_GetParent(swapChain3, IID_IDXGIFactory1, reinterpret_cast<void**>(&parentFactory)); result = swapChain3->GetParent(IID_IDXGIFactory1, reinterpret_cast<void**>(&parentFactory));
if (FAILED(result)) if (FAILED(result))
{ {
Log(LogLevel::Warning, LogCategory::Graphics, "Cannot get SwapChain Parent! Error Code: " HRESULT_FMT, result); Log(LogLevel::Warning, LogCategory::Graphics, "Cannot get SwapChain Parent! Error Code: " HRESULT_FMT, result);
@@ -325,15 +322,15 @@ namespace Juliet::D3D12
else else
{ {
// Disable DXGI window crap // Disable DXGI window crap
result = IDXGIFactory1_MakeWindowAssociation(parentFactory, windowHandle, DXGI_MWA_NO_WINDOW_CHANGES); result = parentFactory->MakeWindowAssociation(windowHandle, DXGI_MWA_NO_WINDOW_CHANGES);
if (FAILED(result)) if (FAILED(result))
{ {
Log(LogLevel::Warning, LogCategory::Graphics, "MakeWindowAssociation failed! Error Code: " HRESULT_FMT, result); Log(LogLevel::Warning, LogCategory::Graphics, "MakeWindowAssociation failed! Error Code: " HRESULT_FMT, result);
} }
IDXGIFactory1_Release(parentFactory); parentFactory->Release();
} }
IDXGISwapChain3_GetDesc1(swapChain3, &swapChainDesc); swapChain3->GetDesc1(&swapChainDesc);
if (FAILED(result)) if (FAILED(result))
{ {
LogError(driver->D3D12Device, "Failed to retrieve SwapChain descriptor", result); LogError(driver->D3D12Device, "Failed to retrieve SwapChain descriptor", result);
@@ -351,7 +348,7 @@ namespace Juliet::D3D12
{ {
if (!CreateSwapChainTexture(driver, swapChain3, composition, &windowData->SwapChainTextureContainers[idx], idx)) if (!CreateSwapChainTexture(driver, swapChain3, composition, &windowData->SwapChainTextureContainers[idx], idx))
{ {
IDXGISwapChain3_Release(swapChain3); swapChain3->Release();
return false; return false;
} }
} }
@@ -372,7 +369,7 @@ namespace Juliet::D3D12
Free(windowData->SwapChainTextureContainers[idx].Textures); Free(windowData->SwapChainTextureContainers[idx].Textures);
} }
IDXGISwapChain_Release(windowData->SwapChain); windowData->SwapChain->Release();
windowData->SwapChain = nullptr; windowData->SwapChain = nullptr;
} }
} // namespace Internal } // namespace Internal

View File

@@ -35,12 +35,12 @@ namespace Juliet::D3D12
if (d3d12driver->GraphicsQueue) if (d3d12driver->GraphicsQueue)
{ {
// Insert a signal into the end of the command queue... // Insert a signal into the end of the command queue...
ID3D12CommandQueue_Signal(d3d12driver->GraphicsQueue, fence->Handle, D3D12_FENCE_SIGNAL_VALUE); d3d12driver->GraphicsQueue->Signal(fence->Handle, D3D12_FENCE_SIGNAL_VALUE);
// ...and then block on it. // ...and then block on it.
if (ID3D12Fence_GetCompletedValue(fence->Handle) != D3D12_FENCE_SIGNAL_VALUE) if (fence->Handle->GetCompletedValue() != D3D12_FENCE_SIGNAL_VALUE)
{ {
HRESULT result = ID3D12Fence_SetEventOnCompletion(fence->Handle, D3D12_FENCE_SIGNAL_VALUE, fence->Event); HRESULT result = fence->Handle->SetEventOnCompletion(D3D12_FENCE_SIGNAL_VALUE, fence->Event);
if (FAILED(result)) if (FAILED(result))
{ {
LogError(d3d12driver->D3D12Device, "Setting fence event failed!", result); LogError(d3d12driver->D3D12Device, "Setting fence event failed!", result);
@@ -82,7 +82,7 @@ namespace Juliet::D3D12
{ {
auto fence = reinterpret_cast<D3D12Fence*>(fences[i]); auto fence = reinterpret_cast<D3D12Fence*>(fences[i]);
HRESULT res = ID3D12Fence_SetEventOnCompletion(fence->Handle, D3D12_FENCE_SIGNAL_VALUE, fence->Event); HRESULT res = fence->Handle->SetEventOnCompletion(D3D12_FENCE_SIGNAL_VALUE, fence->Event);
if (FAILED(res)) if (FAILED(res))
{ {
LogError(d3d12driver->D3D12Device, "Setting fence event failed!", res); LogError(d3d12driver->D3D12Device, "Setting fence event failed!", res);
@@ -104,7 +104,7 @@ namespace Juliet::D3D12
// Clean up // Clean up
for (int32 idx = d3d12driver->SubmittedCommandListCount - 1; idx >= 0; --idx -= 1) for (int32 idx = d3d12driver->SubmittedCommandListCount - 1; idx >= 0; --idx -= 1)
{ {
uint64 fenceValue = ID3D12Fence_GetCompletedValue(d3d12driver->SubmittedCommandLists[idx]->InFlightFence->Handle); uint64 fenceValue = d3d12driver->SubmittedCommandLists[idx]->InFlightFence->Handle->GetCompletedValue();
if (fenceValue == D3D12_FENCE_SIGNAL_VALUE) if (fenceValue == D3D12_FENCE_SIGNAL_VALUE)
{ {
result &= Internal::CleanCommandList(d3d12driver, d3d12driver->SubmittedCommandLists[idx], false); result &= Internal::CleanCommandList(d3d12driver, d3d12driver->SubmittedCommandLists[idx], false);
@@ -166,7 +166,7 @@ namespace Juliet::D3D12
if (numBarriers > 0) if (numBarriers > 0)
{ {
ID3D12GraphicsCommandList_ResourceBarrier(commandList->GraphicsCommandList.CommandList, numBarriers, barrierDesc); commandList->GraphicsCommandList.CommandList->ResourceBarrier(numBarriers, barrierDesc);
} }
} }
@@ -179,7 +179,7 @@ namespace Juliet::D3D12
if (driver->AvailableFenceCount == 0) if (driver->AvailableFenceCount == 0)
{ {
HRESULT result = ID3D12Device_CreateFence(driver->D3D12Device, D3D12_FENCE_UNSIGNALED_VALUE, D3D12_FENCE_FLAG_NONE, HRESULT result = driver->D3D12Device->CreateFence(D3D12_FENCE_UNSIGNALED_VALUE, D3D12_FENCE_FLAG_NONE,
IID_ID3D12Fence, reinterpret_cast<void**>(&handle)); IID_ID3D12Fence, reinterpret_cast<void**>(&handle));
if (FAILED(result)) if (FAILED(result))
{ {
@@ -190,7 +190,7 @@ namespace Juliet::D3D12
fence = static_cast<D3D12Fence*>(Calloc(1, sizeof(D3D12Fence))); fence = static_cast<D3D12Fence*>(Calloc(1, sizeof(D3D12Fence)));
if (!fence) if (!fence)
{ {
ID3D12Fence_Release(handle); handle->Release();
return nullptr; return nullptr;
} }
@@ -202,7 +202,7 @@ namespace Juliet::D3D12
{ {
fence = driver->AvailableFences[driver->AvailableFenceCount - 1]; fence = driver->AvailableFences[driver->AvailableFenceCount - 1];
driver->AvailableFenceCount -= 1; driver->AvailableFenceCount -= 1;
ID3D12Fence_Signal(fence->Handle, D3D12_FENCE_UNSIGNALED_VALUE); fence->Handle->Signal(D3D12_FENCE_UNSIGNALED_VALUE);
} }
fence->ReferenceCount += 1; fence->ReferenceCount += 1;
@@ -213,7 +213,7 @@ namespace Juliet::D3D12
{ {
if (fence->Handle) if (fence->Handle)
{ {
ID3D12Fence_Release(fence->Handle); fence->Handle->Release();
} }
if (fence->Event) if (fence->Event)

View File

@@ -426,7 +426,7 @@ namespace Juliet::D3D12
pClearValue = &clearValue; pClearValue = &clearValue;
} }
HRESULT hr = ID3D12Device_CreateCommittedResource(d3d12Driver->D3D12Device, &heapProps, D3D12_HEAP_FLAG_NONE, &desc, HRESULT hr = d3d12Driver->D3D12Device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc,
D3D12_RESOURCE_STATE_COMMON, pClearValue, IID_ID3D12Resource, D3D12_RESOURCE_STATE_COMMON, pClearValue, IID_ID3D12Resource,
reinterpret_cast<void**>(&resource)); reinterpret_cast<void**>(&resource));
@@ -477,7 +477,7 @@ namespace Juliet::D3D12
rtvDesc.Format = desc.Format; rtvDesc.Format = desc.Format;
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = mip; rtvDesc.Texture2D.MipSlice = mip;
ID3D12Device_CreateRenderTargetView(d3d12Driver->D3D12Device, resource, &rtvDesc, sub.RTVHandles[0].CpuHandle); d3d12Driver->D3D12Device->CreateRenderTargetView(resource, &rtvDesc, sub.RTVHandles[0].CpuHandle);
} }
if ((createInfo.Flags & TextureUsageFlag::DepthStencilTarget) != TextureUsageFlag::None) if ((createInfo.Flags & TextureUsageFlag::DepthStencilTarget) != TextureUsageFlag::None)
@@ -488,12 +488,48 @@ namespace Juliet::D3D12
dsvDesc.Format = Internal::ConvertToD3D12DepthFormat(createInfo.Format); dsvDesc.Format = Internal::ConvertToD3D12DepthFormat(createInfo.Format);
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
dsvDesc.Texture2D.MipSlice = mip; dsvDesc.Texture2D.MipSlice = mip;
ID3D12Device_CreateDepthStencilView(d3d12Driver->D3D12Device, resource, &dsvDesc, sub.DSVHandle.CpuHandle); d3d12Driver->D3D12Device->CreateDepthStencilView(resource, &dsvDesc, sub.DSVHandle.CpuHandle);
} }
} }
} }
// Create SRV for sampled/readable textures (bindless access)
// Assign to the bindless CBV_SRV_UAV heap
{
Internal::D3D12Descriptor descriptor;
if (Internal::AssignDescriptor(d3d12Driver->BindlessDescriptorHeap, descriptor))
{
texture->SRVHandle = D3D12StagingDescriptor{};
texture->SRVHandle.CpuHandleIndex = descriptor.Index;
texture->SRVHandle.CpuHandle = descriptor.CpuHandle;
texture->SRVHandle.Heap = descriptor.Heap;
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = desc.Format;
// Fix SRV format for Depth Buffers (TypeLess -> Typed)
if (createInfo.Format == TextureFormat::D32_FLOAT)
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
else if (createInfo.Format == TextureFormat::D16_UNORM)
srvDesc.Format = DXGI_FORMAT_R16_UNORM;
else if (createInfo.Format == TextureFormat::D24_UNORM_S8_UINT)
srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
else if (createInfo.Format == TextureFormat::D32_FLOAT_S8_UINT)
srvDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = numMips;
srvDesc.Texture2D.PlaneSlice = 0;
srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
d3d12Driver->D3D12Device->CreateShaderResourceView(resource, &srvDesc, descriptor.CpuHandle);
}
}
return reinterpret_cast<Texture*>(textureContainer); return reinterpret_cast<Texture*>(textureContainer);
} }
void DestroyTexture(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture) void DestroyTexture(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture)
@@ -517,7 +553,7 @@ namespace Juliet::D3D12
Internal::ReleaseStagingDescriptor(d3d12Driver, sub.DSVHandle); Internal::ReleaseStagingDescriptor(d3d12Driver, sub.DSVHandle);
} }
} }
ID3D12Resource_Release(d3d12Texture->Resource); d3d12Texture->Resource->Release();
Free(d3d12Texture->Subresources); Free(d3d12Texture->Subresources);
Free(d3d12Texture); Free(d3d12Texture);
} }

View File

@@ -18,7 +18,7 @@ namespace Juliet::D3D12
if (result == DXGI_ERROR_DEVICE_REMOVED) if (result == DXGI_ERROR_DEVICE_REMOVED)
{ {
result = ID3D12Device_GetDeviceRemovedReason(D3D12Device); result = D3D12Device->GetDeviceRemovedReason();
} }
// Try to get the message from the system errors. // Try to get the message from the system errors.

View File

@@ -4,6 +4,8 @@
#include <Core/Logging/LogTypes.h> #include <Core/Logging/LogTypes.h>
#include <Graphics/Graphics.h> #include <Graphics/Graphics.h>
#include <Graphics/GraphicsDevice.h> #include <Graphics/GraphicsDevice.h>
#include <Core/ImGui/ImGuiTests.h>
namespace Juliet namespace Juliet
{ {
@@ -57,9 +59,11 @@ namespace Juliet
{ {
if (GraphicsDevice* newDevice = chosenFactory->CreateGraphicsDevice(config.EnableDebug)) if (GraphicsDevice* newDevice = chosenFactory->CreateGraphicsDevice(config.EnableDebug))
{ {
newDevice->Name = chosenFactory->Name; newDevice->Name = chosenFactory->Name;
return newDevice; return newDevice;
} }
} }
return nullptr; return nullptr;
} }
@@ -259,6 +263,16 @@ namespace Juliet
commandListHeader->Device->SetStencilReference(commandList, reference); commandListHeader->Device->SetStencilReference(commandList, reference);
} }
void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format)
{
auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList.Get());
if (commandListHeader->Device->SetIndexBuffer)
{
commandListHeader->Device->SetIndexBuffer(commandList, buffer, format);
}
}
void BindGraphicsPipeline(NonNullPtr<RenderPass> renderPass, NonNullPtr<GraphicsPipeline> graphicsPipeline) void BindGraphicsPipeline(NonNullPtr<RenderPass> renderPass, NonNullPtr<GraphicsPipeline> graphicsPipeline)
{ {
auto* commandList = reinterpret_cast<GPUPass*>(renderPass.Get())->CommandList; auto* commandList = reinterpret_cast<GPUPass*>(renderPass.Get())->CommandList;
@@ -275,6 +289,21 @@ namespace Juliet
commandListHeader->Device->DrawPrimitives(commandList, numVertices, numInstances, firstVertex, firstInstance); commandListHeader->Device->DrawPrimitives(commandList, numVertices, numInstances, firstVertex, firstInstance);
} }
void DrawIndexedPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numIndices, uint32 numInstances,
uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance)
{
auto* commandList = reinterpret_cast<GPUPass*>(renderPass.Get())->CommandList;
auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList);
if (commandListHeader->Device->DrawIndexedPrimitives)
{
commandListHeader->Device->DrawIndexedPrimitives(commandList, numIndices, numInstances, firstIndex, vertexOffset, firstInstance);
}
}
void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex, void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex,
uint32 numConstants, const void* constants) uint32 numConstants, const void* constants)
{ {
@@ -366,10 +395,21 @@ namespace Juliet
void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst, void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset) NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset)
{ {
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get()); auto* headers = reinterpret_cast<CommandListHeader*>(commandList.Get());
header->Device->CopyBuffer(commandList, dst, src, size, dstOffset, srcOffset); headers->Device->CopyBuffer(commandList, dst, src, size, dstOffset, srcOffset);
} }
void CopyBufferToTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Texture> dst,
NonNullPtr<GraphicsTransferBuffer> src)
{
auto* headers = reinterpret_cast<CommandListHeader*>(commandList.Get());
if (headers->Device->CopyBufferToTexture)
{
headers->Device->CopyBufferToTexture(commandList, dst, src);
}
}
void TransitionBufferToReadable(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer) void TransitionBufferToReadable(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer)
{ {
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get()); auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get());
@@ -378,9 +418,15 @@ namespace Juliet
uint32 GetDescriptorIndex(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer) uint32 GetDescriptorIndex(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
{ {
return device->GetDescriptorIndex(device->Driver, buffer); return device->GetDescriptorIndex(device, buffer);
} }
uint32 GetDescriptorIndex(NonNullPtr<GraphicsDevice> device, NonNullPtr<Texture> texture)
{
return device->GetDescriptorIndexTexture(device, texture);
}
void DestroyGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer) void DestroyGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
{ {
device->DestroyGraphicsBuffer(buffer); device->DestroyGraphicsBuffer(buffer);

View File

@@ -66,10 +66,16 @@ namespace Juliet
void (*SetScissorRect)(NonNullPtr<CommandList> commandList, const Rectangle& viewPort); void (*SetScissorRect)(NonNullPtr<CommandList> commandList, const Rectangle& viewPort);
void (*SetBlendConstants)(NonNullPtr<CommandList> commandList, FColor blendConstants); void (*SetBlendConstants)(NonNullPtr<CommandList> commandList, FColor blendConstants);
void (*SetStencilReference)(NonNullPtr<CommandList> commandList, uint8 reference); void (*SetStencilReference)(NonNullPtr<CommandList> commandList, uint8 reference);
void (*SetIndexBuffer)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format);
void (*BindGraphicsPipeline)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsPipeline> graphicsPipeline); void (*BindGraphicsPipeline)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsPipeline> graphicsPipeline);
void (*DrawPrimitives)(NonNullPtr<CommandList> commandList, uint32 numVertices, uint32 numInstances, void (*DrawPrimitives)(NonNullPtr<CommandList> commandList, uint32 numVertices, uint32 numInstances,
uint32 firstVertex, uint32 firstInstance); uint32 firstVertex, uint32 firstInstance);
void (*DrawIndexedPrimitives)(NonNullPtr<CommandList> commandList, uint32 numIndices, uint32 numInstances,
uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance);
void (*SetPushConstants)(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex, void (*SetPushConstants)(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex,
uint32 numConstants, const void* constants); uint32 numConstants, const void* constants);
@@ -102,10 +108,14 @@ namespace Juliet
void* (*MapGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer); void* (*MapGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
void (*UnmapGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer); void (*UnmapGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
void (*CopyBuffer)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst, void (*CopyBuffer)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset); NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset);
void (*CopyBufferToTexture)(NonNullPtr<CommandList> commandList, NonNullPtr<Texture> dst,
NonNullPtr<GraphicsTransferBuffer> src); // Assume full copy for now
void (*TransitionBufferToReadable)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer); void (*TransitionBufferToReadable)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer);
uint32 (*GetDescriptorIndex)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsBuffer> buffer); uint32 (*GetDescriptorIndex)(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
uint32 (*GetDescriptorIndexTexture)(NonNullPtr<GraphicsDevice> device, NonNullPtr<Texture> texture);
const char* Name = "Unknown"; const char* Name = "Unknown";
GPUDriver* Driver = nullptr; GPUDriver* Driver = nullptr;