Graphics pipeline iteration

Lot of code.
Not working yet
This commit is contained in:
2025-03-09 22:52:08 -04:00
parent a366d75fdc
commit a9fe4683fb
24 changed files with 1100 additions and 80 deletions

View File

@@ -129,6 +129,7 @@
<ClInclude Include="include\Core\JulietInit.h"/>
<ClInclude Include="include\Core\Logging\LogManager.h"/>
<ClInclude Include="include\Core\Logging\LogTypes.h"/>
<ClInclude Include="include\Core\Math\MathUtils.h" />
<ClInclude Include="include\Core\Math\Shape.h"/>
<ClInclude Include="include\Core\Memory\Allocator.h"/>
<ClInclude Include="include\Core\Memory\Utils.h"/>
@@ -163,6 +164,7 @@
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Platform.h"/>
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Private.h"/>
<ClInclude Include="src\Core\HAL\IO\IOStream_Private.h"/>
<ClInclude Include="src\Core\Math\Math_Private.h" />
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h"/>
<ClInclude Include="src\Core\HAL\Win32.h"/>
<ClInclude Include="src\Graphics\D3D12\D3D12Common.h"/>
@@ -200,19 +202,20 @@
<ClCompile Include="src\Core\HotReload\Win32\Win32HotReload.cpp"/>
<ClCompile Include="src\Core\Juliet.cpp"/>
<ClCompile Include="src\Core\Logging\LogManager.cpp"/>
<ClCompile Include="src\Core\Memory\Allocator.cpp"/>
<ClCompile Include="src\Core\Networking\NetworkPacket.cpp"/>
<ClCompile Include="src\Core\Networking\Socket.cpp"/>
<ClCompile Include="src\Core\Networking\TcpListener.cpp"/>
<ClCompile Include="src\Core\Networking\TcpSocket.cpp"/>
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp"/>
<ClCompile Include="src\Engine\Engine.cpp"/>
<ClCompile Include="src\Graphics\D3D12\D3D12Common.cpp"/>
<ClCompile Include="src\Core\Math\MathRound.cpp" />
<ClCompile Include="src\Core\Memory\Allocator.cpp" />
<ClCompile Include="src\Core\Networking\NetworkPacket.cpp" />
<ClCompile Include="src\Core\Networking\Socket.cpp" />
<ClCompile Include="src\Core\Networking\TcpListener.cpp" />
<ClCompile Include="src\Core\Networking\TcpSocket.cpp" />
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp" />
<ClCompile Include="src\Engine\Engine.cpp" />
<ClCompile Include="src\Graphics\D3D12\D3D12Common.cpp" />
<ClCompile Include="src\Graphics\D3D12\D3D12GraphicsPipeline.cpp" />
<ClCompile Include="src\Graphics\D3D12\D3D12RenderPass.cpp"/>
<ClCompile Include="src\Graphics\D3D12\D3D12Shader.cpp"/>
<ClCompile Include="src\Graphics\D3D12\D3D12Synchronization.cpp"/>
<ClCompile Include="src\Graphics\D3D12\D3D12Texture.cpp"/>
<ClCompile Include="src\Graphics\D3D12\D3D12RenderPass.cpp" />
<ClCompile Include="src\Graphics\D3D12\D3D12Shader.cpp" />
<ClCompile Include="src\Graphics\D3D12\D3D12Synchronization.cpp" />
<ClCompile Include="src\Graphics\D3D12\D3D12Texture.cpp" />
<ClCompile Include="src\Graphics\D3D12\D3D12CommandList.cpp" />
<ClCompile Include="src\Graphics\D3D12\D3D12GraphicsDevice.cpp" />
<ClCompile Include="src\Graphics\D3D12\D3D12SwapChain.cpp" />
@@ -277,8 +280,8 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<Content Include="include\Core\Thread\Mutex.h"/>
<Content Include="src\TODO.txt"/>
<Content Include="include\Core\Thread\Mutex.h" />
<Content Include="src\TODO.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
<ImportGroup Label="ExtensionTargets">

View File

@@ -73,31 +73,4 @@ namespace Juliet
}
extern JULIET_API void Free(ByteBuffer& buffer);
// TODO move to math utils
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

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/Common/CoreUtils.h>
#include <Core/Math/MathUtils.h>
#include <Core/Memory/Utils.h>
namespace Juliet

View File

@@ -0,0 +1,37 @@
#pragma once
namespace Juliet
{
extern JULIET_API float RoundF(float value);
inline int32 LRoundF(float value)
{
return RoundF(value);
}
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

View File

@@ -115,7 +115,7 @@ namespace Juliet
extern JULIET_API void DestroyShader(NonNullPtr<GraphicsDevice> device, NonNullPtr<Shader> shader);
// Pipelines
extern JULIET_API GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GraphicsDevice> device,
GraphicsPipelineCreateInfo& createInfo);
extern JULIET_API GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GraphicsDevice> device,
const GraphicsPipelineCreateInfo& createInfo);
} // namespace Juliet

View File

