Compare commits
6 Commits
7e8aaaa891
...
8326772558
| Author | SHA1 | Date | |
|---|---|---|---|
| 8326772558 | |||
| cc9bbf0ef5 | |||
| 857f8c4e69 | |||
| ed9482b8f8 | |||
| f1b7f8eb29 | |||
| ee194b2d69 |
@@ -123,6 +123,7 @@
|
|||||||
<ClInclude Include="include\Core\JulietInit.h"/>
|
<ClInclude Include="include\Core\JulietInit.h"/>
|
||||||
<ClInclude Include="include\Core\Logging\LogManager.h"/>
|
<ClInclude Include="include\Core\Logging\LogManager.h"/>
|
||||||
<ClInclude Include="include\Core\Logging\LogTypes.h"/>
|
<ClInclude Include="include\Core\Logging\LogTypes.h"/>
|
||||||
|
<ClInclude Include="include\Core\Math\Shape.h" />
|
||||||
<ClInclude Include="include\Core\Memory\Allocator.h" />
|
<ClInclude Include="include\Core\Memory\Allocator.h" />
|
||||||
<ClInclude Include="include\Core\Memory\Utils.h" />
|
<ClInclude Include="include\Core\Memory\Utils.h" />
|
||||||
<ClInclude Include="include\Core\Networking\IPAddress.h" />
|
<ClInclude Include="include\Core\Networking\IPAddress.h" />
|
||||||
@@ -134,8 +135,10 @@
|
|||||||
<ClInclude Include="include\Core\Thread\Thread.h" />
|
<ClInclude Include="include\Core\Thread\Thread.h" />
|
||||||
<ClInclude Include="include\Engine\Class.h" />
|
<ClInclude Include="include\Engine\Class.h" />
|
||||||
<ClInclude Include="include\Engine\Engine.h" />
|
<ClInclude Include="include\Engine\Engine.h" />
|
||||||
|
<ClInclude Include="include\Graphics\Colors.h" />
|
||||||
<ClInclude Include="include\Graphics\Graphics.h" />
|
<ClInclude Include="include\Graphics\Graphics.h" />
|
||||||
<ClInclude Include="include\Graphics\GraphicsConfig.h" />
|
<ClInclude Include="include\Graphics\GraphicsConfig.h" />
|
||||||
|
<ClInclude Include="include\Graphics\RenderPass.h" />
|
||||||
<ClInclude Include="include\Graphics\Texture.h" />
|
<ClInclude Include="include\Graphics\Texture.h" />
|
||||||
<ClInclude Include="include\Juliet.h" />
|
<ClInclude Include="include\Juliet.h" />
|
||||||
<ClInclude Include="include\pch.h" />
|
<ClInclude Include="include\pch.h" />
|
||||||
@@ -152,6 +155,8 @@
|
|||||||
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h" />
|
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h" />
|
||||||
<ClInclude Include="src\Core\HAL\Win32.h" />
|
<ClInclude Include="src\Core\HAL\Win32.h" />
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Common.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\D3D12Texture.h" />
|
||||||
<ClInclude Include="src\Graphics\D3D12\DX12CommandList.h" />
|
<ClInclude Include="src\Graphics\D3D12\DX12CommandList.h" />
|
||||||
<ClInclude Include="src\Graphics\D3D12\DX12GraphicsDevice.h" />
|
<ClInclude Include="src\Graphics\D3D12\DX12GraphicsDevice.h" />
|
||||||
@@ -236,6 +241,8 @@
|
|||||||
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp" />
|
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp" />
|
||||||
<ClCompile Include="src\Engine\Engine.cpp" />
|
<ClCompile Include="src\Engine\Engine.cpp" />
|
||||||
<ClCompile Include="src\Graphics\D3D12\D3D12Common.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\D3D12Texture.cpp" />
|
||||||
<ClCompile Include="src\Graphics\D3D12\DX12CommandList.cpp" />
|
<ClCompile Include="src\Graphics\D3D12\DX12CommandList.cpp" />
|
||||||
<ClCompile Include="src\Graphics\D3D12\DX12GraphicsDevice.cpp" />
|
<ClCompile Include="src\Graphics\D3D12\DX12GraphicsDevice.cpp" />
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
using uint8 = uint8_t;
|
using uint8 = uint8_t;
|
||||||
using uint16 = uint16_t;
|
using uint16 = uint16_t;
|
||||||
@@ -24,3 +25,14 @@ struct ByteBuffer
|
|||||||
};
|
};
|
||||||
|
|
||||||
using FunctionPtr = auto (*)(void) -> void;
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <Core/Common/CoreTypes.h>
|
#include <Core/Common/CoreTypes.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
@@ -24,7 +25,8 @@ namespace Juliet
|
|||||||
extern void JULIET_API JulietAssert(const char* expression);
|
extern void JULIET_API JulietAssert(const char* expression);
|
||||||
|
|
||||||
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
|
#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)
|
inline void ZeroSize(size_t size, void* ptr)
|
||||||
{
|
{
|
||||||
auto Byte = (uint8*)ptr;
|
auto Byte = (uint8*)ptr;
|
||||||
@@ -35,4 +37,30 @@ namespace Juliet
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define MemCopy memcpy
|
#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
|
} // 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
|
#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/GraphicsConfig.h>
|
||||||
#include <Graphics/Texture.h>
|
#include <Graphics/RenderPass.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
// Graphics Interface
|
// Graphics Interface
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
struct Window;
|
// Opaque types
|
||||||
|
struct CommandList;
|
||||||
struct GraphicsDevice;
|
struct GraphicsDevice;
|
||||||
|
struct Fence;
|
||||||
|
|
||||||
// Parameters of an indirect draw command
|
// Parameters of an indirect draw command
|
||||||
struct IndirectDrawCommand
|
struct IndirectDrawCommand
|
||||||
@@ -65,8 +69,15 @@ namespace Juliet
|
|||||||
Immediate
|
Immediate
|
||||||
};
|
};
|
||||||
|
|
||||||
// Opaque types
|
struct GraphicsViewPort
|
||||||
struct CommandList;
|
{
|
||||||
|
float X;
|
||||||
|
float Y;
|
||||||
|
float Width;
|
||||||
|
float Height;
|
||||||
|
float MinDepth;
|
||||||
|
float MaxDepth;
|
||||||
|
};
|
||||||
|
|
||||||
extern JULIET_API GraphicsDevice* CreateGraphicsDevice(GraphicsConfig config);
|
extern JULIET_API GraphicsDevice* CreateGraphicsDevice(GraphicsConfig config);
|
||||||
extern JULIET_API void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device);
|
extern JULIET_API void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device);
|
||||||
@@ -81,5 +92,16 @@ namespace Juliet
|
|||||||
|
|
||||||
// Command List
|
// Command List
|
||||||
extern JULIET_API CommandList* AcquireCommandList(NonNullPtr<GraphicsDevice> device, QueueType queueType = QueueType::Graphics);
|
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
|
} // 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
|
||||||
@@ -171,10 +171,11 @@ namespace Juliet
|
|||||||
union
|
union
|
||||||
{
|
{
|
||||||
uint32 LayerCount;
|
uint32 LayerCount;
|
||||||
uint32 Depth;
|
uint32 DepthPlane;
|
||||||
}; // LayerCount is used in 2d array textures and Depth for 3d textures
|
}; // LayerCount is used in 2d array textures and Depth for 3d textures
|
||||||
uint32 MipLevelCount;
|
uint32 MipLevelCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Opaque Type
|
||||||
struct Texture;
|
struct Texture;
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -58,3 +58,6 @@
|
|||||||
#define ANSI_ONLY
|
#define ANSI_ONLY
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Juliet::D3D12
|
|||||||
bool ExtendStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptorPool& pool)
|
bool ExtendStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptorPool& pool)
|
||||||
{
|
{
|
||||||
D3D12DescriptorHeap* heap =
|
D3D12DescriptorHeap* heap =
|
||||||
CreateDescriptorHeap(driver, pool.Heaps[0]->HeapType, kStagingHeapDescriptorExpectedCount, true);
|
Internal::CreateDescriptorHeap(driver, pool.Heaps[0]->HeapType, kStagingHeapDescriptorExpectedCount, true);
|
||||||
if (!heap)
|
if (!heap)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -47,7 +47,10 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging)
|
namespace Internal
|
||||||
|
{
|
||||||
|
D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||||
|
uint32 count, bool isStaging)
|
||||||
{
|
{
|
||||||
ID3D12DescriptorHeap* handle;
|
ID3D12DescriptorHeap* handle;
|
||||||
|
|
||||||
@@ -114,8 +117,8 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
pool->FreeDescriptorCapacity = kStagingHeapDescriptorExpectedCount;
|
pool->FreeDescriptorCapacity = kStagingHeapDescriptorExpectedCount;
|
||||||
pool->FreeDescriptorCount = kStagingHeapDescriptorExpectedCount;
|
pool->FreeDescriptorCount = kStagingHeapDescriptorExpectedCount;
|
||||||
pool->FreeDescriptors =
|
pool->FreeDescriptors = static_cast<D3D12StagingDescriptor*>(
|
||||||
static_cast<D3D12StagingDescriptor*>(Malloc(kStagingHeapDescriptorExpectedCount * sizeof(D3D12StagingDescriptor)));
|
Malloc(kStagingHeapDescriptorExpectedCount * sizeof(D3D12StagingDescriptor)));
|
||||||
|
|
||||||
InitStagingDescriptorPool(heap, pool);
|
InitStagingDescriptorPool(heap, pool);
|
||||||
|
|
||||||
@@ -165,4 +168,5 @@ namespace Juliet::D3D12
|
|||||||
Free(pool->FreeDescriptors);
|
Free(pool->FreeDescriptors);
|
||||||
Free(pool.Get());
|
Free(pool.Get());
|
||||||
}
|
}
|
||||||
|
} // namespace Internal
|
||||||
} // namespace Juliet::D3D12
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
// Inspired (copy pasted a lot) by SDL GPU
|
// Inspired (copy pasted a lot) by SDL GPU
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
struct D3D12Driver;
|
|
||||||
// Forward declare
|
// Forward declare
|
||||||
|
struct D3D12Driver;
|
||||||
struct D3D12StagingDescriptor;
|
struct D3D12StagingDescriptor;
|
||||||
|
|
||||||
// https://learn.microsoft.com/en-us/windows/win32/direct3d12/descriptor-heaps
|
// https://learn.microsoft.com/en-us/windows/win32/direct3d12/descriptor-heaps
|
||||||
@@ -51,8 +51,10 @@ namespace Juliet::D3D12
|
|||||||
uint32 CpuHandleIndex;
|
uint32 CpuHandleIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
namespace Internal
|
||||||
uint32 count, bool isStaging);
|
{
|
||||||
|
extern D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver,
|
||||||
|
D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging);
|
||||||
extern void DestroyDescriptorHeap(NonNullPtr<D3D12DescriptorHeap> heap);
|
extern void DestroyDescriptorHeap(NonNullPtr<D3D12DescriptorHeap> heap);
|
||||||
|
|
||||||
extern D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type);
|
extern D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type);
|
||||||
@@ -60,4 +62,5 @@ namespace Juliet::D3D12
|
|||||||
D3D12StagingDescriptor& outDescriptor);
|
D3D12StagingDescriptor& outDescriptor);
|
||||||
extern void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor);
|
extern void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor);
|
||||||
extern void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool);
|
extern void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool);
|
||||||
|
} // namespace Internal
|
||||||
} // namespace Juliet::D3D12
|
} // 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 <pch.h>
|
||||||
|
|
||||||
|
#include <Core/Common/EnumUtils.h>
|
||||||
|
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||||
#include <Graphics/D3D12/D3D12Texture.h>
|
#include <Graphics/D3D12/D3D12Texture.h>
|
||||||
|
#include <Graphics/D3D12/DX12CommandList.h>
|
||||||
|
|
||||||
namespace Juliet::D3D12
|
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
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
|
// Forward Declare
|
||||||
struct D3D12Texture;
|
struct D3D12Texture;
|
||||||
|
|
||||||
struct D3D12ResourceHeap;
|
struct D3D12ResourceHeap;
|
||||||
|
struct D3D12CommandList;
|
||||||
|
|
||||||
struct D3D12TextureContainer
|
struct D3D12TextureContainer
|
||||||
{
|
{
|
||||||
@@ -30,7 +31,7 @@ namespace Juliet::D3D12
|
|||||||
};
|
};
|
||||||
|
|
||||||
// D3D12 subresourcces: https://learn.microsoft.com/en-us/windows/win32/direct3d12/subresources (mipmaps, etc..)
|
// D3D12 subresourcces: https://learn.microsoft.com/en-us/windows/win32/direct3d12/subresources (mipmaps, etc..)
|
||||||
using D3D12TextureSubresource = struct D3D12TextureSubresource
|
struct D3D12TextureSubresource
|
||||||
{
|
{
|
||||||
D3D12Texture* Parent;
|
D3D12Texture* Parent;
|
||||||
uint32 Layer;
|
uint32 Layer;
|
||||||
@@ -60,4 +61,32 @@ namespace Juliet::D3D12
|
|||||||
// TODO: Should be atomic to support multithreading
|
// TODO: Should be atomic to support multithreading
|
||||||
int32 RefCount;
|
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
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
@@ -1,70 +1,109 @@
|
|||||||
#include <pch.h>
|
#include <pch.h>
|
||||||
|
|
||||||
#include <Core/Memory/Allocator.h>
|
#include <Core/Memory/Allocator.h>
|
||||||
|
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||||
#include <Graphics/D3D12/DX12CommandList.h>
|
#include <Graphics/D3D12/DX12CommandList.h>
|
||||||
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||||
|
#include <Graphics/D3D12/DX12Utils.h>
|
||||||
|
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
namespace
|
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;
|
for (auto& buffer : baseData->Allocator)
|
||||||
auto& queueDesc = driver->QueueDesc[ToUnderlying(queueType)];
|
|
||||||
for (auto& buffer : commandList->CommandAllocator)
|
|
||||||
{
|
{
|
||||||
res = ID3D12Device5_CreateCommandAllocator(driver->D3D12Device, queueDesc.Type, IID_ID3D12CommandAllocator,
|
HRESULT result = ID3D12Device5_CreateCommandAllocator(driver->D3D12Device, queueDesc.Type, IID_ID3D12CommandAllocator,
|
||||||
reinterpret_cast<void**>(&buffer[ToUnderlying(queueType)]));
|
reinterpret_cast<void**>(&buffer));
|
||||||
|
if (FAILED(result))
|
||||||
if (FAILED(res))
|
|
||||||
{
|
{
|
||||||
Assert(false && "Error not implemented: cannot create ID3D12CommandAllocator");
|
Assert(false && "Error not implemented: cannot create ID3D12CommandAllocator");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
auto& commandListSlot = commandList->CommandLists[ToUnderlying(queueType)];
|
bool CreateD3D12CommandListForQueueType(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
|
||||||
if (queueType == QueueType::Graphics || queueType == QueueType::Compute)
|
|
||||||
{
|
{
|
||||||
|
// TODO: String library
|
||||||
|
std::wstring wide_str = L"CommandList ID:" + std::to_wstring(commandList->ID);
|
||||||
|
|
||||||
|
// TODO: Factorize this. Flemme
|
||||||
|
auto& queueDesc = driver->QueueDesc[ToUnderlying(queueType)];
|
||||||
|
switch (queueType)
|
||||||
|
{
|
||||||
|
case QueueType::Graphics:
|
||||||
|
{
|
||||||
|
CreateAllocator(driver, &commandList->GraphicsCommandList, queueDesc);
|
||||||
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
|
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
|
||||||
res = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
HRESULT result =
|
||||||
|
ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||||
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
||||||
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
|
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
|
||||||
if (FAILED(res))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
Assert(false && "Error not implemented: cannot create ID3D12GraphicsCommandList6 (graphics or "
|
Assert(false && "Error not implemented: cannot create ID3D12GraphicsCommandList6 (graphics or "
|
||||||
"compute command list");
|
"compute command list");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
commandListSlot = reinterpret_cast<ID3D12CommandList*>(d3d12GraphicsCommandList);
|
|
||||||
|
commandList->GraphicsCommandList.CommandList = d3d12GraphicsCommandList;
|
||||||
|
ID3D12GraphicsCommandList6_SetName(d3d12GraphicsCommandList, wide_str.c_str());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else if (queueType == QueueType::Copy)
|
case QueueType::Compute:
|
||||||
{
|
{
|
||||||
ID3D12GraphicsCommandList* d3d12CopyCommandList = nullptr;
|
CreateAllocator(driver, &commandList->ComputeCommandList, queueDesc);
|
||||||
res = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
|
||||||
|
HRESULT result =
|
||||||
|
ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||||
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
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));
|
reinterpret_cast<void**>(&d3d12CopyCommandList));
|
||||||
if (FAILED(res))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
Assert(false &&
|
Assert(false &&
|
||||||
"Error not implemented: cannot create ID3D12GraphicsCommandList (copy command list)");
|
"Error not implemented: cannot create ID3D12GraphicsCommandList (copy command list)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
commandListSlot = reinterpret_cast<ID3D12CommandList*>(d3d12CopyCommandList);
|
commandList->CopyCommandList.CommandList = d3d12CopyCommandList;
|
||||||
}
|
ID3D12GraphicsCommandList_SetName(d3d12CopyCommandList, wide_str.c_str());
|
||||||
|
|
||||||
// TODO: String library
|
|
||||||
std::wstring wide_str = L"CommandList ID:" + std::to_wstring(commandList->ID);
|
|
||||||
ID3D12GraphicsCommandList_SetName(commandListSlot, wide_str.c_str());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool AllocateCommandList(NonNullPtr<D3D12Driver> driver, QueueType queueType)
|
bool AllocateCommandList(NonNullPtr<D3D12Driver> driver, QueueType queueType)
|
||||||
{
|
{
|
||||||
@@ -72,6 +111,7 @@ namespace Juliet::D3D12
|
|||||||
if (!commandList)
|
if (!commandList)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "Cannot allocate D3D12CommandList: Out of memory");
|
Log(LogLevel::Error, LogCategory::Graphics, "Cannot allocate D3D12CommandList: Out of memory");
|
||||||
|
Internal::DestroyCommandList(commandList);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,15 +120,20 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
if (!resizedArray)
|
if (!resizedArray)
|
||||||
{
|
{
|
||||||
Assert(false &&
|
Log(LogLevel::Error, LogCategory::Graphics,
|
||||||
"Error not implemented, out of memory, handle that by deallocating stuff and returning false");
|
"Error not implemented, out of memory, handle that by deallocating stuff and returning false");
|
||||||
|
Internal::DestroyCommandList(commandList);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 id = driver->AvailableCommandListCapacity;
|
||||||
|
driver->AvailableCommandListCapacity += 1;
|
||||||
driver->AvailableCommandLists = resizedArray;
|
driver->AvailableCommandLists = resizedArray;
|
||||||
driver->AvailableCommandLists[driver->AvailableCommandListCapacity] = commandList;
|
|
||||||
|
|
||||||
commandList->ID = driver->AvailableCommandListCapacity;
|
driver->AvailableCommandLists[driver->AvailableCommandListCount] = commandList;
|
||||||
|
driver->AvailableCommandListCount += 1;
|
||||||
|
|
||||||
|
commandList->ID = id;
|
||||||
commandList->Driver = driver;
|
commandList->Driver = driver;
|
||||||
|
|
||||||
commandList->PresentDataCapacity = 1;
|
commandList->PresentDataCapacity = 1;
|
||||||
@@ -96,58 +141,298 @@ namespace Juliet::D3D12
|
|||||||
commandList->PresentDatas =
|
commandList->PresentDatas =
|
||||||
static_cast<D3D12PresentData*>(Calloc(commandList->PresentDataCapacity, sizeof(D3D12PresentData)));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
|
||||||
ID3D12GraphicsCommandList6* GetGraphicsCommandList(NonNullPtr<D3D12CommandList> commandList)
|
D3D12CommandList* AcquireCommandListFromPool(NonNullPtr<D3D12Driver> driver, QueueType queueType)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<ID3D12GraphicsCommandList6*>(commandList->CommandLists[ToUnderlying(QueueType::Graphics)]);
|
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)
|
CommandList* AcquireCommandList(NonNullPtr<GPUDriver> driver, QueueType queueType)
|
||||||
{
|
{
|
||||||
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
|
|
||||||
uint8 currentCommandListIndex = d3d12Driver->CommandListCount;
|
D3D12CommandList* commandList = AcquireCommandListFromPool(d3d12Driver, queueType);
|
||||||
if (currentCommandListIndex >= d3d12Driver->AvailableCommandListCapacity)
|
|
||||||
|
// 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];
|
commandList->AutoReleaseFence = true;
|
||||||
if (!HasD3D12CommandList(commandList, queueType))
|
|
||||||
{
|
|
||||||
if (!CreateD3D12CommandList(d3d12Driver, commandList, queueType))
|
|
||||||
{
|
|
||||||
// TODO Shoud destroy the command list here
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reinterpret_cast<CommandList*>(commandList);
|
return reinterpret_cast<CommandList*>(commandList);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SubmitCommandLists(NonNullPtr<GPUDriver> driver)
|
bool SubmitCommandLists(NonNullPtr<CommandList> commandList)
|
||||||
{
|
{
|
||||||
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||||
bool success = true;
|
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
|
D3D12_RESOURCE_BARRIER barrierDesc;
|
||||||
HRESULT result = IDXGISwapChain_Present(d3d12Driver->WindowData->SwapChain, 0, 1);
|
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))
|
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;
|
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
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
@@ -1,15 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/EnumUtils.h>
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/NonNullPtr.h>
|
||||||
|
#include <Core/Math/Shape.h>
|
||||||
#include <Graphics/D3D12/DX12Includes.h>
|
#include <Graphics/D3D12/DX12Includes.h>
|
||||||
#include <Graphics/GraphicsDevice.h>
|
#include <Graphics/GraphicsDevice.h>
|
||||||
|
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
|
// Forward Declare
|
||||||
struct D3D12Driver;
|
struct D3D12Driver;
|
||||||
|
struct D3D12Fence;
|
||||||
|
struct D3D12TextureSubresource;
|
||||||
struct D3D12WindowData;
|
struct D3D12WindowData;
|
||||||
|
|
||||||
|
struct D3D12CommandListBaseData
|
||||||
|
{
|
||||||
|
ID3D12CommandAllocator* Allocator[GPUDriver::kResourceBufferCount];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct D3D12CopyCommandListData : D3D12CommandListBaseData
|
||||||
|
{
|
||||||
|
ID3D12GraphicsCommandList* CommandList;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct D3D12GraphicsCommandListData : D3D12CommandListBaseData
|
||||||
|
{
|
||||||
|
ID3D12GraphicsCommandList6* CommandList;
|
||||||
|
};
|
||||||
|
|
||||||
struct D3D12PresentData
|
struct D3D12PresentData
|
||||||
{
|
{
|
||||||
D3D12WindowData* WindowData;
|
D3D12WindowData* WindowData;
|
||||||
@@ -27,13 +45,27 @@ namespace Juliet::D3D12
|
|||||||
uint32 PresentDataCapacity;
|
uint32 PresentDataCapacity;
|
||||||
uint32 PresentDataCount;
|
uint32 PresentDataCount;
|
||||||
|
|
||||||
// We create kResourceBufferCount allocator per queue to allow reusing the command list every N frames
|
D3D12Fence* InFlightFence;
|
||||||
ID3D12CommandAllocator* CommandAllocator[GPUDriver::kResourceBufferCount][ToUnderlying(QueueType::Count)];
|
bool AutoReleaseFence;
|
||||||
ID3D12CommandList* CommandLists[ToUnderlying(QueueType::Count)];
|
|
||||||
|
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 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
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <core/Common/NonNullPtr.h>
|
#include <core/Common/NonNullPtr.h>
|
||||||
#include <Core/DynLib/DynamicLibrary.h>
|
#include <Core/DynLib/DynamicLibrary.h>
|
||||||
#include <Core/Memory/Allocator.h>
|
#include <Core/Memory/Allocator.h>
|
||||||
|
#include <Graphics/D3D12/D3D12RenderPass.h>
|
||||||
|
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||||
#include <Graphics/D3D12/DX12CommandList.h>
|
#include <Graphics/D3D12/DX12CommandList.h>
|
||||||
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||||
#include <Graphics/D3D12/DX12Includes.h>
|
#include <Graphics/D3D12/DX12Includes.h>
|
||||||
@@ -167,15 +169,42 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
void DestroyDriver_Internal(NonNullPtr<D3D12Driver> driver)
|
void DestroyDriver_Internal(NonNullPtr<D3D12Driver> driver)
|
||||||
{
|
{
|
||||||
|
// Destroy pools
|
||||||
for (uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1)
|
for (uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1)
|
||||||
{
|
{
|
||||||
if (driver->StagingDescriptorPools[i])
|
if (driver->StagingDescriptorPools[i])
|
||||||
{
|
{
|
||||||
DestroyStagingDescriptorPool(driver->StagingDescriptorPools[i]);
|
Internal::DestroyStagingDescriptorPool(driver->StagingDescriptorPools[i]);
|
||||||
driver->StagingDescriptorPools[i] = nullptr;
|
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)
|
if (driver->IndirectDrawCommandSignature)
|
||||||
{
|
{
|
||||||
ID3D12CommandSignature_Release(driver->IndirectDrawCommandSignature);
|
ID3D12CommandSignature_Release(driver->IndirectDrawCommandSignature);
|
||||||
@@ -249,7 +278,7 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
windowData->Window = window;
|
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.");
|
Log(LogLevel::Error, LogCategory::Graphics, "AttachToWindow failure: Cannot create Swap Chain.");
|
||||||
Free(windowData);
|
Free(windowData);
|
||||||
@@ -265,12 +294,21 @@ namespace Juliet::D3D12
|
|||||||
void DetachFromWindow(NonNullPtr<GPUDriver> driver, NonNullPtr<Window> window)
|
void DetachFromWindow(NonNullPtr<GPUDriver> driver, NonNullPtr<Window> window)
|
||||||
{
|
{
|
||||||
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
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);
|
Free(d3d12Driver->WindowData);
|
||||||
d3d12Driver->WindowData = nullptr;
|
d3d12Driver->WindowData = nullptr;
|
||||||
@@ -517,27 +555,46 @@ namespace Juliet::D3D12
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto device = static_cast<GraphicsDevice*>(Calloc(1, sizeof(GraphicsDevice)));
|
// Create Pools
|
||||||
if (!device)
|
driver->SubmittedCommandListCapacity = 4;
|
||||||
|
driver->SubmittedCommandListCount = 0;
|
||||||
|
driver->SubmittedCommandLists =
|
||||||
|
static_cast<D3D12CommandList**>(Calloc(driver->SubmittedCommandListCapacity, sizeof(D3D12CommandList*)));
|
||||||
|
if (!driver->SubmittedCommandLists)
|
||||||
{
|
{
|
||||||
DestroyDriver_Internal(driver);
|
DestroyDriver_Internal(driver);
|
||||||
return nullptr;
|
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)
|
for (uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1)
|
||||||
{
|
{
|
||||||
driver->StagingDescriptorPools[i] =
|
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)
|
if (driver->StagingDescriptorPools[i] == nullptr)
|
||||||
{
|
{
|
||||||
DestroyDriver_Internal(driver);
|
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
|
// Assign Functions to the device
|
||||||
device->DestroyDevice = DestroyGraphicsDevice;
|
device->DestroyDevice = DestroyGraphicsDevice;
|
||||||
|
|
||||||
@@ -549,6 +606,18 @@ namespace Juliet::D3D12
|
|||||||
device->AcquireCommandList = AcquireCommandList;
|
device->AcquireCommandList = AcquireCommandList;
|
||||||
device->SubmitCommandLists = SubmitCommandLists;
|
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;
|
device->Driver = driver;
|
||||||
driver->GraphicsDevice = device;
|
driver->GraphicsDevice = device;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ namespace Juliet
|
|||||||
|
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
|
// Forward Declare
|
||||||
struct D3D12CommandList;
|
struct D3D12CommandList;
|
||||||
|
struct D3D12Fence;
|
||||||
|
|
||||||
struct D3D12WindowData
|
struct D3D12WindowData
|
||||||
{
|
{
|
||||||
@@ -26,7 +28,9 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
PresentMode PresentMode;
|
PresentMode PresentMode;
|
||||||
|
|
||||||
uint32 FrameCounter;
|
Fence* InFlightFences[GPUDriver::kMaxFramesInFlight];
|
||||||
|
|
||||||
|
uint32 WindowFrameCounter; // Specific to that window. See GraphicsDevice for global counter
|
||||||
uint32 Width;
|
uint32 Width;
|
||||||
uint32 Height;
|
uint32 Height;
|
||||||
};
|
};
|
||||||
@@ -63,10 +67,20 @@ namespace Juliet::D3D12
|
|||||||
// Resources
|
// Resources
|
||||||
D3D12CommandList** AvailableCommandLists;
|
D3D12CommandList** AvailableCommandLists;
|
||||||
uint8 AvailableCommandListCapacity;
|
uint8 AvailableCommandListCapacity;
|
||||||
|
uint8 AvailableCommandListCount;
|
||||||
|
|
||||||
|
D3D12CommandList** SubmittedCommandLists;
|
||||||
|
uint8 SubmittedCommandListCapacity;
|
||||||
|
uint8 SubmittedCommandListCount;
|
||||||
|
|
||||||
|
D3D12Fence** AvailableFences;
|
||||||
|
uint32 AvailableFenceCount;
|
||||||
|
uint32 AvailableFenceCapacity;
|
||||||
|
|
||||||
D3D12StagingDescriptorPool* StagingDescriptorPools[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
|
D3D12StagingDescriptorPool* StagingDescriptorPools[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
|
||||||
|
|
||||||
uint8 FramesInFlight;
|
uint8 FramesInFlight;
|
||||||
|
uint64 FrameCounter = 0; // Number of frame since inception
|
||||||
|
|
||||||
bool IsTearingSupported : 1;
|
bool IsTearingSupported : 1;
|
||||||
bool IsUMAAvailable : 1;
|
bool IsUMAAvailable : 1;
|
||||||
|
|||||||
@@ -26,3 +26,6 @@
|
|||||||
#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
|
#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
|
||||||
#define IDXGIINFOQUEUE_SUPPORTED
|
#define IDXGIINFOQUEUE_SUPPORTED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
#include <Core/HAL/Display/Win32/Win32Window.h>
|
#include <Core/HAL/Display/Win32/Win32Window.h>
|
||||||
#include <Core/Memory/Allocator.h>
|
#include <Core/Memory/Allocator.h>
|
||||||
#include <Graphics/D3D12/D3D12Texture.h>
|
#include <Graphics/D3D12/D3D12Texture.h>
|
||||||
|
#include <Graphics/D3D12/DX12CommandList.h>
|
||||||
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||||
#include <Graphics/D3D12/DX12Includes.h>
|
#include <Graphics/D3D12/DX12Includes.h>
|
||||||
#include <Graphics/D3D12/DX12SwapChain.h>
|
#include <Graphics/D3D12/DX12SwapChain.h>
|
||||||
#include <Graphics/D3D12/DX12Utils.h>
|
#include <Graphics/D3D12/DX12Utils.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <DX12CommandList.h>
|
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
@@ -105,7 +106,7 @@ namespace Juliet::D3D12
|
|||||||
texture->IndexInContainer = 0;
|
texture->IndexInContainer = 0;
|
||||||
|
|
||||||
// Assign SRV to the swapchain texture
|
// 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;
|
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||||
srvDesc.Format = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
|
srvDesc.Format = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
|
||||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||||
@@ -118,7 +119,7 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
// Assign RTV to the swapchain texture
|
// Assign RTV to the swapchain texture
|
||||||
DXGI_FORMAT swapchainFormat = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
|
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;
|
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
|
||||||
rtvDesc.Format = (composition == SwapChainComposition::SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : swapchainFormat;
|
rtvDesc.Format = (composition == SwapChainComposition::SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : swapchainFormat;
|
||||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||||
@@ -162,9 +163,8 @@ namespace Juliet::D3D12
|
|||||||
if (d3d12CommandList->PresentDataCount == d3d12CommandList->PresentDataCapacity)
|
if (d3d12CommandList->PresentDataCount == d3d12CommandList->PresentDataCapacity)
|
||||||
{
|
{
|
||||||
d3d12CommandList->PresentDataCapacity += 1;
|
d3d12CommandList->PresentDataCapacity += 1;
|
||||||
d3d12CommandList->PresentDatas =
|
d3d12CommandList->PresentDatas = static_cast<D3D12PresentData*>(
|
||||||
static_cast<D3D12PresentData*>(Realloc(d3d12CommandList->PresentDatas,
|
Realloc(d3d12CommandList->PresentDatas, d3d12CommandList->PresentDataCapacity * sizeof(D3D12PresentData)));
|
||||||
d3d12CommandList->PresentDataCapacity * sizeof(D3D12PresentData)));
|
|
||||||
}
|
}
|
||||||
d3d12CommandList->PresentDatas[d3d12CommandList->PresentDataCount].WindowData = windowData;
|
d3d12CommandList->PresentDatas[d3d12CommandList->PresentDataCount].WindowData = windowData;
|
||||||
d3d12CommandList->PresentDatas[d3d12CommandList->PresentDataCount].SwapChainImageIndex = swapchainIndex;
|
d3d12CommandList->PresentDatas[d3d12CommandList->PresentDataCount].SwapChainImageIndex = swapchainIndex;
|
||||||
@@ -179,7 +179,7 @@ namespace Juliet::D3D12
|
|||||||
barrierDesc.Transition.pResource = windowData->SwapChainTextureContainers[swapchainIndex].ActiveTexture->Resource;
|
barrierDesc.Transition.pResource = windowData->SwapChainTextureContainers[swapchainIndex].ActiveTexture->Resource;
|
||||||
barrierDesc.Transition.Subresource = 0;
|
barrierDesc.Transition.Subresource = 0;
|
||||||
|
|
||||||
ID3D12GraphicsCommandList_ResourceBarrier(GetGraphicsCommandList(d3d12CommandList), 1, &barrierDesc);
|
ID3D12GraphicsCommandList_ResourceBarrier(d3d12CommandList->GraphicsCommandList.CommandList, 1, &barrierDesc);
|
||||||
|
|
||||||
*swapchainTexture = reinterpret_cast<Texture*>(&windowData->SwapChainTextureContainers[swapchainIndex]);
|
*swapchainTexture = reinterpret_cast<Texture*>(&windowData->SwapChainTextureContainers[swapchainIndex]);
|
||||||
|
|
||||||
@@ -187,6 +187,13 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window, Texture** swapChainTexture)
|
||||||
|
{
|
||||||
|
return AcquireSwapChainTexture(false, commandList, window, swapChainTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Internal
|
||||||
|
{
|
||||||
bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
||||||
SwapChainComposition composition, PresentMode presentMode)
|
SwapChainComposition composition, PresentMode presentMode)
|
||||||
{
|
{
|
||||||
@@ -281,7 +288,7 @@ namespace Juliet::D3D12
|
|||||||
windowData->SwapChain = swapChain3;
|
windowData->SwapChain = swapChain3;
|
||||||
windowData->SwapChainColorSpace = SwapchainCompositionToColorSpace[ToUnderlying(composition)];
|
windowData->SwapChainColorSpace = SwapchainCompositionToColorSpace[ToUnderlying(composition)];
|
||||||
windowData->SwapChainComposition = composition;
|
windowData->SwapChainComposition = composition;
|
||||||
windowData->FrameCounter = 0;
|
windowData->WindowFrameCounter = 0;
|
||||||
windowData->Width = swapChainDesc.Width;
|
windowData->Width = swapChainDesc.Width;
|
||||||
windowData->Height = swapChainDesc.Height;
|
windowData->Height = swapChainDesc.Height;
|
||||||
windowData->PresentMode = presentMode;
|
windowData->PresentMode = presentMode;
|
||||||
@@ -298,17 +305,13 @@ namespace Juliet::D3D12
|
|||||||
return true;
|
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)
|
void DestroySwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData)
|
||||||
{
|
{
|
||||||
for (uint32 idx = 0; idx < windowData->SwapChainTextureCount; ++idx)
|
for (uint32 idx = 0; idx < windowData->SwapChainTextureCount; ++idx)
|
||||||
{
|
{
|
||||||
ReleaseStagingDescriptor(driver, windowData->SwapChainTextureContainers[idx].ActiveTexture->SRVHandle);
|
ReleaseStagingDescriptor(driver, windowData->SwapChainTextureContainers[idx].ActiveTexture->SRVHandle);
|
||||||
ReleaseStagingDescriptor(driver, windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles[0]);
|
ReleaseStagingDescriptor(driver,
|
||||||
|
windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles[0]);
|
||||||
|
|
||||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles);
|
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles);
|
||||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources);
|
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources);
|
||||||
@@ -319,4 +322,5 @@ namespace Juliet::D3D12
|
|||||||
IDXGISwapChain_Release(windowData->SwapChain);
|
IDXGISwapChain_Release(windowData->SwapChain);
|
||||||
windowData->SwapChain = nullptr;
|
windowData->SwapChain = nullptr;
|
||||||
}
|
}
|
||||||
|
} // namespace Internal
|
||||||
} // namespace Juliet::D3D12
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
@@ -3,11 +3,16 @@
|
|||||||
|
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
|
// Forward Declare
|
||||||
struct D3D12Driver;
|
struct D3D12Driver;
|
||||||
struct D3D12WindowData;
|
struct D3D12WindowData;
|
||||||
|
|
||||||
|
extern bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window, Texture** swapChainTexture);
|
||||||
|
|
||||||
|
namespace Internal
|
||||||
|
{
|
||||||
extern bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
extern bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
||||||
SwapChainComposition composition, PresentMode presentMode);
|
SwapChainComposition composition, PresentMode presentMode);
|
||||||
extern bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window, Texture** swapChainTexture);
|
|
||||||
extern void DestroySwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData);
|
extern void DestroySwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData);
|
||||||
|
} // namespace Internal
|
||||||
} // namespace Juliet::D3D12
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure valid range
|
// Ensure valid range
|
||||||
dwChars = std::min<DWORD>(dwChars, MAX_ERROR_LEN);
|
dwChars = Min<DWORD>(dwChars, MAX_ERROR_LEN);
|
||||||
|
|
||||||
// Trim whitespace from tail of message
|
// Trim whitespace from tail of message
|
||||||
while (dwChars > 0)
|
while (dwChars > 0)
|
||||||
|
|||||||
@@ -65,9 +65,7 @@ namespace Juliet
|
|||||||
bool AttachToWindow(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
|
bool AttachToWindow(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
|
||||||
{
|
{
|
||||||
GPUDriver* driver = device->Driver;
|
GPUDriver* driver = device->Driver;
|
||||||
bool result = device->AttachToWindow(driver, window);
|
return device->AttachToWindow(driver, window);
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DetachFromWindow(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
|
void DetachFromWindow(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
|
||||||
@@ -93,7 +91,6 @@ namespace Juliet
|
|||||||
{
|
{
|
||||||
GPUDriver* driver = device->Driver;
|
GPUDriver* driver = device->Driver;
|
||||||
CommandList* cmdList = device->AcquireCommandList(driver, queueType);
|
CommandList* cmdList = device->AcquireCommandList(driver, queueType);
|
||||||
|
|
||||||
if (!cmdList)
|
if (!cmdList)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -101,18 +98,81 @@ namespace Juliet
|
|||||||
|
|
||||||
auto header = reinterpret_cast<CommandListHeader*>(cmdList);
|
auto header = reinterpret_cast<CommandListHeader*>(cmdList);
|
||||||
header->Device = device.Get();
|
header->Device = device.Get();
|
||||||
|
header->RenderPass.CommandList = cmdList;
|
||||||
driver->CommandListCount += 1;
|
|
||||||
|
|
||||||
return cmdList;
|
return cmdList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubmitCommandLists(NonNullPtr<GraphicsDevice> device)
|
void SubmitCommandLists(NonNullPtr<CommandList> commandList)
|
||||||
{
|
{
|
||||||
GPUDriver* driver = device->Driver;
|
auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList.Get());
|
||||||
device->SubmitCommandLists(driver);
|
|
||||||
|
|
||||||
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
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -7,25 +7,31 @@
|
|||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
struct Window;
|
|
||||||
|
|
||||||
struct TextureHeader
|
struct TextureHeader
|
||||||
{
|
{
|
||||||
TextureCreateInfo CreateInfo;
|
TextureCreateInfo CreateInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GPUPass
|
||||||
|
{
|
||||||
|
CommandList* CommandList;
|
||||||
|
bool IsInProgress : 1;
|
||||||
|
};
|
||||||
|
|
||||||
struct CommandListHeader
|
struct CommandListHeader
|
||||||
{
|
{
|
||||||
GraphicsDevice* Device = nullptr;
|
GraphicsDevice* Device = nullptr;
|
||||||
bool AcquiredSwapChain = false;
|
bool AcquiredSwapChain = false;
|
||||||
|
bool Submitted = false;
|
||||||
|
|
||||||
|
GPUPass RenderPass;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GPUDriver
|
struct GPUDriver
|
||||||
{
|
{
|
||||||
uint8 CommandListCount;
|
|
||||||
|
|
||||||
static constexpr uint8 kResourceBufferCount = 2;
|
static constexpr uint8 kResourceBufferCount = 2;
|
||||||
static constexpr uint8 kMaxFramesInFlight = 3;
|
static constexpr uint8 kMaxFramesInFlight = 3;
|
||||||
|
static constexpr uint8 kMaxColorTargetInfo = 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GraphicsDevice
|
struct GraphicsDevice
|
||||||
@@ -41,7 +47,22 @@ namespace Juliet
|
|||||||
|
|
||||||
// CommandLists
|
// CommandLists
|
||||||
CommandList* (*AcquireCommandList)(NonNullPtr<GPUDriver> driver, QueueType queueType);
|
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";
|
const char* Name = "Unknown";
|
||||||
GPUDriver* Driver = nullptr;
|
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
|
- 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
|
// TODO : Replace with message box from framework + call main and not winmain + subsystem
|
||||||
#include <Core/DynLib/DynamicLibrary.h>
|
#include <Core/DynLib/DynamicLibrary.h>
|
||||||
#include <Graphics/Graphics.h>
|
#include <Graphics/Graphics.h>
|
||||||
|
#include <Graphics/RenderPass.h>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
// TODO : Think how to do the draw pipeline.
|
// TODO : Think how to do the draw pipeline.
|
||||||
@@ -97,8 +98,20 @@ void Win32EditorApplication::Update()
|
|||||||
return;
|
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
|
// Submit Commands
|
||||||
SubmitCommandLists(GraphicsDevice);
|
SubmitCommandLists(cmdList);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32EditorApplication::IsRunning()
|
bool Win32EditorApplication::IsRunning()
|
||||||
|
|||||||
Reference in New Issue
Block a user