Added:
- Depth buffer - Debug display basics - Basic vector + matrix maths Made partially with gemini + antigravity
This commit is contained in:
BIN
Assets/compiled/Debug.frag.dxil
Normal file
BIN
Assets/compiled/Debug.frag.dxil
Normal file
Binary file not shown.
BIN
Assets/compiled/Debug.vert.dxil
Normal file
BIN
Assets/compiled/Debug.vert.dxil
Normal file
Binary file not shown.
Binary file not shown.
4
Assets/source/Debug.frag.hlsl
Normal file
4
Assets/source/Debug.frag.hlsl
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
float4 main(float4 Color : TEXCOORD0) : SV_Target0
|
||||||
|
{
|
||||||
|
return Color;
|
||||||
|
}
|
||||||
27
Assets/source/Debug.vert.hlsl
Normal file
27
Assets/source/Debug.vert.hlsl
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
struct Output
|
||||||
|
{
|
||||||
|
float4 Color : TEXCOORD0;
|
||||||
|
float4 Position : SV_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "RootConstants.hlsl"
|
||||||
|
|
||||||
|
Output main(uint vertexIndex : SV_VertexID)
|
||||||
|
{
|
||||||
|
Output output;
|
||||||
|
|
||||||
|
// Retrieve the vertex buffer using SM6.6 bindless syntax
|
||||||
|
ByteAddressBuffer buffer = ResourceDescriptorHeap[BufferIndex];
|
||||||
|
|
||||||
|
// Vertex layout: float3 Position (12 bytes) + float4 Color (16 bytes) = 28 bytes stride
|
||||||
|
uint stride = 28;
|
||||||
|
uint offset = vertexIndex * stride;
|
||||||
|
|
||||||
|
float3 pos = asfloat(buffer.Load3(offset));
|
||||||
|
float4 col = asfloat(buffer.Load4(offset + 12));
|
||||||
|
|
||||||
|
// Standard row-major transformation
|
||||||
|
output.Position = mul(ViewProjection, float4(pos, 1.0f));
|
||||||
|
output.Color = col;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
11
Assets/source/RootConstants.hlsl
Normal file
11
Assets/source/RootConstants.hlsl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef ROOT_CONSTANTS_HLSL
|
||||||
|
#define ROOT_CONSTANTS_HLSL
|
||||||
|
|
||||||
|
cbuffer RootConstants : register(b0, space0)
|
||||||
|
{
|
||||||
|
row_major float4x4 ViewProjection;
|
||||||
|
uint BufferIndex;
|
||||||
|
uint _Padding[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ROOT_CONSTANTS_HLSL
|
||||||
@@ -1,26 +1,17 @@
|
|||||||
struct Input
|
|
||||||
{
|
|
||||||
uint VertexIndex : SV_VertexID;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Output
|
struct Output
|
||||||
{
|
{
|
||||||
float4 Color : TEXCOORD0;
|
float4 Color : TEXCOORD0;
|
||||||
float4 Position : SV_Position;
|
float4 Position : SV_Position;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bindless storage buffer access
|
#include "RootConstants.hlsl"
|
||||||
// We assume DescriptorIndex 0 is our buffer for this example, or passed via push constant
|
|
||||||
// Since we don't have push constants hooked up in the C++ simplified example yet,
|
|
||||||
// we will assume the First descriptor in the heap is our buffer (Index 0).
|
|
||||||
// In a real app, 'bufferIndex' would be passed as a Root Constant.
|
|
||||||
|
|
||||||
Output main(Input input)
|
Output main(uint vertexIndex : SV_VertexID)
|
||||||
{
|
{
|
||||||
Output output;
|
Output output;
|
||||||
|
|
||||||
// Retrieve the buffer using SM6.6 bindless syntax
|
// Retrieve the buffer using SM6.6 bindless syntax
|
||||||
// heap index 0 is used for simplicity.
|
// We use index 0 as the sample app doesn't pass push constants yet.
|
||||||
uint bufferIndex = 0;
|
uint bufferIndex = 0;
|
||||||
ByteAddressBuffer buffer = ResourceDescriptorHeap[bufferIndex];
|
ByteAddressBuffer buffer = ResourceDescriptorHeap[bufferIndex];
|
||||||
|
|
||||||
@@ -28,7 +19,7 @@ Output main(Input input)
|
|||||||
// Stride = 2 float (pos) + 4 float (color) = 6 * 4 = 24 bytes ?
|
// Stride = 2 float (pos) + 4 float (color) = 6 * 4 = 24 bytes ?
|
||||||
// Let's assume just position 2D (8 bytes) + Color (16 bytes)
|
// Let's assume just position 2D (8 bytes) + Color (16 bytes)
|
||||||
uint stride = 24;
|
uint stride = 24;
|
||||||
uint offset = input.VertexIndex * stride;
|
uint offset = vertexIndex * stride;
|
||||||
|
|
||||||
float2 pos = asfloat(buffer.Load2(offset));
|
float2 pos = asfloat(buffer.Load2(offset));
|
||||||
float4 col = asfloat(buffer.Load4(offset + 8));
|
float4 col = asfloat(buffer.Load4(offset + 8));
|
||||||
|
|||||||
@@ -53,7 +53,9 @@
|
|||||||
<CustomBuild Include="include\Core\Logging\LogManager.h" />
|
<CustomBuild Include="include\Core\Logging\LogManager.h" />
|
||||||
<CustomBuild Include="include\Core\Logging\LogTypes.h" />
|
<CustomBuild Include="include\Core\Logging\LogTypes.h" />
|
||||||
<CustomBuild Include="include\Core\Math\MathUtils.h" />
|
<CustomBuild Include="include\Core\Math\MathUtils.h" />
|
||||||
|
<CustomBuild Include="include\Core\Math\Matrix.h" />
|
||||||
<CustomBuild Include="include\Core\Math\Shape.h" />
|
<CustomBuild Include="include\Core\Math\Shape.h" />
|
||||||
|
<CustomBuild Include="include\Core\Math\Vector.h" />
|
||||||
<CustomBuild Include="include\Core\Memory\Allocator.h" />
|
<CustomBuild Include="include\Core\Memory\Allocator.h" />
|
||||||
<CustomBuild Include="include\Core\Memory\Utils.h" />
|
<CustomBuild Include="include\Core\Memory\Utils.h" />
|
||||||
<CustomBuild Include="include\Core\Networking\IPAddress.h" />
|
<CustomBuild Include="include\Core\Networking\IPAddress.h" />
|
||||||
@@ -66,7 +68,9 @@
|
|||||||
<CustomBuild Include="include\Core\Thread\Thread.h" />
|
<CustomBuild Include="include\Core\Thread\Thread.h" />
|
||||||
<CustomBuild Include="include\Engine\Class.h" />
|
<CustomBuild Include="include\Engine\Class.h" />
|
||||||
<CustomBuild Include="include\Engine\Engine.h" />
|
<CustomBuild Include="include\Engine\Engine.h" />
|
||||||
|
<CustomBuild Include="include\Graphics\Camera.h" />
|
||||||
<CustomBuild Include="include\Graphics\Colors.h" />
|
<CustomBuild Include="include\Graphics\Colors.h" />
|
||||||
|
<CustomBuild Include="include\Graphics\DebugDisplay.h" />
|
||||||
<CustomBuild Include="include\Graphics\Graphics.h" />
|
<CustomBuild Include="include\Graphics\Graphics.h" />
|
||||||
<CustomBuild Include="include\Graphics\GraphicsBuffer.h" />
|
<CustomBuild Include="include\Graphics\GraphicsBuffer.h" />
|
||||||
<CustomBuild Include="include\Graphics\GraphicsConfig.h" />
|
<CustomBuild Include="include\Graphics\GraphicsConfig.h" />
|
||||||
@@ -166,6 +170,7 @@
|
|||||||
<CustomBuild Include="src\Graphics\D3D12\D3D12Texture.h" />
|
<CustomBuild Include="src\Graphics\D3D12\D3D12Texture.h" />
|
||||||
<CustomBuild Include="src\Graphics\D3D12\D3D12Utils.cpp" />
|
<CustomBuild Include="src\Graphics\D3D12\D3D12Utils.cpp" />
|
||||||
<CustomBuild Include="src\Graphics\D3D12\D3D12Utils.h" />
|
<CustomBuild Include="src\Graphics\D3D12\D3D12Utils.h" />
|
||||||
|
<CustomBuild Include="src\Graphics\DebugDisplayRenderer.cpp" />
|
||||||
<CustomBuild Include="src\Graphics\Graphics.cpp" />
|
<CustomBuild Include="src\Graphics\Graphics.cpp" />
|
||||||
<CustomBuild Include="src\Graphics\GraphicsDevice.h" />
|
<CustomBuild Include="src\Graphics\GraphicsDevice.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -79,9 +79,15 @@
|
|||||||
<CustomBuild Include="include\Core\Math\MathUtils.h">
|
<CustomBuild Include="include\Core\Math\MathUtils.h">
|
||||||
<Filter>include\Core\Math</Filter>
|
<Filter>include\Core\Math</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="include\Core\Math\Matrix.h">
|
||||||
|
<Filter>include\Core\Math</Filter>
|
||||||
|
</CustomBuild>
|
||||||
<CustomBuild Include="include\Core\Math\Shape.h">
|
<CustomBuild Include="include\Core\Math\Shape.h">
|
||||||
<Filter>include\Core\Math</Filter>
|
<Filter>include\Core\Math</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="include\Core\Math\Vector.h">
|
||||||
|
<Filter>include\Core\Math</Filter>
|
||||||
|
</CustomBuild>
|
||||||
<CustomBuild Include="include\Core\Memory\Allocator.h">
|
<CustomBuild Include="include\Core\Memory\Allocator.h">
|
||||||
<Filter>include\Core\Memory</Filter>
|
<Filter>include\Core\Memory</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
@@ -118,9 +124,15 @@
|
|||||||
<CustomBuild Include="include\Engine\Engine.h">
|
<CustomBuild Include="include\Engine\Engine.h">
|
||||||
<Filter>include\Engine</Filter>
|
<Filter>include\Engine</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="include\Graphics\Camera.h">
|
||||||
|
<Filter>include\Graphics</Filter>
|
||||||
|
</CustomBuild>
|
||||||
<CustomBuild Include="include\Graphics\Colors.h">
|
<CustomBuild Include="include\Graphics\Colors.h">
|
||||||
<Filter>include\Graphics</Filter>
|
<Filter>include\Graphics</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="include\Graphics\DebugDisplay.h">
|
||||||
|
<Filter>include\Graphics</Filter>
|
||||||
|
</CustomBuild>
|
||||||
<CustomBuild Include="include\Graphics\Graphics.h">
|
<CustomBuild Include="include\Graphics\Graphics.h">
|
||||||
<Filter>include\Graphics</Filter>
|
<Filter>include\Graphics</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
@@ -417,6 +429,9 @@
|
|||||||
<CustomBuild Include="src\Graphics\D3D12\D3D12Utils.h">
|
<CustomBuild Include="src\Graphics\D3D12\D3D12Utils.h">
|
||||||
<Filter>src\Graphics\D3D12</Filter>
|
<Filter>src\Graphics\D3D12</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="src\Graphics\DebugDisplayRenderer.cpp">
|
||||||
|
<Filter>src\Graphics</Filter>
|
||||||
|
</CustomBuild>
|
||||||
<CustomBuild Include="src\Graphics\Graphics.cpp">
|
<CustomBuild Include="src\Graphics\Graphics.cpp">
|
||||||
<Filter>src\Graphics</Filter>
|
<Filter>src\Graphics</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
|||||||
86
Juliet/include/Core/Math/Matrix.h
Normal file
86
Juliet/include/Core/Math/Matrix.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Math/Vector.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
struct Matrix
|
||||||
|
{
|
||||||
|
float m[4][4];
|
||||||
|
|
||||||
|
static Matrix Identity()
|
||||||
|
{
|
||||||
|
Matrix result = {};
|
||||||
|
result.m[0][0] = 1.0f;
|
||||||
|
result.m[1][1] = 1.0f;
|
||||||
|
result.m[2][2] = 1.0f;
|
||||||
|
result.m[3][3] = 1.0f;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix operator*(const Matrix& rhs) const
|
||||||
|
{
|
||||||
|
Matrix result = {};
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 4; ++j)
|
||||||
|
{
|
||||||
|
for (int k = 0; k < 4; ++k)
|
||||||
|
{
|
||||||
|
result.m[i][j] += m[i][k] * rhs.m[k][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Matrix LookAt(const Vector3& eye, const Vector3& target, const Vector3& up)
|
||||||
|
{
|
||||||
|
// Left-Handed convention
|
||||||
|
Vector3 zaxis = Normalize(target - eye); // Forward is +z
|
||||||
|
Vector3 xaxis = Normalize(Cross(up, zaxis));
|
||||||
|
Vector3 yaxis = Cross(zaxis, xaxis);
|
||||||
|
|
||||||
|
Matrix result = {};
|
||||||
|
// Row 0
|
||||||
|
result.m[0][0] = xaxis.x;
|
||||||
|
result.m[0][1] = xaxis.y;
|
||||||
|
result.m[0][2] = xaxis.z;
|
||||||
|
result.m[0][3] = -Dot(xaxis, eye);
|
||||||
|
|
||||||
|
// Row 1
|
||||||
|
result.m[1][0] = yaxis.x;
|
||||||
|
result.m[1][1] = yaxis.y;
|
||||||
|
result.m[1][2] = yaxis.z;
|
||||||
|
result.m[1][3] = -Dot(yaxis, eye);
|
||||||
|
|
||||||
|
// Row 2
|
||||||
|
result.m[2][0] = zaxis.x;
|
||||||
|
result.m[2][1] = zaxis.y;
|
||||||
|
result.m[2][2] = zaxis.z;
|
||||||
|
result.m[2][3] = -Dot(zaxis, eye);
|
||||||
|
|
||||||
|
// Row 3
|
||||||
|
result.m[3][3] = 1.0f;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Matrix PerspectiveFov(float fovY, float aspectRatio, float nearZ, float farZ)
|
||||||
|
{
|
||||||
|
// Left-Handed Perspective
|
||||||
|
float yScale = 1.0f / tanf(fovY * 0.5f);
|
||||||
|
float xScale = yScale / aspectRatio;
|
||||||
|
|
||||||
|
Matrix result = {};
|
||||||
|
result.m[0][0] = xScale;
|
||||||
|
result.m[1][1] = yScale;
|
||||||
|
result.m[2][2] = farZ / (farZ - nearZ);
|
||||||
|
result.m[2][3] = (-nearZ * farZ) / (farZ - nearZ);
|
||||||
|
result.m[3][2] = 1.0f;
|
||||||
|
result.m[3][3] = 0.0f;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} // namespace Juliet
|
||||||
39
Juliet/include/Core/Math/Vector.h
Normal file
39
Juliet/include/Core/Math/Vector.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
struct Vector3
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
|
||||||
|
Vector3 operator+(const Vector3& rhs) const { return { x + rhs.x, y + rhs.y, z + rhs.z }; }
|
||||||
|
Vector3 operator-(const Vector3& rhs) const { return { x - rhs.x, y - rhs.y, z - rhs.z }; }
|
||||||
|
Vector3 operator*(float s) const { return { x * s, y * s, z * s }; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Vector4
|
||||||
|
{
|
||||||
|
float x, y, z, w;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Vector3 Normalize(const Vector3& v)
|
||||||
|
{
|
||||||
|
float len = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||||
|
if (len > 0.0001f)
|
||||||
|
{
|
||||||
|
return { v.x / len, v.y / len, v.z / len };
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vector3 Cross(const Vector3& a, const Vector3& b)
|
||||||
|
{
|
||||||
|
return { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float Dot(const Vector3& a, const Vector3& b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
|
||||||
|
} // namespace Juliet
|
||||||
33
Juliet/include/Graphics/Camera.h
Normal file
33
Juliet/include/Graphics/Camera.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Math/Matrix.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
struct Camera
|
||||||
|
{
|
||||||
|
Vector3 Position;
|
||||||
|
Vector3 Target;
|
||||||
|
Vector3 Up;
|
||||||
|
float FOV; // In radians
|
||||||
|
float AspectRatio;
|
||||||
|
float NearPlane;
|
||||||
|
float FarPlane;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Matrix Camera_GetViewMatrix(const Camera& cam)
|
||||||
|
{
|
||||||
|
return LookAt(cam.Position, cam.Target, cam.Up);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Matrix Camera_GetProjectionMatrix(const Camera& cam)
|
||||||
|
{
|
||||||
|
return PerspectiveFov(cam.FOV, cam.AspectRatio, cam.NearPlane, cam.FarPlane);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Matrix Camera_GetViewProjectionMatrix(const Camera& cam)
|
||||||
|
{
|
||||||
|
return Camera_GetProjectionMatrix(cam) * Camera_GetViewMatrix(cam);
|
||||||
|
}
|
||||||
|
} // namespace Juliet
|
||||||
17
Juliet/include/Graphics/DebugDisplay.h
Normal file
17
Juliet/include/Graphics/DebugDisplay.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Math/Vector.h>
|
||||||
|
#include <Graphics/Camera.h>
|
||||||
|
#include <Graphics/Colors.h>
|
||||||
|
#include <Graphics/Graphics.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
extern JULIET_API void DebugDisplay_Initialize(GraphicsDevice* device);
|
||||||
|
extern JULIET_API void DebugDisplay_Shutdown(GraphicsDevice* device);
|
||||||
|
extern JULIET_API void DebugDisplay_DrawLine(const Vector3& start, const Vector3& end, const FColor& color, bool overlay);
|
||||||
|
extern JULIET_API void DebugDisplay_DrawSphere(const Vector3& center, float radius, const FColor& color, bool overlay);
|
||||||
|
extern JULIET_API void DebugDisplay_Prepare(CommandList* cmdList);
|
||||||
|
extern JULIET_API void DebugDisplay_Flush(CommandList* cmdList, RenderPass* renderPass, const Camera& camera);
|
||||||
|
} // namespace Juliet
|
||||||
@@ -104,14 +104,20 @@ namespace Juliet
|
|||||||
extern JULIET_API bool WaitForSwapchain(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
extern JULIET_API bool WaitForSwapchain(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
||||||
extern JULIET_API TextureFormat GetSwapChainTextureFormat(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
extern JULIET_API TextureFormat GetSwapChainTextureFormat(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
|
||||||
|
|
||||||
|
// Textures
|
||||||
|
extern JULIET_API Texture* CreateTexture(NonNullPtr<GraphicsDevice> device, const TextureCreateInfo& createInfo);
|
||||||
|
extern JULIET_API void DestroyTexture(NonNullPtr<GraphicsDevice> device, NonNullPtr<Texture> texture);
|
||||||
|
|
||||||
// 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<CommandList> commandList);
|
extern JULIET_API void SubmitCommandLists(NonNullPtr<CommandList> commandList);
|
||||||
|
|
||||||
// RenderPass
|
// RenderPass
|
||||||
extern JULIET_API RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, ColorTargetInfo& colorTargetInfo);
|
extern JULIET_API RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, ColorTargetInfo& colorTargetInfo,
|
||||||
|
DepthStencilTargetInfo* depthStencilTargetInfo = nullptr);
|
||||||
extern JULIET_API RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList,
|
extern JULIET_API RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList,
|
||||||
NonNullPtr<const ColorTargetInfo> colorTargetInfos, uint32 colorTargetInfoCount);
|
NonNullPtr<const ColorTargetInfo> colorTargetInfos, uint32 colorTargetInfoCount,
|
||||||
|
DepthStencilTargetInfo* depthStencilTargetInfo = nullptr);
|
||||||
extern JULIET_API void EndRenderPass(NonNullPtr<RenderPass> renderPass);
|
extern JULIET_API void EndRenderPass(NonNullPtr<RenderPass> renderPass);
|
||||||
|
|
||||||
extern JULIET_API void SetGraphicsViewPort(NonNullPtr<RenderPass> renderPass, const GraphicsViewPort& viewPort);
|
extern JULIET_API void SetGraphicsViewPort(NonNullPtr<RenderPass> renderPass, const GraphicsViewPort& viewPort);
|
||||||
|
|||||||
@@ -41,6 +41,18 @@ namespace Juliet
|
|||||||
StoreOperation StoreOperation;
|
StoreOperation StoreOperation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DepthStencilTargetInfo
|
||||||
|
{
|
||||||
|
Texture* TargetTexture;
|
||||||
|
uint32 MipLevel;
|
||||||
|
uint32 LayerIndex;
|
||||||
|
|
||||||
|
float ClearDepth;
|
||||||
|
uint8 ClearStencil;
|
||||||
|
LoadOperation LoadOperation;
|
||||||
|
StoreOperation StoreOperation;
|
||||||
|
};
|
||||||
|
|
||||||
enum class BlendFactor : uint8
|
enum class BlendFactor : uint8
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
D3D12TextureSubresource* ColorTargetSubresources[GPUDriver::kMaxColorTargetInfo];
|
D3D12TextureSubresource* ColorTargetSubresources[GPUDriver::kMaxColorTargetInfo];
|
||||||
D3D12TextureSubresource* ColorResolveSubresources[GPUDriver::kMaxColorTargetInfo];
|
D3D12TextureSubresource* ColorResolveSubresources[GPUDriver::kMaxColorTargetInfo];
|
||||||
|
D3D12TextureSubresource* DepthStencilSubresource;
|
||||||
|
|
||||||
bool NeedVertexBufferBind : 1;
|
bool NeedVertexBufferBind : 1;
|
||||||
bool NeedVertexSamplerBind : 1;
|
bool NeedVertexSamplerBind : 1;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <Graphics/D3D12/D3D12Shader.h>
|
#include <Graphics/D3D12/D3D12Shader.h>
|
||||||
#include <Graphics/D3D12/D3D12SwapChain.h>
|
#include <Graphics/D3D12/D3D12SwapChain.h>
|
||||||
#include <Graphics/D3D12/D3D12Synchronization.h>
|
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||||
|
#include <Graphics/D3D12/D3D12Texture.h>
|
||||||
#include <Graphics/D3D12/D3D12Utils.h>
|
#include <Graphics/D3D12/D3D12Utils.h>
|
||||||
#include <Graphics/Graphics.h>
|
#include <Graphics/Graphics.h>
|
||||||
#include <Graphics/GraphicsDevice.h>
|
#include <Graphics/GraphicsDevice.h>
|
||||||
@@ -254,13 +255,7 @@ namespace Juliet::D3D12
|
|||||||
.pParameters = parameters,
|
.pParameters = parameters,
|
||||||
.NumStaticSamplers = ArraySize(samplers),
|
.NumStaticSamplers = ArraySize(samplers),
|
||||||
.pStaticSamplers = samplers,
|
.pStaticSamplers = samplers,
|
||||||
.Flags = D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS |
|
.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
|
||||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
|
|
||||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
|
|
||||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
|
|
||||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS |
|
|
||||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_AMPLIFICATION_SHADER_ROOT_ACCESS |
|
|
||||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_MESH_SHADER_ROOT_ACCESS |
|
|
||||||
D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED |
|
D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED |
|
||||||
D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED,
|
D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED,
|
||||||
},
|
},
|
||||||
@@ -1010,6 +1005,8 @@ namespace Juliet::D3D12
|
|||||||
device->CopyBuffer = CopyBuffer;
|
device->CopyBuffer = CopyBuffer;
|
||||||
device->TransitionBufferToReadable = TransitionBufferToReadable;
|
device->TransitionBufferToReadable = TransitionBufferToReadable;
|
||||||
device->GetDescriptorIndex = GetDescriptorIndex;
|
device->GetDescriptorIndex = GetDescriptorIndex;
|
||||||
|
device->CreateTexture = CreateTexture;
|
||||||
|
device->DestroyTexture = DestroyTexture;
|
||||||
|
|
||||||
#if ALLOW_SHADER_HOT_RELOAD
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
device->UpdateGraphicsPipelineShaders = UpdateGraphicsPipelineShaders;
|
device->UpdateGraphicsPipelineShaders = UpdateGraphicsPipelineShaders;
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ namespace Juliet::D3D12
|
|||||||
ToUnderlying(PrimitiveType::Count));
|
ToUnderlying(PrimitiveType::Count));
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void BeginRenderPass(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos, uint32 colorTargetInfoCount)
|
void BeginRenderPass(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
||||||
|
uint32 colorTargetInfoCount, const DepthStencilTargetInfo* depthStencilTargetInfo)
|
||||||
{
|
{
|
||||||
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||||
|
|
||||||
@@ -39,7 +40,38 @@ namespace Juliet::D3D12
|
|||||||
frameBufferHeight = Min(height, frameBufferHeight);
|
frameBufferHeight = Min(height, frameBufferHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : Depth Stencil and DSV
|
// Depth Stencil and DSV
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE DSV;
|
||||||
|
bool hasDSV = false;
|
||||||
|
if (depthStencilTargetInfo && depthStencilTargetInfo->TargetTexture)
|
||||||
|
{
|
||||||
|
auto* container = reinterpret_cast<D3D12TextureContainer*>(depthStencilTargetInfo->TargetTexture);
|
||||||
|
uint32 width = container->Header.CreateInfo.Width;
|
||||||
|
uint32 height = container->Header.CreateInfo.Height;
|
||||||
|
|
||||||
|
frameBufferWidth = Min(width, frameBufferWidth);
|
||||||
|
frameBufferHeight = Min(height, frameBufferHeight);
|
||||||
|
|
||||||
|
D3D12TextureSubresource* subresource = Internal::PrepareTextureSubresourceForWrite(
|
||||||
|
d3d12CommandList, container, 0, 0, false, D3D12_RESOURCE_STATE_DEPTH_WRITE);
|
||||||
|
|
||||||
|
DSV = subresource->DSVHandle.CpuHandle;
|
||||||
|
hasDSV = true;
|
||||||
|
d3d12CommandList->DepthStencilSubresource = subresource;
|
||||||
|
|
||||||
|
Internal::TrackTexture(d3d12CommandList, subresource->Parent);
|
||||||
|
|
||||||
|
if (depthStencilTargetInfo->LoadOperation == LoadOperation::Clear)
|
||||||
|
{
|
||||||
|
D3D12_CLEAR_FLAGS clearFlags = D3D12_CLEAR_FLAG_DEPTH;
|
||||||
|
// TODO: Check if texture has stencil
|
||||||
|
// if (HasStencil(container->Header.CreateInfo.Format)) clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
|
||||||
|
|
||||||
|
ID3D12GraphicsCommandList_ClearDepthStencilView(d3d12CommandList->GraphicsCommandList.CommandList, DSV,
|
||||||
|
clearFlags, depthStencilTargetInfo->ClearDepth,
|
||||||
|
depthStencilTargetInfo->ClearStencil, 0, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE RTVs[GPUDriver::kMaxColorTargetInfo];
|
D3D12_CPU_DESCRIPTOR_HANDLE RTVs[GPUDriver::kMaxColorTargetInfo];
|
||||||
for (uint32 idx = 0; idx < colorTargetInfoCount; ++idx)
|
for (uint32 idx = 0; idx < colorTargetInfoCount; ++idx)
|
||||||
@@ -87,10 +119,8 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO DSV
|
|
||||||
|
|
||||||
ID3D12GraphicsCommandList_OMSetRenderTargets(d3d12CommandList->GraphicsCommandList.CommandList,
|
ID3D12GraphicsCommandList_OMSetRenderTargets(d3d12CommandList->GraphicsCommandList.CommandList,
|
||||||
colorTargetInfoCount, RTVs, false, nullptr);
|
colorTargetInfoCount, RTVs, false, hasDSV ? &DSV : nullptr);
|
||||||
|
|
||||||
// Set defaults graphics states
|
// Set defaults graphics states
|
||||||
GraphicsViewPort defaultViewport;
|
GraphicsViewPort defaultViewport;
|
||||||
@@ -159,7 +189,14 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : Write Depth stencil
|
// Reset Depth Stencil state
|
||||||
|
if (d3d12CommandList->DepthStencilSubresource)
|
||||||
|
{
|
||||||
|
Internal::TextureSubresourceTransitionToDefaultUsage(d3d12CommandList,
|
||||||
|
d3d12CommandList->DepthStencilSubresource,
|
||||||
|
D3D12_RESOURCE_STATE_DEPTH_WRITE);
|
||||||
|
d3d12CommandList->DepthStencilSubresource = nullptr;
|
||||||
|
}
|
||||||
d3d12CommandList->CurrentGraphicsPipeline = nullptr;
|
d3d12CommandList->CurrentGraphicsPipeline = nullptr;
|
||||||
|
|
||||||
ID3D12GraphicsCommandList_OMSetRenderTargets(d3d12CommandList->GraphicsCommandList.CommandList, 0, nullptr, false, nullptr);
|
ID3D12GraphicsCommandList_OMSetRenderTargets(d3d12CommandList->GraphicsCommandList.CommandList, 0, nullptr, false, nullptr);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
extern void BeginRenderPass(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
extern void BeginRenderPass(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
||||||
uint32 colorTargetInfoCount);
|
uint32 colorTargetInfoCount, const DepthStencilTargetInfo* depthStencilTargetInfo);
|
||||||
extern void EndRenderPass(NonNullPtr<CommandList> commandList);
|
extern void EndRenderPass(NonNullPtr<CommandList> commandList);
|
||||||
|
|
||||||
extern void BindGraphicsPipeline(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsPipeline> graphicsPipeline);
|
extern void BindGraphicsPipeline(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsPipeline> graphicsPipeline);
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
#include <Graphics/D3D12/D3D12CommandList.h>
|
#include <Graphics/D3D12/D3D12CommandList.h>
|
||||||
#include <Graphics/D3D12/D3D12Synchronization.h>
|
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||||
#include <Graphics/D3D12/D3D12Texture.h>
|
#include <Graphics/D3D12/D3D12Texture.h>
|
||||||
|
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
|
||||||
|
#include <Graphics/D3D12/D3D12Utils.h>
|
||||||
|
#include <Core/Memory/Allocator.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
@@ -68,11 +72,11 @@ namespace Juliet::D3D12
|
|||||||
DXGI_FORMAT_BC2_UNORM_SRGB, // BC2_UNORM_SRGB
|
DXGI_FORMAT_BC2_UNORM_SRGB, // BC2_UNORM_SRGB
|
||||||
DXGI_FORMAT_BC3_UNORM_SRGB, // BC3_UNORM_SRGB
|
DXGI_FORMAT_BC3_UNORM_SRGB, // BC3_UNORM_SRGB
|
||||||
DXGI_FORMAT_BC7_UNORM_SRGB, // BC7_UNORM_SRGB
|
DXGI_FORMAT_BC7_UNORM_SRGB, // BC7_UNORM_SRGB
|
||||||
DXGI_FORMAT_R16_UNORM, // D16_UNORM
|
DXGI_FORMAT_R16_TYPELESS, // D16_UNORM
|
||||||
DXGI_FORMAT_R24_UNORM_X8_TYPELESS, // D24_UNORM
|
DXGI_FORMAT_R24G8_TYPELESS, // D24_UNORM
|
||||||
DXGI_FORMAT_R32_FLOAT, // D32_FLOAT
|
DXGI_FORMAT_R32_TYPELESS, // D32_FLOAT
|
||||||
DXGI_FORMAT_R24_UNORM_X8_TYPELESS, // D24_UNORM_S8_UINT
|
DXGI_FORMAT_R24G8_TYPELESS, // D24_UNORM_S8_UINT
|
||||||
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, // D32_FLOAT_S8_UINT
|
DXGI_FORMAT_R32G8X24_TYPELESS, // D32_FLOAT_S8_UINT
|
||||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
|
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
|
||||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
|
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
|
||||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
|
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
|
||||||
@@ -360,4 +364,165 @@ namespace Juliet::D3D12
|
|||||||
8, // MSAA 8x
|
8, // MSAA 8x
|
||||||
};
|
};
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|
||||||
|
Texture* CreateTexture(NonNullPtr<GPUDriver> driver, const TextureCreateInfo& createInfo)
|
||||||
|
{
|
||||||
|
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
|
|
||||||
|
D3D12_RESOURCE_DESC desc = {};
|
||||||
|
switch (createInfo.Type)
|
||||||
|
{
|
||||||
|
case TextureType::Texture_2D:
|
||||||
|
case TextureType::Texture_2DArray:
|
||||||
|
case TextureType::Texture_Cube:
|
||||||
|
case TextureType::Texture_CubeArray:
|
||||||
|
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||||
|
break;
|
||||||
|
case TextureType::Texture_3D:
|
||||||
|
case TextureType::Texture_3DArray:
|
||||||
|
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc.Alignment = 0;
|
||||||
|
desc.Width = createInfo.Width;
|
||||||
|
desc.Height = createInfo.Height;
|
||||||
|
desc.DepthOrArraySize = static_cast<uint16>(createInfo.LayerCount);
|
||||||
|
desc.MipLevels = static_cast<uint16>(createInfo.MipLevelCount);
|
||||||
|
desc.Format = Internal::ConvertToD3D12TextureFormat(createInfo.Format);
|
||||||
|
desc.SampleDesc.Count = Internal::JulietToD3D12_SampleCount[ToUnderlying(createInfo.SampleCount)];
|
||||||
|
desc.SampleDesc.Quality = 0;
|
||||||
|
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||||
|
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
|
if ((createInfo.Flags & TextureUsageFlag::ColorTarget) != TextureUsageFlag::None)
|
||||||
|
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||||
|
if ((createInfo.Flags & TextureUsageFlag::DepthStencilTarget) != TextureUsageFlag::None)
|
||||||
|
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||||
|
if ((createInfo.Flags & TextureUsageFlag::ComputeStorageWrite) != TextureUsageFlag::None)
|
||||||
|
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||||
|
|
||||||
|
D3D12_HEAP_PROPERTIES heapProps = {};
|
||||||
|
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||||
|
|
||||||
|
ID3D12Resource* resource = nullptr;
|
||||||
|
D3D12_CLEAR_VALUE clearValue = {};
|
||||||
|
D3D12_CLEAR_VALUE* pClearValue = nullptr;
|
||||||
|
|
||||||
|
if (desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
|
||||||
|
{
|
||||||
|
clearValue.Format = Internal::ConvertToD3D12DepthFormat(createInfo.Format);
|
||||||
|
clearValue.DepthStencil.Depth = 1.0f;
|
||||||
|
clearValue.DepthStencil.Stencil = 0;
|
||||||
|
pClearValue = &clearValue;
|
||||||
|
}
|
||||||
|
else if (desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
|
||||||
|
{
|
||||||
|
clearValue.Format = desc.Format;
|
||||||
|
clearValue.Color[0] = 0.0f;
|
||||||
|
clearValue.Color[1] = 0.0f;
|
||||||
|
clearValue.Color[2] = 0.0f;
|
||||||
|
clearValue.Color[3] = 0.0f;
|
||||||
|
pClearValue = &clearValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hr = ID3D12Device_CreateCommittedResource(d3d12Driver->D3D12Device, &heapProps, D3D12_HEAP_FLAG_NONE, &desc,
|
||||||
|
D3D12_RESOURCE_STATE_COMMON, pClearValue, IID_ID3D12Resource,
|
||||||
|
reinterpret_cast<void**>(&resource));
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
LogError(d3d12Driver->D3D12Device, "Failed to create D3D12 committed resource for texture", hr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* textureContainer = static_cast<D3D12TextureContainer*>(Calloc(1, sizeof(D3D12TextureContainer)));
|
||||||
|
auto* texture = static_cast<D3D12Texture*>(Calloc(1, sizeof(D3D12Texture)));
|
||||||
|
|
||||||
|
textureContainer->Header.CreateInfo = createInfo;
|
||||||
|
textureContainer->ActiveTexture = texture;
|
||||||
|
textureContainer->Textures = static_cast<D3D12Texture**>(Malloc(sizeof(D3D12Texture*)));
|
||||||
|
textureContainer->Textures[0] = texture;
|
||||||
|
textureContainer->Capacity = 1;
|
||||||
|
textureContainer->Count = 1;
|
||||||
|
textureContainer->CanBeCycled = true;
|
||||||
|
|
||||||
|
texture->Container = textureContainer;
|
||||||
|
texture->Resource = resource;
|
||||||
|
texture->ReferenceCount = 1;
|
||||||
|
|
||||||
|
uint32 numLayers = std::max<uint32>(1, createInfo.LayerCount);
|
||||||
|
uint32 numMips = std::max<uint32>(1, createInfo.MipLevelCount);
|
||||||
|
texture->SubresourceCount = numLayers * numMips;
|
||||||
|
texture->Subresources = static_cast<D3D12TextureSubresource*>(Calloc(texture->SubresourceCount, sizeof(D3D12TextureSubresource)));
|
||||||
|
|
||||||
|
for (uint32 layer = 0; layer < numLayers; ++layer)
|
||||||
|
{
|
||||||
|
for (uint32 mip = 0; mip < numMips; ++mip)
|
||||||
|
{
|
||||||
|
uint32 index = mip + (layer * numMips);
|
||||||
|
auto& sub = texture->Subresources[index];
|
||||||
|
sub.Parent = texture;
|
||||||
|
sub.Layer = layer;
|
||||||
|
sub.Level = mip;
|
||||||
|
sub.Index = index;
|
||||||
|
sub.Depth = 1; // 3D texture depth handling would go here
|
||||||
|
|
||||||
|
if ((createInfo.Flags & TextureUsageFlag::ColorTarget) != TextureUsageFlag::None)
|
||||||
|
{
|
||||||
|
sub.RTVHandles = static_cast<D3D12StagingDescriptor*>(Calloc(1, sizeof(D3D12StagingDescriptor)));
|
||||||
|
Internal::AssignStagingDescriptor(d3d12Driver, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, sub.RTVHandles[0]);
|
||||||
|
|
||||||
|
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
|
||||||
|
rtvDesc.Format = desc.Format;
|
||||||
|
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||||
|
rtvDesc.Texture2D.MipSlice = mip;
|
||||||
|
ID3D12Device_CreateRenderTargetView(d3d12Driver->D3D12Device, resource, &rtvDesc, sub.RTVHandles[0].CpuHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((createInfo.Flags & TextureUsageFlag::DepthStencilTarget) != TextureUsageFlag::None)
|
||||||
|
{
|
||||||
|
Internal::AssignStagingDescriptor(d3d12Driver, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, sub.DSVHandle);
|
||||||
|
|
||||||
|
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
|
||||||
|
dsvDesc.Format = Internal::ConvertToD3D12DepthFormat(createInfo.Format);
|
||||||
|
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||||
|
dsvDesc.Texture2D.MipSlice = mip;
|
||||||
|
ID3D12Device_CreateDepthStencilView(d3d12Driver->D3D12Device, resource, &dsvDesc, sub.DSVHandle.CpuHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<Texture*>(textureContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyTexture(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture)
|
||||||
|
{
|
||||||
|
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
|
auto* textureContainer = reinterpret_cast<D3D12TextureContainer*>(texture.Get());
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < textureContainer->Count; ++i)
|
||||||
|
{
|
||||||
|
D3D12Texture* d3d12Texture = textureContainer->Textures[i];
|
||||||
|
for (uint32 j = 0; j < d3d12Texture->SubresourceCount; ++j)
|
||||||
|
{
|
||||||
|
D3D12TextureSubresource& sub = d3d12Texture->Subresources[j];
|
||||||
|
if (sub.RTVHandles)
|
||||||
|
{
|
||||||
|
Internal::ReleaseStagingDescriptor(d3d12Driver, sub.RTVHandles[0]);
|
||||||
|
Free(sub.RTVHandles);
|
||||||
|
}
|
||||||
|
if (sub.DSVHandle.Heap)
|
||||||
|
{
|
||||||
|
Internal::ReleaseStagingDescriptor(d3d12Driver, sub.DSVHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ID3D12Resource_Release(d3d12Texture->Resource);
|
||||||
|
Free(d3d12Texture->Subresources);
|
||||||
|
Free(d3d12Texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
Free(textureContainer->Textures);
|
||||||
|
Free(textureContainer);
|
||||||
|
}
|
||||||
} // namespace Juliet::D3D12
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
@@ -91,4 +91,7 @@ namespace Juliet::D3D12
|
|||||||
extern DXGI_FORMAT ConvertToD3D12DepthFormat(TextureFormat format);
|
extern DXGI_FORMAT ConvertToD3D12DepthFormat(TextureFormat format);
|
||||||
extern uint32 JulietToD3D12_SampleCount[];
|
extern uint32 JulietToD3D12_SampleCount[];
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|
||||||
|
extern Texture* CreateTexture(NonNullPtr<GPUDriver> driver, const TextureCreateInfo& createInfo);
|
||||||
|
extern void DestroyTexture(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture);
|
||||||
} // namespace Juliet::D3D12
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
349
Juliet/src/Graphics/DebugDisplayRenderer.cpp
Normal file
349
Juliet/src/Graphics/DebugDisplayRenderer.cpp
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
#include <Graphics/DebugDisplay.h>
|
||||||
|
|
||||||
|
#include <Core/Logging/LogManager.h>
|
||||||
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
#include <Core/Memory/Allocator.h>
|
||||||
|
#include <Graphics/GraphicsPipeline.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr uint32 kMaxDebugVertices = 65536;
|
||||||
|
|
||||||
|
struct DebugVertex
|
||||||
|
{
|
||||||
|
Vector3 Position;
|
||||||
|
FColor Color;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DebugDisplayState
|
||||||
|
{
|
||||||
|
GraphicsDevice* Device;
|
||||||
|
|
||||||
|
// Pipelines
|
||||||
|
GraphicsPipeline* DepthTestedPipeline;
|
||||||
|
GraphicsPipeline* OverlayPipeline;
|
||||||
|
|
||||||
|
// Vertex data
|
||||||
|
DebugVertex* DepthTestedVertices;
|
||||||
|
uint32 DepthTestedVertexCount;
|
||||||
|
|
||||||
|
DebugVertex* OverlayVertices;
|
||||||
|
uint32 OverlayVertexCount;
|
||||||
|
|
||||||
|
// GPU buffers
|
||||||
|
GraphicsBuffer* DepthTestedBuffer;
|
||||||
|
GraphicsBuffer* OverlayBuffer;
|
||||||
|
GraphicsTransferBuffer* DepthTestedTransfer;
|
||||||
|
GraphicsTransferBuffer* OverlayTransfer;
|
||||||
|
|
||||||
|
bool Initialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
DebugDisplayState g_DebugState = {};
|
||||||
|
|
||||||
|
void AddLine(DebugVertex* vertices, uint32& count, const Vector3& start, const Vector3& end, const FColor& color)
|
||||||
|
{
|
||||||
|
if (count + 2 > kMaxDebugVertices)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertices[count++] = { start, color };
|
||||||
|
vertices[count++] = { end, color };
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddSphereWireframe(DebugVertex* vertices, uint32& count, const Vector3& center, float radius, const FColor& color)
|
||||||
|
{
|
||||||
|
constexpr int segments = 16;
|
||||||
|
constexpr float pi = 3.14159265358979f;
|
||||||
|
|
||||||
|
// Draw 3 circles (XY, XZ, YZ planes)
|
||||||
|
for (int i = 0; i < segments; ++i)
|
||||||
|
{
|
||||||
|
float a1 = (float)i / segments * 2.0f * pi;
|
||||||
|
float a2 = (float)(i + 1) / segments * 2.0f * pi;
|
||||||
|
|
||||||
|
// XY circle
|
||||||
|
Vector3 p1 = { center.x + cosf(a1) * radius, center.y + sinf(a1) * radius, center.z };
|
||||||
|
Vector3 p2 = { center.x + cosf(a2) * radius, center.y + sinf(a2) * radius, center.z };
|
||||||
|
AddLine(vertices, count, p1, p2, color);
|
||||||
|
|
||||||
|
// XZ circle
|
||||||
|
p1 = { center.x + cosf(a1) * radius, center.y, center.z + sinf(a1) * radius };
|
||||||
|
p2 = { center.x + cosf(a2) * radius, center.y, center.z + sinf(a2) * radius };
|
||||||
|
AddLine(vertices, count, p1, p2, color);
|
||||||
|
|
||||||
|
// YZ circle
|
||||||
|
p1 = { center.x, center.y + cosf(a1) * radius, center.z + sinf(a1) * radius };
|
||||||
|
p2 = { center.x, center.y + cosf(a2) * radius, center.z + sinf(a2) * radius };
|
||||||
|
AddLine(vertices, count, p1, p2, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsPipeline* CreateDebugPipeline(GraphicsDevice* device, TextureFormat colorFormat, bool enableDepthTest)
|
||||||
|
{
|
||||||
|
String entryPoint = WrapString("main");
|
||||||
|
ShaderCreateInfo shaderCI = {};
|
||||||
|
shaderCI.EntryPoint = entryPoint;
|
||||||
|
|
||||||
|
String vertPath = WrapString("../../Assets/compiled/Debug.vert.dxil");
|
||||||
|
shaderCI.Stage = ShaderStage::Vertex;
|
||||||
|
Shader* vertexShader = CreateShader(device, vertPath, shaderCI);
|
||||||
|
|
||||||
|
String fragPath = WrapString("../../Assets/compiled/Debug.frag.dxil");
|
||||||
|
shaderCI.Stage = ShaderStage::Fragment;
|
||||||
|
Shader* fragmentShader = CreateShader(device, fragPath, shaderCI);
|
||||||
|
|
||||||
|
if (!vertexShader || !fragmentShader)
|
||||||
|
{
|
||||||
|
LogError(LogCategory::Graphics, "Failed to create debug shaders");
|
||||||
|
if (vertexShader)
|
||||||
|
{
|
||||||
|
DestroyShader(device, vertexShader);
|
||||||
|
}
|
||||||
|
if (fragmentShader)
|
||||||
|
{
|
||||||
|
DestroyShader(device, fragmentShader);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorTargetDescription colorDesc = {};
|
||||||
|
colorDesc.Format = colorFormat;
|
||||||
|
|
||||||
|
GraphicsPipelineCreateInfo createInfo = {};
|
||||||
|
createInfo.VertexShader = vertexShader;
|
||||||
|
createInfo.FragmentShader = fragmentShader;
|
||||||
|
createInfo.PrimitiveType = PrimitiveType::LineList;
|
||||||
|
createInfo.RasterizerState.FillMode = FillMode::Solid;
|
||||||
|
createInfo.RasterizerState.CullMode = CullMode::None;
|
||||||
|
createInfo.RasterizerState.FrontFace = FrontFace::CounterClockwise;
|
||||||
|
createInfo.MultisampleState.SampleCount = TextureSampleCount::One;
|
||||||
|
|
||||||
|
// No vertex input state - using bindless buffer access via SV_VertexID
|
||||||
|
|
||||||
|
createInfo.TargetInfo.ColorTargetDescriptions = &colorDesc;
|
||||||
|
createInfo.TargetInfo.NumColorTargets = 1;
|
||||||
|
|
||||||
|
// Now that we support depth-stencil targets in the backend, we can enable them.
|
||||||
|
createInfo.TargetInfo.HasDepthStencilTarget = true;
|
||||||
|
createInfo.TargetInfo.DepthStencilFormat = TextureFormat::D32_FLOAT;
|
||||||
|
|
||||||
|
if (enableDepthTest)
|
||||||
|
{
|
||||||
|
createInfo.DepthStencilState.EnableDepthTest = true;
|
||||||
|
createInfo.DepthStencilState.EnableDepthWrite = true;
|
||||||
|
createInfo.DepthStencilState.CompareOperation = CompareOperation::Less;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Overlay pipeline: depth test/write off, so it draws on top
|
||||||
|
createInfo.DepthStencilState.EnableDepthTest = false;
|
||||||
|
createInfo.DepthStencilState.EnableDepthWrite = false;
|
||||||
|
createInfo.DepthStencilState.CompareOperation = CompareOperation::Always;
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsPipeline* pipeline = CreateGraphicsPipeline(device, createInfo);
|
||||||
|
|
||||||
|
DestroyShader(device, vertexShader);
|
||||||
|
DestroyShader(device, fragmentShader);
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void DebugDisplay_Initialize(GraphicsDevice* device)
|
||||||
|
{
|
||||||
|
if (g_DebugState.Initialized)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_DebugState.Device = device;
|
||||||
|
|
||||||
|
// Allocate CPU vertex arrays
|
||||||
|
g_DebugState.DepthTestedVertices = static_cast<DebugVertex*>(Malloc(kMaxDebugVertices * sizeof(DebugVertex)));
|
||||||
|
g_DebugState.OverlayVertices = static_cast<DebugVertex*>(Malloc(kMaxDebugVertices * sizeof(DebugVertex)));
|
||||||
|
g_DebugState.DepthTestedVertexCount = 0;
|
||||||
|
g_DebugState.OverlayVertexCount = 0;
|
||||||
|
|
||||||
|
// Create GPU buffers
|
||||||
|
BufferCreateInfo bufferCI = {};
|
||||||
|
bufferCI.Size = kMaxDebugVertices * sizeof(DebugVertex);
|
||||||
|
bufferCI.Usage = BufferUsage::StructuredBuffer;
|
||||||
|
|
||||||
|
g_DebugState.DepthTestedBuffer = CreateGraphicsBuffer(device, bufferCI);
|
||||||
|
g_DebugState.OverlayBuffer = CreateGraphicsBuffer(device, bufferCI);
|
||||||
|
|
||||||
|
TransferBufferCreateInfo transferCI = {};
|
||||||
|
transferCI.Size = kMaxDebugVertices * sizeof(DebugVertex);
|
||||||
|
transferCI.Usage = TransferBufferUsage::Upload;
|
||||||
|
|
||||||
|
g_DebugState.DepthTestedTransfer = CreateGraphicsTransferBuffer(device, transferCI);
|
||||||
|
g_DebugState.OverlayTransfer = CreateGraphicsTransferBuffer(device, transferCI);
|
||||||
|
|
||||||
|
g_DebugState.Initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugDisplay_Shutdown(GraphicsDevice* device)
|
||||||
|
{
|
||||||
|
if (!g_DebugState.Initialized)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_DebugState.DepthTestedPipeline)
|
||||||
|
{
|
||||||
|
DestroyGraphicsPipeline(device, g_DebugState.DepthTestedPipeline);
|
||||||
|
}
|
||||||
|
if (g_DebugState.OverlayPipeline)
|
||||||
|
{
|
||||||
|
DestroyGraphicsPipeline(device, g_DebugState.OverlayPipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_DebugState.DepthTestedBuffer)
|
||||||
|
{
|
||||||
|
DestroyGraphicsBuffer(device, g_DebugState.DepthTestedBuffer);
|
||||||
|
}
|
||||||
|
if (g_DebugState.OverlayBuffer)
|
||||||
|
{
|
||||||
|
DestroyGraphicsBuffer(device, g_DebugState.OverlayBuffer);
|
||||||
|
}
|
||||||
|
if (g_DebugState.DepthTestedTransfer)
|
||||||
|
{
|
||||||
|
DestroyGraphicsTransferBuffer(device, g_DebugState.DepthTestedTransfer);
|
||||||
|
}
|
||||||
|
if (g_DebugState.OverlayTransfer)
|
||||||
|
{
|
||||||
|
DestroyGraphicsTransferBuffer(device, g_DebugState.OverlayTransfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeFree(g_DebugState.DepthTestedVertices);
|
||||||
|
SafeFree(g_DebugState.OverlayVertices);
|
||||||
|
|
||||||
|
g_DebugState = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugDisplay_DrawLine(const Vector3& start, const Vector3& end, const FColor& color, bool overlay)
|
||||||
|
{
|
||||||
|
if (overlay)
|
||||||
|
{
|
||||||
|
AddLine(g_DebugState.OverlayVertices, g_DebugState.OverlayVertexCount, start, end, color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddLine(g_DebugState.DepthTestedVertices, g_DebugState.DepthTestedVertexCount, start, end, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugDisplay_DrawSphere(const Vector3& center, float radius, const FColor& color, bool overlay)
|
||||||
|
{
|
||||||
|
if (overlay)
|
||||||
|
{
|
||||||
|
AddSphereWireframe(g_DebugState.OverlayVertices, g_DebugState.OverlayVertexCount, center, radius, color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddSphereWireframe(g_DebugState.DepthTestedVertices, g_DebugState.DepthTestedVertexCount, center, radius, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugDisplay_Prepare(CommandList* cmdList)
|
||||||
|
{
|
||||||
|
if (!g_DebugState.Initialized)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render depth-tested primitives
|
||||||
|
if (g_DebugState.DepthTestedVertexCount > 0 && g_DebugState.DepthTestedBuffer)
|
||||||
|
{
|
||||||
|
// Upload vertex data
|
||||||
|
void* ptr = MapGraphicsTransferBuffer(g_DebugState.Device, g_DebugState.DepthTestedTransfer);
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
MemCopy(ptr, g_DebugState.DepthTestedVertices, g_DebugState.DepthTestedVertexCount * sizeof(DebugVertex));
|
||||||
|
UnmapGraphicsTransferBuffer(g_DebugState.Device, g_DebugState.DepthTestedTransfer);
|
||||||
|
|
||||||
|
CopyBuffer(cmdList, g_DebugState.DepthTestedBuffer, g_DebugState.DepthTestedTransfer,
|
||||||
|
g_DebugState.DepthTestedVertexCount * sizeof(DebugVertex));
|
||||||
|
TransitionBufferToReadable(cmdList, g_DebugState.DepthTestedBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render overlay primitives
|
||||||
|
if (g_DebugState.OverlayVertexCount > 0 && g_DebugState.OverlayBuffer)
|
||||||
|
{
|
||||||
|
// Upload vertex data
|
||||||
|
void* ptr = MapGraphicsTransferBuffer(g_DebugState.Device, g_DebugState.OverlayTransfer);
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
MemCopy(ptr, g_DebugState.OverlayVertices, g_DebugState.OverlayVertexCount * sizeof(DebugVertex));
|
||||||
|
UnmapGraphicsTransferBuffer(g_DebugState.Device, g_DebugState.OverlayTransfer);
|
||||||
|
|
||||||
|
CopyBuffer(cmdList, g_DebugState.OverlayBuffer, g_DebugState.OverlayTransfer,
|
||||||
|
g_DebugState.OverlayVertexCount * sizeof(DebugVertex));
|
||||||
|
TransitionBufferToReadable(cmdList, g_DebugState.OverlayBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugDisplay_Flush(CommandList* cmdList, RenderPass* renderPass, const Camera& camera)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!g_DebugState.Initialized)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lazy-create pipelines (need swapchain format)
|
||||||
|
if (!g_DebugState.DepthTestedPipeline)
|
||||||
|
{
|
||||||
|
// Use B8G8R8A8_UNORM which matches the SDR swapchain
|
||||||
|
g_DebugState.DepthTestedPipeline = CreateDebugPipeline(g_DebugState.Device, TextureFormat::B8G8R8A8_UNORM, true);
|
||||||
|
g_DebugState.OverlayPipeline = CreateDebugPipeline(g_DebugState.Device, TextureFormat::B8G8R8A8_UNORM, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render depth-tested primitives
|
||||||
|
if (g_DebugState.DepthTestedVertexCount > 0 && g_DebugState.DepthTestedPipeline && g_DebugState.DepthTestedBuffer)
|
||||||
|
{
|
||||||
|
BindGraphicsPipeline(renderPass, g_DebugState.DepthTestedPipeline);
|
||||||
|
|
||||||
|
// Pack VP matrix + buffer index into push constants
|
||||||
|
struct {
|
||||||
|
Matrix vp;
|
||||||
|
uint32 bufferIndex;
|
||||||
|
uint32 padding[3];
|
||||||
|
} pushData;
|
||||||
|
pushData.vp = Camera_GetViewProjectionMatrix(camera);
|
||||||
|
pushData.bufferIndex = GetDescriptorIndex(g_DebugState.Device, g_DebugState.DepthTestedBuffer);
|
||||||
|
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / sizeof(uint32), &pushData);
|
||||||
|
|
||||||
|
DrawPrimitives(renderPass, g_DebugState.DepthTestedVertexCount, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render overlay primitives
|
||||||
|
if (g_DebugState.OverlayVertexCount > 0 && g_DebugState.OverlayPipeline && g_DebugState.OverlayBuffer)
|
||||||
|
{
|
||||||
|
BindGraphicsPipeline(renderPass, g_DebugState.OverlayPipeline);
|
||||||
|
|
||||||
|
// Pack VP matrix + buffer index into push constants
|
||||||
|
struct {
|
||||||
|
Matrix vp;
|
||||||
|
uint32 bufferIndex;
|
||||||
|
uint32 padding[3];
|
||||||
|
} pushData;
|
||||||
|
pushData.vp = Camera_GetViewProjectionMatrix(camera);
|
||||||
|
pushData.bufferIndex = GetDescriptorIndex(g_DebugState.Device, g_DebugState.OverlayBuffer);
|
||||||
|
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / sizeof(uint32), &pushData);
|
||||||
|
|
||||||
|
DrawPrimitives(renderPass, g_DebugState.OverlayVertexCount, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear for next frame
|
||||||
|
g_DebugState.DepthTestedVertexCount = 0;
|
||||||
|
g_DebugState.OverlayVertexCount = 0;
|
||||||
|
}
|
||||||
|
} // namespace Juliet
|
||||||
@@ -159,6 +159,16 @@ namespace Juliet
|
|||||||
return device->GetSwapChainTextureFormat(device->Driver, window);
|
return device->GetSwapChainTextureFormat(device->Driver, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Texture* CreateTexture(NonNullPtr<GraphicsDevice> device, const TextureCreateInfo& createInfo)
|
||||||
|
{
|
||||||
|
return device->CreateTexture(device->Driver, createInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyTexture(NonNullPtr<GraphicsDevice> device, NonNullPtr<Texture> texture)
|
||||||
|
{
|
||||||
|
device->DestroyTexture(device->Driver, texture);
|
||||||
|
}
|
||||||
|
|
||||||
CommandList* AcquireCommandList(NonNullPtr<GraphicsDevice> device, QueueType queueType /* = QueueType::Graphics */)
|
CommandList* AcquireCommandList(NonNullPtr<GraphicsDevice> device, QueueType queueType /* = QueueType::Graphics */)
|
||||||
{
|
{
|
||||||
GPUDriver* driver = device->Driver;
|
GPUDriver* driver = device->Driver;
|
||||||
@@ -185,13 +195,14 @@ namespace Juliet
|
|||||||
commandListHeader->Device->SubmitCommandLists(commandList);
|
commandListHeader->Device->SubmitCommandLists(commandList);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, ColorTargetInfo& colorTargetInfo)
|
RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, ColorTargetInfo& colorTargetInfo,
|
||||||
|
DepthStencilTargetInfo* depthStencilTargetInfo)
|
||||||
{
|
{
|
||||||
return BeginRenderPass(commandList, &colorTargetInfo, 1);
|
return BeginRenderPass(commandList, &colorTargetInfo, 1, depthStencilTargetInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
RenderPass* BeginRenderPass(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
||||||
uint32 colorTargetInfoCount)
|
uint32 colorTargetInfoCount, DepthStencilTargetInfo* depthStencilTargetInfo)
|
||||||
{
|
{
|
||||||
if (colorTargetInfoCount > GPUDriver::kMaxColorTargetInfo)
|
if (colorTargetInfoCount > GPUDriver::kMaxColorTargetInfo)
|
||||||
{
|
{
|
||||||
@@ -200,7 +211,7 @@ namespace Juliet
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get());
|
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get());
|
||||||
header->Device->BeginRenderPass(commandList, colorTargetInfos, colorTargetInfoCount);
|
header->Device->BeginRenderPass(commandList, colorTargetInfos, colorTargetInfoCount, depthStencilTargetInfo);
|
||||||
|
|
||||||
header->RenderPass.IsInProgress = true;
|
header->RenderPass.IsInProgress = true;
|
||||||
return reinterpret_cast<RenderPass*>(&header->RenderPass);
|
return reinterpret_cast<RenderPass*>(&header->RenderPass);
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace Juliet
|
|||||||
|
|
||||||
// RenderPass
|
// RenderPass
|
||||||
void (*BeginRenderPass)(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
void (*BeginRenderPass)(NonNullPtr<CommandList> commandList, NonNullPtr<const ColorTargetInfo> colorTargetInfos,
|
||||||
uint32 colorTargetInfoCount);
|
uint32 colorTargetInfoCount, const DepthStencilTargetInfo* depthStencilTargetInfo);
|
||||||
void (*EndRenderPass)(NonNullPtr<CommandList> commandList);
|
void (*EndRenderPass)(NonNullPtr<CommandList> commandList);
|
||||||
|
|
||||||
void (*SetViewPort)(NonNullPtr<CommandList> commandList, const GraphicsViewPort& viewPort);
|
void (*SetViewPort)(NonNullPtr<CommandList> commandList, const GraphicsViewPort& viewPort);
|
||||||
@@ -89,6 +89,10 @@ namespace Juliet
|
|||||||
bool (*UpdateGraphicsPipelineShaders)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> graphicsPipeline,
|
bool (*UpdateGraphicsPipelineShaders)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> graphicsPipeline,
|
||||||
Shader* optional_vertexShader, Shader* optional_fragmentShader);
|
Shader* optional_vertexShader, Shader* optional_fragmentShader);
|
||||||
|
|
||||||
|
// Textures
|
||||||
|
Texture* (*CreateTexture)(NonNullPtr<GPUDriver> driver, const TextureCreateInfo& createInfo);
|
||||||
|
void (*DestroyTexture)(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture);
|
||||||
|
|
||||||
// Buffers
|
// Buffers
|
||||||
GraphicsBuffer* (*CreateGraphicsBuffer)(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage);
|
GraphicsBuffer* (*CreateGraphicsBuffer)(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage);
|
||||||
void (*DestroyGraphicsBuffer)(NonNullPtr<GraphicsBuffer> buffer);
|
void (*DestroyGraphicsBuffer)(NonNullPtr<GraphicsBuffer> buffer);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include <Core/JulietInit.h>
|
#include <Core/JulietInit.h>
|
||||||
#include <Core/Logging/LogManager.h>
|
#include <Core/Logging/LogManager.h>
|
||||||
#include <Core/Logging/LogTypes.h>
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
#include <Graphics/Camera.h>
|
||||||
|
#include <Graphics/DebugDisplay.h>
|
||||||
#include <Graphics/Graphics.h>
|
#include <Graphics/Graphics.h>
|
||||||
#include <Graphics/GraphicsConfig.h>
|
#include <Graphics/GraphicsConfig.h>
|
||||||
#include <Graphics/GraphicsPipeline.h>
|
#include <Graphics/GraphicsPipeline.h>
|
||||||
@@ -93,9 +95,12 @@ void JulietApplication::Init()
|
|||||||
pipelineCI.PrimitiveType = PrimitiveType::TriangleList;
|
pipelineCI.PrimitiveType = PrimitiveType::TriangleList;
|
||||||
pipelineCI.TargetInfo = { .ColorTargetDescriptions = &colorTargetDescription,
|
pipelineCI.TargetInfo = { .ColorTargetDescriptions = &colorTargetDescription,
|
||||||
.NumColorTargets = 1,
|
.NumColorTargets = 1,
|
||||||
.DepthStencilFormat = {},
|
.DepthStencilFormat = TextureFormat::D32_FLOAT,
|
||||||
.HasDepthStencilTarget = false };
|
.HasDepthStencilTarget = true };
|
||||||
pipelineCI.RasterizerState.FillMode = FillMode::Solid;
|
pipelineCI.RasterizerState.FillMode = FillMode::Solid;
|
||||||
|
pipelineCI.DepthStencilState.EnableDepthTest = true;
|
||||||
|
pipelineCI.DepthStencilState.EnableDepthWrite = true;
|
||||||
|
pipelineCI.DepthStencilState.CompareOperation = CompareOperation::Less;
|
||||||
|
|
||||||
GraphicsPipeline = CreateGraphicsPipeline(GraphicsDevice, pipelineCI);
|
GraphicsPipeline = CreateGraphicsPipeline(GraphicsDevice, pipelineCI);
|
||||||
if (GraphicsPipeline == nullptr)
|
if (GraphicsPipeline == nullptr)
|
||||||
@@ -104,6 +109,23 @@ void JulietApplication::Init()
|
|||||||
Running = false;
|
Running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create Depth Buffer
|
||||||
|
TextureCreateInfo depthCI = {};
|
||||||
|
depthCI.Type = TextureType::Texture_2D;
|
||||||
|
depthCI.Width = 1280;
|
||||||
|
depthCI.Height = 720;
|
||||||
|
depthCI.Format = TextureFormat::D32_FLOAT;
|
||||||
|
depthCI.Flags = TextureUsageFlag::DepthStencilTarget;
|
||||||
|
depthCI.LayerCount = 1;
|
||||||
|
depthCI.MipLevelCount = 1;
|
||||||
|
depthCI.SampleCount = TextureSampleCount::One;
|
||||||
|
DepthBuffer = CreateTexture(GraphicsDevice, depthCI);
|
||||||
|
if (DepthBuffer == nullptr)
|
||||||
|
{
|
||||||
|
LogError(LogCategory::Game, "Failed to create depth buffer!");
|
||||||
|
Running = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Create Buffers
|
// Create Buffers
|
||||||
BufferCreateInfo bufferCI = {};
|
BufferCreateInfo bufferCI = {};
|
||||||
bufferCI.Size = 256;
|
bufferCI.Size = 256;
|
||||||
@@ -138,6 +160,9 @@ void JulietApplication::Init()
|
|||||||
{
|
{
|
||||||
Game.Init();
|
Game.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize DebugDisplay
|
||||||
|
DebugDisplay_Initialize(GraphicsDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,6 +176,12 @@ void JulietApplication::Shutdown()
|
|||||||
ShutdownHotReloadCode(GameCode);
|
ShutdownHotReloadCode(GameCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown DebugDisplay before graphics device
|
||||||
|
if (GraphicsDevice)
|
||||||
|
{
|
||||||
|
DebugDisplay_Shutdown(GraphicsDevice);
|
||||||
|
}
|
||||||
|
|
||||||
if (GraphicsPipeline)
|
if (GraphicsPipeline)
|
||||||
{
|
{
|
||||||
DestroyGraphicsPipeline(GraphicsDevice, GraphicsPipeline);
|
DestroyGraphicsPipeline(GraphicsDevice, GraphicsPipeline);
|
||||||
@@ -163,6 +194,10 @@ void JulietApplication::Shutdown()
|
|||||||
{
|
{
|
||||||
DestroyGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
DestroyGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
||||||
}
|
}
|
||||||
|
if (DepthBuffer)
|
||||||
|
{
|
||||||
|
DestroyTexture(GraphicsDevice, DepthBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
if (MainWindow && GraphicsDevice)
|
if (MainWindow && GraphicsDevice)
|
||||||
{
|
{
|
||||||
@@ -275,7 +310,7 @@ void JulietApplication::Update()
|
|||||||
{
|
{
|
||||||
ColorTargetInfo colorTargetInfo = {};
|
ColorTargetInfo colorTargetInfo = {};
|
||||||
colorTargetInfo.TargetTexture = swapChainTexture;
|
colorTargetInfo.TargetTexture = swapChainTexture;
|
||||||
colorTargetInfo.ClearColor = { .R = .5f, .G = .8f, .B = .0f, .A = 1.f };
|
colorTargetInfo.ClearColor = { .R = .0f, .G = .0f, .B = .0f, .A = 1.f };
|
||||||
colorTargetInfo.LoadOperation = LoadOperation::Clear;
|
colorTargetInfo.LoadOperation = LoadOperation::Clear;
|
||||||
colorTargetInfo.StoreOperation = StoreOperation::Store;
|
colorTargetInfo.StoreOperation = StoreOperation::Store;
|
||||||
|
|
||||||
@@ -303,7 +338,22 @@ void JulietApplication::Update()
|
|||||||
TransitionBufferToReadable(cmdList, ConstantBuffer);
|
TransitionBufferToReadable(cmdList, ConstantBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPass* renderPass = BeginRenderPass(cmdList, colorTargetInfo);
|
// Test lines and sphere - GIANT SCALE
|
||||||
|
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 10.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false); // X-Axis (Red)
|
||||||
|
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 10.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, true); // Y-Axis (Green)
|
||||||
|
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 10.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, true); // Z-Axis (Blue) - Up
|
||||||
|
DebugDisplay_DrawSphere({ 0.0f, 0.0f, 0.0f }, 5.0f, { 1.0f, 1.0f, 0.0f, 1.0f }, true); // Yellow sphere
|
||||||
|
|
||||||
|
// Prepare debug data (outside render pass)
|
||||||
|
DebugDisplay_Prepare(cmdList);
|
||||||
|
|
||||||
|
DepthStencilTargetInfo depthTargetInfo = {};
|
||||||
|
depthTargetInfo.TargetTexture = DepthBuffer;
|
||||||
|
depthTargetInfo.ClearDepth = 1.0f;
|
||||||
|
depthTargetInfo.LoadOperation = LoadOperation::Clear;
|
||||||
|
depthTargetInfo.StoreOperation = StoreOperation::Store;
|
||||||
|
|
||||||
|
RenderPass* renderPass = BeginRenderPass(cmdList, colorTargetInfo, &depthTargetInfo);
|
||||||
BindGraphicsPipeline(renderPass, GraphicsPipeline);
|
BindGraphicsPipeline(renderPass, GraphicsPipeline);
|
||||||
|
|
||||||
// Pass descriptor index via Push Constants AFTER finding the pipeline (RootSignature)
|
// Pass descriptor index via Push Constants AFTER finding the pipeline (RootSignature)
|
||||||
@@ -311,6 +361,23 @@ void JulietApplication::Update()
|
|||||||
SetPushConstants(cmdList, ShaderStage::Vertex, 0, 1, &descriptorIndex);
|
SetPushConstants(cmdList, ShaderStage::Vertex, 0, 1, &descriptorIndex);
|
||||||
|
|
||||||
DrawPrimitives(renderPass, 6, 1, 0, 0);
|
DrawPrimitives(renderPass, 6, 1, 0, 0);
|
||||||
|
|
||||||
|
// Debug Display - render shapes (inside render pass)
|
||||||
|
static float orbitTime = 0.0f;
|
||||||
|
orbitTime += 0.016f; // Rough approximation for 60fps
|
||||||
|
|
||||||
|
float radius = 30.0f;
|
||||||
|
Camera debugCamera = {};
|
||||||
|
debugCamera.Position = { cosf(orbitTime) * radius, sinf(orbitTime) * radius, 10.0f }; // Rotate in XY plane
|
||||||
|
debugCamera.Target = { 0.0f, 0.0f, 0.0f };
|
||||||
|
debugCamera.Up = { 0.0f, 0.0f, 1.0f }; // Z-Up
|
||||||
|
debugCamera.FOV = 1.047f; // 60 degrees
|
||||||
|
debugCamera.AspectRatio = 1200.0f / 800.0f;
|
||||||
|
debugCamera.NearPlane = 0.1f;
|
||||||
|
debugCamera.FarPlane = 1000.0f;
|
||||||
|
|
||||||
|
DebugDisplay_Flush(cmdList, renderPass, debugCamera);
|
||||||
|
|
||||||
EndRenderPass(renderPass);
|
EndRenderPass(renderPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class JulietApplication : public Juliet::IApplication
|
|||||||
Juliet::GraphicsPipeline* GraphicsPipeline = {};
|
Juliet::GraphicsPipeline* GraphicsPipeline = {};
|
||||||
Juliet::GraphicsBuffer* ConstantBuffer = {};
|
Juliet::GraphicsBuffer* ConstantBuffer = {};
|
||||||
Juliet::GraphicsTransferBuffer* TransferBuffer = {};
|
Juliet::GraphicsTransferBuffer* TransferBuffer = {};
|
||||||
|
Juliet::Texture* DepthBuffer = {};
|
||||||
|
|
||||||
bool Running = false;
|
bool Running = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ int main(int argc, char* argv[])
|
|||||||
IOClose(outStream);
|
IOClose(outStream);
|
||||||
}
|
}
|
||||||
// Pause here to not close the console window immediately on stop while debugging
|
// Pause here to not close the console window immediately on stop while debugging
|
||||||
__asm int 3;
|
// __asm int 3;
|
||||||
});
|
});
|
||||||
|
|
||||||
for (int idx = 1; idx < argc; ++idx)
|
for (int idx = 1; idx < argc; ++idx)
|
||||||
|
|||||||
@@ -35,29 +35,40 @@ echo Output Dir: !OUTPUT_DIR!
|
|||||||
REM Créer le dossier de sortie s'il n'existe pas
|
REM Créer le dossier de sortie s'il n'existe pas
|
||||||
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"
|
if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%"
|
||||||
|
|
||||||
REM Parcourir tous les fichiers .frag.hlsl et .vert.hlsl dans le dossier source
|
REM Parcourir tous les fichiers .hlsl dans le dossier source
|
||||||
for %%F in ("%SOURCE_DIR%\*.frag.hlsl" "%SOURCE_DIR%\*.vert.hlsl") do (
|
for %%F in ("%SOURCE_DIR%\*.hlsl") do (
|
||||||
REM Extraire le nom du fichier sans l'extension
|
set "FULL_FILENAME=%%~nF%%~xF"
|
||||||
set "FILENAME=%%~nF"
|
|
||||||
REM Extraire l'extension du fichier
|
REM Skip RootConstants.hlsl or other include files
|
||||||
set "EXTENSION=%%~xF"
|
if /I NOT "!FULL_FILENAME!"=="RootConstants.hlsl" (
|
||||||
REM Remplacer .frag.hlsl par frag et .vert.hlsl par vert
|
REM Detect stage from filename (.vert.hlsl, .frag.hlsl)
|
||||||
if "%%~xF"==".frag.hlsl" (
|
set "SHORT_EXTENSION="
|
||||||
|
set "BASE_NAME=%%~nF"
|
||||||
|
|
||||||
|
echo !FULL_FILENAME! | findstr /I "\.frag\.hlsl" >nul
|
||||||
|
if !ERRORLEVEL! EQU 0 (
|
||||||
set "SHORT_EXTENSION=frag"
|
set "SHORT_EXTENSION=frag"
|
||||||
) else if "%%~xF"==".vert.hlsl" (
|
set "BASE_NAME=!BASE_NAME:.frag=!"
|
||||||
|
) else (
|
||||||
|
echo !FULL_FILENAME! | findstr /I "\.vert\.hlsl" >nul
|
||||||
|
if !ERRORLEVEL! EQU 0 (
|
||||||
set "SHORT_EXTENSION=vert"
|
set "SHORT_EXTENSION=vert"
|
||||||
|
set "BASE_NAME=!BASE_NAME:.vert=!"
|
||||||
)
|
)
|
||||||
REM Construire la ligne de commande
|
)
|
||||||
set "COMMAND=%COMPILER_PATH% %SOURCE_DIR%\!FILENAME!!EXTENSION! -o %OUTPUT_DIR%\!FILENAME!!SHORT_EXTENSION!.dxil"
|
|
||||||
echo !COMMAND!
|
if not "!SHORT_EXTENSION!"=="" (
|
||||||
REM Afficher la ligne de commande pour le débogage
|
set "OUTPUT_FILE=%OUTPUT_DIR%\%%~nF.dxil"
|
||||||
echo Compiling: !FILENAME!!EXTENSION!
|
set "COMMAND=%COMPILER_PATH% %%F -o !OUTPUT_FILE!"
|
||||||
REM Appeler JulietShaderCompiler.exe avec les arguments spécifiés
|
|
||||||
|
echo Compiling: %%F to !OUTPUT_FILE!
|
||||||
!COMMAND!
|
!COMMAND!
|
||||||
|
|
||||||
if !ERRORLEVEL! NEQ 0 (
|
if errorlevel 1 (
|
||||||
echo ERREUR lors de la compilation de %%F
|
echo ERREUR lors de la compilation de %%F
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
|
|||||||
Reference in New Issue
Block a user