Added basic concept of Mesh

Right now can create a quad or a cube.
Need a mesh renderer taht keep the buffer and all to optimally handle the mega buffer.
This commit is contained in:
2026-02-15 17:44:48 -05:00
parent c2a5cb84b2
commit 87831d0fd6
22 changed files with 285 additions and 163 deletions

Binary file not shown.

View File

@@ -8,31 +8,7 @@ struct Input
float4 main(Input input) : SV_Target0 float4 main(Input input) : SV_Target0
{ {
// Retrieve the texture using SM6.6 bindless syntax
// Texture2D texture = ResourceDescriptorHeap[TextureIndex]; (Must cast to Texture2D<float4>)
// Wait, ResourceDescriptorHeap indexing returns a wrapper, usually we use Textures[TextureIndex]?
// Juliet seems to use `ResourceDescriptorHeap` for Buffers.
// Let's check Triangle.vert/frag.
// In bindless, usually:
// Texture2D<float4> tex = ResourceDescriptorHeap[TextureIndex];
// SamplerState samp = SamplerDescriptorHeap[0]; // Assuming static sampler or passed index
// I need to check how Juliet accesses textures.
// I'll assume standard SM6.6 usage.
Texture2D<float4> tex = ResourceDescriptorHeap[TextureIndex]; Texture2D<float4> tex = ResourceDescriptorHeap[TextureIndex];
SamplerState samp = SamplerDescriptorHeap[0]; // Point sampler or Linear? ImGui usually uses Linear. SamplerState samp = SamplerDescriptorHeap[0];
// D3D12GraphicsDevice.cpp created static samplers.
// Root signature has Static Samplers.
// RegisterSpace 0.
// Sampler register 0 is Point/Nearest?
// Let's check CreateGraphicsRootSignature in D3D12GraphicsDevice.cpp.
// It creates s_nearest at 0.
// If I want Linear, I might need another sampler or rely on s_nearest for font (pixel art font?)
// Default ImGui font is usually antialiased, so Linear is preferred.
// But pixel aligned UI...
// I will use `SamplerDescriptorHeap[0]` for now.
return input.Color * tex.Sample(samp, input.UV); return input.Color * tex.Sample(samp, input.UV);
} }

View File