@@ -1,5 +1,6 @@
#pragma once
#include <Graphics/Shader.h>
#include <Graphics/Texture.h>
namespace Juliet
{
@@ -9,20 +10,23 @@ namespace Juliet
enum class FillMode : uint8
{
Wireframe,
Solid
Solid,
Count
};
enum class CullMode : uint8
{
None,
Front,
Back
Back,
Count
};
enum class FrontFace : uint8
{
CounterClockwise,
Clockwise
Clockwise,
Count
};
enum class PrimitiveType : uint8
@@ -32,6 +36,7 @@ namespace Juliet
LineList,
LineStrip,
PointList,
Count
};
struct RasterizerState
@@ -39,21 +44,180 @@ namespace Juliet
FillMode FillMode;
CullMode CullMode;
FrontFace FrontFace;
float DepthBiasConstantFactor; // How much depth value is added to each fragment
float DepthBiasClamp; // Maximum depth bias
float DepthBiasSlopeFactor; // Scalar applied to Fragment's slope
bool EnableDepthBias; // Bias fragment depth values
bool EnableDepthClip; // True to clip, false to clamp
};
enum class VertexInputRate : uint8
{
Vertex, // Use vertex index
Instance, // Use instance index
Count
};
struct VertexBufferDescription
{
uint32 Slot; // Binding Slot
uint32 PitchInBytes; // Pitch between two elements
VertexInputRate InputRate;
uint32 InstanceStepRate; // Only used when input rate == Instance. Number of instances to draw before advancing in the instance buffer by 1
};
enum class VertexElementFormat : uint8
{
Invalid,
/* 32-bit Signed Integers */
Int,
Int2,
Int3,
Int4,
/* 32-bit Unsigned Integers */
UInt,
UInt2,
UInt3,
UInt4,
/* 32-bit Floats */
Float,
Float2,
Float3,
Float4,
/* 8-bit Signed Integers */
Byte2,
Byte4,
/* 8-bit Unsigned Integers */
UByte2,
UByte4,
/* 8-bit Signed Normalized */
Byte2_Norm,
Byte4_Norm,
/* 8-bit Unsigned Normalized */
UByte2_Norm,
UByte4_Norm,
/* 16-bit Signed Integers */
Short2,
Short4,
/* 16-bit Unsigned Integers */
UShort2,
UShort4,
/* 16-bit Signed Normalized */
Short2_Norm,
Short4_Norm,
/* 16-bit Unsigned Normalized */
UShort2_Norm,
UShort4_Norm,
/* 16-bit Floats */
Half2,
Half4,
//
Count
};
struct VertexAttribute
{
uint32 Location; // Shader input location index
uint32 BufferSlot; // Binding slot of associated vertex buffer
VertexElementFormat Format; // Size and type of attribute
uint32 Offset; // Offset of this attribute relative to the start of the vertex element
};
struct VertexInputState
{
const VertexBufferDescription* VertexBufferDescriptions;
uint32 NumVertexBufferDescriptions;
const VertexAttribute* VertexAttributes;
uint32 NumVertexAttributes;
};
struct GraphicsPipelineTargetInfo
{
const ColorTargetDescription* ColorTargetDescriptions;
size_t NumColorTargets;
TextureFormat DepthStencilFormat;
bool HasDepthStencilTarget;
};
enum class CompareOperation : uint8
{
Invalid,
Never, // The comparison always evaluates false.
Less, // The comparison evaluates reference < test.
Equal, // The comparison evaluates reference == test.
LessOrEqual, // The comparison evaluates reference <= test.
Greater, // The comparison evaluates reference > test.
NotEqual, // The comparison evaluates reference != test.
GreaterOrEqual, // The comparison evalutes reference >= test.
Always, // The comparison always evaluates true.
Count
};
enum class StencilOperation : uint8
{
Invalid,
Keep, // Keeps the current value.
Zero, // Sets the value to 0.
Replace, // Sets the value to reference.
IncrementAndClamp, // Increments the current value and clamps to the maximum value.
DecrementAndClamp, // Decrements the current value and clamps to 0.
Invert, // Bitwise-inverts the current value.
IncrementAndWrap, // Increments the current value and wraps back to 0.
DecrementAndWrap, // Decrements the current value and wraps to the maximum value.
Count
};
struct StencilOperationState
{
StencilOperation FailOperation; // The action performed on samples that fail the stencil test.
StencilOperation PassOperation; // The action performed on samples that pass the depth and stencil tests.
StencilOperation DepthFailOperation; // The action performed on samples that pass the stencil test and fail the depth test.
StencilOperation CompareOperation; // The comparison operator used in the stencil test.
};
struct DepthStencilState
{
CompareOperation CompareOperation; // The comparison operator used for depth testing.
StencilOperationState BackStencilState; // The stencil op state for back-facing triangles.
StencilOperationState FrontStencilState; // The stencil op state for front-facing triangles.
uint8 CompareMask; // Selects the bits of the stencil values participating in the stencil test.
uint8 WriteMask; // Selects the bits of the stencil values updated by the stencil test.
bool EnableDepthTest : 1; // true enables the depth test.
bool EnableDepthWrite : 1; // true enables depth writes. Depth writes are always disabled when enable_depth_test is false.
bool EnableStencilTest : 1; // true enables the stencil test.
};
struct MultisampleState
{
TextureSampleCount SampleCount;
uint32 SampleMask; // Which sample should be updated. If Enabled mask == false -> 0xFFFFFFFF
bool EnableMask;
};
struct GraphicsPipelineCreateInfo
{
Shader* VertexShader;
Shader* FragmentShader;
RasterizerState RasterizerState;
PrimitiveType PrimitiveType;
GraphicsPipelineTargetInfo TargetInfo;
RasterizerState RasterizerState;
MultisampleState MultisampleState;
VertexInputState VertexInputState;
DepthStencilState DepthStencilState;
};
// Opaque type

View File

@@ -41,14 +41,60 @@ namespace Juliet
StoreOperation StoreOperation;
};
enum class BlendFactor : uint8
{
Invalid,
Zero,
One,
Src_Color,
One_Minus_Src_Color,
Dst_Color,
One_Minus_Dst_Color,
Src_Alpha,
One_Minus_Src_Alpha,
Dst_Alpha,
One_Minus_Dst_Alpha,
Constant_Color,
One_MINUS_Constant_Color,
Src_Alpha_Saturate, // min(source alpha, 1 - destination alpha)
Count
};
enum class BlendOperation : uint8
{
Invalid,
Add, // (source * source_factor) + (destination * destination_factor)
Subtract, // (source * source_factor) - (destination * destination_factor)
ReverseSubtract, // (destination * destination_factor) - (source * source_factor)
Min, // min(source, destination)
Max, // max(source, destination)
Count
};
enum class ColorComponentFlags : uint8
{
R = 1u << 0,
G = 1u << 1,
B = 1u << 2,
A = 1u << 3
};
struct ColorTargetBlendState
{
BlendFactor SourceColorBlendFactor; // The value to be multiplied by the source RGB value.
BlendFactor DestinationColorBlendFactor; // The value to be multiplied by the destination RGB value.
BlendOperation ColorBlendOperation; // The blend operation for the RGB components.
BlendFactor SourceAlphaBlendFactor; // The value to be multiplied by the source alpha.
BlendFactor DestinationAlphaBlendFactor; // The value to be multiplied by the destination alpha.
BlendOperation AlphaBlendOperation; // The blend operation for the alpha component.
ColorComponentFlags ColorWriteMask; // A bitmask specifying which of the RGBA components are enabled for writing. Writes to all channels if enable_color_write_mask is false.
bool EnableBlend : 1; // Whether blending is enabled for the color target.
bool EnableColorWriteMask : 1; // Whether the color write mask is enabled.
};
struct ColorTargetDescription
{
TextureFormat Format;
TextureFormat Format;
ColorTargetBlendState BlendState;
};

View File

@@ -124,7 +124,9 @@ namespace Juliet
ASTC_10x8_FLOAT,
ASTC_10x10_FLOAT,
ASTC_12x10_FLOAT,
ASTC_12x12_FLOAT
ASTC_12x12_FLOAT,
Count
};
enum struct TextureUsageFlag : uint8

View File

