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;
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

View File

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

View File

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

View File

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

View File

@@ -12,13 +12,6 @@ namespace Juliet::D3D12
{
namespace
{
struct D3D12Buffer
{
Internal::D3D12Descriptor Descriptor;
ID3D12Resource* Handle;
D3D12_RESOURCE_STATES CurrentState;
};
enum class D3D12BufferType : uint8
{
Base,
@@ -26,6 +19,30 @@ namespace Juliet::D3D12
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)
{
if (!buffer)
@@ -40,7 +57,7 @@ namespace Juliet::D3D12
if (buffer->Handle)
{
ID3D12Resource_Release(buffer->Handle);
buffer->Handle->Release();
}
Free(buffer);
}
@@ -78,6 +95,7 @@ namespace Juliet::D3D12
case BufferUsage::IndexBuffer:
case BufferUsage::StructuredBuffer:
case BufferUsage::VertexBuffer:
{
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
@@ -99,8 +117,13 @@ namespace Juliet::D3D12
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
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;
}
}
@@ -130,7 +153,7 @@ namespace Juliet::D3D12
D3D12_RESOURCE_DESC desc = {};
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
desc.Alignment = 0;
desc.Width = size;
desc.Height = 1;
desc.DepthOrArraySize = 1;
@@ -141,13 +164,22 @@ namespace Juliet::D3D12
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
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;
HRESULT result = ID3D12Device_CreateCommittedResource(d3d12Driver->D3D12Device, &heapProperties, heapFlags,
&desc, initialState, nullptr, IID_ID3D12Resource,
reinterpret_cast<void**>(&handle));
HRESULT result = d3d12Driver->D3D12Device->CreateCommittedResource(&heapProperties, heapFlags,
&desc, initialState, nullptr,
IID_ID3D12Resource, reinterpret_cast<void**>(&handle));
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);
return nullptr;
}
@@ -155,6 +187,7 @@ namespace Juliet::D3D12
buffer->Handle = handle;
buffer->CurrentState = initialState;
buffer->Descriptor.Index = UINT32_MAX;
buffer->Size = size;
if (usage == BufferUsage::ConstantBuffer || usage == BufferUsage::StructuredBuffer)
{
@@ -169,25 +202,22 @@ namespace Juliet::D3D12
if (usage == BufferUsage::ConstantBuffer)
{
cbvDesc.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(handle);
cbvDesc.BufferLocation = handle->GetGPUVirtualAddress();
cbvDesc.SizeInBytes = static_cast<uint32>(size);
ID3D12Device_CreateConstantBufferView(d3d12Driver->D3D12Device, &cbvDesc, cpuHandle);
d3d12Driver->D3D12Device->CreateConstantBufferView(&cbvDesc, cpuHandle);
}
else if (usage == BufferUsage::StructuredBuffer)
{
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Buffer.FirstElement = 0;
srvDesc.Buffer.NumElements = static_cast<uint32>(
size / 4); // Assuming 4 bytes stride for raw access or similar. Ideally should be provided.
srvDesc.Buffer.StructureByteStride = 0; // Raw buffer for simplicity, or 4 if typed?
// 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.
// Actually, let's treat it as a ByteAddressBuffer (Raw) for most flexibility in bindless.
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
srvDesc.Buffer.NumElements = static_cast<uint32>(size / 4);
srvDesc.Buffer.StructureByteStride = 0;
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
ID3D12Device_CreateShaderResourceView(d3d12Driver->D3D12Device, handle, &srvDesc, cpuHandle);
d3d12Driver->D3D12Device->CreateShaderResourceView(handle, &srvDesc, cpuHandle);
Log(LogLevel::Message, LogCategory::Graphics, " -> SRV DescriptorIndex=%u", descriptor.Index);
}
}
else
@@ -230,7 +260,7 @@ namespace Juliet::D3D12
void* ptr = nullptr;
// 0-0 range means we don't intend to read anything.
D3D12_RANGE readRange = { 0, 0 };
if (FAILED(ID3D12Resource_Map(d3d12Buffer->Handle, 0, &readRange, &ptr)))
if (FAILED(d3d12Buffer->Handle->Map(0, &readRange, &ptr)))
{
return nullptr;
}
@@ -240,7 +270,7 @@ namespace Juliet::D3D12
void UnmapBuffer(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsTransferBuffer> buffer)
{
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)
@@ -267,7 +297,7 @@ namespace Juliet::D3D12
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
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;
}
@@ -275,7 +305,7 @@ namespace Juliet::D3D12
// 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.
ID3D12GraphicsCommandList_CopyBufferRegion(d3d12CmdList->GraphicsCommandList.CommandList, d3d12Dst->Handle,
d3d12CmdList->GraphicsCommandList.CommandList->CopyBufferRegion(d3d12Dst->Handle,
dstOffset, d3d12Src->Handle, srcOffset, size);
}
@@ -296,7 +326,7 @@ namespace Juliet::D3D12
barrier.Transition.StateAfter = neededState;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
ID3D12GraphicsCommandList_ResourceBarrier(d3d12CmdList->GraphicsCommandList.CommandList, 1, &barrier);
d3d12CmdList->GraphicsCommandList.CommandList->ResourceBarrier(1, &barrier);
d3d12Buffer->CurrentState = neededState;
}
}