@@ -18,14 +18,10 @@ Output main(uint vertexIndex : SV_VertexID)
{ {
Output output; Output output;
// Retrieve the vertex buffer using SM6.6 bindless syntax
ByteAddressBuffer buffer = ResourceDescriptorHeap[BufferIndex]; ByteAddressBuffer buffer = ResourceDescriptorHeap[BufferIndex];
// Add VertexOffset for indexed drawing with bindless buffers
// (SV_VertexID in indexed draw is raw index from index buffer, doesn't include BaseVertexLocation)
uint actualVertexIndex = vertexIndex + VertexOffset; uint actualVertexIndex = vertexIndex + VertexOffset;
// ImDrawVert stride = 20 bytes (Vec2 pos + Vec2 uv + uint color)
uint stride = 20; uint stride = 20;
uint offset = actualVertexIndex * stride; uint offset = actualVertexIndex * stride;
@@ -33,34 +29,12 @@ Output main(uint vertexIndex : SV_VertexID)
float2 uv = asfloat(buffer.Load2(offset + 8)); float2 uv = asfloat(buffer.Load2(offset + 8));
uint col = buffer.Load(offset + 16); uint col = buffer.Load(offset + 16);
// Unpack color (uint to float4)
// ImGui colors are 0xAABBGGRR (ABGR packed)
// We need to unpack to float4.
// HLSL unpacks as little endian.
// uint 0xAABBGGRR -> byte0=RR, byte1=GG, byte2=BB, byte3=AA
float4 c; float4 c;
c.x = float(col & 0xFF) / 255.0f; c.x = float(col & 0xFF) / 255.0f;
c.y = float((col >> 8) & 0xFF) / 255.0f; c.y = float((col >> 8) & 0xFF) / 255.0f;
c.z = float((col >> 16) & 0xFF) / 255.0f; c.z = float((col >> 16) & 0xFF) / 255.0f;
c.w = float((col >> 24) & 0xFF) / 255.0f; c.w = float((col >> 24) & 0xFF) / 255.0f;
// Transform
// ImGui sends pixel coordinates.
// We need to transform to NDC [-1, 1].
// PushConstants should contain Scale and Translate.
// float2 Scale = 2.0 / DisplaySize
// float2 Translate = -1.0 - (DisplayPos * Scale)
// We will assume PushConstants are float2 Scale, float2 Translate.
// Struct in RootConstants.hlsl?
// RootConstants.hlsl likely defines `cbuffer PushConstants : register(b0)`.
// Let's assume standard push constants usage.
// Debug.vert.hlsl used `ViewProjection`.
// We need to customize PushConstants or reuse `ViewProjection` slot?
// Juliet uses 128 bytes of push constants.
// We can map float4 ProjectionMatrix (or similar).
// Use Scale and Translate from RootConstants
output.Position = float4(pos * Scale + Translate, 0.0f, 1.0f); output.Position = float4(pos * Scale + Translate, 0.0f, 1.0f);
output.Color = c; output.Color = c;
output.UV = uv; output.UV = uv;

View File

@@ -10,20 +10,16 @@ Output main(uint vertexIndex : SV_VertexID)
{ {
Output output; Output output;
// Retrieve the buffer using SM6.6 bindless syntax
// Use BufferIndex from RootConstants (pushed via SetPushConstants)
ByteAddressBuffer buffer = ResourceDescriptorHeap[BufferIndex]; ByteAddressBuffer buffer = ResourceDescriptorHeap[BufferIndex];
// Read position from buffer (Index * stride) uint stride = 28;
// Stride = 2 float (pos) + 4 float (color) = 6 * 4 = 24 bytes ?
// Let's assume just position 2D (8 bytes) + Color (16 bytes)
uint stride = 24;
uint offset = vertexIndex * stride; uint offset = vertexIndex * stride;
float2 pos = asfloat(buffer.Load2(offset)); float3 pos = asfloat(buffer.Load3(offset));
float4 col = asfloat(buffer.Load4(offset + 8)); float4 col = asfloat(buffer.Load4(offset + 12));
output.Position = float4(pos, 0.0f, 1.0f); //output.Position = float4(pos, 1.0f);
output.Position = mul(ViewProjection, float4(pos, 1.0f));
output.Color = col; output.Color = col;
return output; return output;
} }

View File

@@ -108,9 +108,11 @@
<CustomBuild Include="include\Graphics\GraphicsConfig.h" /> <CustomBuild Include="include\Graphics\GraphicsConfig.h" />
<CustomBuild Include="include\Graphics\GraphicsPipeline.h" /> <CustomBuild Include="include\Graphics\GraphicsPipeline.h" />
<CustomBuild Include="include\Graphics\ImGuiRenderer.h" /> <CustomBuild Include="include\Graphics\ImGuiRenderer.h" />
<CustomBuild Include="include\Graphics\Mesh.h" />
<CustomBuild Include="include\Graphics\RenderPass.h" /> <CustomBuild Include="include\Graphics\RenderPass.h" />
<CustomBuild Include="include\Graphics\Shader.h" /> <CustomBuild Include="include\Graphics\Shader.h" />
<CustomBuild Include="include\Graphics\Texture.h" /> <CustomBuild Include="include\Graphics\Texture.h" />
<CustomBuild Include="include\Graphics\VertexData.h" />
<CustomBuild Include="include\Juliet.h" /> <CustomBuild Include="include\Juliet.h" />
<CustomBuild Include="Juliet.bff" /> <CustomBuild Include="Juliet.bff" />
<CustomBuild Include="src\Core\Application\ApplicationManager.cpp" /> <CustomBuild Include="src\Core\Application\ApplicationManager.cpp" />
@@ -220,6 +222,7 @@
<CustomBuild Include="src\Graphics\Graphics.cpp" /> <CustomBuild Include="src\Graphics\Graphics.cpp" />
<CustomBuild Include="src\Graphics\GraphicsDevice.h" /> <CustomBuild Include="src\Graphics\GraphicsDevice.h" />
<CustomBuild Include="src\Graphics\ImGuiRenderer.cpp" /> <CustomBuild Include="src\Graphics\ImGuiRenderer.cpp" />
<CustomBuild Include="src\Graphics\Mesh.cpp" />
<CustomBuild Include="src\UnitTest\Container\VectorUnitTest.cpp" /> <CustomBuild Include="src\UnitTest\Container\VectorUnitTest.cpp" />
<CustomBuild Include="src\UnitTest\RunUnitTests.cpp" /> <CustomBuild Include="src\UnitTest\RunUnitTests.cpp" />
</ItemGroup> </ItemGroup>

View File

@@ -172,6 +172,9 @@
<CustomBuild Include="include\Graphics\ImGuiRenderer.h"> <CustomBuild Include="include\Graphics\ImGuiRenderer.h">
<Filter>include\Graphics</Filter> <Filter>include\Graphics</Filter>
</CustomBuild> </CustomBuild>
<CustomBuild Include="include\Graphics\Mesh.h">
<Filter>include\Graphics</Filter>
</CustomBuild>
<CustomBuild Include="include\Graphics\RenderPass.h"> <CustomBuild Include="include\Graphics\RenderPass.h">
<Filter>include\Graphics</Filter> <Filter>include\Graphics</Filter>
</CustomBuild> </CustomBuild>
@@ -181,6 +184,9 @@
<CustomBuild Include="include\Graphics\Texture.h"> <CustomBuild Include="include\Graphics\Texture.h">
<Filter>include\Graphics</Filter> <Filter>include\Graphics</Filter>
</CustomBuild> </CustomBuild>
<CustomBuild Include="include\Graphics\VertexData.h">
<Filter>include\Graphics</Filter>
</CustomBuild>
<CustomBuild Include="include\Juliet.h"> <CustomBuild Include="include\Juliet.h">
<Filter>include</Filter> <Filter>include</Filter>
</CustomBuild> </CustomBuild>
@@ -507,6 +513,9 @@
<CustomBuild Include="src\Graphics\ImGuiRenderer.cpp"> <CustomBuild Include="src\Graphics\ImGuiRenderer.cpp">
<Filter>src\Graphics</Filter> <Filter>src\Graphics</Filter>
</CustomBuild> </CustomBuild>
<CustomBuild Include="src\Graphics\Mesh.cpp">
<Filter>src\Graphics</Filter>
</CustomBuild>
<CustomBuild Include="src\UnitTest\Container\VectorUnitTest.cpp"> <CustomBuild Include="src\UnitTest\Container\VectorUnitTest.cpp">
<Filter>src\UnitTest\Container</Filter> <Filter>src\UnitTest\Container</Filter>
</CustomBuild> </CustomBuild>

View File

@@ -17,7 +17,7 @@ namespace Juliet
DataFirst = DataLast = nullptr; DataFirst = DataLast = nullptr;
Count = 0; Count = 0;
JULIET_DEBUG_ONLY(Name = name ? name : Name); JULIET_DEBUG_ONLY(Name = name ? name : Name;)
ArenaParams params{ .AllowRealloc = AllowRealloc JULIET_DEBUG_PARAM(.CanReserveMore = false) }; ArenaParams params{ .AllowRealloc = AllowRealloc JULIET_DEBUG_PARAM(.CanReserveMore = false) };
Arena = ArenaAllocate(params JULIET_DEBUG_PARAM(Name)); Arena = ArenaAllocate(params JULIET_DEBUG_PARAM(Name));
InternalArena = true; InternalArena = true;
@@ -29,7 +29,7 @@ namespace Juliet
{ {
Assert(!Arena); Assert(!Arena);
JULIET_DEBUG_ONLY(Name = name ? name : Name); JULIET_DEBUG_ONLY(Name = name ? name : Name;)
DataFirst = DataLast = nullptr; DataFirst = DataLast = nullptr;
Count = 0; Count = 0;
@@ -196,7 +196,7 @@ namespace Juliet
size_t Count; size_t Count;
size_t Capacity; size_t Capacity;
bool InternalArena : 1; bool InternalArena : 1;
JULIET_DEBUG_ONLY(const char* Name = "VectorArena"); JULIET_DEBUG_ONLY(const char* Name = "VectorArena";)
}; };
static_assert(std::is_standard_layout_v<VectorArena<int>>, static_assert(std::is_standard_layout_v<VectorArena<int>>,
"VectorArena must have a standard layout to remain POD-like."); "VectorArena must have a standard layout to remain POD-like.");

View File

@@ -85,23 +85,17 @@ namespace Juliet
[[nodiscard]] JULIET_API size_t ArenaPos(NonNullPtr<Arena> arena); [[nodiscard]] JULIET_API size_t ArenaPos(NonNullPtr<Arena> arena);
template <typename Type> template <typename Type>
[[nodiscard]] Type* ArenaPushStruct(NonNullPtr<Arena> arena) [[nodiscard]] Type* ArenaPushStruct(NonNullPtr<Arena> arena JULIET_DEBUG_PARAM(const char* tag = nullptr))
{ {
return static_cast<Type*>( return static_cast<Type*>(
ArenaPush(arena, sizeof(Type) * 1, AlignOf(Type), true JULIET_DEBUG_ONLY(, typeid(Type).name()))); ArenaPush(arena, sizeof(Type) * 1, AlignOf(Type), true JULIET_DEBUG_PARAM(tag ? tag : typeid(Type).name())));
} }
template <typename Type> template <typename Type>
[[nodiscard]] Type* ArenaPushArray(NonNullPtr<Arena> arena, size_t count JULIET_DEBUG_ONLY(, const char* tag)) [[nodiscard]] Type* ArenaPushArray(NonNullPtr<Arena> arena, size_t count JULIET_DEBUG_PARAM(const char* tag = nullptr))
{
return static_cast<Type*>(ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)), true JULIET_DEBUG_ONLY(, tag)));
}
template <typename Type>
[[nodiscard]] Type* ArenaPushArray(NonNullPtr<Arena> arena, size_t count)
{ {
return static_cast<Type*>(ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)), return static_cast<Type*>(ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)),
true JULIET_DEBUG_ONLY(, typeid(Type).name()))); true JULIET_DEBUG_PARAM(tag ? tag : typeid(Type).name())));
} }
TempArena ArenaTempBegin(NonNullPtr<Arena> arena); TempArena ArenaTempBegin(NonNullPtr<Arena> arena);