@@ -0,0 +1,63 @@
#include <pch.h>
#include <Core/Math/Math_Private.h>
namespace Juliet
{
// From MUSL lib https://github.com/rofl0r/musl
#if FLT_EVAL_METHOD == 0
#define EPS FLT_EPSILON
#elif FLT_EVAL_METHOD == 1
#define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD == 2
#define EPS LDBL_EPSILON
#endif
namespace
{
const float_t toint = 1 / EPS;
}
float RoundF(float value)
{
union
{
float f;
uint32_t i;
} u = { value };
int e = u.i >> 23 & 0xff;
float_t y;
if (e >= 0x7f + 23)
{
return value;
}
if (u.i >> 31)
{
value = -value;
}
if (e < 0x7f - 1)
{
FORCE_EVAL(value + toint);
return 0 * u.f;
}
y = value + toint - toint - value;
if (y > 0.5f)
{
y = y + value - 1;
}
else if (y <= -0.5f)
{
y = y + value + 1;
}
else
{
y = y + value;
}
if (u.i >> 31)
{
y = -y;
}
return y;
}
} // namespace Juliet

View File

@@ -0,0 +1,51 @@
#pragma once
namespace Juliet
{
// From MUSL lib https://github.com/rofl0r/musl
#ifndef fp_force_evalf
#define fp_force_evalf fp_force_evalf
static inline void fp_force_evalf(float x)
{
volatile float y;
y = x;
}
#endif
#ifndef fp_force_eval
#define fp_force_eval fp_force_eval
static inline void fp_force_eval(double x)
{
volatile double y;
y = x;
}
#endif
#ifndef fp_force_evall
#define fp_force_evall fp_force_evall
static inline void fp_force_evall(long double x)
{
volatile long double y;
y = x;
}
#endif
#define FORCE_EVAL(x) \
do \
{ \
if (sizeof(x) == sizeof(float)) \
{ \
fp_force_evalf(x); \
} \
else if (sizeof(x) == sizeof(double)) \
{ \
fp_force_eval(x); \
} \
else \
{ \
fp_force_evall(x); \
} \
} \
while (0)
} // namespace Juliet

View File

@@ -329,7 +329,7 @@ namespace Juliet::D3D12
}
}
// TODO Destroy anything (buffer, texture, etc...)
Internal::DisposePendingResourcces(d3d12Driver);
++d3d12Driver->FrameCounter;

View File

@@ -10,6 +10,7 @@
// SRV = Shader Resource View
// UAV = Unordered Access View
// CBV = Constant Buffer View
// PSO = Pipeline State Object
// Inspired (copy pasted a lot) by SDL GPU
namespace Juliet::D3D12

View File

@@ -620,11 +620,32 @@ namespace Juliet::D3D12
device->Driver = driver;
driver->GraphicsDevice = device;
driver->Semantic = WrapString("TEXCOORD");
driver->FramesInFlight = 2;
return device;
}
} // namespace
namespace Internal
{
void DisposePendingResourcces(NonNullPtr<D3D12Driver> driver)
{
// TODO Destroy anything (buffer, texture, etc...)
for (uint32 idx = driver->GraphicsPipelinesToDisposeCount - 1; idx >= 0ul; --idx)
{
if (--driver->GraphicsPipelinesToDispose[idx]->ReferenceCount == 0)
{
ReleaseGraphicsPipeline(driver->GraphicsPipelinesToDispose[idx]);
driver->GraphicsPipelinesToDispose[idx] =
driver->GraphicsPipelinesToDispose[driver->GraphicsPipelinesToDisposeCount - 1];
driver->GraphicsPipelinesToDisposeCount -= 1;
}
}
}
} // namespace Internal
} // namespace Juliet::D3D12
namespace Juliet

View File

@@ -2,6 +2,7 @@
#include <Core/Common/EnumUtils.h>
#include <Graphics/D3D12/D3D12Common.h>
#include <Graphics/D3D12/D3D12GraphicsPipeline.h>
#include <Graphics/D3D12/D3D12Texture.h>
#include <Graphics/GraphicsDevice.h>
@@ -77,8 +78,14 @@ namespace Juliet::D3D12
uint32 AvailableFenceCount;
uint32 AvailableFenceCapacity;
D3D12GraphicsPipeline** GraphicsPipelinesToDispose;
uint32 GraphicsPipelinesToDisposeCount;
uint32 GraphicsPipelinesToDisposeCapacity;
D3D12StagingDescriptorPool* StagingDescriptorPools[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
String Semantic;
uint8 FramesInFlight;
uint64 FrameCounter = 0; // Number of frame since inception
@@ -87,4 +94,9 @@ namespace Juliet::D3D12
bool IsUMACacheCoherent : 1;
bool GPUUploadHeapSupported : 1;
};
namespace Internal
{
void DisposePendingResourcces(NonNullPtr<D3D12Driver> driver);
}
} // namespace Juliet::D3D12

View File