View File

@@ -1,7 +1,9 @@
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/NonNullPtr.h>
#include <Graphics/GraphicsBuffer.h>
#include <Graphics/D3D12/D3D12DescriptorHeap.h>
namespace Juliet
{
@@ -10,6 +12,14 @@ namespace Juliet
} // namespace Juliet
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 void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer);

View File

@@ -1,5 +1,7 @@
#include <Core/Memory/Allocator.h>
#include <Graphics/D3D12/D3D12CommandList.h>
#include <Graphics/D3D12/D3D12CommandList.h>
#include <Graphics/D3D12/D3D12Buffer.h>
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
#include <Graphics/D3D12/D3D12Synchronization.h>
#include <Graphics/D3D12/D3D12Utils.h>
@@ -26,15 +28,14 @@ namespace Juliet::D3D12
bool CreateAllocator(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandListBaseData> baseData,
D3D12_COMMAND_QUEUE_DESC queueDesc)
{
HRESULT result = ID3D12Device5_CreateCommandAllocator(driver->D3D12Device, queueDesc.Type, IID_ID3D12CommandAllocator,
reinterpret_cast<void**>(&baseData->Allocator));
HRESULT result = driver->D3D12Device->CreateCommandAllocator(queueDesc.Type, IID_ID3D12CommandAllocator, reinterpret_cast<void**>(&baseData->Allocator));
if (FAILED(result))
{
AssertHR(result, "Cannot create ID3D12CommandAllocator");
return false;
}
ID3D12CommandAllocator_Reset(baseData->Allocator);
baseData->Allocator->Reset();
return true;
}
@@ -54,7 +55,7 @@ namespace Juliet::D3D12
CreateAllocator(driver, &commandList->GraphicsCommandList, queueDesc);
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
HRESULT result =
ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
driver->D3D12Device->CreateCommandList1(queueDesc.NodeMask, queueDesc.Type,
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
if (FAILED(result))
@@ -65,8 +66,8 @@ namespace Juliet::D3D12
}
commandList->GraphicsCommandList.CommandList = d3d12GraphicsCommandList;
ID3D12GraphicsCommandList6_SetName(d3d12GraphicsCommandList, wide_str.c_str());
ID3D12GraphicsCommandList6_Reset(d3d12GraphicsCommandList, commandList->GraphicsCommandList.Allocator, nullptr);
d3d12GraphicsCommandList->SetName(wide_str.c_str());
d3d12GraphicsCommandList->Reset(commandList->GraphicsCommandList.Allocator, nullptr);
return true;
}
@@ -75,7 +76,7 @@ namespace Juliet::D3D12
CreateAllocator(driver, &commandList->ComputeCommandList, queueDesc);
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
HRESULT result =
ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
driver->D3D12Device->CreateCommandList1(queueDesc.NodeMask, queueDesc.Type,
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
if (FAILED(result))
@@ -86,8 +87,8 @@ namespace Juliet::D3D12
}
commandList->ComputeCommandList.CommandList = d3d12GraphicsCommandList;
ID3D12GraphicsCommandList6_SetName(d3d12GraphicsCommandList, wide_str.c_str());
ID3D12GraphicsCommandList6_Reset(d3d12GraphicsCommandList, commandList->ComputeCommandList.Allocator, nullptr);
d3d12GraphicsCommandList->SetName(wide_str.c_str());
d3d12GraphicsCommandList->Reset(commandList->ComputeCommandList.Allocator, nullptr);
return true;
}
@@ -95,9 +96,8 @@ namespace Juliet::D3D12
{
CreateAllocator(driver, &commandList->CopyCommandList, queueDesc);
ID3D12GraphicsCommandList* d3d12CopyCommandList = nullptr;
HRESULT result = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList,
reinterpret_cast<void**>(&d3d12CopyCommandList));
HRESULT result = driver->D3D12Device->CreateCommandList1(queueDesc.NodeMask, queueDesc.Type,
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList, reinterpret_cast<void**>(&d3d12CopyCommandList));
if (FAILED(result))
{
@@ -105,8 +105,8 @@ namespace Juliet::D3D12
return false;
}
commandList->CopyCommandList.CommandList = d3d12CopyCommandList;
ID3D12GraphicsCommandList_SetName(d3d12CopyCommandList, wide_str.c_str());
ID3D12GraphicsCommandList_Reset(d3d12CopyCommandList, commandList->CopyCommandList.Allocator, nullptr);
d3d12CopyCommandList->SetName(wide_str.c_str());
d3d12CopyCommandList->Reset(commandList->CopyCommandList.Allocator, nullptr);
return true;
}
@@ -227,30 +227,21 @@ namespace Juliet::D3D12
barrierDesc.Transition.pResource = subresource->Parent->Resource;
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
HRESULT result = ID3D12GraphicsCommandList_Close(d3d12CommandList->GraphicsCommandList.CommandList);
HRESULT result = d3d12CommandList->GraphicsCommandList.CommandList->Close();
if (FAILED(result))
{
LogError(d3d12Driver->D3D12Device, "Failed to close command list!", result);
return false;
}
ID3D12CommandList* commandLists[1];
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;
}
ID3D12CommandList* ppCommandLists[] = { d3d12CommandList->GraphicsCommandList.CommandList };
// Submit the command list to the queue
ID3D12CommandQueue_ExecuteCommandLists(d3d12Driver->GraphicsQueue, 1, commandLists);
ID3D12CommandList_Release(commandLists[0]);
d3d12Driver->GraphicsQueue->ExecuteCommandLists(1, ppCommandLists);
// Acquire a fence and set it to the in-flight fence
d3d12CommandList->InFlightFence = Internal::AcquireFence(d3d12Driver);
@@ -260,7 +251,7 @@ namespace Juliet::D3D12
}
// 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))
{
LogError(d3d12Driver->D3D12Device, "Failed to enqueue fence signal!", result);
@@ -299,14 +290,13 @@ namespace Juliet::D3D12
presentFlags = DXGI_PRESENT_ALLOW_TEARING;
}
result = IDXGISwapChain_Present(windowData->SwapChain, syncInterval, presentFlags);
result = windowData->SwapChain->Present(syncInterval, presentFlags);
if (FAILED(result))
{
success = false;
}
ID3D12Resource_Release(
windowData->SwapChainTextureContainers[presentData->SwapChainImageIndex].ActiveTexture->Resource);
windowData->SwapChainTextureContainers[presentData->SwapChainImageIndex].ActiveTexture->Resource->Release();
windowData->InFlightFences[windowData->WindowFrameCounter] = reinterpret_cast<Fence*>(d3d12CommandList->InFlightFence);
d3d12CommandList->InFlightFence->ReferenceCount += 1;
@@ -317,7 +307,7 @@ namespace Juliet::D3D12
// Check for cleanups
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)
{
success &= Internal::CleanCommandList(d3d12Driver, d3d12Driver->SubmittedCommandLists[i], false);
@@ -342,7 +332,7 @@ namespace Juliet::D3D12
d3d12Viewport.Height = viewPort.Height;
d3d12Viewport.MinDepth = viewPort.MinDepth;
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)
@@ -353,20 +343,48 @@ namespace Juliet::D3D12
scissorRect.top = rectangle.Y;
scissorRect.right = rectangle.X + rectangle.Width;
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)
{
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
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)
{
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,
@@ -374,7 +392,7 @@ namespace Juliet::D3D12
{
auto d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
// 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);
}
@@ -396,7 +414,7 @@ namespace Juliet::D3D12
heaps[0] = viewHeap->Handle;
heaps[1] = samplerHeap->Handle;
ID3D12GraphicsCommandList_SetDescriptorHeaps(commandList->GraphicsCommandList.CommandList, 2, heaps);
commandList->GraphicsCommandList.CommandList->SetDescriptorHeaps(2, heaps);
}
void DestroyCommandList(NonNullPtr<D3D12CommandList> commandList)
@@ -404,10 +422,10 @@ namespace Juliet::D3D12
// TODO : Handle other kind of command list (copy compute)
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->UsedTextures);
@@ -420,14 +438,14 @@ namespace Juliet::D3D12
// No more presentation data
commandList->PresentDataCount = 0;
HRESULT result = ID3D12CommandAllocator_Reset(commandList->GraphicsCommandList.Allocator);
HRESULT result = commandList->GraphicsCommandList.Allocator->Reset();
if (FAILED(result))
{
LogError(driver->D3D12Device, "Could not reset command allocator", result);
return false;
}
result = ID3D12GraphicsCommandList_Reset(commandList->GraphicsCommandList.CommandList,
result = commandList->GraphicsCommandList.CommandList->Reset(
commandList->GraphicsCommandList.Allocator, nullptr);
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 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);
namespace Internal