View File

@@ -134,13 +134,11 @@ namespace Juliet
extern JULIET_API void BindGraphicsPipeline(NonNullPtr<RenderPass> renderPass, NonNullPtr<GraphicsPipeline> graphicsPipeline); extern JULIET_API void BindGraphicsPipeline(NonNullPtr<RenderPass> renderPass, NonNullPtr<GraphicsPipeline> graphicsPipeline);
extern JULIET_API void DrawPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numVertices, uint32 numInstances, extern JULIET_API void DrawPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numVertices, uint32 numInstances,
uint32 firstVertex, uint32 firstInstance); uint32 firstVertex, uint32 firstInstance);
extern JULIET_API void DrawIndexedPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numIndices, extern JULIET_API void DrawIndexedPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numIndices, uint32 numInstances,
uint32 numInstances, uint32 firstIndex, uint32 vertexOffset, uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance);
uint32 firstInstance);
extern JULIET_API void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format);
extern JULIET_API void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer,
IndexFormat format, size_t indexCount, index_t offset);
extern JULIET_API void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, extern JULIET_API void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage,
uint32 rootParameterIndex, uint32 numConstants, const void* constants); uint32 rootParameterIndex, uint32 numConstants, const void* constants);

View File

@@ -0,0 +1,28 @@
#pragma once
#include <Core/Common/CoreTypes.h>
#include <Core/Common/NonNullPtr.h>
#include <Juliet.h>
namespace Juliet
{
struct Arena;
struct Vertex;
struct Mesh
{
Vertex* Vertices;
uint16* Indices;
size_t VertexCount;
size_t IndexCount;
index_t VertexOffset;
index_t IndexOffset;
index_t IndexByteOffset;
};
JULIET_API Mesh* CreateCubeMesh(NonNullPtr<Arena> arena);
JULIET_API Mesh* CreateQuadMesh(NonNullPtr<Arena> arena);
JULIET_API void DestroyMesh(NonNullPtr<Mesh> mesh);
} // namespace Juliet

View File

@@ -0,0 +1,10 @@
#pragma once
namespace Juliet
{
struct Vertex
{
float Position[3];
float Color[4];
};
} // namespace Juliet

View File