@@ -1,14 +1,478 @@
#include <pch.h>
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
#include <Graphics/D3D12/D3D12GraphicsPipeline.h>
#include <Graphics/D3D12/D3D12Utils.h>
#include <Core/Common/NonNullPtr.h>
#include <Graphics/GraphicsDevice.h>
#include <Core/Memory/Allocator.h>
namespace Juliet::D3D12
{
GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GPUDriver> driver, GraphicsPipelineCreateInfo& createInfo)
namespace
{
return nullptr;
// clang-format off
D3D12_INPUT_CLASSIFICATION JulietToD3D12_InputRate[] =
{
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, // VERTEX
D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA // INSTANCE
};
// clang-format on
static_assert(sizeof(JulietToD3D12_InputRate) / sizeof(JulietToD3D12_InputRate[0]) == ToUnderlying(VertexInputRate::Count));
// clang-format off
D3D12_CULL_MODE JulietToD3D12_CullMode[] =
{
D3D12_CULL_MODE_NONE,
D3D12_CULL_MODE_FRONT,
D3D12_CULL_MODE_BACK
};
// clang-format on
static_assert(sizeof(JulietToD3D12_CullMode) / sizeof(JulietToD3D12_CullMode[0]) == ToUnderlying(CullMode::Count));
// clang-format off
D3D12_FILL_MODE JulietToD3D12_FillMode[] =
{
D3D12_FILL_MODE_SOLID,
D3D12_FILL_MODE_WIREFRAME
};
// clang-format on
static_assert(sizeof(JulietToD3D12_FillMode) / sizeof(JulietToD3D12_FillMode[0]) == ToUnderlying(FillMode::Count));
DXGI_FORMAT JulietToD3D12_VertexFormat[] = {
DXGI_FORMAT_UNKNOWN, // Unknown
DXGI_FORMAT_R32_SINT, // Int
DXGI_FORMAT_R32G32_SINT, // Int2
DXGI_FORMAT_R32G32B32_SINT, // Int3
DXGI_FORMAT_R32G32B32A32_SINT, // Int4
DXGI_FORMAT_R32_UINT, // UInt
DXGI_FORMAT_R32G32_UINT, // UInt2
DXGI_FORMAT_R32G32B32_UINT, // UInt3
DXGI_FORMAT_R32G32B32A32_UINT, // UInt4
DXGI_FORMAT_R32_FLOAT, // Float
DXGI_FORMAT_R32G32_FLOAT, // Float2
DXGI_FORMAT_R32G32B32_FLOAT, // Float3
DXGI_FORMAT_R32G32B32A32_FLOAT, // Float4
DXGI_FORMAT_R8G8_SINT, // Byte2
DXGI_FORMAT_R8G8B8A8_SINT, // Byte4
DXGI_FORMAT_R8G8_UINT, // UByte2
DXGI_FORMAT_R8G8B8A8_UINT, // UByte4
DXGI_FORMAT_R8G8_SNORM, // Byte2_Norm
DXGI_FORMAT_R8G8B8A8_SNORM, // Byte4_Norm
DXGI_FORMAT_R8G8_UNORM, // UByte2_Norm
DXGI_FORMAT_R8G8B8A8_UNORM, // UByte4_Norm
DXGI_FORMAT_R16G16_SINT, // Short2
DXGI_FORMAT_R16G16B16A16_SINT, // Short4
DXGI_FORMAT_R16G16_UINT, // UShort2
DXGI_FORMAT_R16G16B16A16_UINT, // UShort4
DXGI_FORMAT_R16G16_SNORM, // Short2_Norm
DXGI_FORMAT_R16G16B16A16_SNORM, // Short4_Norm
DXGI_FORMAT_R16G16_UNORM, // UShort2_Norm
DXGI_FORMAT_R16G16B16A16_UNORM, // UShort4_Norm
DXGI_FORMAT_R16G16_FLOAT, // Half2
DXGI_FORMAT_R16G16B16A16_FLOAT // Half4
};
static_assert(sizeof(JulietToD3D12_VertexFormat) / sizeof(JulietToD3D12_VertexFormat[0]) ==
ToUnderlying(VertexElementFormat::Count));
// clang-format off
D3D12_PRIMITIVE_TOPOLOGY_TYPE JulietToD3D12_PrimitiveTopologyType[] = {
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE,
D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE,
D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT
};
// clang-format on
static_assert(sizeof(JulietToD3D12_PrimitiveTopologyType) / sizeof(JulietToD3D12_PrimitiveTopologyType[0]) ==
ToUnderlying(PrimitiveType::Count));
// clang-format off
D3D12_BLEND JulietToD3D12_BlendFactor[] =
{
D3D12_BLEND_ZERO,
D3D12_BLEND_ZERO,
D3D12_BLEND_ONE,
D3D12_BLEND_SRC_COLOR,
D3D12_BLEND_INV_SRC_COLOR,
D3D12_BLEND_DEST_COLOR,
D3D12_BLEND_INV_DEST_COLOR,
D3D12_BLEND_SRC_ALPHA,
D3D12_BLEND_INV_SRC_ALPHA,
D3D12_BLEND_DEST_ALPHA,
D3D12_BLEND_INV_DEST_ALPHA,
D3D12_BLEND_BLEND_FACTOR,
D3D12_BLEND_INV_BLEND_FACTOR,
D3D12_BLEND_SRC_ALPHA_SAT,
};
// clang-format on
static_assert(sizeof(JulietToD3D12_BlendFactor) / sizeof(JulietToD3D12_BlendFactor[0]) == ToUnderlying(BlendFactor::Count));
// clang-format off
D3D12_BLEND JulietToD3D12_BlendFactorAlpha[] =
{
D3D12_BLEND_ZERO,
D3D12_BLEND_ZERO,
D3D12_BLEND_ONE,
D3D12_BLEND_SRC_ALPHA,
D3D12_BLEND_INV_SRC_ALPHA,
D3D12_BLEND_DEST_ALPHA,
D3D12_BLEND_INV_DEST_ALPHA,
D3D12_BLEND_SRC_ALPHA,
D3D12_BLEND_INV_SRC_ALPHA,
D3D12_BLEND_DEST_ALPHA,
D3D12_BLEND_INV_DEST_ALPHA,
D3D12_BLEND_BLEND_FACTOR,
D3D12_BLEND_INV_BLEND_FACTOR,
D3D12_BLEND_SRC_ALPHA_SAT,
};
// clang-format on
static_assert(sizeof(JulietToD3D12_BlendFactorAlpha) / sizeof(JulietToD3D12_BlendFactorAlpha[0]) ==
ToUnderlying(BlendFactor::Count));
// clang-format off
D3D12_BLEND_OP JulietToD3D12_BlendOperation[] =
{
D3D12_BLEND_OP_ADD,
D3D12_BLEND_OP_ADD,
D3D12_BLEND_OP_SUBTRACT,
D3D12_BLEND_OP_REV_SUBTRACT,
D3D12_BLEND_OP_MIN,
D3D12_BLEND_OP_MAX
};
// clang-format on
static_assert(sizeof(JulietToD3D12_BlendOperation) / sizeof(JulietToD3D12_BlendOperation[0]) ==
ToUnderlying(BlendOperation::Count));
// clang-format off
D3D12_COMPARISON_FUNC JulietToD3D12_CompareOperation[] =
{
D3D12_COMPARISON_FUNC_NEVER,
D3D12_COMPARISON_FUNC_NEVER,
D3D12_COMPARISON_FUNC_LESS,
D3D12_COMPARISON_FUNC_EQUAL,
D3D12_COMPARISON_FUNC_LESS_EQUAL,
D3D12_COMPARISON_FUNC_GREATER,
D3D12_COMPARISON_FUNC_NOT_EQUAL,
D3D12_COMPARISON_FUNC_GREATER_EQUAL,
D3D12_COMPARISON_FUNC_ALWAYS
};
// clang-format on
static_assert(sizeof(JulietToD3D12_CompareOperation) / sizeof(JulietToD3D12_CompareOperation[0]) ==
ToUnderlying(CompareOperation::Count));
// clang-format off
D3D12_STENCIL_OP JulietToD3D12_StencilOperation[] =
{
D3D12_STENCIL_OP_KEEP,
D3D12_STENCIL_OP_KEEP,
D3D12_STENCIL_OP_ZERO,
D3D12_STENCIL_OP_REPLACE,
D3D12_STENCIL_OP_INCR_SAT,
D3D12_STENCIL_OP_DECR_SAT,
D3D12_STENCIL_OP_INVERT,
D3D12_STENCIL_OP_INCR,
D3D12_STENCIL_OP_DECR
};
// clang-format on
static_assert(sizeof(JulietToD3D12_StencilOperation) / sizeof(JulietToD3D12_StencilOperation[0]) ==
ToUnderlying(StencilOperation::Count));
bool ConvertVertexInputState(const VertexInputState& vertexInputState, D3D12_INPUT_ELEMENT_DESC* desc, String semantic)
{
if (desc == nullptr || vertexInputState.NumVertexAttributes == 0)
{
return false;
}
for (uint32 idx = 0; idx < vertexInputState.NumVertexAttributes; ++idx)
{
VertexAttribute attribute = vertexInputState.VertexAttributes[idx];
desc[idx].SemanticName = CStr(semantic);
desc[idx].SemanticIndex = attribute.Location;
desc[idx].Format = JulietToD3D12_VertexFormat[ToUnderlying(attribute.Format)];
desc[idx].InputSlot = attribute.BufferSlot;
desc[idx].AlignedByteOffset = attribute.Offset;
desc[idx].InputSlotClass =
JulietToD3D12_InputRate[ToUnderlying(vertexInputState.VertexBufferDescriptions[attribute.BufferSlot].InputRate)];
desc[idx].InstanceDataStepRate =
(vertexInputState.VertexBufferDescriptions[attribute.BufferSlot].InputRate == VertexInputRate::Instance)
? vertexInputState.VertexBufferDescriptions[attribute.BufferSlot].InstanceStepRate
: 0;
}
return true;
}
bool ConvertRasterizerState(const RasterizerState& rasterizerState, D3D12_RASTERIZER_DESC& desc)
{
desc.FillMode = JulietToD3D12_FillMode[ToUnderlying(rasterizerState.FillMode)];
desc.CullMode = JulietToD3D12_CullMode[ToUnderlying(rasterizerState.CullMode)];
switch (rasterizerState.FrontFace)
{
case FrontFace::CounterClockwise: desc.FrontCounterClockwise = TRUE; break;
case FrontFace::Clockwise: desc.FrontCounterClockwise = FALSE; break;
default: return false;
}
static_assert(ToUnderlying(FrontFace::Count) == 2);
if (rasterizerState.EnableDepthBias)
{
desc.DepthBias = LRoundF(rasterizerState.DepthBiasConstantFactor);
desc.DepthBiasClamp = rasterizerState.DepthBiasClamp;
desc.SlopeScaledDepthBias = rasterizerState.DepthBiasSlopeFactor;
}
else
{
desc.DepthBias = 0;
desc.DepthBiasClamp = 0.0f;
desc.SlopeScaledDepthBias = 0.0f;
}
desc.DepthClipEnable = rasterizerState.EnableDepthClip;
desc.MultisampleEnable = FALSE;
desc.AntialiasedLineEnable = FALSE;
desc.ForcedSampleCount = 0;
desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
return true;
}
bool ConvertBlendState(const GraphicsPipelineCreateInfo& createInfo, D3D12_BLEND_DESC& blendDesc)
{
ZeroStruct(blendDesc);
blendDesc.AlphaToCoverageEnable = FALSE;
blendDesc.IndependentBlendEnable = FALSE;
for (UINT i = 0; i < GPUDriver::kMaxColorTargetInfo; i += 1)
{
D3D12_RENDER_TARGET_BLEND_DESC rtBlendDesc;
rtBlendDesc.BlendEnable = FALSE;
rtBlendDesc.LogicOpEnable = FALSE;
rtBlendDesc.SrcBlend = D3D12_BLEND_ONE;
rtBlendDesc.DestBlend = D3D12_BLEND_ZERO;
rtBlendDesc.BlendOp = D3D12_BLEND_OP_ADD;
rtBlendDesc.SrcBlendAlpha = D3D12_BLEND_ONE;
rtBlendDesc.DestBlendAlpha = D3D12_BLEND_ZERO;
rtBlendDesc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
rtBlendDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
rtBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
// If target_info has more blend states, you can set IndependentBlendEnable to TRUE and assign different blend states to each render target slot
if (i < createInfo.TargetInfo.NumColorTargets)
{
ColorTargetBlendState blendState = createInfo.TargetInfo.ColorTargetDescriptions[i].BlendState;
ColorComponentFlags colorWriteMask =
blendState.EnableColorWriteMask ? blendState.ColorWriteMask : static_cast<ColorComponentFlags>(0xF);
rtBlendDesc.BlendEnable = blendState.EnableBlend;
rtBlendDesc.SrcBlend = JulietToD3D12_BlendFactor[ToUnderlying(blendState.SourceColorBlendFactor)];
rtBlendDesc.DestBlend = JulietToD3D12_BlendFactor[ToUnderlying(blendState.DestinationColorBlendFactor)];
rtBlendDesc.BlendOp = JulietToD3D12_BlendOperation[ToUnderlying(blendState.ColorBlendOperation)];
rtBlendDesc.SrcBlendAlpha = JulietToD3D12_BlendFactorAlpha[ToUnderlying(blendState.SourceAlphaBlendFactor)];
rtBlendDesc.DestBlendAlpha =
JulietToD3D12_BlendFactorAlpha[ToUnderlying(blendState.DestinationAlphaBlendFactor)];
rtBlendDesc.BlendOpAlpha = JulietToD3D12_BlendOperation[ToUnderlying(blendState.AlphaBlendOperation)];
rtBlendDesc.RenderTargetWriteMask = ToUnderlying(colorWriteMask);
if (i > 0)
{
blendDesc.IndependentBlendEnable = TRUE;
}
}
blendDesc.RenderTarget[i] = rtBlendDesc;
}
return true;
}
bool ConvertDepthStencilState(DepthStencilState depthStencilState, D3D12_DEPTH_STENCIL_DESC& desc)
{
desc.DepthEnable = depthStencilState.EnableDepthTest == true ? TRUE : FALSE;
desc.DepthWriteMask = depthStencilState.EnableDepthWrite == true ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
desc.DepthFunc = JulietToD3D12_CompareOperation[ToUnderlying(depthStencilState.CompareOperation)];
desc.StencilEnable = depthStencilState.EnableStencilTest == true ? TRUE : FALSE;
desc.StencilReadMask = depthStencilState.CompareMask;
desc.StencilWriteMask = depthStencilState.WriteMask;
desc.FrontFace.StencilFailOp =
JulietToD3D12_StencilOperation[ToUnderlying(depthStencilState.FrontStencilState.FailOperation)];
desc.FrontFace.StencilDepthFailOp =
JulietToD3D12_StencilOperation[ToUnderlying(depthStencilState.FrontStencilState.DepthFailOperation)];
desc.FrontFace.StencilPassOp =
JulietToD3D12_StencilOperation[ToUnderlying(depthStencilState.FrontStencilState.PassOperation)];
desc.FrontFace.StencilFunc =
JulietToD3D12_CompareOperation[ToUnderlying(depthStencilState.FrontStencilState.CompareOperation)];
desc.BackFace.StencilFailOp =
JulietToD3D12_StencilOperation[ToUnderlying(depthStencilState.BackStencilState.FailOperation)];
desc.BackFace.StencilDepthFailOp =
JulietToD3D12_StencilOperation[ToUnderlying(depthStencilState.BackStencilState.DepthFailOperation)];
desc.BackFace.StencilPassOp =
JulietToD3D12_StencilOperation[ToUnderlying(depthStencilState.BackStencilState.PassOperation)];
desc.BackFace.StencilFunc =
JulietToD3D12_CompareOperation[ToUnderlying(depthStencilState.BackStencilState.CompareOperation)];
return true;
}
D3D12GraphicsRootSignature* CreateGraphicsRootSignature(NonNullPtr<D3D12Driver> renderer, NonNullPtr<D3D12Shader> vertexShader,
NonNullPtr<D3D12Shader> fragmentShader)
{
return nullptr;
}
void DestroyGraphicsRootSignature(NonNullPtr<D3D12GraphicsRootSignature> rootSignature)
{
if (!rootSignature)
{
return;
}
if (rootSignature->handle)
{
ID3D12RootSignature_Release(rootSignature->handle);
}
Free(rootSignature.Get());
}
} // namespace
GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GPUDriver> driver, const GraphicsPipelineCreateInfo& createInfo)
{
auto d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
auto vertexShader = reinterpret_cast<D3D12Shader*>(createInfo.VertexShader);
auto fragmentShader = reinterpret_cast<D3D12Shader*>(createInfo.FragmentShader);
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.VS.pShaderBytecode = vertexShader->ByteCode.Data;
psoDesc.VS.BytecodeLength = vertexShader->ByteCode.Size;
psoDesc.PS.pShaderBytecode = fragmentShader->ByteCode.Data; // PS == Pixel Shader == Fragment Shader
psoDesc.PS.BytecodeLength = fragmentShader->ByteCode.Size;
D3D12_INPUT_ELEMENT_DESC inputElementDescs[D3D12_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
if (createInfo.VertexInputState.NumVertexAttributes > 0)
{
psoDesc.InputLayout.pInputElementDescs = inputElementDescs;
psoDesc.InputLayout.NumElements = createInfo.VertexInputState.NumVertexAttributes;
ConvertVertexInputState(createInfo.VertexInputState, inputElementDescs, d3d12Driver->Semantic);
}
psoDesc.PrimitiveTopologyType = JulietToD3D12_PrimitiveTopologyType[ToUnderlying(createInfo.PrimitiveType)];
if (!ConvertRasterizerState(createInfo.RasterizerState, psoDesc.RasterizerState))
{
return nullptr;
}
if (!ConvertBlendState(createInfo, psoDesc.BlendState))
{
return nullptr;
}
if (!ConvertDepthStencilState(createInfo.DepthStencilState, psoDesc.DepthStencilState))
{
return nullptr;
}
auto pipeline = static_cast<D3D12GraphicsPipeline*>(Calloc(1, sizeof(D3D12GraphicsPipeline)));
if (!pipeline)
{
return nullptr;
}
uint32 sampleMask = createInfo.MultisampleState.EnableMask ? createInfo.MultisampleState.SampleMask : 0xFFFFFFFF;
psoDesc.SampleMask = sampleMask;
psoDesc.SampleDesc.Count = Internal::JulietToD3D12_SampleCount[ToUnderlying(createInfo.MultisampleState.SampleCount)];
psoDesc.SampleDesc.Quality =
(createInfo.MultisampleState.SampleCount > TextureSampleCount::One) ? DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN : 0;
psoDesc.DSVFormat = Internal::ConvertToD3D12DepthFormat(createInfo.TargetInfo.DepthStencilFormat);
psoDesc.NumRenderTargets = static_cast<uint32>(createInfo.TargetInfo.NumColorTargets);
for (uint32_t idx = 0; idx < createInfo.TargetInfo.NumColorTargets; ++idx)
{
psoDesc.RTVFormats[idx] =
Internal::ConvertToD3D12TextureFormat(createInfo.TargetInfo.ColorTargetDescriptions[idx].Format);
}
// Assuming some default values or further initialization
psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
psoDesc.CachedPSO.CachedBlobSizeInBytes = 0;
psoDesc.CachedPSO.pCachedBlob = nullptr;
psoDesc.NodeMask = 0;
D3D12GraphicsRootSignature* rootSignature = CreateGraphicsRootSignature(d3d12Driver, vertexShader, fragmentShader);
if (rootSignature == NULL)
{
Internal::ReleaseGraphicsPipeline(pipeline);
return nullptr;
}
pipeline->RootSignature = rootSignature;
ID3D12PipelineState* pipelineState;
HRESULT res = ID3D12Device_CreateGraphicsPipelineState(d3d12Driver->D3D12Device, &psoDesc, IID_ID3D12PipelineState,
reinterpret_cast<void**>(&pipelineState));
if (FAILED(res))
{
LogError(d3d12Driver, "Could not create graphics pipeline state", res);
Internal::ReleaseGraphicsPipeline(pipeline);
return nullptr;
}
pipeline->PipelineState = pipelineState;
for (uint32 i = 0; i < createInfo.VertexInputState.NumVertexBufferDescriptions; i += 1)
{
pipeline->VertexStrides[createInfo.VertexInputState.VertexBufferDescriptions[i].Slot] =
createInfo.VertexInputState.VertexBufferDescriptions[i].PitchInBytes;
}
pipeline->PrimitiveType = createInfo.PrimitiveType;
pipeline->VertexSamplerCount = vertexShader->NumSamplers;
pipeline->VertexStorageTextureCount = vertexShader->NumStorageTextures;
pipeline->VertexStorageBufferCount = vertexShader->NumStorageBuffers;
pipeline->VertexUniformBufferCount = vertexShader->NumUniformBuffers;
pipeline->FragmentSamplerCount = fragmentShader->NumSamplers;
pipeline->FragmentStorageTextureCount = fragmentShader->NumStorageTextures;
pipeline->FragmentStorageBufferCount = fragmentShader->NumStorageBuffers;
pipeline->FragmentUniformBufferCount = fragmentShader->NumUniformBuffers;
pipeline->ReferenceCount = 0;
return reinterpret_cast<GraphicsPipeline*>(pipeline);
}
extern void DestroyGraphicsPipeline(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> graphicsPipeline)
{
auto d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
auto d3d12GraphicsPipeline = reinterpret_cast<D3D12GraphicsPipeline*>(graphicsPipeline.Get());
if (d3d12Driver->GraphicsPipelinesToDisposeCount + 1 >= d3d12Driver->GraphicsPipelinesToDisposeCapacity)
{
d3d12Driver->GraphicsPipelinesToDisposeCapacity = d3d12Driver->GraphicsPipelinesToDisposeCapacity * 2;
d3d12Driver->GraphicsPipelinesToDispose = static_cast<D3D12GraphicsPipeline**>(
Realloc(d3d12Driver->GraphicsPipelinesToDispose,
sizeof(D3D12GraphicsPipeline*) * d3d12Driver->GraphicsPipelinesToDisposeCapacity));
}
d3d12Driver->GraphicsPipelinesToDispose[d3d12Driver->GraphicsPipelinesToDisposeCount] = d3d12GraphicsPipeline;
d3d12Driver->GraphicsPipelinesToDisposeCount += 1;
}
namespace Internal
{
void ReleaseGraphicsPipeline(NonNullPtr<D3D12GraphicsPipeline> d3d12GraphicsPipeline)
{
if (d3d12GraphicsPipeline->PipelineState)
{
ID3D12PipelineState_Release(d3d12GraphicsPipeline->PipelineState);
}
DestroyGraphicsRootSignature(d3d12GraphicsPipeline->RootSignature);
Free(d3d12GraphicsPipeline.Get());
}
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -1,6 +1,9 @@
#pragma once
#include <Core/Common/NonNullPtr.h>
#include <Graphics/D3D12/D3D12Includes.h>
#include <Graphics/GraphicsDevice.h>
#include <Graphics/GraphicsPipeline.h>
namespace Juliet
{
@@ -11,5 +14,51 @@ namespace Juliet
namespace Juliet::D3D12
{
extern GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GPUDriver> driver, GraphicsPipelineCreateInfo& createInfo);
}
struct D3D12GraphicsRootSignature
{
ID3D12RootSignature* handle;
int32 VertexSamplerRootIndex;
int32 VertexSamplerTextureRootIndex;
int32 VertexStorageTextureRootIndex;
int32 VertexStorageBufferRootIndex;
int32 VertexUniformBufferRootIndex[GPUDriver::kMaxUniformBuffersPerStage];
int32 FragmentSamplerRootIndex;
int32 FragmentSamplerTextureRootIndex;
int32 FragmentStorageTextureRootIndex;
int32 FragmentStorageBufferRootIndex;
int32 FragmentUniformBufferRootIndex[GPUDriver::kMaxUniformBuffersPerStage];
};
struct D3D12GraphicsPipeline
{
ID3D12PipelineState* PipelineState;
D3D12GraphicsRootSignature* RootSignature;
PrimitiveType PrimitiveType;
uint32 VertexStrides[GPUDriver::kMaxVertexBuffers];
uint32 VertexSamplerCount;
uint32 VertexUniformBufferCount;
uint32 VertexStorageBufferCount;
uint32 VertexStorageTextureCount;
uint32 FragmentSamplerCount;
uint32 FragmentUniformBufferCount;
uint32 FragmentStorageBufferCount;
uint32 FragmentStorageTextureCount;
int ReferenceCount;
};
extern GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GPUDriver> driver, const GraphicsPipelineCreateInfo& createInfo);
extern void DestroyGraphicsPipeline(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> graphicsPipeline);
namespace Internal
{
extern void ReleaseGraphicsPipeline(NonNullPtr<D3D12GraphicsPipeline> d3d12GraphicsPipeline);
}
} // namespace Juliet::D3D12