View File

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

View File

@@ -46,8 +46,8 @@ namespace Juliet::D3D12
bool CheckResourceTypeTier(ID3D12Device5* device)
{
D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
HRESULT result = ID3D12Device5_CheckFeatureSupport(device, D3D12_FEATURE_D3D12_OPTIONS, &options,
sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS));
HRESULT result =
device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS));
if (SUCCEEDED(result))
{
if (options.ResourceBindingTier < D3D12_RESOURCE_BINDING_TIER_3)
@@ -83,7 +83,7 @@ namespace Juliet::D3D12
for (auto allModelVersion : allModelVersions)
{
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));
if (result != E_INVALIDARG)
{
@@ -142,40 +142,40 @@ namespace Juliet::D3D12
// Can query the 1.4 factory ?
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))
{
IDXGIFactory1_Release(factory1);
factory1->Release();
Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Failed to query DXGI1.4.");
return false;
}
IDXGIFactory4_Release(factory4);
factory4->Release();
// Check for 1.6. (It's not mandatory).
IDXGIAdapter1* adapter = 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))
{
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));
IDXGIFactory6_Release(factory6);
factory6->Release();
}
else
{
result = IDXGIFactory1_EnumAdapters1(factory1, 0, &adapter);
result = factory1->EnumAdapters1(0, &adapter);
}
if (FAILED(result))
{
Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Failed to find an adapter for D3D12.");
IDXGIFactory1_Release(factory1);
factory1->Release();
return false;
}
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));
bool driverIsValid = true;
@@ -184,7 +184,7 @@ namespace Juliet::D3D12
driverIsValid &= CheckShaderModel(device);
driverIsValid &= CheckResourceTypeTier(device);
ID3D12Device5_Release(device);
device->Release();
}
else
{
@@ -192,8 +192,8 @@ namespace Juliet::D3D12
"DX12: Failed to create a D3D12Device with feature level %s.", kD3DFeatureLevelStr);
driverIsValid = false;
}
IDXGIAdapter1_Release(adapter);
IDXGIFactory1_Release(factory1);
adapter->Release();
factory1->Release();
return driverIsValid;
}
@@ -206,7 +206,7 @@ namespace Juliet::D3D12
}
if (rootSignature->Handle)
{
ID3D12RootSignature_Release(rootSignature->Handle);
rootSignature->Handle->Release();
}
Free(rootSignature);
}
@@ -272,9 +272,10 @@ namespace Juliet::D3D12
{
if (errorBlob)
{
auto errorBuffer = ID3D10Blob_GetBufferPointer(errorBlob);
auto errorBuffer = errorBlob->GetBufferPointer();
LogError(LogCategory::Graphics, "Failed to serialize RootSignature: %s", errorBuffer);
ID3D10Blob_Release(errorBlob);
errorBlob->Release();
}
DestroyGraphicsRootSignature(d3d12GraphicsRootSignature);
return nullptr;
@@ -282,16 +283,16 @@ namespace Juliet::D3D12
// Create the root signature
ID3D12RootSignature* rootSignature;
res = ID3D12Device_CreateRootSignature(d3d12Driver->D3D12Device, 0, ID3D10Blob_GetBufferPointer(serializedRootSignature),
ID3D10Blob_GetBufferSize(serializedRootSignature),
IID_ID3D12RootSignature, reinterpret_cast<void**>(&rootSignature));
res = d3d12Driver->D3D12Device->CreateRootSignature(0, serializedRootSignature->GetBufferPointer(),
serializedRootSignature->GetBufferSize(), IID_ID3D12RootSignature,
reinterpret_cast<void**>(&rootSignature));
if (FAILED(res))
{
if (errorBlob)
{
LogError(LogCategory::Graphics, "Failed to create RootSignature: %s",
(const char*)ID3D10Blob_GetBufferPointer(errorBlob));
ID3D10Blob_Release(errorBlob);
(const char*)errorBlob->GetBufferPointer());
errorBlob->Release();
}
DestroyGraphicsRootSignature(d3d12GraphicsRootSignature);
return nullptr;
@@ -332,12 +333,9 @@ namespace Juliet::D3D12
}
else
{
IDXGIInfoQueue_SetBreakOnSeverity(driver->DXGIInfoQueue, DXGI_DEBUG_ALL,
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
IDXGIInfoQueue_SetBreakOnSeverity(driver->DXGIInfoQueue, DXGI_DEBUG_ALL,
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
IDXGIInfoQueue_SetBreakOnSeverity(driver->DXGIInfoQueue, DXGI_DEBUG_ALL,
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING, TRUE);
driver->DXGIInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
driver->DXGIInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
driver->DXGIInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING, TRUE);
}
}
}
@@ -346,9 +344,9 @@ namespace Juliet::D3D12
{
if (driver->DXGIDebug)
{
IDXGIDebug_ReportLiveObjects(driver->DXGIDebug, DXGI_DEBUG_ALL,
static_cast<DXGI_DEBUG_RLO_FLAGS>(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL));
IDXGIDebug_Release(driver->DXGIDebug);
driver->DXGIDebug->ReportLiveObjects(DXGI_DEBUG_ALL, static_cast<DXGI_DEBUG_RLO_FLAGS>(
DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL));
driver->DXGIDebug->Release();
driver->DXGIDebug = nullptr;
}
@@ -380,7 +378,7 @@ namespace Juliet::D3D12
return;
}
ID3D12Debug1_EnableDebugLayer(driver->D3D12Debug);
driver->D3D12Debug->EnableDebugLayer();
}
bool InitializeD3D12DebugInfoQueue(NonNullPtr<D3D12Driver> driver)
@@ -388,8 +386,7 @@ namespace Juliet::D3D12
ID3D12InfoQueue* infoQueue = nullptr;
D3D12_MESSAGE_SEVERITY severities[] = { D3D12_MESSAGE_SEVERITY_INFO };
HRESULT result =
ID3D12Device_QueryInterface(driver->D3D12Device, IID_ID3D12InfoQueue, reinterpret_cast<void**>(&infoQueue));
HRESULT result = driver->D3D12Device->QueryInterface(IID_ID3D12InfoQueue, reinterpret_cast<void**>(&infoQueue));
if (FAILED(result))
{
LogError(driver->D3D12Device, "Failed to convert ID3D12Device to ID3D12InfoQueue", result);
@@ -399,14 +396,13 @@ namespace Juliet::D3D12
D3D12_INFO_QUEUE_FILTER filter = {};
filter.DenyList.NumSeverities = 1;
filter.DenyList.pSeverityList = severities;
ID3D12InfoQueue_PushStorageFilter(infoQueue, &filter);
ID3D12InfoQueue_SetBreakOnSeverity(infoQueue, D3D12_MESSAGE_SEVERITY_CORRUPTION, true);
ID3D12InfoQueue_Release(infoQueue);
infoQueue->PushStorageFilter(&filter);
// infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true);
infoQueue->Release();
return true;
}
#ifdef ID3D12InfoQueue1_SUPPORTED
void WINAPI OnD3D12DebugInfoMsg(D3D12_MESSAGE_CATEGORY category, D3D12_MESSAGE_SEVERITY severity,
D3D12_MESSAGE_ID id, LPCSTR description, void* /*context*/)
{
@@ -451,19 +447,16 @@ namespace Juliet::D3D12
{
// Only supported on Win 11 apparently
ID3D12InfoQueue1* infoQueue = nullptr;
HRESULT result =
ID3D12Device5_QueryInterface(driver->D3D12Device, IID_ID3D12InfoQueue1, reinterpret_cast<void**>(&infoQueue));
HRESULT result = driver->D3D12Device->QueryInterface(IID_ID3D12InfoQueue1, reinterpret_cast<void**>(&infoQueue));
if (FAILED(result))
{
return;
}
ID3D12InfoQueue1_RegisterMessageCallback(infoQueue, OnD3D12DebugInfoMsg, D3D12_MESSAGE_CALLBACK_FLAG_NONE,
nullptr, nullptr);
ID3D12InfoQueue1_Release(infoQueue);
infoQueue->RegisterMessageCallback(OnD3D12DebugInfoMsg, D3D12_MESSAGE_CALLBACK_FLAG_NONE, nullptr, nullptr);
infoQueue->Release();
Log(LogLevel::Message, LogCategory::Graphics, "DX12: Debug Info Logger Initialized");
}
#endif
#endif
void DestroyDriver_Internal(NonNullPtr<D3D12Driver> driver)
@@ -520,6 +513,7 @@ namespace Juliet::D3D12
Internal::DestroyDescriptorHeap(driver->BindlessDescriptorHeap);
// Clean allocations
SafeFree(driver->AvailableCommandLists);
SafeFree(driver->SubmittedCommandLists);
SafeFree(driver->GraphicsPipelinesToDispose);
@@ -528,41 +522,40 @@ namespace Juliet::D3D12
if (driver->IndirectDrawCommandSignature)
{
ID3D12CommandSignature_Release(driver->IndirectDrawCommandSignature);
driver->IndirectDrawCommandSignature = nullptr;
driver->IndirectDrawCommandSignature->Release();
}
if (driver->IndirectIndexedDrawCommandSignature)
{
ID3D12CommandSignature_Release(driver->IndirectIndexedDrawCommandSignature);
driver->IndirectIndexedDrawCommandSignature->Release();
driver->IndirectIndexedDrawCommandSignature = nullptr;
}
if (driver->IndirectDispatchCommandSignature)
{
ID3D12CommandSignature_Release(driver->IndirectDispatchCommandSignature);
driver->IndirectDispatchCommandSignature->Release();
driver->IndirectDispatchCommandSignature = nullptr;
}
if (driver->GraphicsQueue)
{
ID3D12CommandQueue_Release(driver->GraphicsQueue);
driver->GraphicsQueue->Release();
driver->GraphicsQueue = nullptr;
}
if (driver->D3D12Device)
{
ID3D12Device5_Release(driver->D3D12Device);
driver->D3D12Device->Release();
driver->D3D12Device = nullptr;
}
if (driver->DXGIAdapter)
{
IDXGIAdapter1_Release(driver->DXGIAdapter);
driver->DXGIAdapter->Release();
driver->DXGIAdapter = nullptr;
}
if (driver->DXGIFactory)
{
IDXGIFactory4_Release(driver->DXGIFactory);
driver->DXGIFactory->Release();
driver->DXGIFactory = nullptr;
}
@@ -598,6 +591,7 @@ namespace Juliet::D3D12
Log(LogLevel::Error, LogCategory::Graphics, "OOM: D3D12WindowData");
return false;
}
d3d12Driver->WindowData = windowData;
windowData->Window = window;
@@ -609,7 +603,6 @@ namespace Juliet::D3D12
}
d3d12Driver->WindowData = windowData;
// TODO : React to resize. Need event system.
return true;
}
@@ -645,12 +638,116 @@ namespace Juliet::D3D12
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)
{
#if JULIET_DEBUG
// Unit Tests for D3D12 Logic
UnitTest::TestDescriptorHeapPool();
#endif
auto driver = static_cast<D3D12Driver*>(Calloc(1, sizeof(D3D12Driver)));
@@ -671,7 +768,7 @@ namespace Juliet::D3D12
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))
{
DestroyDriver_Internal(driver);
@@ -679,43 +776,40 @@ namespace Juliet::D3D12
"checked in CheckDriver");
return nullptr;
}
IDXGIFactory1_Release(factory1);
factory1->Release();
// Query DXGI1.5 and check for monitor Tearing support
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))
{
bool isTearingSupported = false;
result = IDXGIFactory5_CheckFeatureSupport(factory5, DXGI_FEATURE_PRESENT_ALLOW_TEARING,
&isTearingSupported, sizeof(isTearingSupported));
result = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &isTearingSupported,
sizeof(isTearingSupported));
driver->IsTearingSupported = isTearingSupported;
if (FAILED(result))
{
driver->IsTearingSupported = false;
}
IDXGIFactory5_Release(factory5);
factory5->Release();
}
// 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.
// Lets support not having it for now...
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))
{
// TODO: Put into the config
static constexpr bool useLowPower = false;
result = IDXGIFactory6_EnumAdapterByGpuPreference(factory6, 0,
useLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER
: DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
IID_IDXGIAdapter1,
reinterpret_cast<void**>(&driver->DXGIAdapter));
IDXGIFactory6_Release(factory6);
result = factory6->EnumAdapterByGpuPreference(0, useLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER : DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
IID_IDXGIAdapter1, reinterpret_cast<void**>(&driver->DXGIAdapter));
factory6->Release();
}
else
{
result = IDXGIFactory4_EnumAdapters1(driver->DXGIFactory, 0, &driver->DXGIAdapter);
result = driver->DXGIFactory->EnumAdapters1(0, &driver->DXGIAdapter);
}
if (FAILED(result))
@@ -727,7 +821,7 @@ namespace Juliet::D3D12
// Adapter is setup, get all the relevant info in the descriptor
DXGI_ADAPTER_DESC1 adapterDesc;
result = IDXGIAdapter1_GetDesc1(driver->DXGIAdapter, &adapterDesc);
result = driver->DXGIAdapter->GetDesc1(&adapterDesc);
if (FAILED(result))
{
DestroyDriver_Internal(driver);
@@ -737,7 +831,7 @@ namespace Juliet::D3D12
// Driver version
LARGE_INTEGER umdVersion;
result = IDXGIAdapter1_CheckInterfaceSupport(driver->DXGIAdapter, IID_IDXGIDevice, &umdVersion);
result = driver->DXGIAdapter->CheckInterfaceSupport(IID_IDXGIDevice, &umdVersion);
if (FAILED(result))
{
DestroyDriver_Internal(driver);
@@ -784,7 +878,7 @@ namespace Juliet::D3D12
}
#endif
result = D3D12CreateDeviceFuncPtr(reinterpret_cast<IUnknown*>(driver->DXGIAdapter), kD3DFeatureLevel,
result = D3D12CreateDeviceFuncPtr(static_cast<IUnknown*>(driver->DXGIAdapter), kD3DFeatureLevel,
IID_ID3D12Device5, reinterpret_cast<void**>(&driver->D3D12Device));
if (FAILED(result))
{
@@ -793,6 +887,8 @@ namespace Juliet::D3D12
return nullptr;
}
Log(LogLevel::Message, LogCategory::Graphics, "DX12: D3D12Device Created: %p", (void*)driver->D3D12Device);
#if JULIET_DEBUG
if (enableDebug)
{
@@ -800,16 +896,14 @@ namespace Juliet::D3D12
{
return nullptr;
}
#ifdef ID3D12InfoQueue1_SUPPORTED
InitializeD3D12DebugInfoLogger(driver);
#endif
}
#endif
// Check if UMA (unified memory architecture) is available. Used on APU i think ??
D3D12_FEATURE_DATA_ARCHITECTURE architecture;
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));
if (FAILED(result))
{
@@ -823,8 +917,7 @@ namespace Juliet::D3D12
// Check "GPU Upload Heap" support (for fast uniform buffers. Not supported on my 5700xt
D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16;
driver->GPUUploadHeapSupported = false;
result = ID3D12Device5_CheckFeatureSupport(driver->D3D12Device, D3D12_FEATURE_D3D12_OPTIONS16, &options16,
sizeof(options16));
result = driver->D3D12Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS16, &options16, sizeof(options16));
if (SUCCEEDED(result))
{
driver->GPUUploadHeapSupported = options16.GPUUploadHeapSupported;
@@ -840,7 +933,7 @@ namespace Juliet::D3D12
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
queueDesc.NodeMask = 0;
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));
if (FAILED(result))
{
@@ -848,9 +941,15 @@ namespace Juliet::D3D12
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create D3D12CommandQueue: Graphics");
return nullptr;
}
ID3D12CommandQueue_SetName(driver->GraphicsQueue, L"GRAPHICS_QUEUE");
driver->GraphicsQueue->SetName(L"GRAPHICS_QUEUE");
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
D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc;
D3D12_INDIRECT_ARGUMENT_DESC indirectArgumentDesc;
@@ -861,7 +960,7 @@ namespace Juliet::D3D12
commandSignatureDesc.ByteStride = sizeof(IndirectDrawCommand);
commandSignatureDesc.NumArgumentDescs = 1;
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));
if (FAILED(result))
{
@@ -874,7 +973,7 @@ namespace Juliet::D3D12
commandSignatureDesc.ByteStride = sizeof(IndexedIndirectDrawCommand);
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));
if (FAILED(result))
{
@@ -888,7 +987,7 @@ namespace Juliet::D3D12
commandSignatureDesc.ByteStride = sizeof(IndirectDispatchCommand);
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));
if (FAILED(result))
{
@@ -984,35 +1083,42 @@ namespace Juliet::D3D12
device->AcquireSwapChainTexture = AcquireSwapChainTexture;
device->WaitAndAcquireSwapChainTexture = WaitAndAcquireSwapChainTexture;
device->GetSwapChainTextureFormat = GetSwapChainTextureFormat;
device->AcquireCommandList = AcquireCommandList;
device->SubmitCommandLists = SubmitCommandLists;
device->BeginRenderPass = BeginRenderPass;
device->EndRenderPass = EndRenderPass;
device->SetViewPort = SetViewPort;
device->SetScissorRect = SetScissorRect;
device->SetBlendConstants = SetBlendConstants;
device->SetStencilReference = SetStencilReference;
device->BindGraphicsPipeline = BindGraphicsPipeline;
device->DrawPrimitives = DrawPrimitives;
device->WaitUntilGPUIsIdle = WaitUntilGPUIsIdle;
device->SetPushConstants = SetPushConstants;
device->QueryFence = QueryFence;
device->ReleaseFence = ReleaseFence;
device->CreateShader = CreateShader;
device->DestroyShader = DestroyShader;
device->CreateGraphicsPipeline = CreateGraphicsPipeline;
device->AcquireCommandList = D3D12::AcquireCommandList;
device->SubmitCommandLists = D3D12::SubmitCommandLists;
device->BeginRenderPass = D3D12::BeginRenderPass;
device->EndRenderPass = D3D12::EndRenderPass;
device->SetViewPort = D3D12::SetViewPort;
device->SetScissorRect = D3D12::SetScissorRect;
device->SetBlendConstants = D3D12::SetBlendConstants;
device->SetStencilReference = D3D12::SetStencilReference;
device->BindGraphicsPipeline = D3D12::BindGraphicsPipeline;
device->DrawPrimitives = D3D12::DrawPrimitives;
device->DrawIndexedPrimitives = DrawIndexedPrimitives;
device->SetIndexBuffer = D3D12::SetIndexBuffer;
device->WaitUntilGPUIsIdle = D3D12::WaitUntilGPUIsIdle;
device->SetPushConstants = D3D12::SetPushConstants;
device->QueryFence = D3D12::QueryFence;
device->ReleaseFence = D3D12::ReleaseFence;
device->CreateShader = D3D12::CreateShader;
device->DestroyShader = D3D12::DestroyShader;
device->CreateGraphicsPipeline = D3D12::CreateGraphicsPipeline;
device->DestroyGraphicsPipeline = DestroyGraphicsPipeline;
device->CreateGraphicsBuffer = CreateGraphicsBuffer;
device->DestroyGraphicsBuffer = DestroyGraphicsBuffer;
device->CreateGraphicsTransferBuffer = CreateGraphicsTransferBuffer;
device->DestroyGraphicsTransferBuffer = DestroyGraphicsTransferBuffer;
device->MapGraphicsTransferBuffer = MapBuffer;
device->UnmapGraphicsTransferBuffer = UnmapBuffer;
device->CreateGraphicsBuffer = D3D12::CreateGraphicsBuffer;
device->DestroyGraphicsBuffer = D3D12::DestroyGraphicsBuffer;
device->CreateGraphicsTransferBuffer = D3D12::CreateGraphicsTransferBuffer;
device->DestroyGraphicsTransferBuffer = D3D12::DestroyGraphicsTransferBuffer;
device->MapGraphicsTransferBuffer = D3D12::MapBuffer;
device->UnmapGraphicsTransferBuffer = D3D12::UnmapBuffer;
device->CopyBuffer = CopyBuffer;
device->TransitionBufferToReadable = TransitionBufferToReadable;
device->CopyBufferToTexture = CopyBufferToTexture;
device->TransitionBufferToReadable = D3D12::TransitionBufferToReadable;
device->GetDescriptorIndex = GetDescriptorIndex;
device->CreateTexture = CreateTexture;
device->DestroyTexture = DestroyTexture;
device->GetDescriptorIndexTexture = GetDescriptorIndexTexture;
device->CreateTexture = D3D12::CreateTexture;
device->DestroyTexture = D3D12::DestroyTexture;
#if ALLOW_SHADER_HOT_RELOAD
device->UpdateGraphicsPipelineShaders = UpdateGraphicsPipelineShaders;
@@ -1024,7 +1130,8 @@ namespace Juliet::D3D12
driver->GraphicsDevice = device;
// 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;
}

