Renderpass first iteration
This commit is contained in:
@@ -134,9 +134,11 @@
|
|||||||
<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\Texture.h" />
|
<ClInclude Include="include\Graphics\RenderPass.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"/>
|
||||||
<ClInclude Include="src\Core\HAL\Display\DisplayDevice.h"/>
|
<ClInclude Include="src\Core\HAL\Display\DisplayDevice.h"/>
|
||||||
@@ -151,8 +153,10 @@
|
|||||||
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h"/>
|
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h"/>
|
||||||
<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\D3D12Texture.h" />
|
<ClInclude Include="src\Graphics\D3D12\D3D12RenderPass.h"/>
|
||||||
|
<ClInclude Include="src\Graphics\D3D12\D3D12Synchronization.h" />
|
||||||
|
<ClInclude Include="src\Graphics\D3D12\D3D12Texture.h"/>
|
||||||
<ClInclude Include="src\Graphics\D3D12\DX12CommandList.h"/>
|
<ClInclude Include="src\Graphics\D3D12\DX12CommandList.h"/>
|
||||||
<ClInclude Include="src\Graphics\D3D12\DX12GraphicsDevice.h"/>
|
<ClInclude Include="src\Graphics\D3D12\DX12GraphicsDevice.h"/>
|
||||||
<ClInclude Include="src\Graphics\D3D12\DX12Includes.h"/>
|
<ClInclude Include="src\Graphics\D3D12\DX12Includes.h"/>
|
||||||
@@ -235,12 +239,14 @@
|
|||||||
<ClCompile Include="src\Core\Networking\TcpSocket.cpp"/>
|
<ClCompile Include="src\Core\Networking\TcpSocket.cpp"/>
|
||||||
<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\D3D12Texture.cpp" />
|
<ClCompile Include="src\Graphics\D3D12\D3D12RenderPass.cpp"/>
|
||||||
|
<ClCompile Include="src\Graphics\D3D12\D3D12Synchronization.cpp" />
|
||||||
|
<ClCompile Include="src\Graphics\D3D12\D3D12Texture.cpp"/>
|
||||||
<ClCompile Include="src\Graphics\D3D12\DX12CommandList.cpp"/>
|
<ClCompile Include="src\Graphics\D3D12\DX12CommandList.cpp"/>
|
||||||
<ClCompile Include="src\Graphics\D3D12\DX12GraphicsDevice.cpp"/>
|
<ClCompile Include="src\Graphics\D3D12\DX12GraphicsDevice.cpp"/>
|
||||||
<ClCompile Include="src\Graphics\D3D12\DX12SwapChain.cpp"/>
|
<ClCompile Include="src\Graphics\D3D12\DX12SwapChain.cpp"/>
|
||||||
<ClCompile Include="src\Graphics\D3D12\DX12Utils.cpp" />
|
<ClCompile Include="src\Graphics\D3D12\DX12Utils.cpp"/>
|
||||||
<ClCompile Include="src\Graphics\Graphics.cpp">
|
<ClCompile Include="src\Graphics\Graphics.cpp">
|
||||||
<RuntimeLibrary>MultiThreadedDebugDll</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDll</RuntimeLibrary>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
@@ -302,7 +308,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="include\Core\Thread\Mutex.h"/>
|
<Content Include="include\Core\Thread\Mutex.h"/>
|
||||||
<Content Include="src\TODO.txt" />
|
<Content Include="src\TODO.txt"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
@@ -35,4 +36,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
|
||||||
|
|||||||
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,14 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <core/Common/NonNullPtr.h>
|
#include <core/Common/NonNullPtr.h>
|
||||||
|
#include <Core/HAL/Display/Display.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;
|
||||||
|
|
||||||
// Parameters of an indirect draw command
|
// Parameters of an indirect draw command
|
||||||
@@ -65,9 +67,6 @@ namespace Juliet
|
|||||||
Immediate
|
Immediate
|
||||||
};
|
};
|
||||||
|
|
||||||
// Opaque types
|
|
||||||
struct CommandList;
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@@ -82,4 +81,9 @@ 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<GraphicsDevice> device);
|
||||||
|
|
||||||
|
// 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);
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
40
Juliet/include/Graphics/RenderPass.h
Normal file
40
Juliet/include/Graphics/RenderPass.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#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* Texture;
|
||||||
|
uint32 MipLevel;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32 DepthPlane;
|
||||||
|
uint32 LayerCount;
|
||||||
|
};
|
||||||
|
FColor ClearColor;
|
||||||
|
LoadOperation LoadOperation;
|
||||||
|
StoreOperation StoreOperation;
|
||||||
|
bool Cycle; // Whether the texture should be cycled if already bound (and load operation != LOAD)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Opaque Type
|
||||||
|
struct RenderPass;
|
||||||
|
} // namespace Juliet
|
||||||
@@ -161,9 +161,9 @@ namespace Juliet
|
|||||||
// Create Information structs
|
// Create Information structs
|
||||||
struct TextureCreateInfo
|
struct TextureCreateInfo
|
||||||
{
|
{
|
||||||
TextureType Type;
|
TextureType Type;
|
||||||
TextureFormat Format;
|
TextureFormat Format;
|
||||||
TextureUsageFlag Flags;
|
TextureUsageFlag Flags;
|
||||||
TextureSampleCount SampleCount;
|
TextureSampleCount SampleCount;
|
||||||
|
|
||||||
uint32 Width;
|
uint32 Width;
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
57
Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp
Normal file
57
Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#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].Texture);
|
||||||
|
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].Texture);
|
||||||
|
D3D12TextureSubresource* subresource = PrepareTextureSubresourceForWrite(
|
||||||
|
d3d12CommandList, container,
|
||||||
|
container->Header.CreateInfo.Type == TextureType::Texture_3D ? 0 : colorTargetInfos[idx].LayerCount,
|
||||||
|
colorTargetInfos[idx].MipLevel, colorTargetInfos[idx].Cycle, 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Juliet::D3D12
|
||||||
11
Juliet/src/Graphics/D3D12/D3D12RenderPass.h
Normal file
11
Juliet/src/Graphics/D3D12/D3D12RenderPass.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
41
Juliet/src/Graphics/D3D12/D3D12Synchronization.cpp
Normal file
41
Juliet/src/Graphics/D3D12/D3D12Synchronization.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <pch.h>
|
||||||
|
|
||||||
|
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||||
|
#include <Graphics/D3D12/DX12CommandList.h>
|
||||||
|
|
||||||
|
namespace Juliet::D3D12
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Juliet::D3D12
|
||||||
14
Juliet/src/Graphics/D3D12/D3D12Synchronization.h
Normal file
14
Juliet/src/Graphics/D3D12/D3D12Synchronization.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/NonNullPtr.h>
|
||||||
|
#include <Graphics/D3D12/D3D12Common.h>
|
||||||
|
|
||||||
|
namespace Juliet::D3D12
|
||||||
|
{
|
||||||
|
// Forward Declare
|
||||||
|
struct D3D12CommandList;
|
||||||
|
|
||||||
|
extern void ResourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState, D3D12_RESOURCE_STATES destinationState,
|
||||||
|
ID3D12Resource* resource, uint32 subresourceIndex, bool needsUavBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,8 +1,102 @@
|
|||||||
#include <pch.h>
|
#include <pch.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
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTextureSubresourceTransitionFromDefault(NonNullPtr<D3D12CommandList> commandList,
|
||||||
|
NonNullPtr<D3D12TextureSubresource> subresource,
|
||||||
|
D3D12_RESOURCE_STATES newTextureUsage)
|
||||||
|
{
|
||||||
|
D3D12_RESOURCE_STATES defaultUsage =
|
||||||
|
GetDefaultTextureResourceState(subresource->Parent->Container->Header.CreateInfo.Flags);
|
||||||
|
TextureSubresourceBarrier(commandList, defaultUsage, newTextureUsage, subresource);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTextureTransitionFromDefault(NonNullPtr<D3D12CommandList> commandList, NonNullPtr<D3D12Texture> texture,
|
||||||
|
D3D12_RESOURCE_STATES newTextureUsage)
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < texture->SubresourceCount; ++i)
|
||||||
|
{
|
||||||
|
SetTextureSubresourceTransitionFromDefault(commandList, &texture->Subresources[i], newTextureUsage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
D3D12TextureSubresource* PrepareTextureSubresourceForWrite(NonNullPtr<D3D12CommandList> commandList,
|
||||||
|
NonNullPtr<D3D12TextureContainer> container, uint32 layer,
|
||||||
|
uint32 level, bool shouldCycle, D3D12_RESOURCE_STATES newTextureUsage)
|
||||||
|
{
|
||||||
|
D3D12TextureSubresource* subresource = 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 = FetchTextureSubresource(container, layer, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetTextureSubresourceTransitionFromDefault(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);
|
||||||
|
ResourceBarrier(commandList, sourceState, destinationState, textureSubresource->Parent->Resource,
|
||||||
|
textureSubresource->Index, needsUAVBarrier);
|
||||||
|
}
|
||||||
|
} // 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,13 @@ namespace Juliet::D3D12
|
|||||||
// TODO: Should be atomic to support multithreading
|
// TODO: Should be atomic to support multithreading
|
||||||
int32 RefCount;
|
int32 RefCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
} // namespace Juliet::D3D12
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
@@ -3,67 +3,105 @@
|
|||||||
#include <Core/Memory/Allocator.h>
|
#include <Core/Memory/Allocator.h>
|
||||||
#include <Graphics/D3D12/DX12CommandList.h>
|
#include <Graphics/D3D12/DX12CommandList.h>
|
||||||
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||||
|
#define IID_PPV_ARGS(ppType) __uuidof(decltype(**(ppType))), reinterpret_cast<void**>(ppType)
|
||||||
|
#define PPV_ARGS(x) IID_PPV_ARGS(&x)
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
bool HasD3D12CommandList(NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
|
bool HasD3D12CommandList(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 CreateD3D12CommandList(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
|
||||||
if (queueType == QueueType::Graphics || queueType == QueueType::Compute)
|
{
|
||||||
{
|
|
||||||
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
|
|
||||||
res = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
|
||||||
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
|
||||||
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
|
|
||||||
if (FAILED(res))
|
|
||||||
{
|
|
||||||
Assert(false && "Error not implemented: cannot create ID3D12GraphicsCommandList6 (graphics or "
|
|
||||||
"compute command list");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
commandListSlot = reinterpret_cast<ID3D12CommandList*>(d3d12GraphicsCommandList);
|
|
||||||
}
|
|
||||||
else if (queueType == QueueType::Copy)
|
|
||||||
{
|
|
||||||
ID3D12GraphicsCommandList* d3d12CopyCommandList = nullptr;
|
|
||||||
res = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
|
||||||
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
|
||||||
reinterpret_cast<void**>(&d3d12CopyCommandList));
|
|
||||||
if (FAILED(res))
|
|
||||||
{
|
|
||||||
Assert(false &&
|
|
||||||
"Error not implemented: cannot create ID3D12GraphicsCommandList (copy command list)");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
commandListSlot = reinterpret_cast<ID3D12CommandList*>(d3d12CopyCommandList);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: String library
|
// TODO: String library
|
||||||
std::wstring wide_str = L"CommandList ID:" + std::to_wstring(commandList->ID);
|
std::wstring wide_str = L"CommandList ID:" + std::to_wstring(commandList->ID);
|
||||||
ID3D12GraphicsCommandList_SetName(commandListSlot, wide_str.c_str());
|
|
||||||
|
|
||||||
return true;
|
// TODO: Factorize this. Flemme
|
||||||
|
auto& queueDesc = driver->QueueDesc[ToUnderlying(queueType)];
|
||||||
|
switch (queueType)
|
||||||
|
{
|
||||||
|
case QueueType::Graphics:
|
||||||
|
{
|
||||||
|
CreateAllocator(driver, &commandList->GraphicsCommandList, queueDesc);
|
||||||
|
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
|
||||||
|
HRESULT result =
|
||||||
|
ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||||
|
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
||||||
|
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
Assert(false && "Error not implemented: cannot create ID3D12GraphicsCommandList6 (graphics or "
|
||||||
|
"compute command list");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
commandList->GraphicsCommandList.CommandList = d3d12GraphicsCommandList;
|
||||||
|
ID3D12GraphicsCommandList6_SetName(d3d12GraphicsCommandList, wide_str.c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case QueueType::Compute:
|
||||||
|
{
|
||||||
|
CreateAllocator(driver, &commandList->ComputeCommandList, queueDesc);
|
||||||
|
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
|
||||||
|
HRESULT result =
|
||||||
|
ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||||
|
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
||||||
|
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
Assert(false && "Error not implemented: cannot create ID3D12GraphicsCommandList6 (graphics or "
|
||||||
|
"compute command list");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
commandList->ComputeCommandList.CommandList = d3d12GraphicsCommandList;
|
||||||
|
ID3D12GraphicsCommandList6_SetName(d3d12GraphicsCommandList, wide_str.c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case QueueType::Copy:
|
||||||
|
{
|
||||||
|
CreateAllocator(driver, &commandList->CopyCommandList, queueDesc);
|
||||||
|
ID3D12GraphicsCommandList* d3d12CopyCommandList = nullptr;
|
||||||
|
HRESULT result = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||||
|
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList,
|
||||||
|
reinterpret_cast<void**>(&d3d12CopyCommandList));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
Assert(false &&
|
||||||
|
"Error not implemented: cannot create ID3D12GraphicsCommandList (copy command list)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
commandList->CopyCommandList.CommandList = d3d12CopyCommandList;
|
||||||
|
ID3D12GraphicsCommandList_SetName(d3d12CopyCommandList, wide_str.c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AllocateCommandList(NonNullPtr<D3D12Driver> driver, QueueType queueType)
|
bool AllocateCommandList(NonNullPtr<D3D12Driver> driver, QueueType queueType)
|
||||||
@@ -102,16 +140,11 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ID3D12GraphicsCommandList6* GetGraphicsCommandList(NonNullPtr<D3D12CommandList> commandList)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<ID3D12GraphicsCommandList6*>(commandList->CommandLists[ToUnderlying(QueueType::Graphics)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
uint8 currentCommandListIndex = d3d12Driver->AvailableCommandListCount;
|
||||||
if (currentCommandListIndex >= d3d12Driver->AvailableCommandListCapacity)
|
if (currentCommandListIndex >= d3d12Driver->AvailableCommandListCapacity)
|
||||||
{
|
{
|
||||||
if (!AllocateCommandList(d3d12Driver, queueType))
|
if (!AllocateCommandList(d3d12Driver, queueType))
|
||||||
@@ -130,6 +163,35 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Proper allocator for the frame and reset both it and the requested queue
|
||||||
|
uint8 bufferIndex = d3d12Driver->FrameCounter % GPUDriver::kResourceBufferCount;
|
||||||
|
switch (queueType)
|
||||||
|
{
|
||||||
|
case QueueType::Graphics:
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
d3d12Driver->AvailableCommandListCount += 1;
|
||||||
return reinterpret_cast<CommandList*>(commandList);
|
return reinterpret_cast<CommandList*>(commandList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +200,7 @@ namespace Juliet::D3D12
|
|||||||
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
uint8 commandLastIndex = d3d12Driver->CommandListCount;
|
uint8 commandLastIndex = d3d12Driver->AvailableCommandListCount;
|
||||||
|
|
||||||
// TODO : Get window data from the command list: We associate the swapchain texture to a window with a missing function
|
// TODO : Get window data from the command list: We associate the swapchain texture to a window with a missing function
|
||||||
HRESULT result = IDXGISwapChain_Present(d3d12Driver->WindowData->SwapChain, 0, 1);
|
HRESULT result = IDXGISwapChain_Present(d3d12Driver->WindowData->SwapChain, 0, 1);
|
||||||
@@ -147,6 +209,9 @@ namespace Juliet::D3D12
|
|||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d3d12Driver->AvailableCommandListCount = 0;
|
||||||
|
++d3d12Driver->FrameCounter;
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,29 @@
|
|||||||
|
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
|
// Forward Declare
|
||||||
struct D3D12Driver;
|
struct D3D12Driver;
|
||||||
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;
|
||||||
uint32 SwapChainImageIndex;
|
uint32 SwapChainImageIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct D3D12CommandList
|
struct D3D12CommandList
|
||||||
@@ -24,16 +40,14 @@ namespace Juliet::D3D12
|
|||||||
D3D12Driver* Driver;
|
D3D12Driver* Driver;
|
||||||
|
|
||||||
D3D12PresentData* PresentDatas;
|
D3D12PresentData* PresentDatas;
|
||||||
uint32 PresentDataCapacity;
|
uint32 PresentDataCapacity;
|
||||||
uint32 PresentDataCount;
|
uint32 PresentDataCount;
|
||||||
|
|
||||||
// We create kResourceBufferCount allocator per queue to allow reusing the command list every N frames
|
D3D12GraphicsCommandListData GraphicsCommandList;
|
||||||
ID3D12CommandAllocator* CommandAllocator[GPUDriver::kResourceBufferCount][ToUnderlying(QueueType::Count)];
|
D3D12GraphicsCommandListData ComputeCommandList;
|
||||||
ID3D12CommandList* CommandLists[ToUnderlying(QueueType::Count)];
|
D3D12CopyCommandListData CopyCommandList;
|
||||||
};
|
};
|
||||||
|
|
||||||
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<GPUDriver> driver);
|
||||||
} // namespace Juliet::D3D12
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#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/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>
|
||||||
@@ -549,6 +550,8 @@ namespace Juliet::D3D12
|
|||||||
device->AcquireCommandList = AcquireCommandList;
|
device->AcquireCommandList = AcquireCommandList;
|
||||||
device->SubmitCommandLists = SubmitCommandLists;
|
device->SubmitCommandLists = SubmitCommandLists;
|
||||||
|
|
||||||
|
device->BeginRenderPass = BeginRenderPass;
|
||||||
|
|
||||||
device->Driver = driver;
|
device->Driver = driver;
|
||||||
driver->GraphicsDevice = device;
|
driver->GraphicsDevice = device;
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace Juliet
|
|||||||
|
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
|
// Forward Declare
|
||||||
struct D3D12CommandList;
|
struct D3D12CommandList;
|
||||||
|
|
||||||
struct D3D12WindowData
|
struct D3D12WindowData
|
||||||
@@ -26,7 +27,7 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
PresentMode PresentMode;
|
PresentMode PresentMode;
|
||||||
|
|
||||||
uint32 FrameCounter;
|
uint32 WindowFrameCounter; // Specific to that window. See GraphicsDevice for global counter
|
||||||
uint32 Width;
|
uint32 Width;
|
||||||
uint32 Height;
|
uint32 Height;
|
||||||
};
|
};
|
||||||
@@ -63,10 +64,12 @@ namespace Juliet::D3D12
|
|||||||
// Resources
|
// Resources
|
||||||
D3D12CommandList** AvailableCommandLists;
|
D3D12CommandList** AvailableCommandLists;
|
||||||
uint8 AvailableCommandListCapacity;
|
uint8 AvailableCommandListCapacity;
|
||||||
|
uint8 AvailableCommandListCount;
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -162,11 +162,10 @@ 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;
|
||||||
d3d12CommandList->PresentDataCount += 1;
|
d3d12CommandList->PresentDataCount += 1;
|
||||||
|
|
||||||
@@ -179,7 +178,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]);
|
||||||
|
|
||||||
@@ -281,7 +280,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;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
|
// Forward Declare
|
||||||
struct D3D12Driver;
|
struct D3D12Driver;
|
||||||
struct D3D12WindowData;
|
struct D3D12WindowData;
|
||||||
|
|
||||||
|
|||||||
@@ -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,16 +91,14 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -111,8 +107,27 @@ namespace Juliet
|
|||||||
{
|
{
|
||||||
GPUDriver* driver = device->Driver;
|
GPUDriver* driver = device->Driver;
|
||||||
device->SubmitCommandLists(driver);
|
device->SubmitCommandLists(driver);
|
||||||
|
}
|
||||||
|
|
||||||
driver->CommandListCount = 0;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -7,25 +7,30 @@
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
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
|
||||||
@@ -43,6 +48,10 @@ namespace Juliet
|
|||||||
CommandList* (*AcquireCommandList)(NonNullPtr<GPUDriver> driver, QueueType queueType);
|
CommandList* (*AcquireCommandList)(NonNullPtr<GPUDriver> driver, QueueType queueType);
|
||||||
bool (*SubmitCommandLists)(NonNullPtr<GPUDriver> driver);
|
bool (*SubmitCommandLists)(NonNullPtr<GPUDriver> driver);
|
||||||
|
|
||||||
|
// RenderPass
|
||||||
|
void (*BeginRenderPass)(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
||||||
|
uint32 colorTargetInfoCount);
|
||||||
|
|
||||||
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,6 +98,17 @@ void Win32EditorApplication::Update()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (swapChainTexture)
|
||||||
|
{
|
||||||
|
ColorTargetInfo colorTargetInfo = {};
|
||||||
|
colorTargetInfo.Texture = swapChainTexture;
|
||||||
|
colorTargetInfo.ClearColor = { .R = .5f, .G = .8f, .B = .0f, .A = 1.f };
|
||||||
|
colorTargetInfo.LoadOperation = LoadOperation::Clear;
|
||||||
|
colorTargetInfo.StoreOperation = StoreOperation::Store;
|
||||||
|
|
||||||
|
BeginRenderPass(cmdList, colorTargetInfo);
|
||||||
|
}
|
||||||
|
|
||||||
// Submit Commands
|
// Submit Commands
|
||||||
SubmitCommandLists(GraphicsDevice);
|
SubmitCommandLists(GraphicsDevice);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class Win32EditorApplication : public Juliet::IApplication
|
|||||||
private:
|
private:
|
||||||
Juliet::Window* MainWindow = {};
|
Juliet::Window* MainWindow = {};
|
||||||
Juliet::GraphicsDevice* GraphicsDevice = {};
|
Juliet::GraphicsDevice* GraphicsDevice = {};
|
||||||
Juliet::DynamicLibrary* Game = {};
|
Juliet::DynamicLibrary* Game = {};
|
||||||
|
|
||||||
bool Running = false;
|
bool Running = false;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user