View File

@@ -5,14 +5,6 @@
namespace Juliet::D3D12
{
namespace
{
struct D3D12Shader
{
ByteBuffer ByteCode;
};
} // namespace
Shader* CreateShader(NonNullPtr<GPUDriver> driver, ByteBuffer shaderByteCode, ShaderCreateInfo& shaderCreateInfo)
{
if (!IsValid(shaderByteCode))

View File

@@ -6,6 +6,16 @@
namespace Juliet::D3D12
{
struct D3D12Shader
{
ByteBuffer ByteCode;
uint32 NumSamplers;
uint32 NumUniformBuffers;
uint32 NumStorageBuffers;
uint32 NumStorageTextures;
};
extern Shader* CreateShader(NonNullPtr<GPUDriver> driver, ByteBuffer shaderByteCode, ShaderCreateInfo& shaderCreateInfo);
extern void DestroyShader(NonNullPtr<GPUDriver> driver, NonNullPtr<Shader> shader);
} // namespace Juliet::D3D12

View File

@@ -66,6 +66,8 @@ namespace Juliet::D3D12
result &= Internal::CleanCommandList(d3d12driver, d3d12driver->SubmittedCommandLists[idx], false);
}
Internal::DisposePendingResourcces(d3d12driver);
return result;
}

View File