View File

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

View File

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

View File

@@ -17,21 +17,13 @@
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#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 <Graphics/D3D12/AgilitySDK/d3d12.h>
#if JULIET_DEBUG
#include <dxgidebug.h>
#endif
//#include <dxgi.h>
#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
#define IDXGIINFOQUEUE_SUPPORTED
#endif

View File

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

View File

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

View File

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

View File

@@ -35,12 +35,12 @@ namespace Juliet::D3D12
if (d3d12driver->GraphicsQueue)
{
// 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.
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))
{
LogError(d3d12driver->D3D12Device, "Setting fence event failed!", result);
@@ -82,7 +82,7 @@ namespace Juliet::D3D12
{
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))
{
LogError(d3d12driver->D3D12Device, "Setting fence event failed!", res);
@@ -104,7 +104,7 @@ namespace Juliet::D3D12
// Clean up
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)
{
result &= Internal::CleanCommandList(d3d12driver, d3d12driver->SubmittedCommandLists[idx], false);
@@ -166,7 +166,7 @@ namespace Juliet::D3D12
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)
{
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));
if (FAILED(result))
{
@@ -190,7 +190,7 @@ namespace Juliet::D3D12
fence = static_cast<D3D12Fence*>(Calloc(1, sizeof(D3D12Fence)));
if (!fence)
{
ID3D12Fence_Release(handle);
handle->Release();
return nullptr;
}
@@ -202,7 +202,7 @@ namespace Juliet::D3D12
{
fence = driver->AvailableFences[driver->AvailableFenceCount - 1];
driver->AvailableFenceCount -= 1;
ID3D12Fence_Signal(fence->Handle, D3D12_FENCE_UNSIGNALED_VALUE);
fence->Handle->Signal(D3D12_FENCE_UNSIGNALED_VALUE);
}
fence->ReferenceCount += 1;
@@ -213,7 +213,7 @@ namespace Juliet::D3D12
{
if (fence->Handle)
{
ID3D12Fence_Release(fence->Handle);
fence->Handle->Release();
}
if (fence->Event)

View File

@@ -426,7 +426,7 @@ namespace Juliet::D3D12
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,
reinterpret_cast<void**>(&resource));
@@ -477,7 +477,7 @@ namespace Juliet::D3D12
rtvDesc.Format = desc.Format;
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
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)
@@ -488,12 +488,48 @@ namespace Juliet::D3D12
dsvDesc.Format = Internal::ConvertToD3D12DepthFormat(createInfo.Format);
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
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);
}
void DestroyTexture(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture)
@@ -517,7 +553,7 @@ namespace Juliet::D3D12
Internal::ReleaseStagingDescriptor(d3d12Driver, sub.DSVHandle);
}
}
ID3D12Resource_Release(d3d12Texture->Resource);
d3d12Texture->Resource->Release();
Free(d3d12Texture->Subresources);
Free(d3d12Texture);
}