@@ -361,30 +361,40 @@ namespace Juliet::D3D12
d3d12CommandList->GraphicsCommandList.CommandList->OMSetStencilRef(reference); d3d12CommandList->GraphicsCommandList.CommandList->OMSetStencilRef(reference);
} }
void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format) void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format,
size_t indexCount, index_t offset)
{ {
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get()); auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
auto* d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get()); auto* d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
// Transition to INDEX_BUFFER state if needed // Transition to INDEX_BUFFER state if needed
if (d3d12Buffer->CurrentState != D3D12_RESOURCE_STATE_INDEX_BUFFER) if (d3d12Buffer->CurrentState != D3D12_RESOURCE_STATE_GENERIC_READ)
{ {
D3D12_RESOURCE_BARRIER barrier = {}; D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = d3d12Buffer->Handle; barrier.Transition.pResource = d3d12Buffer->Handle;
barrier.Transition.StateBefore = d3d12Buffer->CurrentState; barrier.Transition.StateBefore = d3d12Buffer->CurrentState;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_INDEX_BUFFER; barrier.Transition.StateAfter =
D3D12_RESOURCE_STATE_GENERIC_READ; // Since we use a mega buffer we use the generic read that includes D3D12_RESOURCE_STATE_INDEX_BUFFER
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
d3d12CommandList->GraphicsCommandList.CommandList->ResourceBarrier(1, &barrier); d3d12CommandList->GraphicsCommandList.CommandList->ResourceBarrier(1, &barrier);
d3d12Buffer->CurrentState = D3D12_RESOURCE_STATE_INDEX_BUFFER; d3d12Buffer->CurrentState = D3D12_RESOURCE_STATE_GENERIC_READ;
} }
D3D12_INDEX_BUFFER_VIEW ibView; D3D12_INDEX_BUFFER_VIEW ibView;
ibView.BufferLocation = d3d12Buffer->Handle->GetGPUVirtualAddress(); ibView.BufferLocation = d3d12Buffer->Handle->GetGPUVirtualAddress() + offset;
ibView.SizeInBytes = static_cast<UINT>(d3d12Buffer->Size); if (format == IndexFormat::UInt16)
ibView.Format = (format == IndexFormat::UInt16) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; {
ibView.SizeInBytes = static_cast<UINT>(indexCount * sizeof(uint16));
ibView.Format = DXGI_FORMAT_R16_UINT;
}
else
{
ibView.SizeInBytes = static_cast<UINT>(indexCount * sizeof(uint32));
ibView.Format = DXGI_FORMAT_R32_UINT;
}
d3d12CommandList->GraphicsCommandList.CommandList->IASetIndexBuffer(&ibView); d3d12CommandList->GraphicsCommandList.CommandList->IASetIndexBuffer(&ibView);
} }

View File

@@ -97,7 +97,8 @@ namespace Juliet::D3D12
extern void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants); extern void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants);
extern void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants); extern void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants);
extern void SetStencilReference(NonNullPtr<CommandList> commandList, uint8 reference); extern void SetStencilReference(NonNullPtr<CommandList> commandList, uint8 reference);
extern void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format); extern void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer,
IndexFormat format, index_t offset);
extern void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex, extern void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex,
uint32 numConstants, const void* constants); uint32 numConstants, const void* constants);

View File

@@ -623,27 +623,6 @@ namespace Juliet::D3D12
Free(device.Get()); Free(device.Get());
} }
// Note: SetViewPort, SetScissorRect, SetBlendConstants, SetStencilReference
// are defined in D3D12CommandList.cpp and used directly via D3D12:: namespace
// BindGraphicsPipeline is now assigned directly from D3D12:: namespace
// DrawPrimitives is now assigned directly from D3D12:: namespace
void DrawIndexedPrimitives(NonNullPtr<CommandList> commandList, uint32 numIndices, uint32 numInstances,
uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance)
{
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
d3d12CommandList->GraphicsCommandList.CommandList->DrawIndexedInstanced(numIndices, numInstances, firstIndex,
static_cast<INT>(vertexOffset), firstInstance);
}
// WaitUntilGPUIsIdle, SetPushConstants are now assigned directly from D3D12:: namespace
// QueryFence, ReleaseFence, CreateShader, DestroyShader are now assigned directly from D3D12:: namespace
// CreateGraphicsPipeline is assigned directly from D3D12:: namespace
void DestroyGraphicsPipeline(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> pipeline) void DestroyGraphicsPipeline(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> pipeline)
{ {
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get()); auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
@@ -656,8 +635,6 @@ namespace Juliet::D3D12
} }
} }
// Buffer functions are assigned directly from D3D12:: namespace
void CopyBufferToTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Texture> dst, NonNullPtr<GraphicsTransferBuffer> src) void CopyBufferToTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Texture> dst, NonNullPtr<GraphicsTransferBuffer> src)
{ {
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get()); auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
@@ -1053,7 +1030,7 @@ namespace Juliet::D3D12
device->SetStencilReference = D3D12::SetStencilReference; device->SetStencilReference = D3D12::SetStencilReference;
device->BindGraphicsPipeline = D3D12::BindGraphicsPipeline; device->BindGraphicsPipeline = D3D12::BindGraphicsPipeline;
device->DrawPrimitives = D3D12::DrawPrimitives; device->DrawPrimitives = D3D12::DrawPrimitives;
device->DrawIndexedPrimitives = DrawIndexedPrimitives; device->DrawIndexedPrimitives = D3D12::DrawIndexedPrimitives;
device->SetIndexBuffer = D3D12::SetIndexBuffer; device->SetIndexBuffer = D3D12::SetIndexBuffer;
device->WaitUntilGPUIsIdle = D3D12::WaitUntilGPUIsIdle; device->WaitUntilGPUIsIdle = D3D12::WaitUntilGPUIsIdle;

View File

@@ -283,4 +283,12 @@ namespace Juliet::D3D12
d3d12CommandList->GraphicsCommandList.CommandList->DrawInstanced(numVertices, numInstances, firstVertex, firstInstance); d3d12CommandList->GraphicsCommandList.CommandList->DrawInstanced(numVertices, numInstances, firstVertex, firstInstance);
} }
void DrawIndexedPrimitives(NonNullPtr<CommandList> commandList, uint32 numIndices, uint32 numInstances,
uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance)
{
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
d3d12CommandList->GraphicsCommandList.CommandList->DrawIndexedInstanced(numIndices, numInstances, firstIndex,
static_cast<INT>(vertexOffset), firstInstance);
}
} // namespace Juliet::D3D12 } // namespace Juliet::D3D12

View File

@@ -13,4 +13,6 @@ namespace Juliet::D3D12
extern void BindGraphicsPipeline(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsPipeline> graphicsPipeline); extern void BindGraphicsPipeline(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsPipeline> graphicsPipeline);
extern void DrawPrimitives(NonNullPtr<CommandList> commandList, uint32 numVertices, uint32 numInstances, extern void DrawPrimitives(NonNullPtr<CommandList> commandList, uint32 numVertices, uint32 numInstances,
uint32 firstVertex, uint32 firstInstance); uint32 firstVertex, uint32 firstInstance);
void DrawIndexedPrimitives(NonNullPtr<CommandList> commandList, uint32 numIndices, uint32 numInstances,
uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance);
} // namespace Juliet::D3D12 } // namespace Juliet::D3D12