@@ -116,6 +116,117 @@ namespace Juliet::D3D12
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
};
static_assert(sizeof(JulietToD3D12_TextureFormat) / sizeof(JulietToD3D12_TextureFormat[0]) ==
ToUnderlying(TextureFormat::Count));
DXGI_FORMAT JulietToD3D12_DepthFormat[] = {
DXGI_FORMAT_UNKNOWN, // INVALID
DXGI_FORMAT_UNKNOWN, // A8_UNORM
DXGI_FORMAT_UNKNOWN, // R8_UNORM
DXGI_FORMAT_UNKNOWN, // R8G8_UNORM
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UNORM
DXGI_FORMAT_UNKNOWN, // R16_UNORM
DXGI_FORMAT_UNKNOWN, // R16G16_UNORM
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_UNORM
DXGI_FORMAT_UNKNOWN, // R10G10B10A2_UNORM
DXGI_FORMAT_UNKNOWN, // B5G6R5_UNORM
DXGI_FORMAT_UNKNOWN, // B5G5R5A1_UNORM
DXGI_FORMAT_UNKNOWN, // B4G4R4A4_UNORM
DXGI_FORMAT_UNKNOWN, // B8G8R8A8_UNORM
DXGI_FORMAT_UNKNOWN, // BC1_UNORM
DXGI_FORMAT_UNKNOWN, // BC2_UNORM
DXGI_FORMAT_UNKNOWN, // BC3_UNORM
DXGI_FORMAT_UNKNOWN, // BC4_UNORM
DXGI_FORMAT_UNKNOWN, // BC5_UNORM
DXGI_FORMAT_UNKNOWN, // BC7_UNORM
DXGI_FORMAT_UNKNOWN, // BC6H_FLOAT
DXGI_FORMAT_UNKNOWN, // BC6H_UFLOAT
DXGI_FORMAT_UNKNOWN, // R8_SNORM
DXGI_FORMAT_UNKNOWN, // R8G8_SNORM
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_SNORM
DXGI_FORMAT_UNKNOWN, // R16_SNORM
DXGI_FORMAT_UNKNOWN, // R16G16_SNORM
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_SNORM
DXGI_FORMAT_UNKNOWN, // R16_FLOAT
DXGI_FORMAT_UNKNOWN, // R16G16_FLOAT
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_FLOAT
DXGI_FORMAT_UNKNOWN, // R32_FLOAT
DXGI_FORMAT_UNKNOWN, // R32G32_FLOAT
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_FLOAT
DXGI_FORMAT_UNKNOWN, // R11G11B10_UFLOAT
DXGI_FORMAT_UNKNOWN, // R8_UINT
DXGI_FORMAT_UNKNOWN, // R8G8_UINT
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UINT
DXGI_FORMAT_UNKNOWN, // R16_UINT
DXGI_FORMAT_UNKNOWN, // R16G16_UINT
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_UINT
DXGI_FORMAT_UNKNOWN, // R32_UINT
DXGI_FORMAT_UNKNOWN, // R32G32_UINT
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_UINT
DXGI_FORMAT_UNKNOWN, // R8_INT
DXGI_FORMAT_UNKNOWN, // R8G8_INT
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_INT
DXGI_FORMAT_UNKNOWN, // R16_INT
DXGI_FORMAT_UNKNOWN, // R16G16_INT
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_INT
DXGI_FORMAT_UNKNOWN, // R32_INT
DXGI_FORMAT_UNKNOWN, // R32G32_INT
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_INT
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // B8G8R8A8_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC1_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC2_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC3_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC7_UNORM_SRGB
DXGI_FORMAT_D16_UNORM, // D16_UNORM
DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM
DXGI_FORMAT_D32_FLOAT, // D32_FLOAT
DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT
DXGI_FORMAT_D32_FLOAT_S8X24_UINT, // 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
};
static_assert(sizeof(JulietToD3D12_DepthFormat) / sizeof(JulietToD3D12_DepthFormat[0]) == ToUnderlying(TextureFormat::Count));
uint32 ComputeSubresourceIndex(uint32 mipLevel, uint32 layer, uint32 numLevels)
{
@@ -236,5 +347,17 @@ namespace Juliet::D3D12
{
return JulietToD3D12_TextureFormat[ToUnderlying(format)];
}
DXGI_FORMAT ConvertToD3D12DepthFormat(TextureFormat format)
{
return JulietToD3D12_DepthFormat[ToUnderlying(format)];
}
uint32 JulietToD3D12_SampleCount[] = {
1, // MSAA 1x
2, // MSAA 2x
4, // MSAA 4x
8, // MSAA 8x
};
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -88,5 +88,7 @@ namespace Juliet::D3D12
// Utils
extern DXGI_FORMAT ConvertToD3D12TextureFormat(TextureFormat format);
extern DXGI_FORMAT ConvertToD3D12DepthFormat(TextureFormat format);
extern uint32 JulietToD3D12_SampleCount[];
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -218,8 +218,8 @@ namespace Juliet
device->DestroyShader(device->Driver, shader);
}
GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GraphicsDevice> device, GraphicsPipelineCreateInfo& createInfo)
GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GraphicsDevice> device, const GraphicsPipelineCreateInfo& createInfo)
{
device->CreateGraphicsPipeline(device->Driver, createInfo);
return device->CreateGraphicsPipeline(device->Driver, createInfo);
}
} // namespace Juliet