View File

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

View File

@@ -4,6 +4,8 @@
#include <Core/Logging/LogTypes.h>
#include <Graphics/Graphics.h>
#include <Graphics/GraphicsDevice.h>
#include <Core/ImGui/ImGuiTests.h>
namespace Juliet
{
@@ -57,9 +59,11 @@ namespace Juliet
{
if (GraphicsDevice* newDevice = chosenFactory->CreateGraphicsDevice(config.EnableDebug))
{
newDevice->Name = chosenFactory->Name;
return newDevice;
}
}
return nullptr;
}
@@ -259,6 +263,16 @@ namespace Juliet
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)
{
auto* commandList = reinterpret_cast<GPUPass*>(renderPass.Get())->CommandList;
@@ -275,6 +289,21 @@ namespace Juliet
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,
uint32 numConstants, const void* constants)
{
@@ -366,10 +395,21 @@ namespace Juliet
void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset)
{
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get());
header->Device->CopyBuffer(commandList, dst, src, size, dstOffset, srcOffset);
auto* headers = reinterpret_cast<CommandListHeader*>(commandList.Get());
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)
{
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get());
@@ -378,9 +418,15 @@ namespace Juliet
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)
{
device->DestroyGraphicsBuffer(buffer);

View File

@@ -66,10 +66,16 @@ namespace Juliet
void (*SetScissorRect)(NonNullPtr<CommandList> commandList, const Rectangle& viewPort);
void (*SetBlendConstants)(NonNullPtr<CommandList> commandList, FColor blendConstants);
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 (*DrawPrimitives)(NonNullPtr<CommandList> commandList, uint32 numVertices, uint32 numInstances,
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,
uint32 numConstants, const void* constants);
@@ -104,8 +110,12 @@ namespace Juliet
void (*UnmapGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
void (*CopyBuffer)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
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);
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";
GPUDriver* Driver = nullptr;