View File

@@ -1,11 +1,10 @@
#include <Core/HAL/Filesystem/Filesystem.h> #include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/HAL/IO/IOStream.h> #include <Core/HAL/IO/IOStream.h>
#include <Core/ImGui/ImGuiTests.h>
#include <Core/Logging/LogManager.h> #include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h> #include <Core/Logging/LogTypes.h>
#include <Graphics/Graphics.h> #include <Graphics/Graphics.h>
#include <Graphics/GraphicsDevice.h> #include <Graphics/GraphicsDevice.h>
#include <Core/ImGui/ImGuiTests.h>
namespace Juliet namespace Juliet
{ {
@@ -63,7 +62,6 @@ namespace Juliet
newDevice->Name = chosenFactory->Name; newDevice->Name = chosenFactory->Name;
return newDevice; return newDevice;
} }
} }
return nullptr; return nullptr;
} }
@@ -263,13 +261,14 @@ namespace Juliet
commandListHeader->Device->SetStencilReference(commandList, reference); commandListHeader->Device->SetStencilReference(commandList, reference);
} }
void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format) void SetIndexBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format,
size_t indexCount, index_t offset)
{ {
auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList.Get()); auto* commandListHeader = reinterpret_cast<CommandListHeader*>(commandList.Get());
if (commandListHeader->Device->SetIndexBuffer) if (commandListHeader->Device->SetIndexBuffer)
{ {
commandListHeader->Device->SetIndexBuffer(commandList, buffer, format); commandListHeader->Device->SetIndexBuffer(commandList, buffer, format, indexCount, offset);
} }
} }
@@ -297,13 +296,11 @@ namespace Juliet
if (commandListHeader->Device->DrawIndexedPrimitives) if (commandListHeader->Device->DrawIndexedPrimitives)
{ {
commandListHeader->Device->DrawIndexedPrimitives(commandList, numIndices, numInstances, firstIndex, vertexOffset, firstInstance); commandListHeader->Device->DrawIndexedPrimitives(commandList, numIndices, numInstances, firstIndex,
vertexOffset, firstInstance);
} }
} }
void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex, void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex,
uint32 numConstants, const void* constants) uint32 numConstants, const void* constants)
{ {
@@ -399,8 +396,7 @@ namespace Juliet
headers->Device->CopyBuffer(commandList, dst, src, size, dstOffset, srcOffset); headers->Device->CopyBuffer(commandList, dst, src, size, dstOffset, srcOffset);
} }
void CopyBufferToTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Texture> dst, void CopyBufferToTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Texture> dst, NonNullPtr<GraphicsTransferBuffer> src)
NonNullPtr<GraphicsTransferBuffer> src)
{ {
auto* headers = reinterpret_cast<CommandListHeader*>(commandList.Get()); auto* headers = reinterpret_cast<CommandListHeader*>(commandList.Get());
if (headers->Device->CopyBufferToTexture) if (headers->Device->CopyBufferToTexture)
@@ -409,7 +405,6 @@ namespace Juliet
} }
} }
void TransitionBufferToReadable(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer) void TransitionBufferToReadable(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer)
{ {
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get()); auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get());
@@ -426,7 +421,6 @@ namespace Juliet
return device->GetDescriptorIndexTexture(device, texture); return device->GetDescriptorIndexTexture(device, texture);
} }
void DestroyGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer) void DestroyGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
{ {
device->DestroyGraphicsBuffer(buffer); device->DestroyGraphicsBuffer(buffer);

View File

@@ -68,7 +68,8 @@ namespace Juliet
void (*SetScissorRect)(NonNullPtr<CommandList> commandList, const Rectangle& viewPort); void (*SetScissorRect)(NonNullPtr<CommandList> commandList, const Rectangle& viewPort);
void (*SetBlendConstants)(NonNullPtr<CommandList> commandList, FColor blendConstants); void (*SetBlendConstants)(NonNullPtr<CommandList> commandList, FColor blendConstants);
void (*SetStencilReference)(NonNullPtr<CommandList> commandList, uint8 reference); void (*SetStencilReference)(NonNullPtr<CommandList> commandList, uint8 reference);
void (*SetIndexBuffer)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer, IndexFormat format); void (*SetIndexBuffer)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer,
IndexFormat format, size_t indexCount, index_t offset);
void (*BindGraphicsPipeline)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsPipeline> graphicsPipeline); void (*BindGraphicsPipeline)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsPipeline> graphicsPipeline);
void (*DrawPrimitives)(NonNullPtr<CommandList> commandList, uint32 numVertices, uint32 numInstances, void (*DrawPrimitives)(NonNullPtr<CommandList> commandList, uint32 numVertices, uint32 numInstances,

View File

@@ -223,9 +223,7 @@ namespace Juliet
DestroyShader(device, g_ImGuiState.VertexShader); DestroyShader(device, g_ImGuiState.VertexShader);
} }
if (g_ImGuiState.FragmentShader) if (g_ImGuiState.FragmentShader)
{ {
DestroyShader(device, g_ImGuiState.FragmentShader); DestroyShader(device, g_ImGuiState.FragmentShader);
} }
if (g_ImGuiState.FontTexture) if (g_ImGuiState.FontTexture)
@@ -344,7 +342,7 @@ namespace Juliet
TransitionBufferToReadable(cmdList, currentFrame.VertexBuffer); TransitionBufferToReadable(cmdList, currentFrame.VertexBuffer);
// SetIndexBuffer transitions from COPY_DEST to INDEX_BUFFER (barrier waits for copy to complete) // SetIndexBuffer transitions from COPY_DEST to INDEX_BUFFER (barrier waits for copy to complete)
SetIndexBuffer(cmdList, currentFrame.IndexBuffer, IndexFormat::UInt16); SetIndexBuffer(cmdList, currentFrame.IndexBuffer, IndexFormat::UInt16, totalIdx, 0);
// Render // Render
BindGraphicsPipeline(renderPass, g_ImGuiState.Pipeline); BindGraphicsPipeline(renderPass, g_ImGuiState.Pipeline);
@@ -379,7 +377,7 @@ namespace Juliet
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback != nullptr) if (pcmd->UserCallback != nullptr)
{ {
// pcmd->UserCallback(cmd_list, pcmd); pcmd->UserCallback(cmd_list, pcmd);
} }
else else
{ {

View File

@@ -0,0 +1,99 @@
#include <Graphics/Mesh.h>
#include <Core/Memory/MemoryArena.h>
#include <Graphics/VertexData.h>
namespace Juliet
{
Mesh* CreateCubeMesh(NonNullPtr<Arena> arena)
{
Mesh* result = ArenaPushStruct<Mesh>(arena.Get());
constexpr Vertex vertexData[] = {
// Front Face (Z = -0.5f)
{ { -0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f } }, // 0: Top Left
{ { 0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f } }, // 1: Top Right
{ { 0.5f, -0.5f, -0.5f }, { 1.0f, 1.0f } }, // 2: Bottom Right
{ { -0.5f, -0.5f, -0.5f }, { 0.0f, 1.0f } }, // 3: Bottom Left
// Back Face (Z = 0.5f)
{ { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f } }, // 4: Top Left
{ { -0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f } }, // 5: Top Right
{ { -0.5f, -0.5f, 0.5f }, { 1.0f, 1.0f } }, // 6: Bottom Right
{ { 0.5f, -0.5f, 0.5f }, { 0.0f, 1.0f } }, // 7: Bottom Left
// Top Face (Y = 0.5f)
{ { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f } }, // 8: Top Left
{ { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f } }, // 9: Top Right
{ { 0.5f, 0.5f, -0.5f }, { 1.0f, 1.0f } }, // 10: Bottom Right
{ { -0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f } }, // 11: Bottom Left
// Bottom Face (Y = -0.5f)
{ { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f } }, // 12: Top Left
{ { 0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f } }, // 13: Top Right
{ { 0.5f, -0.5f, 0.5f }, { 1.0f, 1.0f } }, // 14: Bottom Right
{ { -0.5f, -0.5f, 0.5f }, { 0.0f, 1.0f } }, // 15: Bottom Left
// Right Face (X = 0.5f)
{ { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f } }, // 16: Top Left
{ { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f } }, // 17: Top Right
{ { 0.5f, -0.5f, 0.5f }, { 1.0f, 1.0f } }, // 18: Bottom Right
{ { 0.5f, -0.5f, -0.5f }, { 0.0f, 1.0f } }, // 19: Bottom Left
// Left Face (X = -0.5f)
{ { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f } }, // 20: Top Left
{ { -0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f } }, // 21: Top Right
{ { -0.5f, -0.5f, -0.5f }, { 1.0f, 1.0f } }, // 22: Bottom Right
{ { -0.5f, -0.5f, 0.5f }, { 0.0f, 1.0f } } // 23: Bottom Left
};
constexpr size_t cubeVertexCount = ArraySize(vertexData);
result->VertexCount = cubeVertexCount;
result->Vertices = ArenaPushArray<Vertex>(arena.Get(), cubeVertexCount);
MemCopy(result->Vertices, vertexData, sizeof(Vertex) * cubeVertexCount);
constexpr uint16 indices[] = { 0, 1, 2, 0, 2, 3, // Front
4, 5, 6, 4, 6, 7, // Back
8, 9, 10, 8, 10, 11, // Top
12, 13, 14, 12, 14, 15, // Bottom
16, 17, 18, 16, 18, 19, // Right
20, 21, 22, 20, 22, 23 }; // Left
constexpr size_t indexCubeCount = ArraySize(indices);
result->IndexCount = indexCubeCount;
result->Indices = ArenaPushArray<uint16>(arena.Get(), indexCubeCount JULIET_DEBUG_PARAM("Indices"));
MemCopy(result->Indices, indices, sizeof(uint16) * indexCubeCount);
return result;
}
Mesh* CreateQuadMesh(NonNullPtr<Arena> arena)
{
Mesh* result = ArenaPushStruct<Mesh>(arena.Get());
// Using the exact 6 vertices from the working triangles!
constexpr Vertex vertexData[] = {
// Triangle 1 (Clockwise)
{ { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 0: Red
{ { 0.0f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1: Green
{ { 0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2: Blue
// Triangle 2 (Clockwise)
{ { -0.5f, 0.5f, 0.0f }, { 1.0f, 1.0f, 0.0f, 1.0f } }, // 3: Yellow
{ { 0.0f, 0.8f, 0.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, // 4: Cyan
{ { 0.5f, 0.5f, 0.0f }, { 1.0f, 0.0f, 1.0f, 1.0f } } // 5: Magenta
};
constexpr size_t triVertexCount = ArraySize(vertexData);
result->VertexCount = triVertexCount;
result->Vertices = ArenaPushArray<Vertex>(arena.Get(), triVertexCount);
MemCopy(result->Vertices, vertexData, sizeof(Vertex) * triVertexCount);
// Just the 6 indices for the two triangles
constexpr uint16 indices[] = { 0, 1, 2, 3, 4, 5 };
constexpr size_t triIndexCount = ArraySize(indices);
result->IndexCount = triIndexCount;
result->Indices = ArenaPushArray<uint16>(arena.Get(), triIndexCount JULIET_DEBUG_PARAM("Indices"));
MemCopy(result->Indices, indices, sizeof(uint16) * triIndexCount);
return result;
}
} // namespace Juliet

View File

@@ -20,7 +20,9 @@
#include <Graphics/Graphics.h> #include <Graphics/Graphics.h>
#include <Graphics/GraphicsConfig.h> #include <Graphics/GraphicsConfig.h>
#include <Graphics/GraphicsPipeline.h> #include <Graphics/GraphicsPipeline.h>
#include <Graphics/Mesh.h>
#include <Graphics/RenderPass.h> #include <Graphics/RenderPass.h>
#include <Graphics/VertexData.h>
#include <Juliet.h> #include <Juliet.h>
#ifdef JULIET_ENABLE_IMGUI #ifdef JULIET_ENABLE_IMGUI
@@ -63,12 +65,6 @@ namespace
const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" }; const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" };
} // namespace } // namespace
struct Vertex
{
float Position[2];
float Color[4];
};
void JulietApplication::Init() void JulietApplication::Init()
{ {
Log(LogLevel::Message, LogCategory::Tool, "Initializing Juliet Application..."); Log(LogLevel::Message, LogCategory::Tool, "Initializing Juliet Application...");
@@ -88,7 +84,6 @@ void JulietApplication::Init()
if (Running) if (Running)
{ {
AttachToWindow(GraphicsDevice, MainWindow); AttachToWindow(GraphicsDevice, MainWindow);
{ {
// Create graphics pipeline // Create graphics pipeline
String entryPoint = WrapString("main"); String entryPoint = WrapString("main");
@@ -146,12 +141,12 @@ void JulietApplication::Init()
// Create Buffers - Using StructuredBuffer for bindless SRV access in shader // Create Buffers - Using StructuredBuffer for bindless SRV access in shader
BufferCreateInfo bufferCI = {}; BufferCreateInfo bufferCI = {};
bufferCI.Size = 256; bufferCI.Size = 1024;
bufferCI.Usage = BufferUsage::StructuredBuffer; // SRV for ResourceDescriptorHeap access bufferCI.Usage = BufferUsage::StructuredBuffer; // SRV for ResourceDescriptorHeap access
ConstantBuffer = CreateGraphicsBuffer(GraphicsDevice, bufferCI); ConstantBuffer = CreateGraphicsBuffer(GraphicsDevice, bufferCI);
TransferBufferCreateInfo transferCI = {}; TransferBufferCreateInfo transferCI = {};
transferCI.Size = 256; transferCI.Size = 1024;
transferCI.Usage = TransferBufferUsage::Upload; transferCI.Usage = TransferBufferUsage::Upload;
TransferBuffer = CreateGraphicsTransferBuffer(GraphicsDevice, transferCI); TransferBuffer = CreateGraphicsTransferBuffer(GraphicsDevice, transferCI);
@@ -176,6 +171,10 @@ void JulietApplication::Init()
} }
} }
CubeArena = ArenaAllocate({ .ReserveSize = Kilobytes(1llu), .CommitSize = Kilobytes(1llu) } JULIET_DEBUG_PARAM("CubeArena"));
CubeMesh = CreateCubeMesh(CubeArena);
// CubeMesh = CreateQuadMesh(CubeArena);
if (vertexShader) if (vertexShader)
{ {
DestroyShader(GraphicsDevice, vertexShader); DestroyShader(GraphicsDevice, vertexShader);
@@ -209,6 +208,8 @@ void JulietApplication::Shutdown()
{ {
Log(LogLevel::Message, LogCategory::Tool, "Shutting down Juliet Application..."); Log(LogLevel::Message, LogCategory::Tool, "Shutting down Juliet Application...");
ArenaRelease(CubeArena);
if (GameCode.IsValid) if (GameCode.IsValid)
{ {
Game.Shutdown(); Game.Shutdown();
@@ -283,10 +284,10 @@ void JulietApplication::Update()
ImGui::ShowDemoWindow(); ImGui::ShowDemoWindow();
#endif #endif
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 10.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false); DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false);
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 10.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, true); DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, true);
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 10.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, true); DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, true);
DebugDisplay_DrawSphere({ 0.0f, 0.0f, 0.0f }, 5.0f, { 1.0f, 1.0f, 0.0f, 1.0f }, true); DebugDisplay_DrawSphere({ 0.0f, 0.0f, 0.0f }, 0.5f, { 1.0f, 1.0f, 0.0f, 1.0f }, true);
Game.Update(0.0f); Game.Update(0.0f);
@@ -362,28 +363,49 @@ void JulietApplication::Update()
void JulietApplication::OnPreRender(CommandList* cmd) void JulietApplication::OnPreRender(CommandList* cmd)
{ {
index_t index = 0;
// Buffer uploads // Buffer uploads
if (ConstantBuffer && TransferBuffer) if (ConstantBuffer && TransferBuffer)
{ {
void* ptr = MapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer); void* ptr = MapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
if (ptr) if (ptr)
{ {
auto vertices = static_cast<Vertex*>(ptr); Vertex* vertices = static_cast<Vertex*>(ptr);
// Triangle 1 // // Triangle 1
vertices[0] = { { -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f, 1.0f } }; // Red // vertices[index++] = { { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }; // Red
vertices[1] = { { 0.0f, 0.5f }, { 0.0f, 1.0f, 0.0f, 1.0f } }; // Green // vertices[index++] = { { 0.0f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }; // Green
vertices[2] = { { 0.5f, -0.5f }, { 0.0f, 0.0f, 1.0f, 1.0f } }; // Blue // vertices[index++] = { { 0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }; // Blue
//
// // Triangle 2
// vertices[index++] = { { -0.5f, 0.5f, 0.0f }, { 1.0f, 1.0f, 0.0f, 1.0f } }; // Yellow
// vertices[index++] = { { 0.0f, 0.8f, 0.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }; // Cyan
// vertices[index++] = { { 0.5f, 0.5f, 0.0f }, { 1.0f, 0.0f, 1.0f, 1.0f } }; // Magenta
// Triangle 2 if (CubeMesh)
vertices[3] = { { -0.5f, 0.5f }, { 1.0f, 1.0f, 0.0f, 1.0f } }; // Yellow {
vertices[4] = { { 0.0f, 0.8f }, { 0.0f, 1.0f, 1.0f, 1.0f } }; // Cyan CubeMesh->VertexOffset = index;
vertices[5] = { { 0.5f, 0.5f }, { 1.0f, 0.0f, 1.0f, 1.0f } }; // Magenta size_t vertexSize = CubeMesh->VertexCount * sizeof(Vertex);
MemCopy(vertices + index, CubeMesh->Vertices, vertexSize);
CubeMesh->IndexByteOffset = (index + CubeMesh->VertexCount) * sizeof(Vertex);
// Align
CubeMesh->IndexByteOffset = (CubeMesh->IndexByteOffset + 255) & static_cast<size_t>(~255);
size_t indexSize = CubeMesh->IndexCount * sizeof(uint16);
CubeMesh->IndexOffset = 0;
uint8* ptrOneByte = static_cast<uint8*>(ptr);
uint16* dst = reinterpret_cast<uint16*>(ptrOneByte + CubeMesh->IndexByteOffset);
MemCopy(dst, CubeMesh->Indices, indexSize);
}
UnmapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer); UnmapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
} }
CopyBuffer(cmd, ConstantBuffer, TransferBuffer, 256); CopyBuffer(cmd, ConstantBuffer, TransferBuffer, CubeMesh->IndexByteOffset + (CubeMesh->IndexCount * sizeof(uint16)));
TransitionBufferToReadable(cmd, ConstantBuffer); TransitionBufferToReadable(cmd, ConstantBuffer);
} }
} }
@@ -396,14 +418,19 @@ void JulietApplication::OnRender(RenderPass* pass, CommandList* cmd)
struct PushData struct PushData
{ {
float ViewProjection[16]; Matrix ViewProjection;
uint32 BufferIndex; uint32 BufferIndex;
} pushData = {}; } pushData = {};
pushData.BufferIndex = descriptorIndex; pushData.BufferIndex = descriptorIndex;
pushData.ViewProjection = Camera_GetViewProjectionMatrix(GetDebugCamera());
SetPushConstants(cmd, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData); SetPushConstants(cmd, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
DrawPrimitives(pass, 6, 1, 0, 0); SetIndexBuffer(cmd, ConstantBuffer, IndexFormat::UInt16, CubeMesh->IndexCount, CubeMesh->IndexByteOffset);
// DrawIndexedPrimitives(pass, static_cast<uint32>(CubeMesh->IndexCount), 1, 0, 0, 0);
DrawIndexedPrimitives(pass, static_cast<uint32>(CubeMesh->IndexCount), 1,
static_cast<uint32>(CubeMesh->IndexOffset), static_cast<uint32>(CubeMesh->VertexOffset), 0);
} }
ColorTargetInfo JulietApplication::GetColorTargetInfo(Texture* swapchainTexture) ColorTargetInfo JulietApplication::GetColorTargetInfo(Texture* swapchainTexture)
@@ -428,18 +455,32 @@ DepthStencilTargetInfo* JulietApplication::GetDepthTargetInfo()
Camera JulietApplication::GetDebugCamera() Camera JulietApplication::GetDebugCamera()
{ {
static float orbitTime = 0.0f; static float time = 0.0f;
orbitTime += 0.016f; time += 0.016f;
float orbitSpeed = 0.5f;
float currentOrbitTime = time * orbitSpeed;
// --- Adjusted for 1-Meter Scale ---
float baseRadius = 2.5f; // Hover 2.5 meters away (down from 15.0f)
float radius = baseRadius;
/* Uncomment for active zoom
float zoomAmplitude = 1.0f; // Oscillate between 1.5m and 3.5m away
float zoomSpeed = 0.8f;
radius = baseRadius + (sinf(time * zoomSpeed) * zoomAmplitude);
*/
float zHeight = radius * 0.5f; // Keep a nice downward viewing angle
float radius = 30.0f;
Camera cam = {}; Camera cam = {};
cam.Position = { cosf(orbitTime) * radius, sinf(orbitTime) * radius, 10.0f }; cam.Position = { cosf(currentOrbitTime) * radius, sinf(currentOrbitTime) * radius, zHeight };
cam.Target = { 0.0f, 0.0f, 0.0f }; cam.Target = { 0.0f, 0.0f, 0.0f };
cam.Up = { 0.0f, 0.0f, 1.0f }; cam.Up = { 0.0f, 0.0f, 1.0f };
cam.FOV = 1.047f; cam.FOV = 1.047f;
cam.AspectRatio = 1200.0f / 800.0f; cam.AspectRatio = 1200.0f / 800.0f;
cam.NearPlane = 0.1f; cam.NearPlane = 0.1f;
cam.FarPlane = 1000.0f; cam.FarPlane = 1000.0f;
return cam; return cam;
} }
@@ -447,7 +488,6 @@ bool JulietApplication::IsRunning()
{ {
return Running; return Running;
} }
namespace namespace
{ {
JulietApplication EditorApplication; JulietApplication EditorApplication;

View File

@@ -8,6 +8,7 @@
namespace Juliet namespace Juliet
{ {
struct Mesh;
struct GraphicsTransferBuffer; struct GraphicsTransferBuffer;
struct GraphicsBuffer; struct GraphicsBuffer;
struct GraphicsDevice; struct GraphicsDevice;
@@ -45,11 +46,14 @@ class JulietApplication : public Juliet::IApplication
Juliet::GraphicsTransferBuffer* TransferBuffer = {}; Juliet::GraphicsTransferBuffer* TransferBuffer = {};
Juliet::Texture* DepthBuffer = {}; Juliet::Texture* DepthBuffer = {};
Juliet::Mesh* CubeMesh = {};
Juliet::Arena* CubeArena = nullptr;
Juliet::Arena* GameArena = nullptr; Juliet::Arena* GameArena = nullptr;
Juliet::Arena* GameScratchArena = nullptr; Juliet::Arena* GameScratchArena = nullptr;
bool Running = false;
int AutoCloseFrameCount = -1; int AutoCloseFrameCount = -1;
bool Running = false;
}; };
JulietApplication& GetEditorApplication(); JulietApplication& GetEditorApplication();