View File

@@ -30,9 +30,11 @@ namespace Juliet
struct GPUDriver
{
static constexpr uint8 kResourceBufferCount = 2;
static constexpr uint8 kMaxFramesInFlight = 3;
static constexpr uint8 kMaxColorTargetInfo = 4;
static constexpr uint8 kResourceBufferCount = 2;
static constexpr uint8 kMaxFramesInFlight = 3;
static constexpr uint8 kMaxColorTargetInfo = 4;
static constexpr uint8 kMaxUniformBuffersPerStage = 4;
static constexpr uint8 kMaxVertexBuffers = 16;
};
struct GraphicsDevice
@@ -71,7 +73,7 @@ namespace Juliet
void (*DestroyShader)(NonNullPtr<GPUDriver> driver, NonNullPtr<Shader> shader);
// Pipeline
GraphicsPipeline* (*CreateGraphicsPipeline)(NonNullPtr<GPUDriver> driver, GraphicsPipelineCreateInfo& createInfo);
GraphicsPipeline* (*CreateGraphicsPipeline)(NonNullPtr<GPUDriver> driver, const GraphicsPipelineCreateInfo& createInfo);
const char* Name = "Unknown";
GPUDriver* Driver = nullptr;

View File

@@ -74,18 +74,21 @@ void JulietApplication::Init()
shaderCI.Stage = ShaderStage::Fragment;
Shader* fragmentShader = CreateShader(GraphicsDevice, shaderPath, shaderCI);
ColorTargetDescription colorTargetDescription = { .Format = GetSwapChainTextureFormat(GraphicsDevice, MainWindow) };
GraphicsPipelineCreateInfo pipelineCI = {
.VertexShader = vertexShader,
.FragmentShader = fragmentShader,
.PrimitiveType = PrimitiveType::TriangleList,
.TargetInfo = {
.ColorTargetDescriptions = &colorTargetDescription,
.NumColorTargets = 1,
},
ColorTargetDescription colorTargetDescription = {};
colorTargetDescription.Format = GetSwapChainTextureFormat(GraphicsDevice, MainWindow);
GraphicsPipelineCreateInfo pipelineCI = {};
pipelineCI.VertexShader = vertexShader;
pipelineCI.FragmentShader = fragmentShader;
pipelineCI.PrimitiveType = PrimitiveType::TriangleList;
pipelineCI.TargetInfo = {
.ColorTargetDescriptions = &colorTargetDescription,
.NumColorTargets = 1,
};
pipelineCI.RasterizerState.FillMode = FillMode::Solid;
GraphicsPipeline* mainPipeline = CreateGraphicsPipeline(GraphicsDevice, pipelineCI);
if (vertexShader)
{
DestroyShader(GraphicsDevice, vertexShader);