Compare commits
6 Commits
7e8aaaa891
...
8326772558
| Author | SHA1 | Date | |
|---|---|---|---|
| 8326772558 | |||
| cc9bbf0ef5 | |||
| 857f8c4e69 | |||
| ed9482b8f8 | |||
| f1b7f8eb29 | |||
| ee194b2d69 |
@@ -123,46 +123,51 @@
|
||||
<ClInclude Include="include\Core\JulietInit.h"/>
|
||||
<ClInclude Include="include\Core\Logging\LogManager.h"/>
|
||||
<ClInclude Include="include\Core\Logging\LogTypes.h"/>
|
||||
<ClInclude Include="include\Core\Memory\Allocator.h"/>
|
||||
<ClInclude Include="include\Core\Memory\Utils.h"/>
|
||||
<ClInclude Include="include\Core\Networking\IPAddress.h"/>
|
||||
<ClInclude Include="include\Core\Networking\NetworkPacket.h"/>
|
||||
<ClInclude Include="include\Core\Networking\Socket.h"/>
|
||||
<ClInclude Include="include\Core\Networking\SocketHandle.h"/>
|
||||
<ClInclude Include="include\Core\Networking\TcpListener.h"/>
|
||||
<ClInclude Include="include\Core\Networking\TcpSocket.h"/>
|
||||
<ClInclude Include="include\Core\Thread\Thread.h"/>
|
||||
<ClInclude Include="include\Engine\Class.h"/>
|
||||
<ClInclude Include="include\Engine\Engine.h"/>
|
||||
<ClInclude Include="include\Graphics\Graphics.h"/>
|
||||
<ClInclude Include="include\Graphics\GraphicsConfig.h"/>
|
||||
<ClInclude Include="include\Core\Math\Shape.h" />
|
||||
<ClInclude Include="include\Core\Memory\Allocator.h" />
|
||||
<ClInclude Include="include\Core\Memory\Utils.h" />
|
||||
<ClInclude Include="include\Core\Networking\IPAddress.h" />
|
||||
<ClInclude Include="include\Core\Networking\NetworkPacket.h" />
|
||||
<ClInclude Include="include\Core\Networking\Socket.h" />
|
||||
<ClInclude Include="include\Core\Networking\SocketHandle.h" />
|
||||
<ClInclude Include="include\Core\Networking\TcpListener.h" />
|
||||
<ClInclude Include="include\Core\Networking\TcpSocket.h" />
|
||||
<ClInclude Include="include\Core\Thread\Thread.h" />
|
||||
<ClInclude Include="include\Engine\Class.h" />
|
||||
<ClInclude Include="include\Engine\Engine.h" />
|
||||
<ClInclude Include="include\Graphics\Colors.h" />
|
||||
<ClInclude Include="include\Graphics\Graphics.h" />
|
||||
<ClInclude Include="include\Graphics\GraphicsConfig.h" />
|
||||
<ClInclude Include="include\Graphics\RenderPass.h" />
|
||||
<ClInclude Include="include\Graphics\Texture.h" />
|
||||
<ClInclude Include="include\Juliet.h"/>
|
||||
<ClInclude Include="include\pch.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Display\DisplayDevice.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Display\Display_Private.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Display\Win32\Win32Window.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Display\Window.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Event\KeyboardMapping.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Event\Keyboard_Private.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Event\Mouse_Private.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Event\Win32ScanCode.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h"/>
|
||||
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h"/>
|
||||
<ClInclude Include="src\Core\HAL\Win32.h"/>
|
||||
<ClInclude Include="include\Juliet.h" />
|
||||
<ClInclude Include="include\pch.h" />
|
||||
<ClInclude Include="src\Core\HAL\Display\DisplayDevice.h" />
|
||||
<ClInclude Include="src\Core\HAL\Display\Display_Private.h" />
|
||||
<ClInclude Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.h" />
|
||||
<ClInclude Include="src\Core\HAL\Display\Win32\Win32Window.h" />
|
||||
<ClInclude Include="src\Core\HAL\Display\Window.h" />
|
||||
<ClInclude Include="src\Core\HAL\Event\KeyboardMapping.h" />
|
||||
<ClInclude Include="src\Core\HAL\Event\Keyboard_Private.h" />
|
||||
<ClInclude Include="src\Core\HAL\Event\Mouse_Private.h" />
|
||||
<ClInclude Include="src\Core\HAL\Event\Win32ScanCode.h" />
|
||||
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h" />
|
||||
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h" />
|
||||
<ClInclude Include="src\Core\HAL\Win32.h" />
|
||||
<ClInclude Include="src\Graphics\D3D12\D3D12Common.h" />
|
||||
<ClInclude Include="src\Graphics\D3D12\D3D12RenderPass.h" />
|
||||
<ClInclude Include="src\Graphics\D3D12\D3D12Synchronization.h" />
|
||||
<ClInclude Include="src\Graphics\D3D12\D3D12Texture.h" />
|
||||
<ClInclude Include="src\Graphics\D3D12\DX12CommandList.h"/>
|
||||
<ClInclude Include="src\Graphics\D3D12\DX12GraphicsDevice.h"/>
|
||||
<ClInclude Include="src\Graphics\D3D12\DX12Includes.h"/>
|
||||
<ClInclude Include="src\Graphics\D3D12\DX12SwapChain.h"/>
|
||||
<ClInclude Include="src\Graphics\D3D12\DX12Utils.h"/>
|
||||
<ClInclude Include="src\Graphics\GraphicsDevice.h"/>
|
||||
<ClInclude Include="src\Graphics\D3D12\DX12CommandList.h" />
|
||||
<ClInclude Include="src\Graphics\D3D12\DX12GraphicsDevice.h" />
|
||||
<ClInclude Include="src\Graphics\D3D12\DX12Includes.h" />
|
||||
<ClInclude Include="src\Graphics\D3D12\DX12SwapChain.h" />
|
||||
<ClInclude Include="src\Graphics\D3D12\DX12Utils.h" />
|
||||
<ClInclude Include="src\Graphics\GraphicsDevice.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\Core\Application\ApplicationManager.cpp"/>
|
||||
<ClCompile Include="src\Core\Common\CoreUtils.cpp"/>
|
||||
<ClCompile Include="src\Core\Application\ApplicationManager.cpp" />
|
||||
<ClCompile Include="src\Core\Common\CoreUtils.cpp" />
|
||||
<ClCompile Include="src\Core\DynLib\Win32\DynamicLibrary.cpp">
|
||||
<RuntimeLibrary>MultiThreadedDebugDll</RuntimeLibrary>
|
||||
<Optimization>Disabled</Optimization>
|
||||
@@ -217,29 +222,31 @@
|
||||
<MSCVersion>Default</MSCVersion>
|
||||
<AdditionalOptions>--target=amd64-pc-windows-msvc</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Core\HAL\Display\Display.cpp"/>
|
||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayDevice.cpp"/>
|
||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.cpp"/>
|
||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32Window.cpp"/>
|
||||
<ClCompile Include="src\Core\HAL\Event\Keyboard.cpp"/>
|
||||
<ClCompile Include="src\Core\HAL\Event\KeyboardMapping.cpp"/>
|
||||
<ClCompile Include="src\Core\HAL\Event\Mouse.cpp"/>
|
||||
<ClCompile Include="src\Core\HAL\Event\SystemEvent.cpp"/>
|
||||
<ClCompile Include="src\Core\HAL\Event\WindowEvent.cpp"/>
|
||||
<ClCompile Include="src\Core\Juliet.cpp"/>
|
||||
<ClCompile Include="src\Core\Logging\LogManager.cpp"/>
|
||||
<ClCompile Include="src\Core\Memory\Allocator.cpp"/>
|
||||
<ClCompile Include="src\Core\Networking\NetworkPacket.cpp"/>
|
||||
<ClCompile Include="src\Core\Networking\Socket.cpp"/>
|
||||
<ClCompile Include="src\Core\Networking\TcpListener.cpp"/>
|
||||
<ClCompile Include="src\Core\Networking\TcpSocket.cpp"/>
|
||||
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp"/>
|
||||
<ClCompile Include="src\Engine\Engine.cpp"/>
|
||||
<ClCompile Include="src\Core\HAL\Display\Display.cpp" />
|
||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayDevice.cpp" />
|
||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.cpp" />
|
||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32Window.cpp" />
|
||||
<ClCompile Include="src\Core\HAL\Event\Keyboard.cpp" />
|
||||
<ClCompile Include="src\Core\HAL\Event\KeyboardMapping.cpp" />
|
||||
<ClCompile Include="src\Core\HAL\Event\Mouse.cpp" />
|
||||
<ClCompile Include="src\Core\HAL\Event\SystemEvent.cpp" />
|
||||
<ClCompile Include="src\Core\HAL\Event\WindowEvent.cpp" />
|
||||
<ClCompile Include="src\Core\Juliet.cpp" />
|
||||
<ClCompile Include="src\Core\Logging\LogManager.cpp" />
|
||||
<ClCompile Include="src\Core\Memory\Allocator.cpp" />
|
||||
<ClCompile Include="src\Core\Networking\NetworkPacket.cpp" />
|
||||
<ClCompile Include="src\Core\Networking\Socket.cpp" />
|
||||
<ClCompile Include="src\Core\Networking\TcpListener.cpp" />
|
||||
<ClCompile Include="src\Core\Networking\TcpSocket.cpp" />
|
||||
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp" />
|
||||
<ClCompile Include="src\Engine\Engine.cpp" />
|
||||
<ClCompile Include="src\Graphics\D3D12\D3D12Common.cpp" />
|
||||
<ClCompile Include="src\Graphics\D3D12\D3D12RenderPass.cpp" />
|
||||
<ClCompile Include="src\Graphics\D3D12\D3D12Synchronization.cpp" />
|
||||
<ClCompile Include="src\Graphics\D3D12\D3D12Texture.cpp" />
|
||||
<ClCompile Include="src\Graphics\D3D12\DX12CommandList.cpp"/>
|
||||
<ClCompile Include="src\Graphics\D3D12\DX12GraphicsDevice.cpp"/>
|
||||
<ClCompile Include="src\Graphics\D3D12\DX12SwapChain.cpp"/>
|
||||
<ClCompile Include="src\Graphics\D3D12\DX12CommandList.cpp" />
|
||||
<ClCompile Include="src\Graphics\D3D12\DX12GraphicsDevice.cpp" />
|
||||
<ClCompile Include="src\Graphics\D3D12\DX12SwapChain.cpp" />
|
||||
<ClCompile Include="src\Graphics\D3D12\DX12Utils.cpp" />
|
||||
<ClCompile Include="src\Graphics\Graphics.cpp">
|
||||
<RuntimeLibrary>MultiThreadedDebugDll</RuntimeLibrary>
|
||||
@@ -301,7 +308,7 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="include\Core\Thread\Mutex.h"/>
|
||||
<Content Include="include\Core\Thread\Mutex.h" />
|
||||
<Content Include="src\TODO.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
using uint8 = uint8_t;
|
||||
using uint16 = uint16_t;
|
||||
@@ -24,3 +25,14 @@ struct ByteBuffer
|
||||
};
|
||||
|
||||
using FunctionPtr = auto (*)(void) -> void;
|
||||
|
||||
// Limits
|
||||
template <typename Type>
|
||||
consteval Type MaxValueOf()
|
||||
{
|
||||
return std::numeric_limits<Type>::max();
|
||||
}
|
||||
constexpr uint32 uint8Max = MaxValueOf<uint8>();
|
||||
constexpr uint32 uint16Max = MaxValueOf<uint16>();
|
||||
constexpr uint32 uint32Max = MaxValueOf<uint32>();
|
||||
constexpr uint32 uint64Max = MaxValueOf<uint64>();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <Core/Common/CoreTypes.h>
|
||||
#include <Juliet.h>
|
||||
|
||||
@@ -24,7 +25,8 @@ namespace Juliet
|
||||
extern void JULIET_API JulietAssert(const char* expression);
|
||||
|
||||
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
|
||||
#define ZeroArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), Pointer)
|
||||
#define ZeroArray(array) ZeroSize(sizeof((array)), (array))
|
||||
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), Pointer)
|
||||
inline void ZeroSize(size_t size, void* ptr)
|
||||
{
|
||||
auto Byte = (uint8*)ptr;
|
||||
@@ -35,4 +37,30 @@ namespace Juliet
|
||||
}
|
||||
|
||||
#define MemCopy memcpy
|
||||
|
||||
template <typename Type>
|
||||
constexpr Type Min(Type lhs, Type rhs)
|
||||
{
|
||||
return rhs < lhs ? rhs : lhs;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
constexpr Type Max(Type lhs, Type rhs)
|
||||
{
|
||||
return lhs < rhs ? rhs : lhs;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
constexpr Type Clamp(Type val, Type min, Type max)
|
||||
{
|
||||
if (val < min)
|
||||
{
|
||||
return min;
|
||||
}
|
||||
if (val > max)
|
||||
{
|
||||
return max;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
} // namespace Juliet
|
||||
|
||||
12
Juliet/include/Core/Math/Shape.h
Normal file
12
Juliet/include/Core/Math/Shape.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
struct Rectangle
|
||||
{
|
||||
int32 X;
|
||||
int32 Y;
|
||||
int32 Width;
|
||||
int32 Height;
|
||||
};
|
||||
}
|
||||
16
Juliet/include/Graphics/Colors.h
Normal file
16
Juliet/include/Graphics/Colors.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
template <typename Type>
|
||||
struct ColorType
|
||||
{
|
||||
Type R;
|
||||
Type G;
|
||||
Type B;
|
||||
Type A;
|
||||
};
|
||||
|
||||
using FColor = ColorType<float>;
|
||||
using Color = ColorType<uint8>;
|
||||
} // namespace Juliet
|
||||
@@ -1,15 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <core/Common/NonNullPtr.h>
|
||||
#include <Core/Common/NonNullPtr.h>
|
||||
#include <Core/HAL/Display/Display.h>
|
||||
#include <Core/Math/Shape.h>
|
||||
#include <Graphics/GraphicsConfig.h>
|
||||
#include <Graphics/Texture.h>
|
||||
#include <Graphics/RenderPass.h>
|
||||
#include <Juliet.h>
|
||||
|
||||
// Graphics Interface
|
||||
namespace Juliet
|
||||
{
|
||||
struct Window;
|
||||
// Opaque types
|
||||
struct CommandList;
|
||||
struct GraphicsDevice;
|
||||
struct Fence;
|
||||
|
||||
// Parameters of an indirect draw command
|
||||
struct IndirectDrawCommand
|
||||
@@ -65,8 +69,15 @@ namespace Juliet
|
||||
Immediate
|
||||
};
|
||||
|
||||
// Opaque types
|
||||
struct CommandList;
|
||||
struct GraphicsViewPort
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Width;
|
||||
float Height;
|
||||
float MinDepth;
|
||||
float MaxDepth;
|
||||
};
|
||||
|
||||
extern JULIET_API GraphicsDevice* CreateGraphicsDevice(GraphicsConfig config);
|
||||
extern JULIET_API void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device);
|
||||
@@ -81,5 +92,16 @@ namespace Juliet
|
||||
|
||||
// Command List
|
||||
extern JULIET_API CommandList* AcquireCommandList(NonNullPtr<GraphicsDevice> device, QueueType queueType = QueueType::Graphics);
|
||||
extern JULIET_API void SubmitCommandLists(NonNullPtr<GraphicsDevice> device);
|
||||
extern JULIET_API void SubmitCommandLists(NonNullPtr<CommandList> commandList);
|
||||
|
||||
// RenderPass
|
||||
extern JULIET_API RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, ColorTargetInfo& colorTargetInfo);
|
||||
extern JULIET_API RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList,
|
||||
NonNullPtr<const ColorTargetInfo> colorTargetInfos, uint32 colorTargetInfoCount);
|
||||
extern JULIET_API void EndRenderPass(NonNullPtr<RenderPass> renderPass);
|
||||
|
||||
extern JULIET_API void SetGraphicsViewPort(NonNullPtr<RenderPass> renderPass, const GraphicsViewPort& viewPort);
|
||||
extern JULIET_API void SetScissorRect(NonNullPtr<RenderPass> renderPass, const Rectangle& rectangle);
|
||||
extern JULIET_API void SetBlendConstants(NonNullPtr<RenderPass> renderPass, FColor blendConstants);
|
||||
extern JULIET_API void SetStencilReference(NonNullPtr<RenderPass> renderPass, uint8 reference);
|
||||
} // namespace Juliet
|
||||
|
||||
46
Juliet/include/Graphics/RenderPass.h
Normal file
46
Juliet/include/Graphics/RenderPass.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <Graphics/Colors.h>
|
||||
#include <Graphics/Texture.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
enum struct LoadOperation : uint8
|
||||
{
|
||||
Load, // Load the texture from memory (preserve)
|
||||
Clear, // Clear the texture
|
||||
Ignore // Ignore the content of the texture (undefined)
|
||||
};
|
||||
|
||||
enum struct StoreOperation : uint8
|
||||
{
|
||||
Store, // Store the result of the render pass into memory
|
||||
Ignore, // Whatever is generated is ignored (undefined)
|
||||
Resolve, // Resolve MipMaps into non mip map texture. Discard MipMap content
|
||||
ResolveAndStore // Same but store the MipMap content to memory
|
||||
};
|
||||
|
||||
struct ColorTargetInfo
|
||||
{
|
||||
Texture* TargetTexture;
|
||||
uint32 MipLevel;
|
||||
union
|
||||
{
|
||||
uint32 DepthPlane;
|
||||
uint32 LayerIndex;
|
||||
};
|
||||
bool CycleTexture; // Whether the texture should be cycled if already bound (and load operation != LOAD)
|
||||
|
||||
Texture* ResolveTexture;
|
||||
uint32 ResolveMipLevel;
|
||||
uint32 ResolveLayerIndex;
|
||||
bool CycleResolveTexture;
|
||||
|
||||
FColor ClearColor;
|
||||
LoadOperation LoadOperation;
|
||||
StoreOperation StoreOperation;
|
||||
};
|
||||
|
||||
// Opaque Type
|
||||
struct RenderPass;
|
||||
} // namespace Juliet
|
||||
@@ -161,9 +161,9 @@ namespace Juliet
|
||||
// Create Information structs
|
||||
struct TextureCreateInfo
|
||||
{
|
||||
TextureType Type;
|
||||
TextureFormat Format;
|
||||
TextureUsageFlag Flags;
|
||||
TextureType Type;
|
||||
TextureFormat Format;
|
||||
TextureUsageFlag Flags;
|
||||
TextureSampleCount SampleCount;
|
||||
|
||||
uint32 Width;
|
||||
@@ -171,10 +171,11 @@ namespace Juliet
|
||||
union
|
||||
{
|
||||
uint32 LayerCount;
|
||||
uint32 Depth;
|
||||
uint32 DepthPlane;
|
||||
}; // LayerCount is used in 2d array textures and Depth for 3d textures
|
||||
uint32 MipLevelCount;
|
||||
};
|
||||
|
||||
// Opaque Type
|
||||
struct Texture;
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -58,3 +58,6 @@
|
||||
#define ANSI_ONLY
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Juliet::D3D12
|
||||
bool ExtendStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptorPool& pool)
|
||||
{
|
||||
D3D12DescriptorHeap* heap =
|
||||
CreateDescriptorHeap(driver, pool.Heaps[0]->HeapType, kStagingHeapDescriptorExpectedCount, true);
|
||||
Internal::CreateDescriptorHeap(driver, pool.Heaps[0]->HeapType, kStagingHeapDescriptorExpectedCount, true);
|
||||
if (!heap)
|
||||
{
|
||||
return false;
|
||||
@@ -47,122 +47,126 @@ namespace Juliet::D3D12
|
||||
}
|
||||
} // namespace
|
||||
|
||||
D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging)
|
||||
namespace Internal
|
||||
{
|
||||
ID3D12DescriptorHeap* handle;
|
||||
|
||||
auto heap = static_cast<D3D12DescriptorHeap*>(Calloc(1, sizeof(D3D12DescriptorHeap)));
|
||||
if (!heap)
|
||||
D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
uint32 count, bool isStaging)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
ID3D12DescriptorHeap* handle;
|
||||
|
||||
heap->CurrentDescriptorIndex = 0;
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC heapDesc;
|
||||
heapDesc.NumDescriptors = count;
|
||||
heapDesc.Type = type;
|
||||
heapDesc.Flags = isStaging ? D3D12_DESCRIPTOR_HEAP_FLAG_NONE : D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
heapDesc.NodeMask = 0;
|
||||
|
||||
HRESULT result =
|
||||
ID3D12Device_CreateDescriptorHeap(driver->D3D12Device, &heapDesc, IID_ID3D12DescriptorHeap, (void**)&handle);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to create descriptor heap!", result);
|
||||
DestroyDescriptorHeap(heap);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
heap->Handle = handle;
|
||||
heap->HeapType = type;
|
||||
heap->MaxDescriptors = count;
|
||||
heap->Staging = isStaging;
|
||||
heap->DescriptorSize = ID3D12Device_GetDescriptorHandleIncrementSize(driver->D3D12Device, type);
|
||||
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(handle, &heap->DescriptorHeapCPUStart);
|
||||
if (!isStaging)
|
||||
{
|
||||
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(handle, &heap->DescriptorHeapGPUStart);
|
||||
}
|
||||
|
||||
return heap;
|
||||
}
|
||||
|
||||
void DestroyDescriptorHeap(NonNullPtr<D3D12DescriptorHeap> heap)
|
||||
{
|
||||
if (heap->Handle)
|
||||
{
|
||||
ID3D12DescriptorHeap_Release(heap->Handle);
|
||||
}
|
||||
Free(heap.Get());
|
||||
}
|
||||
|
||||
D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type)
|
||||
{
|
||||
D3D12DescriptorHeap* heap = CreateDescriptorHeap(driver, type, kStagingHeapDescriptorExpectedCount, true);
|
||||
if (!heap)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pool = static_cast<D3D12StagingDescriptorPool*>(Calloc(1, sizeof(D3D12StagingDescriptorPool)));
|
||||
|
||||
// First create the heaps
|
||||
pool->HeapCount = 1;
|
||||
pool->Heaps = static_cast<D3D12DescriptorHeap**>(Malloc(sizeof(D3D12DescriptorHeap*)));
|
||||
pool->Heaps[0] = heap;
|
||||
|
||||
pool->FreeDescriptorCapacity = kStagingHeapDescriptorExpectedCount;
|
||||
pool->FreeDescriptorCount = kStagingHeapDescriptorExpectedCount;
|
||||
pool->FreeDescriptors =
|
||||
static_cast<D3D12StagingDescriptor*>(Malloc(kStagingHeapDescriptorExpectedCount * sizeof(D3D12StagingDescriptor)));
|
||||
|
||||
InitStagingDescriptorPool(heap, pool);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
bool AssignStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12StagingDescriptor& outDescriptor)
|
||||
{
|
||||
// TODO: Make it thread safe
|
||||
D3D12StagingDescriptor* descriptor = nullptr;
|
||||
D3D12StagingDescriptorPool* pool = driver->StagingDescriptorPools[type];
|
||||
|
||||
if (pool->FreeDescriptorCount == 0)
|
||||
{
|
||||
if (!ExtendStagingDescriptorPool(driver, *pool))
|
||||
auto heap = static_cast<D3D12DescriptorHeap*>(Calloc(1, sizeof(D3D12DescriptorHeap)));
|
||||
if (!heap)
|
||||
{
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
heap->CurrentDescriptorIndex = 0;
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC heapDesc;
|
||||
heapDesc.NumDescriptors = count;
|
||||
heapDesc.Type = type;
|
||||
heapDesc.Flags = isStaging ? D3D12_DESCRIPTOR_HEAP_FLAG_NONE : D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
heapDesc.NodeMask = 0;
|
||||
|
||||
HRESULT result =
|
||||
ID3D12Device_CreateDescriptorHeap(driver->D3D12Device, &heapDesc, IID_ID3D12DescriptorHeap, (void**)&handle);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to create descriptor heap!", result);
|
||||
DestroyDescriptorHeap(heap);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
heap->Handle = handle;
|
||||
heap->HeapType = type;
|
||||
heap->MaxDescriptors = count;
|
||||
heap->Staging = isStaging;
|
||||
heap->DescriptorSize = ID3D12Device_GetDescriptorHandleIncrementSize(driver->D3D12Device, type);
|
||||
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(handle, &heap->DescriptorHeapCPUStart);
|
||||
if (!isStaging)
|
||||
{
|
||||
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(handle, &heap->DescriptorHeapGPUStart);
|
||||
}
|
||||
|
||||
return heap;
|
||||
}
|
||||
|
||||
void DestroyDescriptorHeap(NonNullPtr<D3D12DescriptorHeap> heap)
|
||||
{
|
||||
if (heap->Handle)
|
||||
{
|
||||
ID3D12DescriptorHeap_Release(heap->Handle);
|
||||
}
|
||||
Free(heap.Get());
|
||||
}
|
||||
|
||||
D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type)
|
||||
{
|
||||
D3D12DescriptorHeap* heap = CreateDescriptorHeap(driver, type, kStagingHeapDescriptorExpectedCount, true);
|
||||
if (!heap)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pool = static_cast<D3D12StagingDescriptorPool*>(Calloc(1, sizeof(D3D12StagingDescriptorPool)));
|
||||
|
||||
// First create the heaps
|
||||
pool->HeapCount = 1;
|
||||
pool->Heaps = static_cast<D3D12DescriptorHeap**>(Malloc(sizeof(D3D12DescriptorHeap*)));
|
||||
pool->Heaps[0] = heap;
|
||||
|
||||
pool->FreeDescriptorCapacity = kStagingHeapDescriptorExpectedCount;
|
||||
pool->FreeDescriptorCount = kStagingHeapDescriptorExpectedCount;
|
||||
pool->FreeDescriptors = static_cast<D3D12StagingDescriptor*>(
|
||||
Malloc(kStagingHeapDescriptorExpectedCount * sizeof(D3D12StagingDescriptor)));
|
||||
|
||||
InitStagingDescriptorPool(heap, pool);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
bool AssignStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12StagingDescriptor& outDescriptor)
|
||||
{
|
||||
// TODO: Make it thread safe
|
||||
D3D12StagingDescriptor* descriptor = nullptr;
|
||||
D3D12StagingDescriptorPool* pool = driver->StagingDescriptorPools[type];
|
||||
|
||||
if (pool->FreeDescriptorCount == 0)
|
||||
{
|
||||
if (!ExtendStagingDescriptorPool(driver, *pool))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
descriptor = &pool->FreeDescriptors[pool->FreeDescriptorCount - 1];
|
||||
MemCopy(&outDescriptor, descriptor, sizeof(D3D12StagingDescriptor));
|
||||
pool->FreeDescriptorCount -= 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor)
|
||||
{
|
||||
D3D12StagingDescriptorPool* pool = cpuDescriptor.Pool;
|
||||
|
||||
if (pool != nullptr)
|
||||
{
|
||||
MemCopy(&pool->FreeDescriptors[pool->FreeDescriptorCount], &cpuDescriptor, sizeof(D3D12StagingDescriptor));
|
||||
pool->FreeDescriptorCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
descriptor = &pool->FreeDescriptors[pool->FreeDescriptorCount - 1];
|
||||
MemCopy(&outDescriptor, descriptor, sizeof(D3D12StagingDescriptor));
|
||||
pool->FreeDescriptorCount -= 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor)
|
||||
{
|
||||
D3D12StagingDescriptorPool* pool = cpuDescriptor.Pool;
|
||||
|
||||
if (pool != nullptr)
|
||||
void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool)
|
||||
{
|
||||
MemCopy(&pool->FreeDescriptors[pool->FreeDescriptorCount], &cpuDescriptor, sizeof(D3D12StagingDescriptor));
|
||||
pool->FreeDescriptorCount += 1;
|
||||
}
|
||||
}
|
||||
for (uint32 i = 0; i < pool->HeapCount; i += 1)
|
||||
{
|
||||
DestroyDescriptorHeap(pool->Heaps[i]);
|
||||
}
|
||||
|
||||
void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool)
|
||||
{
|
||||
for (uint32 i = 0; i < pool->HeapCount; i += 1)
|
||||
{
|
||||
DestroyDescriptorHeap(pool->Heaps[i]);
|
||||
Free(pool->Heaps);
|
||||
Free(pool->FreeDescriptors);
|
||||
Free(pool.Get());
|
||||
}
|
||||
|
||||
Free(pool->Heaps);
|
||||
Free(pool->FreeDescriptors);
|
||||
Free(pool.Get());
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
// Inspired (copy pasted a lot) by SDL GPU
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
struct D3D12Driver;
|
||||
// Forward declare
|
||||
struct D3D12Driver;
|
||||
struct D3D12StagingDescriptor;
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/direct3d12/descriptor-heaps
|
||||
@@ -51,13 +51,16 @@ namespace Juliet::D3D12
|
||||
uint32 CpuHandleIndex;
|
||||
};
|
||||
|
||||
extern D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
uint32 count, bool isStaging);
|
||||
extern void DestroyDescriptorHeap(NonNullPtr<D3D12DescriptorHeap> heap);
|
||||
namespace Internal
|
||||
{
|
||||
extern D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging);
|
||||
extern void DestroyDescriptorHeap(NonNullPtr<D3D12DescriptorHeap> heap);
|
||||
|
||||
extern D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type);
|
||||
extern bool AssignStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
D3D12StagingDescriptor& outDescriptor);
|
||||
extern void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor);
|
||||
extern void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool);
|
||||
extern D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type);
|
||||
extern bool AssignStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
D3D12StagingDescriptor& outDescriptor);
|
||||
extern void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor);
|
||||
extern void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool);
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
160
Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp
Normal file
160
Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#include <pch.h>
|
||||
|
||||
#include <Graphics/D3D12/D3D12RenderPass.h>
|
||||
#include <Graphics/D3D12/D3D12Texture.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
void BeginRenderPass(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos, uint32 colorTargetInfoCount)
|
||||
{
|
||||
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||
|
||||
uint32 frameBufferWidth = uint32Max;
|
||||
uint32 frameBufferHeight = uint32Max;
|
||||
|
||||
for (uint32 idx = 0; idx < colorTargetInfoCount; ++idx)
|
||||
{
|
||||
auto* container = reinterpret_cast<D3D12TextureContainer*>(colorTargetInfos[idx].TargetTexture);
|
||||
uint32 width = container->Header.CreateInfo.Width >> colorTargetInfos[idx].MipLevel;
|
||||
uint32 height = container->Header.CreateInfo.Height >> colorTargetInfos[idx].MipLevel;
|
||||
|
||||
// Scale the framebuffer to fit the smallest target.
|
||||
frameBufferWidth = Min(width, frameBufferWidth);
|
||||
frameBufferHeight = Min(height, frameBufferHeight);
|
||||
}
|
||||
|
||||
// TODO : Depth Stencil and DSV
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE RTVs[GPUDriver::kMaxColorTargetInfo];
|
||||
for (uint32 idx = 0; idx < colorTargetInfoCount; ++idx)
|
||||
{
|
||||
auto* container = reinterpret_cast<D3D12TextureContainer*>(colorTargetInfos[idx].TargetTexture);
|
||||
D3D12TextureSubresource* subresource = Internal::PrepareTextureSubresourceForWrite(
|
||||
d3d12CommandList, container,
|
||||
container->Header.CreateInfo.Type == TextureType::Texture_3D ? 0 : colorTargetInfos[idx].LayerIndex,
|
||||
colorTargetInfos[idx].MipLevel, colorTargetInfos[idx].CycleTexture, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
|
||||
uint32 RTVIndex = container->Header.CreateInfo.Type == TextureType::Texture_3D ? colorTargetInfos[idx].DepthPlane : 0;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtv = subresource->RTVHandles[RTVIndex].CpuHandle;
|
||||
|
||||
if (colorTargetInfos[idx].LoadOperation == LoadOperation::Clear)
|
||||
{
|
||||
float clearColor[4];
|
||||
clearColor[0] = colorTargetInfos[idx].ClearColor.R;
|
||||
clearColor[1] = colorTargetInfos[idx].ClearColor.G;
|
||||
clearColor[2] = colorTargetInfos[idx].ClearColor.B;
|
||||
clearColor[3] = colorTargetInfos[idx].ClearColor.A;
|
||||
|
||||
ID3D12GraphicsCommandList6_ClearRenderTargetView(d3d12CommandList->GraphicsCommandList.CommandList, rtv,
|
||||
clearColor, 0, nullptr);
|
||||
}
|
||||
|
||||
RTVs[idx] = rtv;
|
||||
d3d12CommandList->ColorTargetSubresources[idx] = subresource;
|
||||
|
||||
// TODO: TrackTexture
|
||||
|
||||
if (colorTargetInfos[idx].StoreOperation == StoreOperation::Resolve ||
|
||||
colorTargetInfos[idx].StoreOperation == StoreOperation::ResolveAndStore)
|
||||
{
|
||||
auto resolveContainer = reinterpret_cast<D3D12TextureContainer*>(colorTargetInfos[idx].ResolveTexture);
|
||||
D3D12TextureSubresource* resolveSubresource =
|
||||
Internal::PrepareTextureSubresourceForWrite(d3d12CommandList, resolveContainer,
|
||||
colorTargetInfos[idx].ResolveLayerIndex,
|
||||
colorTargetInfos[idx].ResolveMipLevel,
|
||||
colorTargetInfos[idx].CycleResolveTexture,
|
||||
D3D12_RESOURCE_STATE_RESOLVE_DEST);
|
||||
|
||||
d3d12CommandList->ColorResolveSubresources[idx] = resolveSubresource;
|
||||
|
||||
// TODO: TrackTexture Resolve
|
||||
}
|
||||
}
|
||||
|
||||
// TODO DSV
|
||||
|
||||
ID3D12GraphicsCommandList_OMSetRenderTargets(d3d12CommandList->GraphicsCommandList.CommandList,
|
||||
colorTargetInfoCount, RTVs, false, nullptr);
|
||||
|
||||
// Set defaults graphics states
|
||||
GraphicsViewPort defaultViewport;
|
||||
defaultViewport.X = 0.f;
|
||||
defaultViewport.Y = 0.f;
|
||||
defaultViewport.Width = static_cast<float>(frameBufferWidth);
|
||||
defaultViewport.Height = static_cast<float>(frameBufferHeight);
|
||||
defaultViewport.MinDepth = 0.f;
|
||||
defaultViewport.MaxDepth = 1.f;
|
||||
SetViewPort(commandList, defaultViewport);
|
||||
|
||||
Rectangle defaultScissor;
|
||||
defaultScissor.X = 0;
|
||||
defaultScissor.Y = 0;
|
||||
defaultScissor.Width = static_cast<int32>(frameBufferWidth);
|
||||
defaultScissor.Height = static_cast<int32>(frameBufferHeight);
|
||||
SetScissorRect(commandList, defaultScissor);
|
||||
|
||||
SetStencilReference(commandList, 0);
|
||||
|
||||
FColor blendConstants;
|
||||
blendConstants.R = 1.0f;
|
||||
blendConstants.G = 1.0f;
|
||||
blendConstants.B = 1.0f;
|
||||
blendConstants.A = 1.0f;
|
||||
SetBlendConstants(commandList, blendConstants);
|
||||
}
|
||||
|
||||
void EndRenderPass(NonNullPtr<CommandList> commandList)
|
||||
{
|
||||
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||
|
||||
// Reset Color Target state and optionally resolve color texture
|
||||
for (uint32 idx = 0; idx < GPUDriver::kMaxColorTargetInfo; ++idx)
|
||||
{
|
||||
if (d3d12CommandList->ColorTargetSubresources[idx])
|
||||
{
|
||||
if (d3d12CommandList->ColorResolveSubresources[idx])
|
||||
{
|
||||
Internal::TextureSubresourceBarrier(d3d12CommandList, D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
|
||||
d3d12CommandList->ColorTargetSubresources[idx]);
|
||||
ID3D12GraphicsCommandList_ResolveSubresource(
|
||||
d3d12CommandList->GraphicsCommandList.CommandList,
|
||||
d3d12CommandList->ColorResolveSubresources[idx]->Parent->Resource,
|
||||
d3d12CommandList->ColorResolveSubresources[idx]->Index,
|
||||
d3d12CommandList->ColorTargetSubresources[idx]->Parent->Resource,
|
||||
d3d12CommandList->ColorTargetSubresources[idx]->Index,
|
||||
Internal::ConvertToD3D12TextureFormat(
|
||||
d3d12CommandList->ColorTargetSubresources[idx]->Parent->Container->Header.CreateInfo.Format));
|
||||
|
||||
Internal::TextureSubresourceTransitionToDefaultUsage(d3d12CommandList,
|
||||
d3d12CommandList->ColorTargetSubresources[idx],
|
||||
D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
|
||||
|
||||
Internal::TextureSubresourceTransitionToDefaultUsage(d3d12CommandList,
|
||||
d3d12CommandList->ColorResolveSubresources[idx],
|
||||
D3D12_RESOURCE_STATE_RESOLVE_DEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
Internal::TextureSubresourceTransitionToDefaultUsage(d3d12CommandList,
|
||||
d3d12CommandList->ColorTargetSubresources[idx],
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO : Write Depth stencil
|
||||
// TODO : Reset graphics pipeline
|
||||
|
||||
ID3D12GraphicsCommandList_OMSetRenderTargets(d3d12CommandList->GraphicsCommandList.CommandList, 0, NULL, false, NULL);
|
||||
|
||||
// Reset bind states
|
||||
ZeroArray(d3d12CommandList->ColorTargetSubresources);
|
||||
ZeroArray(d3d12CommandList->ColorResolveSubresources);
|
||||
// TODO : reset depth stencil subresources
|
||||
// TODO : vertex buffer
|
||||
// TODO :Vertex sampler and fragment sampler
|
||||
}
|
||||
} // namespace Juliet::D3D12
|
||||
12
Juliet/src/Graphics/D3D12/D3D12RenderPass.h
Normal file
12
Juliet/src/Graphics/D3D12/D3D12RenderPass.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <core/Common/NonNullPtr.h>
|
||||
#include <Graphics/D3D12/DX12CommandList.h>
|
||||
#include <Graphics/RenderPass.h>
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
extern void BeginRenderPass(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
||||
uint32 colorTargetInfoCount);
|
||||
extern void EndRenderPass(NonNullPtr<CommandList> commandList);
|
||||
} // namespace Juliet::D3D12
|
||||
178
Juliet/src/Graphics/D3D12/D3D12Synchronization.cpp
Normal file
178
Juliet/src/Graphics/D3D12/D3D12Synchronization.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#include <pch.h>
|
||||
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||
#include <Graphics/D3D12/DX12CommandList.h>
|
||||
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||
#include <Graphics/D3D12/DX12Utils.h>
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void ReleaseFenceToPool(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12Fence> fence)
|
||||
{
|
||||
if (driver->AvailableFenceCount + 1 >= driver->AvailableFenceCapacity)
|
||||
{
|
||||
driver->AvailableFenceCapacity = driver->AvailableFenceCapacity * 2;
|
||||
driver->AvailableFences = static_cast<D3D12Fence**>(
|
||||
Realloc(driver->AvailableFences, sizeof(D3D12Fence*) * driver->AvailableFenceCapacity));
|
||||
}
|
||||
driver->AvailableFences[driver->AvailableFenceCount] = fence;
|
||||
driver->AvailableFenceCount += 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool Wait(NonNullPtr<GPUDriver> driver)
|
||||
{
|
||||
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
||||
D3D12Fence* fence = Internal::AcquireFence(d3d12driver);
|
||||
if (!fence)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d3d12driver->GraphicsQueue)
|
||||
{
|
||||
// Insert a signal into the end of the command queue...
|
||||
ID3D12CommandQueue_Signal(d3d12driver->GraphicsQueue, fence->Handle, D3D12_FENCE_SIGNAL_VALUE);
|
||||
|
||||
// ...and then block on it.
|
||||
if (ID3D12Fence_GetCompletedValue(fence->Handle) != D3D12_FENCE_SIGNAL_VALUE)
|
||||
{
|
||||
HRESULT result = ID3D12Fence_SetEventOnCompletion(fence->Handle, D3D12_FENCE_SIGNAL_VALUE, fence->Event);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(d3d12driver, "Setting fence event failed!", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD waitResult = WaitForSingleObject(fence->Event, INFINITE);
|
||||
if (waitResult == WAIT_FAILED)
|
||||
{
|
||||
LogError(d3d12driver, "Wait failed!", result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseFence(driver, reinterpret_cast<Fence*>(fence));
|
||||
|
||||
bool result = true;
|
||||
|
||||
// Clean up
|
||||
for (int32 idx = d3d12driver->SubmittedCommandListCount - 1; idx >= 0; idx -= 1)
|
||||
{
|
||||
result &= Internal::CleanCommandList(d3d12driver, d3d12driver->SubmittedCommandLists[idx], false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool QueryFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence)
|
||||
{
|
||||
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
||||
auto d3d12Fence = reinterpret_cast<D3D12Fence*>(fence.Get());
|
||||
|
||||
if (--d3d12Fence->ReferenceCount == 0)
|
||||
{
|
||||
ReleaseFenceToPool(d3d12driver, d3d12Fence);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
void ResourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
|
||||
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource, uint32 subresourceIndex,
|
||||
bool needsUavBarrier)
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER barrierDesc[2];
|
||||
uint32 numBarriers = 0;
|
||||
|
||||
// No transition barrier is needed if the state is not changing.
|
||||
if (sourceState != destinationState)
|
||||
{
|
||||
barrierDesc[numBarriers].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrierDesc[numBarriers].Flags = static_cast<D3D12_RESOURCE_BARRIER_FLAGS>(0);
|
||||
barrierDesc[numBarriers].Transition.StateBefore = sourceState;
|
||||
barrierDesc[numBarriers].Transition.StateAfter = destinationState;
|
||||
barrierDesc[numBarriers].Transition.pResource = resource;
|
||||
barrierDesc[numBarriers].Transition.Subresource = subresourceIndex;
|
||||
|
||||
numBarriers += 1;
|
||||
}
|
||||
|
||||
if (needsUavBarrier)
|
||||
{
|
||||
barrierDesc[numBarriers].Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
|
||||
barrierDesc[numBarriers].Flags = static_cast<D3D12_RESOURCE_BARRIER_FLAGS>(0);
|
||||
barrierDesc[numBarriers].UAV.pResource = resource;
|
||||
|
||||
numBarriers += 1;
|
||||
}
|
||||
|
||||
if (numBarriers > 0)
|
||||
{
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(commandList->GraphicsCommandList.CommandList, numBarriers, barrierDesc);
|
||||
}
|
||||
}
|
||||
|
||||
D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver)
|
||||
{
|
||||
D3D12Fence* fence;
|
||||
ID3D12Fence* handle;
|
||||
|
||||
// TODO :Thread safe (lock + atomic)
|
||||
|
||||
if (driver->AvailableFenceCount == 0)
|
||||
{
|
||||
HRESULT result = ID3D12Device_CreateFence(driver->D3D12Device, D3D12_FENCE_UNSIGNALED_VALUE, D3D12_FENCE_FLAG_NONE,
|
||||
IID_ID3D12Fence, reinterpret_cast<void**>(&handle));
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to create fence!", result);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fence = static_cast<D3D12Fence*>(Calloc(1, sizeof(D3D12Fence)));
|
||||
if (!fence)
|
||||
{
|
||||
ID3D12Fence_Release(handle);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
fence->Handle = handle;
|
||||
fence->Event = CreateEvent(nullptr, false, false, nullptr);
|
||||
fence->ReferenceCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fence = driver->AvailableFences[driver->AvailableFenceCount - 1];
|
||||
driver->AvailableFenceCount -= 1;
|
||||
ID3D12Fence_Signal(fence->Handle, D3D12_FENCE_UNSIGNALED_VALUE);
|
||||
}
|
||||
|
||||
fence->ReferenceCount += 1;
|
||||
return fence;
|
||||
}
|
||||
|
||||
void DestroyFence(NonNullPtr<D3D12Fence> fence)
|
||||
{
|
||||
if (fence->Handle)
|
||||
{
|
||||
ID3D12Fence_Release(fence->Handle);
|
||||
}
|
||||
|
||||
if (fence->Event)
|
||||
{
|
||||
CloseHandle(fence->Event);
|
||||
}
|
||||
Free(fence.Get());
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
41
Juliet/src/Graphics/D3D12/D3D12Synchronization.h
Normal file
41
Juliet/src/Graphics/D3D12/D3D12Synchronization.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/Common/NonNullPtr.h>
|
||||
#include <Graphics/D3D12/D3D12Common.h>
|
||||
#include <Graphics/GraphicsDevice.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
struct Fence;
|
||||
struct GPUDriver;
|
||||
} // namespace Juliet
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
#define D3D12_FENCE_UNSIGNALED_VALUE 0
|
||||
#define D3D12_FENCE_SIGNAL_VALUE 1
|
||||
|
||||
// Forward Declare
|
||||
struct D3D12CommandList;
|
||||
|
||||
struct D3D12Fence
|
||||
{
|
||||
ID3D12Fence* Handle;
|
||||
HANDLE Event; // used for blocking
|
||||
int32 ReferenceCount; // TODO : Atomic
|
||||
};
|
||||
|
||||
extern bool Wait(NonNullPtr<GPUDriver> driver);
|
||||
extern bool QueryFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
extern void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
extern void ResourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
|
||||
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource,
|
||||
uint32 subresourceIndex, bool needsUavBarrier);
|
||||
|
||||
extern D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver);
|
||||
extern void DestroyFence(NonNullPtr<D3D12Fence> fence);
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
@@ -1,8 +1,240 @@
|
||||
#include <pch.h>
|
||||
|
||||
#include <Core/Common/EnumUtils.h>
|
||||
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||
#include <Graphics/D3D12/D3D12Texture.h>
|
||||
#include <Graphics/D3D12/DX12CommandList.h>
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
namespace
|
||||
{
|
||||
DXGI_FORMAT JulietToD3D12_TextureFormat[] = {
|
||||
DXGI_FORMAT_UNKNOWN, // INVALID
|
||||
DXGI_FORMAT_A8_UNORM, // A8_UNORM
|
||||
DXGI_FORMAT_R8_UNORM, // R8_UNORM
|
||||
DXGI_FORMAT_R8G8_UNORM, // R8G8_UNORM
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM
|
||||
DXGI_FORMAT_R16_UNORM, // R16_UNORM
|
||||
DXGI_FORMAT_R16G16_UNORM, // R16G16_UNORM
|
||||
DXGI_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM, // R10G10B10A2_UNORM
|
||||
DXGI_FORMAT_B5G6R5_UNORM, // B5G6R5_UNORM
|
||||
DXGI_FORMAT_B5G5R5A1_UNORM, // B5G5R5A1_UNORM
|
||||
DXGI_FORMAT_B4G4R4A4_UNORM, // B4G4R4A4_UNORM
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM
|
||||
DXGI_FORMAT_BC1_UNORM, // BC1_UNORM
|
||||
DXGI_FORMAT_BC2_UNORM, // BC2_UNORM
|
||||
DXGI_FORMAT_BC3_UNORM, // BC3_UNORM
|
||||
DXGI_FORMAT_BC4_UNORM, // BC4_UNORM
|
||||
DXGI_FORMAT_BC5_UNORM, // BC5_UNORM
|
||||
DXGI_FORMAT_BC7_UNORM, // BC7_UNORM
|
||||
DXGI_FORMAT_BC6H_SF16, // BC6H_FLOAT
|
||||
DXGI_FORMAT_BC6H_UF16, // BC6H_UFLOAT
|
||||
DXGI_FORMAT_R8_SNORM, // R8_SNORM
|
||||
DXGI_FORMAT_R8G8_SNORM, // R8G8_SNORM
|
||||
DXGI_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM
|
||||
DXGI_FORMAT_R16_SNORM, // R16_SNORM
|
||||
DXGI_FORMAT_R16G16_SNORM, // R16G16_SNORM
|
||||
DXGI_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM
|
||||
DXGI_FORMAT_R16_FLOAT, // R16_FLOAT
|
||||
DXGI_FORMAT_R16G16_FLOAT, // R16G16_FLOAT
|
||||
DXGI_FORMAT_R16G16B16A16_FLOAT, // R16G16B16A16_FLOAT
|
||||
DXGI_FORMAT_R32_FLOAT, // R32_FLOAT
|
||||
DXGI_FORMAT_R32G32_FLOAT, // R32G32_FLOAT
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT, // R32G32B32A32_FLOAT
|
||||
DXGI_FORMAT_R11G11B10_FLOAT, // R11G11B10_UFLOAT
|
||||
DXGI_FORMAT_R8_UINT, // R8_UINT
|
||||
DXGI_FORMAT_R8G8_UINT, // R8G8_UINT
|
||||
DXGI_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT
|
||||
DXGI_FORMAT_R16_UINT, // R16_UINT
|
||||
DXGI_FORMAT_R16G16_UINT, // R16G16_UINT
|
||||
DXGI_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT
|
||||
DXGI_FORMAT_R32_UINT, // R32_UINT
|
||||
DXGI_FORMAT_R32G32_UINT, // R32G32_UINT
|
||||
DXGI_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT
|
||||
DXGI_FORMAT_R8_SINT, // R8_INT
|
||||
DXGI_FORMAT_R8G8_SINT, // R8G8_INT
|
||||
DXGI_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT
|
||||
DXGI_FORMAT_R16_SINT, // R16_INT
|
||||
DXGI_FORMAT_R16G16_SINT, // R16G16_INT
|
||||
DXGI_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT
|
||||
DXGI_FORMAT_R32_SINT, // R32_INT
|
||||
DXGI_FORMAT_R32G32_SINT, // R32G32_INT
|
||||
DXGI_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, // R8G8B8A8_UNORM_SRGB
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, // B8G8R8A8_UNORM_SRGB
|
||||
DXGI_FORMAT_BC1_UNORM_SRGB, // BC1_UNORM_SRGB
|
||||
DXGI_FORMAT_BC2_UNORM_SRGB, // BC2_UNORM_SRGB
|
||||
DXGI_FORMAT_BC3_UNORM_SRGB, // BC3_UNORM_SRGB
|
||||
DXGI_FORMAT_BC7_UNORM_SRGB, // BC7_UNORM_SRGB
|
||||
DXGI_FORMAT_R16_UNORM, // D16_UNORM
|
||||
DXGI_FORMAT_R24_UNORM_X8_TYPELESS, // D24_UNORM
|
||||
DXGI_FORMAT_R32_FLOAT, // D32_FLOAT
|
||||
DXGI_FORMAT_R24_UNORM_X8_TYPELESS, // D24_UNORM_S8_UINT
|
||||
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, // D32_FLOAT_S8_UINT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
|
||||
};
|
||||
|
||||
}
|
||||
uint32 ComputeSubresourceIndex(uint32 mipLevel, uint32 layer, uint32 numLevels)
|
||||
{
|
||||
return mipLevel + (layer * numLevels);
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_STATES GetDefaultTextureResourceState(TextureUsageFlag usageFlags)
|
||||
{
|
||||
if ((usageFlags & TextureUsageFlag::Sampler) != TextureUsageFlag::None)
|
||||
{
|
||||
return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
|
||||
}
|
||||
if ((usageFlags & TextureUsageFlag::GraphicsStorageRead) != TextureUsageFlag::None)
|
||||
{
|
||||
return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
|
||||
}
|
||||
if ((usageFlags & TextureUsageFlag::ColorTarget) != TextureUsageFlag::None)
|
||||
{
|
||||
return D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
}
|
||||
if ((usageFlags & TextureUsageFlag::DepthStencilTarget) != TextureUsageFlag::None)
|
||||
{
|
||||
return D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
||||
}
|
||||
if ((usageFlags & TextureUsageFlag::ComputeStorageRead) != TextureUsageFlag::None)
|
||||
{
|
||||
return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
|
||||
}
|
||||
if ((usageFlags & TextureUsageFlag::ComputeStorageWrite) != TextureUsageFlag::None)
|
||||
{
|
||||
return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
}
|
||||
if ((usageFlags & TextureUsageFlag::ComputeStorageSimultaneousReadWrite) != TextureUsageFlag::None)
|
||||
{
|
||||
return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
}
|
||||
Log(LogLevel::Error, LogCategory::Graphics, "Texture has no default usage mode!");
|
||||
return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
D3D12TextureSubresource* PrepareTextureSubresourceForWrite(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureContainer> container,
|
||||
uint32 layer, uint32 level, bool shouldCycle,
|
||||
D3D12_RESOURCE_STATES newTextureUsage)
|
||||
{
|
||||
D3D12TextureSubresource* subresource = Internal::FetchTextureSubresource(container, layer, level);
|
||||
if (shouldCycle and container->CanBeCycled and subresource->Parent->RefCount > 0)
|
||||
{
|
||||
// TODO: Cycle the active texture to an available one. Not needed for swap chain (current objective)
|
||||
// CycleActiveTexture(commandList->Driver, container);
|
||||
|
||||
subresource = Internal::FetchTextureSubresource(container, layer, level);
|
||||
}
|
||||
|
||||
Internal::TextureSubresourceTransitionFromDefaultUsage(commandList, subresource, newTextureUsage);
|
||||
|
||||
return subresource;
|
||||
}
|
||||
|
||||
D3D12TextureSubresource* FetchTextureSubresource(NonNullPtr<D3D12TextureContainer> container, uint32 layer, uint32 level)
|
||||
{
|
||||
uint32 index = ComputeSubresourceIndex(level, layer, container->Header.CreateInfo.MipLevelCount);
|
||||
return &container->ActiveTexture->Subresources[index];
|
||||
}
|
||||
|
||||
void TextureSubresourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
|
||||
D3D12_RESOURCE_STATES destinationState, NonNullPtr<D3D12TextureSubresource> textureSubresource)
|
||||
{
|
||||
TextureUsageFlag currentFlag = textureSubresource->Parent->Container->Header.CreateInfo.Flags;
|
||||
bool needsUAVBarrier =
|
||||
((currentFlag & TextureUsageFlag::ComputeStorageWrite) != TextureUsageFlag::None) ||
|
||||
((currentFlag & TextureUsageFlag::ComputeStorageSimultaneousReadWrite) != TextureUsageFlag::None);
|
||||
Internal::ResourceBarrier(commandList, sourceState, destinationState, textureSubresource->Parent->Resource,
|
||||
textureSubresource->Index, needsUAVBarrier);
|
||||
}
|
||||
|
||||
void TextureSubresourceTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureSubresource> subresource,
|
||||
D3D12_RESOURCE_STATES toTextureUsage)
|
||||
{
|
||||
D3D12_RESOURCE_STATES defaultUsage =
|
||||
GetDefaultTextureResourceState(subresource->Parent->Container->Header.CreateInfo.Flags);
|
||||
TextureSubresourceBarrier(commandList, defaultUsage, toTextureUsage, subresource);
|
||||
}
|
||||
|
||||
void TextureTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12Texture> texture, D3D12_RESOURCE_STATES toTextureUsage)
|
||||
{
|
||||
for (uint32 i = 0; i < texture->SubresourceCount; ++i)
|
||||
{
|
||||
TextureSubresourceTransitionFromDefaultUsage(commandList, &texture->Subresources[i], toTextureUsage);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSubresourceTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureSubresource> subresource,
|
||||
D3D12_RESOURCE_STATES fromTextureUsage)
|
||||
{
|
||||
D3D12_RESOURCE_STATES defaultUsage =
|
||||
GetDefaultTextureResourceState(subresource->Parent->Container->Header.CreateInfo.Flags);
|
||||
TextureSubresourceBarrier(commandList, fromTextureUsage, defaultUsage, subresource);
|
||||
}
|
||||
|
||||
void TextureTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList, NonNullPtr<D3D12Texture> texture,
|
||||
D3D12_RESOURCE_STATES fromTextureUsage)
|
||||
{
|
||||
for (uint32 i = 0; i < texture->SubresourceCount; ++i)
|
||||
{
|
||||
TextureSubresourceTransitionToDefaultUsage(commandList, &texture->Subresources[i], fromTextureUsage);
|
||||
}
|
||||
}
|
||||
|
||||
// Utils
|
||||
DXGI_FORMAT ConvertToD3D12TextureFormat(TextureFormat format)
|
||||
{
|
||||
return JulietToD3D12_TextureFormat[ToUnderlying(format)];
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -8,9 +8,10 @@ struct ID3D12Resource;
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
// Forward Declare
|
||||
struct D3D12Texture;
|
||||
|
||||
struct D3D12ResourceHeap;
|
||||
struct D3D12CommandList;
|
||||
|
||||
struct D3D12TextureContainer
|
||||
{
|
||||
@@ -30,7 +31,7 @@ namespace Juliet::D3D12
|
||||
};
|
||||
|
||||
// D3D12 subresourcces: https://learn.microsoft.com/en-us/windows/win32/direct3d12/subresources (mipmaps, etc..)
|
||||
using D3D12TextureSubresource = struct D3D12TextureSubresource
|
||||
struct D3D12TextureSubresource
|
||||
{
|
||||
D3D12Texture* Parent;
|
||||
uint32 Layer;
|
||||
@@ -60,4 +61,32 @@ namespace Juliet::D3D12
|
||||
// TODO: Should be atomic to support multithreading
|
||||
int32 RefCount;
|
||||
};
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
extern D3D12TextureSubresource* PrepareTextureSubresourceForWrite(NonNullPtr<D3D12CommandList>,
|
||||
NonNullPtr<D3D12TextureContainer> container,
|
||||
uint32 layer, uint32 level, bool shouldCycle,
|
||||
D3D12_RESOURCE_STATES newTextureUsage);
|
||||
extern D3D12TextureSubresource* FetchTextureSubresource(NonNullPtr<D3D12TextureContainer> container,
|
||||
uint32 layer, uint32 level);
|
||||
extern void TextureSubresourceBarrier(NonNullPtr<D3D12CommandList> commandList,
|
||||
D3D12_RESOURCE_STATES sourceState, D3D12_RESOURCE_STATES destinationState,
|
||||
NonNullPtr<D3D12TextureSubresource> textureSubresource);
|
||||
|
||||
// Texture usage transition
|
||||
extern void TextureSubresourceTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureSubresource> subresource,
|
||||
D3D12_RESOURCE_STATES toTextureUsage);
|
||||
extern void TextureTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12Texture> texture, D3D12_RESOURCE_STATES toTextureUsage);
|
||||
extern void TextureSubresourceTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureSubresource> subresource,
|
||||
D3D12_RESOURCE_STATES fromTextureUsage);
|
||||
extern void TextureTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList, NonNullPtr<D3D12Texture> texture,
|
||||
D3D12_RESOURCE_STATES fromTextureUsage);
|
||||
|
||||
// Utils
|
||||
extern DXGI_FORMAT ConvertToD3D12TextureFormat(TextureFormat format);
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -1,69 +1,108 @@
|
||||
#include <pch.h>
|
||||
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||
#include <Graphics/D3D12/DX12CommandList.h>
|
||||
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||
#include <Graphics/D3D12/DX12Utils.h>
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool HasD3D12CommandList(NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
|
||||
bool HasD3D12CommandListForQueueType(NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
|
||||
{
|
||||
return commandList->CommandLists[ToUnderlying(queueType)] != nullptr;
|
||||
switch (queueType)
|
||||
{
|
||||
case QueueType::Graphics: return commandList->GraphicsCommandList.CommandList != nullptr;
|
||||
case QueueType::Compute: return commandList->ComputeCommandList.CommandList != nullptr;
|
||||
case QueueType::Copy: return commandList->CopyCommandList.CommandList != nullptr;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CreateD3D12CommandList(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
|
||||
bool CreateAllocator(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandListBaseData> baseData,
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc)
|
||||
{
|
||||
HRESULT res = 0;
|
||||
auto& queueDesc = driver->QueueDesc[ToUnderlying(queueType)];
|
||||
for (auto& buffer : commandList->CommandAllocator)
|
||||
for (auto& buffer : baseData->Allocator)
|
||||
{
|
||||
res = ID3D12Device5_CreateCommandAllocator(driver->D3D12Device, queueDesc.Type, IID_ID3D12CommandAllocator,
|
||||
reinterpret_cast<void**>(&buffer[ToUnderlying(queueType)]));
|
||||
|
||||
if (FAILED(res))
|
||||
HRESULT result = ID3D12Device5_CreateCommandAllocator(driver->D3D12Device, queueDesc.Type, IID_ID3D12CommandAllocator,
|
||||
reinterpret_cast<void**>(&buffer));
|
||||
if (FAILED(result))
|
||||
{
|
||||
Assert(false && "Error not implemented: cannot create ID3D12CommandAllocator");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& commandListSlot = commandList->CommandLists[ToUnderlying(queueType)];
|
||||
if (queueType == QueueType::Graphics || queueType == QueueType::Compute)
|
||||
{
|
||||
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
|
||||
res = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
||||
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
|
||||
if (FAILED(res))
|
||||
{
|
||||
Assert(false && "Error not implemented: cannot create ID3D12GraphicsCommandList6 (graphics or "
|
||||
"compute command list");
|
||||
return false;
|
||||
}
|
||||
commandListSlot = reinterpret_cast<ID3D12CommandList*>(d3d12GraphicsCommandList);
|
||||
}
|
||||
else if (queueType == QueueType::Copy)
|
||||
{
|
||||
ID3D12GraphicsCommandList* d3d12CopyCommandList = nullptr;
|
||||
res = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
||||
reinterpret_cast<void**>(&d3d12CopyCommandList));
|
||||
if (FAILED(res))
|
||||
{
|
||||
Assert(false &&
|
||||
"Error not implemented: cannot create ID3D12GraphicsCommandList (copy command list)");
|
||||
return false;
|
||||
}
|
||||
commandListSlot = reinterpret_cast<ID3D12CommandList*>(d3d12CopyCommandList);
|
||||
}
|
||||
|
||||
bool CreateD3D12CommandListForQueueType(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
|
||||
{
|
||||
// TODO: String library
|
||||
std::wstring wide_str = L"CommandList ID:" + std::to_wstring(commandList->ID);
|
||||
ID3D12GraphicsCommandList_SetName(commandListSlot, wide_str.c_str());
|
||||
|
||||
return true;
|
||||
// TODO: Factorize this. Flemme
|
||||
auto& queueDesc = driver->QueueDesc[ToUnderlying(queueType)];
|
||||
switch (queueType)
|
||||
{
|
||||
case QueueType::Graphics:
|
||||
{
|
||||
CreateAllocator(driver, &commandList->GraphicsCommandList, queueDesc);
|
||||
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
|
||||
HRESULT result =
|
||||
ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
||||
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
|
||||
if (FAILED(result))
|
||||
{
|
||||
Assert(false && "Error not implemented: cannot create ID3D12GraphicsCommandList6 (graphics or "
|
||||
"compute command list");
|
||||
return false;
|
||||
}
|
||||
|
||||
commandList->GraphicsCommandList.CommandList = d3d12GraphicsCommandList;
|
||||
ID3D12GraphicsCommandList6_SetName(d3d12GraphicsCommandList, wide_str.c_str());
|
||||
return true;
|
||||
}
|
||||
case QueueType::Compute:
|
||||
{
|
||||
CreateAllocator(driver, &commandList->ComputeCommandList, queueDesc);
|
||||
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
|
||||
HRESULT result =
|
||||
ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
||||
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
|
||||
if (FAILED(result))
|
||||
{
|
||||
Assert(false && "Error not implemented: cannot create ID3D12GraphicsCommandList6 (graphics or "
|
||||
"compute command list");
|
||||
return false;
|
||||
}
|
||||
|
||||
commandList->ComputeCommandList.CommandList = d3d12GraphicsCommandList;
|
||||
ID3D12GraphicsCommandList6_SetName(d3d12GraphicsCommandList, wide_str.c_str());
|
||||
return true;
|
||||
}
|
||||
case QueueType::Copy:
|
||||
{
|
||||
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));
|
||||
if (FAILED(result))
|
||||
{
|
||||
Assert(false &&
|
||||
"Error not implemented: cannot create ID3D12GraphicsCommandList (copy command list)");
|
||||
return false;
|
||||
}
|
||||
commandList->CopyCommandList.CommandList = d3d12CopyCommandList;
|
||||
ID3D12GraphicsCommandList_SetName(d3d12CopyCommandList, wide_str.c_str());
|
||||
return true;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool AllocateCommandList(NonNullPtr<D3D12Driver> driver, QueueType queueType)
|
||||
@@ -72,6 +111,7 @@ namespace Juliet::D3D12
|
||||
if (!commandList)
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Graphics, "Cannot allocate D3D12CommandList: Out of memory");
|
||||
Internal::DestroyCommandList(commandList);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -80,15 +120,20 @@ namespace Juliet::D3D12
|
||||
|
||||
if (!resizedArray)
|
||||
{
|
||||
Assert(false &&
|
||||
"Error not implemented, out of memory, handle that by deallocating stuff and returning false");
|
||||
Log(LogLevel::Error, LogCategory::Graphics,
|
||||
"Error not implemented, out of memory, handle that by deallocating stuff and returning false");
|
||||
Internal::DestroyCommandList(commandList);
|
||||
return false;
|
||||
}
|
||||
|
||||
driver->AvailableCommandLists = resizedArray;
|
||||
driver->AvailableCommandLists[driver->AvailableCommandListCapacity] = commandList;
|
||||
uint32 id = driver->AvailableCommandListCapacity;
|
||||
driver->AvailableCommandListCapacity += 1;
|
||||
driver->AvailableCommandLists = resizedArray;
|
||||
|
||||
commandList->ID = driver->AvailableCommandListCapacity;
|
||||
driver->AvailableCommandLists[driver->AvailableCommandListCount] = commandList;
|
||||
driver->AvailableCommandListCount += 1;
|
||||
|
||||
commandList->ID = id;
|
||||
commandList->Driver = driver;
|
||||
|
||||
commandList->PresentDataCapacity = 1;
|
||||
@@ -96,58 +141,298 @@ namespace Juliet::D3D12
|
||||
commandList->PresentDatas =
|
||||
static_cast<D3D12PresentData*>(Calloc(commandList->PresentDataCapacity, sizeof(D3D12PresentData)));
|
||||
|
||||
driver->AvailableCommandListCapacity += 1;
|
||||
// TODO : Simplify this
|
||||
if (!HasD3D12CommandListForQueueType(commandList, queueType))
|
||||
{
|
||||
if (!CreateD3D12CommandListForQueueType(driver, commandList, queueType))
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Graphics, "Cannot Create D3D12 command list");
|
||||
Internal::DestroyCommandList(commandList);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ID3D12GraphicsCommandList6* GetGraphicsCommandList(NonNullPtr<D3D12CommandList> commandList)
|
||||
{
|
||||
return reinterpret_cast<ID3D12GraphicsCommandList6*>(commandList->CommandLists[ToUnderlying(QueueType::Graphics)]);
|
||||
}
|
||||
D3D12CommandList* AcquireCommandListFromPool(NonNullPtr<D3D12Driver> driver, QueueType queueType)
|
||||
{
|
||||
if (driver->AvailableCommandListCount == 0)
|
||||
{
|
||||
if (!AllocateCommandList(driver, queueType))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
D3D12CommandList* commandList = driver->AvailableCommandLists[driver->AvailableCommandListCount - 1];
|
||||
driver->AvailableCommandListCount -= 1;
|
||||
|
||||
return commandList;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
CommandList* AcquireCommandList(NonNullPtr<GPUDriver> driver, QueueType queueType)
|
||||
{
|
||||
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||
|
||||
uint8 currentCommandListIndex = d3d12Driver->CommandListCount;
|
||||
if (currentCommandListIndex >= d3d12Driver->AvailableCommandListCapacity)
|
||||
D3D12CommandList* commandList = AcquireCommandListFromPool(d3d12Driver, queueType);
|
||||
|
||||
// Get Proper allocator for the frame and reset both it and the requested queue
|
||||
uint8 bufferIndex = d3d12Driver->FrameCounter % GPUDriver::kResourceBufferCount;
|
||||
switch (queueType)
|
||||
{
|
||||
if (!AllocateCommandList(d3d12Driver, queueType))
|
||||
case QueueType::Graphics:
|
||||
{
|
||||
return nullptr;
|
||||
auto* allocator = commandList->GraphicsCommandList.Allocator[bufferIndex];
|
||||
ID3D12CommandAllocator_Reset(allocator);
|
||||
ID3D12GraphicsCommandList6_Reset(commandList->GraphicsCommandList.CommandList, allocator, nullptr);
|
||||
break;
|
||||
}
|
||||
case QueueType::Compute:
|
||||
{
|
||||
auto* allocator = commandList->ComputeCommandList.Allocator[bufferIndex];
|
||||
ID3D12CommandAllocator_Reset(allocator);
|
||||
ID3D12GraphicsCommandList6_Reset(commandList->ComputeCommandList.CommandList, allocator, nullptr);
|
||||
break;
|
||||
}
|
||||
case QueueType::Copy:
|
||||
{
|
||||
auto* allocator = commandList->CopyCommandList.Allocator[bufferIndex];
|
||||
ID3D12CommandAllocator_Reset(allocator);
|
||||
ID3D12GraphicsCommandList6_Reset(commandList->CopyCommandList.CommandList, allocator, nullptr);
|
||||
break;
|
||||
}
|
||||
default: Assert(false && "Unsupported QueueType"); return nullptr;
|
||||
}
|
||||
|
||||
D3D12CommandList* commandList = d3d12Driver->AvailableCommandLists[currentCommandListIndex];
|
||||
if (!HasD3D12CommandList(commandList, queueType))
|
||||
{
|
||||
if (!CreateD3D12CommandList(d3d12Driver, commandList, queueType))
|
||||
{
|
||||
// TODO Shoud destroy the command list here
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
commandList->AutoReleaseFence = true;
|
||||
|
||||
return reinterpret_cast<CommandList*>(commandList);
|
||||
}
|
||||
|
||||
bool SubmitCommandLists(NonNullPtr<GPUDriver> driver)
|
||||
bool SubmitCommandLists(NonNullPtr<CommandList> commandList)
|
||||
{
|
||||
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||
bool success = true;
|
||||
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||
auto* d3d12Driver = d3d12CommandList->Driver;
|
||||
// TODO : Use QueueType to choose the correct CommandList and Command Queue
|
||||
// Only use graphics for now
|
||||
|
||||
uint8 commandLastIndex = d3d12Driver->CommandListCount;
|
||||
// Transition present textures to present mode
|
||||
for (uint32 i = 0; i < d3d12CommandList->PresentDataCount; i += 1)
|
||||
{
|
||||
uint32 swapchainIndex = d3d12CommandList->PresentDatas[i].SwapChainImageIndex;
|
||||
D3D12TextureContainer* container =
|
||||
&d3d12CommandList->PresentDatas[i].WindowData->SwapChainTextureContainers[swapchainIndex];
|
||||
D3D12TextureSubresource* subresource = Internal::FetchTextureSubresource(container, 0, 0);
|
||||
|
||||
// TODO : Get window data from the command list: We associate the swapchain texture to a window with a missing function
|
||||
HRESULT result = IDXGISwapChain_Present(d3d12Driver->WindowData->SwapChain, 0, 1);
|
||||
D3D12_RESOURCE_BARRIER barrierDesc;
|
||||
barrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrierDesc.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrierDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||
barrierDesc.Transition.pResource = subresource->Parent->Resource;
|
||||
barrierDesc.Transition.Subresource = subresource->Index;
|
||||
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(d3d12CommandList->GraphicsCommandList.CommandList, 1, &barrierDesc);
|
||||
}
|
||||
|
||||
// Notify the command buffer that we have completed recording
|
||||
HRESULT result = ID3D12GraphicsCommandList_Close(d3d12CommandList->GraphicsCommandList.CommandList);
|
||||
if (FAILED(result))
|
||||
{
|
||||
success = false;
|
||||
LogError(d3d12Driver, "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, "Failed to convert command list!", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Submit the command list to the queue
|
||||
ID3D12CommandQueue_ExecuteCommandLists(d3d12Driver->GraphicsQueue, 1, commandLists);
|
||||
|
||||
ID3D12CommandList_Release(commandLists[0]);
|
||||
|
||||
// Acquire a fence and set it to the in-flight fence
|
||||
d3d12CommandList->InFlightFence = Internal::AcquireFence(d3d12Driver);
|
||||
if (!d3d12CommandList->InFlightFence)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark that a fence should be signaled after command list execution
|
||||
result = ID3D12CommandQueue_Signal(d3d12Driver->GraphicsQueue, d3d12CommandList->InFlightFence->Handle, D3D12_FENCE_SIGNAL_VALUE);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(d3d12Driver, "Failed to enqueue fence signal!", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark the command list as submitted
|
||||
if (d3d12Driver->SubmittedCommandListCount + 1 >= d3d12Driver->SubmittedCommandListCapacity)
|
||||
{
|
||||
d3d12Driver->SubmittedCommandListCapacity = d3d12Driver->SubmittedCommandListCount + 1;
|
||||
|
||||
d3d12Driver->SubmittedCommandLists = static_cast<D3D12CommandList**>(
|
||||
Realloc(d3d12Driver->SubmittedCommandLists, sizeof(D3D12CommandList*) * d3d12Driver->SubmittedCommandListCapacity));
|
||||
}
|
||||
d3d12Driver->SubmittedCommandLists[d3d12Driver->SubmittedCommandListCount] = d3d12CommandList;
|
||||
d3d12Driver->SubmittedCommandListCount += 1;
|
||||
|
||||
bool success = true;
|
||||
for (uint32 i = 0; i < d3d12CommandList->PresentDataCount; i += 1)
|
||||
{
|
||||
D3D12PresentData* presentData = &d3d12CommandList->PresentDatas[i];
|
||||
auto* windowData = presentData->WindowData;
|
||||
|
||||
// NOTE: flip discard always supported since DXGI 1.4 is required
|
||||
uint32 syncInterval = 1;
|
||||
if (windowData->PresentMode == PresentMode::Immediate || windowData->PresentMode == PresentMode::Mailbox)
|
||||
{
|
||||
syncInterval = 0;
|
||||
}
|
||||
|
||||
uint32 presentFlags = 0;
|
||||
if (d3d12Driver->IsTearingSupported && windowData->PresentMode == PresentMode::Immediate)
|
||||
{
|
||||
presentFlags = DXGI_PRESENT_ALLOW_TEARING;
|
||||
}
|
||||
|
||||
result = IDXGISwapChain_Present(windowData->SwapChain, syncInterval, presentFlags);
|
||||
if (FAILED(result))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
ID3D12Resource_Release(
|
||||
windowData->SwapChainTextureContainers[presentData->SwapChainImageIndex].ActiveTexture->Resource);
|
||||
|
||||
windowData->InFlightFences[windowData->WindowFrameCounter] = reinterpret_cast<Fence*>(d3d12CommandList->InFlightFence);
|
||||
d3d12CommandList->InFlightFence->ReferenceCount += 1;
|
||||
windowData->WindowFrameCounter = (windowData->WindowFrameCounter + 1) % d3d12Driver->FramesInFlight;
|
||||
}
|
||||
|
||||
// TODO : Correctly clean up and destroy
|
||||
// Check for cleanups
|
||||
for (int32 i = d3d12Driver->SubmittedCommandListCount - 1; i >= 0; i -= 1)
|
||||
{
|
||||
uint64 fenceValue = ID3D12Fence_GetCompletedValue(d3d12Driver->SubmittedCommandLists[i]->InFlightFence->Handle);
|
||||
if (fenceValue == D3D12_FENCE_SIGNAL_VALUE)
|
||||
{
|
||||
result &= Internal::CleanCommandList(d3d12Driver, d3d12Driver->SubmittedCommandLists[i], false);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Destroy anything (buffer, texture, etc...)
|
||||
|
||||
++d3d12Driver->FrameCounter;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void SetViewPort(NonNullPtr<CommandList> commandList, const GraphicsViewPort& viewPort)
|
||||
{
|
||||
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||
|
||||
D3D12_VIEWPORT d3d12Viewport;
|
||||
d3d12Viewport.TopLeftX = viewPort.X;
|
||||
d3d12Viewport.TopLeftY = viewPort.Y;
|
||||
d3d12Viewport.Width = viewPort.Width;
|
||||
d3d12Viewport.Height = viewPort.Height;
|
||||
d3d12Viewport.MinDepth = viewPort.MinDepth;
|
||||
d3d12Viewport.MaxDepth = viewPort.MaxDepth;
|
||||
ID3D12GraphicsCommandList_RSSetViewports(d3d12CommandList->GraphicsCommandList.CommandList, 1, &d3d12Viewport);
|
||||
}
|
||||
|
||||
void SetScissorRect(NonNullPtr<CommandList> commandList, const Rectangle& rectangle)
|
||||
{
|
||||
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||
D3D12_RECT scissorRect;
|
||||
scissorRect.left = rectangle.X;
|
||||
scissorRect.top = rectangle.Y;
|
||||
scissorRect.right = rectangle.X + rectangle.Width;
|
||||
scissorRect.bottom = rectangle.Y + rectangle.Height;
|
||||
ID3D12GraphicsCommandList_RSSetScissorRects(d3d12CommandList->GraphicsCommandList.CommandList, 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);
|
||||
}
|
||||
|
||||
void SetStencilReference(NonNullPtr<CommandList> commandList, uint8 reference)
|
||||
{
|
||||
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||
ID3D12GraphicsCommandList_OMSetStencilRef(d3d12CommandList->GraphicsCommandList.CommandList, reference);
|
||||
}
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
void DestroyCommandList(NonNullPtr<D3D12CommandList> commandList)
|
||||
{
|
||||
// TODO : Handle other kind of command list (copy compute)
|
||||
if (commandList->GraphicsCommandList.CommandList)
|
||||
{
|
||||
ID3D12GraphicsCommandList_Release(commandList->GraphicsCommandList.CommandList);
|
||||
}
|
||||
|
||||
for (auto* allocator : commandList->GraphicsCommandList.Allocator)
|
||||
{
|
||||
if (allocator)
|
||||
{
|
||||
ID3D12CommandAllocator_Release(allocator);
|
||||
}
|
||||
}
|
||||
|
||||
Free(commandList->PresentDatas);
|
||||
Free(commandList.Get());
|
||||
}
|
||||
|
||||
bool CleanCommandList(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, bool cancel)
|
||||
{
|
||||
// No more presentation data
|
||||
commandList->PresentDataCount = 0;
|
||||
|
||||
// Release Fence if needed
|
||||
if (commandList->AutoReleaseFence)
|
||||
{
|
||||
ReleaseFence(driver.Get(), reinterpret_cast<Fence*>(commandList->InFlightFence));
|
||||
commandList->InFlightFence = nullptr;
|
||||
}
|
||||
|
||||
// Return the command list to the pool
|
||||
if (driver->AvailableCommandListCount == driver->AvailableCommandListCapacity)
|
||||
{
|
||||
driver->AvailableCommandListCapacity += 1;
|
||||
driver->AvailableCommandLists = static_cast<D3D12CommandList**>(
|
||||
Realloc(driver->AvailableCommandLists, driver->AvailableCommandListCapacity * sizeof(D3D12CommandList*)));
|
||||
}
|
||||
driver->AvailableCommandLists[driver->AvailableCommandListCount] = commandList;
|
||||
driver->AvailableCommandListCount += 1;
|
||||
|
||||
// Remove this command list from the submitted list
|
||||
if (!cancel)
|
||||
{
|
||||
for (uint32 idx = 0; idx < driver->SubmittedCommandListCount; idx += 1)
|
||||
{
|
||||
if (driver->SubmittedCommandLists[idx] == commandList)
|
||||
{
|
||||
driver->SubmittedCommandLists[idx] = driver->SubmittedCommandLists[driver->SubmittedCommandListCount - 1];
|
||||
driver->SubmittedCommandListCount -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -1,19 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/Common/EnumUtils.h>
|
||||
#include <Core/Common/NonNullPtr.h>
|
||||
#include <Core/Math/Shape.h>
|
||||
#include <Graphics/D3D12/DX12Includes.h>
|
||||
#include <Graphics/GraphicsDevice.h>
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
// Forward Declare
|
||||
struct D3D12Driver;
|
||||
struct D3D12Fence;
|
||||
struct D3D12TextureSubresource;
|
||||
struct D3D12WindowData;
|
||||
|
||||
struct D3D12CommandListBaseData
|
||||
{
|
||||
ID3D12CommandAllocator* Allocator[GPUDriver::kResourceBufferCount];
|
||||
};
|
||||
|
||||
struct D3D12CopyCommandListData : D3D12CommandListBaseData
|
||||
{
|
||||
ID3D12GraphicsCommandList* CommandList;
|
||||
};
|
||||
|
||||
struct D3D12GraphicsCommandListData : D3D12CommandListBaseData
|
||||
{
|
||||
ID3D12GraphicsCommandList6* CommandList;
|
||||
};
|
||||
|
||||
struct D3D12PresentData
|
||||
{
|
||||
D3D12WindowData* WindowData;
|
||||
uint32 SwapChainImageIndex;
|
||||
uint32 SwapChainImageIndex;
|
||||
};
|
||||
|
||||
struct D3D12CommandList
|
||||
@@ -24,16 +42,30 @@ namespace Juliet::D3D12
|
||||
D3D12Driver* Driver;
|
||||
|
||||
D3D12PresentData* PresentDatas;
|
||||
uint32 PresentDataCapacity;
|
||||
uint32 PresentDataCount;
|
||||
uint32 PresentDataCapacity;
|
||||
uint32 PresentDataCount;
|
||||
|
||||
// We create kResourceBufferCount allocator per queue to allow reusing the command list every N frames
|
||||
ID3D12CommandAllocator* CommandAllocator[GPUDriver::kResourceBufferCount][ToUnderlying(QueueType::Count)];
|
||||
ID3D12CommandList* CommandLists[ToUnderlying(QueueType::Count)];
|
||||
D3D12Fence* InFlightFence;
|
||||
bool AutoReleaseFence;
|
||||
|
||||
D3D12GraphicsCommandListData GraphicsCommandList;
|
||||
D3D12GraphicsCommandListData ComputeCommandList;
|
||||
D3D12CopyCommandListData CopyCommandList;
|
||||
|
||||
D3D12TextureSubresource* ColorTargetSubresources[GPUDriver::kMaxColorTargetInfo];
|
||||
D3D12TextureSubresource* ColorResolveSubresources[GPUDriver::kMaxColorTargetInfo];
|
||||
};
|
||||
|
||||
ID3D12GraphicsCommandList6* GetGraphicsCommandList(NonNullPtr<D3D12CommandList> commandList);
|
||||
|
||||
extern CommandList* AcquireCommandList(NonNullPtr<GPUDriver> driver, QueueType queueType);
|
||||
extern bool SubmitCommandLists(NonNullPtr<GPUDriver> driver);
|
||||
extern bool SubmitCommandLists(NonNullPtr<CommandList> commandList);
|
||||
extern void SetViewPort(NonNullPtr<CommandList> commandList, const GraphicsViewPort& viewPort);
|
||||
extern void SetScissorRect(NonNullPtr<CommandList> commandList, const Rectangle& rectangle);
|
||||
extern void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants);
|
||||
extern void SetStencilReference(NonNullPtr<CommandList> commandList, uint8 reference);
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
extern void DestroyCommandList(NonNullPtr<D3D12CommandList> commandList);
|
||||
extern bool CleanCommandList(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, bool cancel);
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <core/Common/NonNullPtr.h>
|
||||
#include <Core/DynLib/DynamicLibrary.h>
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Graphics/D3D12/D3D12RenderPass.h>
|
||||
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||
#include <Graphics/D3D12/DX12CommandList.h>
|
||||
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||
#include <Graphics/D3D12/DX12Includes.h>
|
||||
@@ -167,15 +169,42 @@ namespace Juliet::D3D12
|
||||
|
||||
void DestroyDriver_Internal(NonNullPtr<D3D12Driver> driver)
|
||||
{
|
||||
// Destroy pools
|
||||
for (uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1)
|
||||
{
|
||||
if (driver->StagingDescriptorPools[i])
|
||||
{
|
||||
DestroyStagingDescriptorPool(driver->StagingDescriptorPools[i]);
|
||||
Internal::DestroyStagingDescriptorPool(driver->StagingDescriptorPools[i]);
|
||||
driver->StagingDescriptorPools[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Release command buffers
|
||||
for (uint32 i = 0; i < driver->AvailableCommandListCount; i += 1)
|
||||
{
|
||||
if (driver->AvailableCommandLists[i])
|
||||
{
|
||||
Internal::DestroyCommandList(driver->AvailableCommandLists[i]);
|
||||
driver->AvailableCommandLists[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Release fences
|
||||
for (uint32 i = 0; i < driver->AvailableFenceCount; i += 1)
|
||||
{
|
||||
if (driver->AvailableFences[i])
|
||||
{
|
||||
Internal::DestroyFence(driver->AvailableFences[i]);
|
||||
driver->AvailableFences[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean allocations
|
||||
Free(driver->AvailableCommandLists);
|
||||
Free(driver->SubmittedCommandLists);
|
||||
//Free(driver->WindowData); // TODO Should free the vector of WindowData, but we have only one for now
|
||||
Free(driver->AvailableFences);
|
||||
|
||||
if (driver->IndirectDrawCommandSignature)
|
||||
{
|
||||
ID3D12CommandSignature_Release(driver->IndirectDrawCommandSignature);
|
||||
@@ -249,7 +278,7 @@ namespace Juliet::D3D12
|
||||
|
||||
windowData->Window = window;
|
||||
|
||||
if (!CreateSwapChain(d3d12Driver, windowData, SwapChainComposition::SDR, PresentMode::VSync))
|
||||
if (!Internal::CreateSwapChain(d3d12Driver, windowData, SwapChainComposition::SDR, PresentMode::VSync))
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Graphics, "AttachToWindow failure: Cannot create Swap Chain.");
|
||||
Free(windowData);
|
||||
@@ -265,12 +294,21 @@ namespace Juliet::D3D12
|
||||
void DetachFromWindow(NonNullPtr<GPUDriver> driver, NonNullPtr<Window> window)
|
||||
{
|
||||
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||
auto* windowData = d3d12Driver->WindowData;
|
||||
Assert(windowData && "Trying to destroy a swapchain but no Window Data exists");
|
||||
|
||||
Assert(d3d12Driver->WindowData && "Trying to destroy a swapchain but no Window Data exists");
|
||||
Wait(driver);
|
||||
|
||||
// TODO : Wait for any remaining work and release the fences.
|
||||
for (uint32 idx = 0; idx < GPUDriver::kMaxFramesInFlight; idx += 1)
|
||||
{
|
||||
if (windowData->InFlightFences[idx] != nullptr)
|
||||
{
|
||||
ReleaseFence(driver, windowData->InFlightFences[idx]);
|
||||
windowData->InFlightFences[idx] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DestroySwapChain(d3d12Driver, d3d12Driver->WindowData);
|
||||
Internal::DestroySwapChain(d3d12Driver, d3d12Driver->WindowData);
|
||||
|
||||
Free(d3d12Driver->WindowData);
|
||||
d3d12Driver->WindowData = nullptr;
|
||||
@@ -517,27 +555,46 @@ namespace Juliet::D3D12
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto device = static_cast<GraphicsDevice*>(Calloc(1, sizeof(GraphicsDevice)));
|
||||
if (!device)
|
||||
// Create Pools
|
||||
driver->SubmittedCommandListCapacity = 4;
|
||||
driver->SubmittedCommandListCount = 0;
|
||||
driver->SubmittedCommandLists =
|
||||
static_cast<D3D12CommandList**>(Calloc(driver->SubmittedCommandListCapacity, sizeof(D3D12CommandList*)));
|
||||
if (!driver->SubmittedCommandLists)
|
||||
{
|
||||
DestroyDriver_Internal(driver);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create Pools
|
||||
driver->AvailableFenceCapacity = 4;
|
||||
driver->AvailableFenceCount = 0;
|
||||
driver->AvailableFences = static_cast<D3D12Fence**>(Calloc(driver->AvailableFenceCapacity, sizeof(D3D12Fence*)));
|
||||
if (!driver->AvailableFences)
|
||||
{
|
||||
DestroyDriver_Internal(driver);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Staging descriptor pools
|
||||
for (uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1)
|
||||
{
|
||||
driver->StagingDescriptorPools[i] =
|
||||
CreateStagingDescriptorPool(driver, static_cast<D3D12_DESCRIPTOR_HEAP_TYPE>(i));
|
||||
Internal::CreateStagingDescriptorPool(driver, static_cast<D3D12_DESCRIPTOR_HEAP_TYPE>(i));
|
||||
|
||||
if (driver->StagingDescriptorPools[i] == nullptr)
|
||||
{
|
||||
DestroyDriver_Internal(driver);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
auto device = static_cast<GraphicsDevice*>(Calloc(1, sizeof(GraphicsDevice)));
|
||||
if (!device)
|
||||
{
|
||||
DestroyDriver_Internal(driver);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Assign Functions to the device
|
||||
device->DestroyDevice = DestroyGraphicsDevice;
|
||||
|
||||
@@ -549,6 +606,18 @@ namespace Juliet::D3D12
|
||||
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->Wait = Wait;
|
||||
device->QueryFence = QueryFence;
|
||||
device->ReleaseFence = ReleaseFence;
|
||||
|
||||
device->Driver = driver;
|
||||
driver->GraphicsDevice = device;
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@ namespace Juliet
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
// Forward Declare
|
||||
struct D3D12CommandList;
|
||||
struct D3D12Fence;
|
||||
|
||||
struct D3D12WindowData
|
||||
{
|
||||
@@ -26,7 +28,9 @@ namespace Juliet::D3D12
|
||||
|
||||
PresentMode PresentMode;
|
||||
|
||||
uint32 FrameCounter;
|
||||
Fence* InFlightFences[GPUDriver::kMaxFramesInFlight];
|
||||
|
||||
uint32 WindowFrameCounter; // Specific to that window. See GraphicsDevice for global counter
|
||||
uint32 Width;
|
||||
uint32 Height;
|
||||
};
|
||||
@@ -63,10 +67,20 @@ namespace Juliet::D3D12
|
||||
// Resources
|
||||
D3D12CommandList** AvailableCommandLists;
|
||||
uint8 AvailableCommandListCapacity;
|
||||
uint8 AvailableCommandListCount;
|
||||
|
||||
D3D12CommandList** SubmittedCommandLists;
|
||||
uint8 SubmittedCommandListCapacity;
|
||||
uint8 SubmittedCommandListCount;
|
||||
|
||||
D3D12Fence** AvailableFences;
|
||||
uint32 AvailableFenceCount;
|
||||
uint32 AvailableFenceCapacity;
|
||||
|
||||
D3D12StagingDescriptorPool* StagingDescriptorPools[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
|
||||
|
||||
uint8 FramesInFlight;
|
||||
uint8 FramesInFlight;
|
||||
uint64 FrameCounter = 0; // Number of frame since inception
|
||||
|
||||
bool IsTearingSupported : 1;
|
||||
bool IsUMAAvailable : 1;
|
||||
|
||||
@@ -26,3 +26,6 @@
|
||||
#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
|
||||
#define IDXGIINFOQUEUE_SUPPORTED
|
||||
#endif
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
#include <Core/HAL/Display/Win32/Win32Window.h>
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Graphics/D3D12/D3D12Texture.h>
|
||||
#include <Graphics/D3D12/DX12CommandList.h>
|
||||
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||
#include <Graphics/D3D12/DX12Includes.h>
|
||||
#include <Graphics/D3D12/DX12SwapChain.h>
|
||||
#include <Graphics/D3D12/DX12Utils.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <DX12CommandList.h>
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
namespace
|
||||
@@ -105,7 +106,7 @@ namespace Juliet::D3D12
|
||||
texture->IndexInContainer = 0;
|
||||
|
||||
// Assign SRV to the swapchain texture
|
||||
AssignStagingDescriptor(driver, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, texture->SRVHandle);
|
||||
Internal::AssignStagingDescriptor(driver, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, texture->SRVHandle);
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
srvDesc.Format = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
@@ -118,7 +119,7 @@ namespace Juliet::D3D12
|
||||
|
||||
// Assign RTV to the swapchain texture
|
||||
DXGI_FORMAT swapchainFormat = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
|
||||
AssignStagingDescriptor(driver, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, texture->Subresources[0].RTVHandles[0]);
|
||||
Internal::AssignStagingDescriptor(driver, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, texture->Subresources[0].RTVHandles[0]);
|
||||
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
|
||||
rtvDesc.Format = (composition == SwapChainComposition::SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : swapchainFormat;
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
@@ -162,11 +163,10 @@ namespace Juliet::D3D12
|
||||
if (d3d12CommandList->PresentDataCount == d3d12CommandList->PresentDataCapacity)
|
||||
{
|
||||
d3d12CommandList->PresentDataCapacity += 1;
|
||||
d3d12CommandList->PresentDatas =
|
||||
static_cast<D3D12PresentData*>(Realloc(d3d12CommandList->PresentDatas,
|
||||
d3d12CommandList->PresentDataCapacity * sizeof(D3D12PresentData)));
|
||||
d3d12CommandList->PresentDatas = static_cast<D3D12PresentData*>(
|
||||
Realloc(d3d12CommandList->PresentDatas, d3d12CommandList->PresentDataCapacity * sizeof(D3D12PresentData)));
|
||||
}
|
||||
d3d12CommandList->PresentDatas[d3d12CommandList->PresentDataCount].WindowData = windowData;
|
||||
d3d12CommandList->PresentDatas[d3d12CommandList->PresentDataCount].WindowData = windowData;
|
||||
d3d12CommandList->PresentDatas[d3d12CommandList->PresentDataCount].SwapChainImageIndex = swapchainIndex;
|
||||
d3d12CommandList->PresentDataCount += 1;
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Juliet::D3D12
|
||||
barrierDesc.Transition.pResource = windowData->SwapChainTextureContainers[swapchainIndex].ActiveTexture->Resource;
|
||||
barrierDesc.Transition.Subresource = 0;
|
||||
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(GetGraphicsCommandList(d3d12CommandList), 1, &barrierDesc);
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(d3d12CommandList->GraphicsCommandList.CommandList, 1, &barrierDesc);
|
||||
|
||||
*swapchainTexture = reinterpret_cast<Texture*>(&windowData->SwapChainTextureContainers[swapchainIndex]);
|
||||
|
||||
@@ -187,136 +187,140 @@ namespace Juliet::D3D12
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
||||
SwapChainComposition composition, PresentMode presentMode)
|
||||
{
|
||||
auto windowWin32State = static_cast<Win32::Window32State*>(windowData->Window->State);
|
||||
HWND windowHandle = windowWin32State->Handle;
|
||||
if (!IsWindow(windowHandle))
|
||||
{
|
||||
Assert(false && "windowWin32State->Handle is not a window handle ???");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: I have no way to test HDR easily except the steamdeck
|
||||
DXGI_FORMAT swapChainFormat = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
|
||||
|
||||
windowData->SwapChainTextureCount = std::clamp<uint8>(driver->FramesInFlight, 2, 3);
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.Width = 0; // Use the whole width
|
||||
swapChainDesc.Height = 0; // Use the whole height
|
||||
swapChainDesc.Format = swapChainFormat;
|
||||
swapChainDesc.Stereo = 0;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = windowData->SwapChainTextureCount;
|
||||
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||
if (driver->IsTearingSupported)
|
||||
{
|
||||
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
||||
}
|
||||
else
|
||||
{
|
||||
swapChainDesc.Flags = 0;
|
||||
}
|
||||
|
||||
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc = {};
|
||||
swapChainFullscreenDesc.RefreshRate.Numerator = 0;
|
||||
swapChainFullscreenDesc.RefreshRate.Denominator = 0;
|
||||
swapChainFullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
swapChainFullscreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
swapChainFullscreenDesc.Windowed = true;
|
||||
|
||||
IDXGISwapChain1* swapChain = nullptr;
|
||||
HRESULT result =
|
||||
IDXGIFactory4_CreateSwapChainForHwnd(driver->DXGIFactory, reinterpret_cast<IUnknown*>(driver->GraphicsQueue),
|
||||
windowHandle, &swapChainDesc, &swapChainFullscreenDesc, nullptr, &swapChain);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to create SwapChain", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
IDXGISwapChain3* swapChain3 = nullptr;
|
||||
result = IDXGISwapChain1_QueryInterface(swapChain, IID_IDXGISwapChain3, reinterpret_cast<void**>(&swapChain3));
|
||||
IDXGISwapChain1_Release(swapChain);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Could not query IDXGISwapChain3 interface", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (composition != SwapChainComposition::SDR)
|
||||
{
|
||||
IDXGISwapChain3_SetColorSpace1(swapChain3, SwapchainCompositionToColorSpace[ToUnderlying(composition)]);
|
||||
}
|
||||
|
||||
IDXGIFactory1* parentFactory = nullptr;
|
||||
result = IDXGISwapChain3_GetParent(swapChain3, IID_IDXGIFactory1, reinterpret_cast<void**>(&parentFactory));
|
||||
if (FAILED(result))
|
||||
{
|
||||
Log(LogLevel::Warning, LogCategory::Graphics, "Cannot get SwapChain Parent! Error Code: " HRESULT_FMT, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable DXGI window crap
|
||||
result = IDXGIFactory1_MakeWindowAssociation(parentFactory, windowHandle, DXGI_MWA_NO_WINDOW_CHANGES);
|
||||
if (FAILED(result))
|
||||
{
|
||||
Log(LogLevel::Warning, LogCategory::Graphics, "MakeWindowAssociation failed! Error Code: " HRESULT_FMT, result);
|
||||
}
|
||||
IDXGIFactory1_Release(parentFactory);
|
||||
}
|
||||
|
||||
IDXGISwapChain3_GetDesc1(swapChain3, &swapChainDesc);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to retrieve SwapChain descriptor", result);
|
||||
return false;
|
||||
}
|
||||
windowData->SwapChain = swapChain3;
|
||||
windowData->SwapChainColorSpace = SwapchainCompositionToColorSpace[ToUnderlying(composition)];
|
||||
windowData->SwapChainComposition = composition;
|
||||
windowData->FrameCounter = 0;
|
||||
windowData->Width = swapChainDesc.Width;
|
||||
windowData->Height = swapChainDesc.Height;
|
||||
windowData->PresentMode = presentMode;
|
||||
|
||||
for (uint8 idx = 0; idx < windowData->SwapChainTextureCount; ++idx)
|
||||
{
|
||||
if (!CreateSwapChainTexture(driver, swapChain3, composition, &windowData->SwapChainTextureContainers[idx], idx))
|
||||
{
|
||||
IDXGISwapChain3_Release(swapChain3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window, Texture** swapChainTexture)
|
||||
{
|
||||
return AcquireSwapChainTexture(false, commandList, window, swapChainTexture);
|
||||
}
|
||||
|
||||
void DestroySwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData)
|
||||
namespace Internal
|
||||
{
|
||||
for (uint32 idx = 0; idx < windowData->SwapChainTextureCount; ++idx)
|
||||
bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
||||
SwapChainComposition composition, PresentMode presentMode)
|
||||
{
|
||||
ReleaseStagingDescriptor(driver, windowData->SwapChainTextureContainers[idx].ActiveTexture->SRVHandle);
|
||||
ReleaseStagingDescriptor(driver, windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles[0]);
|
||||
auto windowWin32State = static_cast<Win32::Window32State*>(windowData->Window->State);
|
||||
HWND windowHandle = windowWin32State->Handle;
|
||||
if (!IsWindow(windowHandle))
|
||||
{
|
||||
Assert(false && "windowWin32State->Handle is not a window handle ???");
|
||||
return false;
|
||||
}
|
||||
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles);
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources);
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture);
|
||||
Free(windowData->SwapChainTextureContainers[idx].Textures);
|
||||
// TODO: I have no way to test HDR easily except the steamdeck
|
||||
DXGI_FORMAT swapChainFormat = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
|
||||
|
||||
windowData->SwapChainTextureCount = std::clamp<uint8>(driver->FramesInFlight, 2, 3);
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.Width = 0; // Use the whole width
|
||||
swapChainDesc.Height = 0; // Use the whole height
|
||||
swapChainDesc.Format = swapChainFormat;
|
||||
swapChainDesc.Stereo = 0;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = windowData->SwapChainTextureCount;
|
||||
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||
if (driver->IsTearingSupported)
|
||||
{
|
||||
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
||||
}
|
||||
else
|
||||
{
|
||||
swapChainDesc.Flags = 0;
|
||||
}
|
||||
|
||||
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc = {};
|
||||
swapChainFullscreenDesc.RefreshRate.Numerator = 0;
|
||||
swapChainFullscreenDesc.RefreshRate.Denominator = 0;
|
||||
swapChainFullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
swapChainFullscreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
swapChainFullscreenDesc.Windowed = true;
|
||||
|
||||
IDXGISwapChain1* swapChain = nullptr;
|
||||
HRESULT result =
|
||||
IDXGIFactory4_CreateSwapChainForHwnd(driver->DXGIFactory, reinterpret_cast<IUnknown*>(driver->GraphicsQueue),
|
||||
windowHandle, &swapChainDesc, &swapChainFullscreenDesc, nullptr, &swapChain);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to create SwapChain", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
IDXGISwapChain3* swapChain3 = nullptr;
|
||||
result = IDXGISwapChain1_QueryInterface(swapChain, IID_IDXGISwapChain3, reinterpret_cast<void**>(&swapChain3));
|
||||
IDXGISwapChain1_Release(swapChain);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Could not query IDXGISwapChain3 interface", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (composition != SwapChainComposition::SDR)
|
||||
{
|
||||
IDXGISwapChain3_SetColorSpace1(swapChain3, SwapchainCompositionToColorSpace[ToUnderlying(composition)]);
|
||||
}
|
||||
|
||||
IDXGIFactory1* parentFactory = nullptr;
|
||||
result = IDXGISwapChain3_GetParent(swapChain3, IID_IDXGIFactory1, reinterpret_cast<void**>(&parentFactory));
|
||||
if (FAILED(result))
|
||||
{
|
||||
Log(LogLevel::Warning, LogCategory::Graphics, "Cannot get SwapChain Parent! Error Code: " HRESULT_FMT, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable DXGI window crap
|
||||
result = IDXGIFactory1_MakeWindowAssociation(parentFactory, windowHandle, DXGI_MWA_NO_WINDOW_CHANGES);
|
||||
if (FAILED(result))
|
||||
{
|
||||
Log(LogLevel::Warning, LogCategory::Graphics, "MakeWindowAssociation failed! Error Code: " HRESULT_FMT, result);
|
||||
}
|
||||
IDXGIFactory1_Release(parentFactory);
|
||||
}
|
||||
|
||||
IDXGISwapChain3_GetDesc1(swapChain3, &swapChainDesc);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to retrieve SwapChain descriptor", result);
|
||||
return false;
|
||||
}
|
||||
windowData->SwapChain = swapChain3;
|
||||
windowData->SwapChainColorSpace = SwapchainCompositionToColorSpace[ToUnderlying(composition)];
|
||||
windowData->SwapChainComposition = composition;
|
||||
windowData->WindowFrameCounter = 0;
|
||||
windowData->Width = swapChainDesc.Width;
|
||||
windowData->Height = swapChainDesc.Height;
|
||||
windowData->PresentMode = presentMode;
|
||||
|
||||
for (uint8 idx = 0; idx < windowData->SwapChainTextureCount; ++idx)
|
||||
{
|
||||
if (!CreateSwapChainTexture(driver, swapChain3, composition, &windowData->SwapChainTextureContainers[idx], idx))
|
||||
{
|
||||
IDXGISwapChain3_Release(swapChain3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IDXGISwapChain_Release(windowData->SwapChain);
|
||||
windowData->SwapChain = nullptr;
|
||||
}
|
||||
void DestroySwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData)
|
||||
{
|
||||
for (uint32 idx = 0; idx < windowData->SwapChainTextureCount; ++idx)
|
||||
{
|
||||
ReleaseStagingDescriptor(driver, windowData->SwapChainTextureContainers[idx].ActiveTexture->SRVHandle);
|
||||
ReleaseStagingDescriptor(driver,
|
||||
windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles[0]);
|
||||
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles);
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources);
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture);
|
||||
Free(windowData->SwapChainTextureContainers[idx].Textures);
|
||||
}
|
||||
|
||||
IDXGISwapChain_Release(windowData->SwapChain);
|
||||
windowData->SwapChain = nullptr;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -3,11 +3,16 @@
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
// Forward Declare
|
||||
struct D3D12Driver;
|
||||
struct D3D12WindowData;
|
||||
|
||||
extern bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
||||
SwapChainComposition composition, PresentMode presentMode);
|
||||
extern bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window, Texture** swapChainTexture);
|
||||
extern void DestroySwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData);
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
extern bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
||||
SwapChainComposition composition, PresentMode presentMode);
|
||||
extern void DestroySwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData);
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Juliet::D3D12
|
||||
}
|
||||
|
||||
// Ensure valid range
|
||||
dwChars = std::min<DWORD>(dwChars, MAX_ERROR_LEN);
|
||||
dwChars = Min<DWORD>(dwChars, MAX_ERROR_LEN);
|
||||
|
||||
// Trim whitespace from tail of message
|
||||
while (dwChars > 0)
|
||||
|
||||
@@ -65,9 +65,7 @@ namespace Juliet
|
||||
bool AttachToWindow(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
|
||||
{
|
||||
GPUDriver* driver = device->Driver;
|
||||
bool result = device->AttachToWindow(driver, window);
|
||||
|
||||
return result;
|
||||
return device->AttachToWindow(driver, window);
|
||||
}
|
||||
|
||||
void DetachFromWindow(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
|
||||
@@ -93,26 +91,88 @@ namespace Juliet
|
||||
{
|
||||
GPUDriver* driver = device->Driver;
|
||||
CommandList* cmdList = device->AcquireCommandList(driver, queueType);
|
||||
|
||||
if (!cmdList)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto header = reinterpret_cast<CommandListHeader*>(cmdList);
|
||||
header->Device = device.Get();
|
||||
|
||||
driver->CommandListCount += 1;
|
||||
auto header = reinterpret_cast<CommandListHeader*>(cmdList);
|
||||
header->Device = device.Get();
|
||||
header->RenderPass.CommandList = cmdList;
|
||||
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
void SubmitCommandLists(NonNullPtr<GraphicsDevice> device)
|
||||
void SubmitCommandLists(NonNullPtr<CommandList> commandList)
|
||||
{
|
||||
GPUDriver* driver = device->Driver;
|
||||
device->SubmitCommandLists(driver);
|
||||
auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList.Get());
|
||||
|
||||
driver->CommandListCount = 0;
|
||||
commandListHeader->Submitted = true;
|
||||
|
||||
commandListHeader->Device->SubmitCommandLists(commandList);
|
||||
}
|
||||
|
||||
RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, ColorTargetInfo& colorTargetInfo)
|
||||
{
|
||||
return BeginRenderPass(commandList, &colorTargetInfo, 1);
|
||||
}
|
||||
|
||||
RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
||||
uint32 colorTargetInfoCount)
|
||||
{
|
||||
if (colorTargetInfoCount > GPUDriver::kMaxColorTargetInfo)
|
||||
{
|
||||
Log(LogLevel::Error, LogCategory::Graphics, "BeginRenderPass: ColorTargetInfoCount is > than kMaxColorTargetInfo");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get());
|
||||
header->Device->BeginRenderPass(commandList, colorTargetInfos, colorTargetInfoCount);
|
||||
|
||||
header->RenderPass.IsInProgress = true;
|
||||
return reinterpret_cast<RenderPass*>(&header->RenderPass);
|
||||
}
|
||||
|
||||
void EndRenderPass(NonNullPtr<RenderPass> renderPass)
|
||||
{
|
||||
auto* commandList = reinterpret_cast<GPUPass*>(renderPass.Get())->CommandList;
|
||||
auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList);
|
||||
|
||||
commandListHeader->Device->EndRenderPass(commandList);
|
||||
|
||||
commandListHeader->RenderPass.IsInProgress = false;
|
||||
}
|
||||
|
||||
void SetGraphicsViewPort(NonNullPtr<RenderPass> renderPass, const GraphicsViewPort& viewPort)
|
||||
{
|
||||
auto* commandList = reinterpret_cast<GPUPass*>(renderPass.Get())->CommandList;
|
||||
auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList);
|
||||
|
||||
commandListHeader->Device->SetViewPort(commandList, viewPort);
|
||||
}
|
||||
|
||||
void SetScissorRect(NonNullPtr<RenderPass> renderPass, const Rectangle& rectangle)
|
||||
{
|
||||
auto* commandList = reinterpret_cast<GPUPass*>(renderPass.Get())->CommandList;
|
||||
auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList);
|
||||
|
||||
commandListHeader->Device->SetScissorRect(commandList, rectangle);
|
||||
}
|
||||
|
||||
void SetBlendConstants(NonNullPtr<RenderPass> renderPass, FColor blendConstants)
|
||||
{
|
||||
auto* commandList = reinterpret_cast<GPUPass*>(renderPass.Get())->CommandList;
|
||||
auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList);
|
||||
|
||||
commandListHeader->Device->SetBlendConstants(commandList, blendConstants);
|
||||
}
|
||||
|
||||
void SetStencilReference(NonNullPtr<RenderPass> renderPass, uint8 reference)
|
||||
{
|
||||
auto* commandList = reinterpret_cast<GPUPass*>(renderPass.Get())->CommandList;
|
||||
auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList);
|
||||
|
||||
commandListHeader->Device->SetStencilReference(commandList, reference);
|
||||
}
|
||||
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -7,25 +7,31 @@
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
struct Window;
|
||||
|
||||
struct TextureHeader
|
||||
{
|
||||
TextureCreateInfo CreateInfo;
|
||||
};
|
||||
|
||||
struct GPUPass
|
||||
{
|
||||
CommandList* CommandList;
|
||||
bool IsInProgress : 1;
|
||||
};
|
||||
|
||||
struct CommandListHeader
|
||||
{
|
||||
GraphicsDevice* Device = nullptr;
|
||||
bool AcquiredSwapChain = false;
|
||||
bool Submitted = false;
|
||||
|
||||
GPUPass RenderPass;
|
||||
};
|
||||
|
||||
struct GPUDriver
|
||||
{
|
||||
uint8 CommandListCount;
|
||||
|
||||
static constexpr uint8 kResourceBufferCount = 2;
|
||||
static constexpr uint8 kMaxFramesInFlight = 3;
|
||||
static constexpr uint8 kMaxColorTargetInfo = 4;
|
||||
};
|
||||
|
||||
struct GraphicsDevice
|
||||
@@ -41,7 +47,22 @@ namespace Juliet
|
||||
|
||||
// CommandLists
|
||||
CommandList* (*AcquireCommandList)(NonNullPtr<GPUDriver> driver, QueueType queueType);
|
||||
bool (*SubmitCommandLists)(NonNullPtr<GPUDriver> driver);
|
||||
bool (*SubmitCommandLists)(NonNullPtr<CommandList> commandList);
|
||||
|
||||
// RenderPass
|
||||
void (*BeginRenderPass)(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
||||
uint32 colorTargetInfoCount);
|
||||
void (*EndRenderPass)(NonNullPtr<CommandList> commandList);
|
||||
|
||||
void (*SetViewPort)(NonNullPtr<CommandList> commandList, const GraphicsViewPort& viewPort);
|
||||
void (*SetScissorRect)(NonNullPtr<CommandList> commandList, const Rectangle& viewPort);
|
||||
void (*SetBlendConstants)(NonNullPtr<CommandList> commandList, FColor blendConstants);
|
||||
void (*SetStencilReference)(NonNullPtr<CommandList> commandList, uint8 reference);
|
||||
|
||||
// Fences
|
||||
bool (*Wait)(NonNullPtr<GPUDriver> driver);
|
||||
bool (*QueryFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
void (*ReleaseFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
|
||||
const char* Name = "Unknown";
|
||||
GPUDriver* Driver = nullptr;
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
Rename DX12 files to D3D12
|
||||
|
||||
- Create Simple vector class to make the vector stuff a bit more easier than writing Capacity and Count
|
||||
@@ -13,6 +13,7 @@
|
||||
// TODO : Replace with message box from framework + call main and not winmain + subsystem
|
||||
#include <Core/DynLib/DynamicLibrary.h>
|
||||
#include <Graphics/Graphics.h>
|
||||
#include <Graphics/RenderPass.h>
|
||||
#include <Windows.h>
|
||||
|
||||
// TODO : Think how to do the draw pipeline.
|
||||
@@ -97,8 +98,20 @@ void Win32EditorApplication::Update()
|
||||
return;
|
||||
}
|
||||
|
||||
if (swapChainTexture)
|
||||
{
|
||||
ColorTargetInfo colorTargetInfo = {};
|
||||
colorTargetInfo.TargetTexture = swapChainTexture;
|
||||
colorTargetInfo.ClearColor = { .R = .5f, .G = .8f, .B = .0f, .A = 1.f };
|
||||
colorTargetInfo.LoadOperation = LoadOperation::Clear;
|
||||
colorTargetInfo.StoreOperation = StoreOperation::Store;
|
||||
|
||||
RenderPass* renderPass = BeginRenderPass(cmdList, colorTargetInfo);
|
||||
EndRenderPass(renderPass);
|
||||
}
|
||||
|
||||
// Submit Commands
|
||||
SubmitCommandLists(GraphicsDevice);
|
||||
SubmitCommandLists(cmdList);
|
||||
}
|
||||
|
||||
bool Win32EditorApplication::IsRunning()
|
||||
|
||||
@@ -21,7 +21,7 @@ class Win32EditorApplication : public Juliet::IApplication
|
||||
private:
|
||||
Juliet::Window* MainWindow = {};
|
||||
Juliet::GraphicsDevice* GraphicsDevice = {};
|
||||
Juliet::DynamicLibrary* Game = {};
|
||||
Juliet::DynamicLibrary* Game = {};
|
||||
|
||||
bool Running = false;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user