diff --git a/Assets/compiled/Triangle.vert.dxil b/Assets/compiled/Triangle.vert.dxil index 5ebdfc1..9416589 100644 Binary files a/Assets/compiled/Triangle.vert.dxil and b/Assets/compiled/Triangle.vert.dxil differ diff --git a/Assets/source/ImGui.frag.hlsl b/Assets/source/ImGui.frag.hlsl index 23e7d5d..8a957e6 100644 --- a/Assets/source/ImGui.frag.hlsl +++ b/Assets/source/ImGui.frag.hlsl @@ -8,31 +8,7 @@ struct Input float4 main(Input input) : SV_Target0 { - // Retrieve the texture using SM6.6 bindless syntax - // Texture2D texture = ResourceDescriptorHeap[TextureIndex]; (Must cast to Texture2D) - // 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 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 tex = ResourceDescriptorHeap[TextureIndex]; - SamplerState samp = SamplerDescriptorHeap[0]; // Point sampler or Linear? ImGui usually uses Linear. - // 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. - + SamplerState samp = SamplerDescriptorHeap[0]; return input.Color * tex.Sample(samp, input.UV); } diff --git a/Assets/source/ImGui.vert.hlsl b/Assets/source/ImGui.vert.hlsl index 0b415c4..d033dc6 100644 --- a/Assets/source/ImGui.vert.hlsl +++ b/Assets/source/ImGui.vert.hlsl @@ -18,14 +18,10 @@ Output main(uint vertexIndex : SV_VertexID) { Output output; - // Retrieve the vertex buffer using SM6.6 bindless syntax 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; - // ImDrawVert stride = 20 bytes (Vec2 pos + Vec2 uv + uint color) uint stride = 20; uint offset = actualVertexIndex * stride; @@ -33,34 +29,12 @@ Output main(uint vertexIndex : SV_VertexID) float2 uv = asfloat(buffer.Load2(offset + 8)); 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; c.x = float(col & 0xFF) / 255.0f; c.y = float((col >> 8) & 0xFF) / 255.0f; c.z = float((col >> 16) & 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.Color = c; output.UV = uv; diff --git a/Assets/source/Triangle.vert.hlsl b/Assets/source/Triangle.vert.hlsl index 2d2bf78..79c1663 100644 --- a/Assets/source/Triangle.vert.hlsl +++ b/Assets/source/Triangle.vert.hlsl @@ -10,20 +10,16 @@ Output main(uint vertexIndex : SV_VertexID) { Output output; - // Retrieve the buffer using SM6.6 bindless syntax - // Use BufferIndex from RootConstants (pushed via SetPushConstants) ByteAddressBuffer buffer = ResourceDescriptorHeap[BufferIndex]; - // Read position from buffer (Index * stride) - // 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 stride = 28; uint offset = vertexIndex * stride; - float2 pos = asfloat(buffer.Load2(offset)); - float4 col = asfloat(buffer.Load4(offset + 8)); + float3 pos = asfloat(buffer.Load3(offset)); + 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; return output; } diff --git a/Juliet/Juliet.vcxproj b/Juliet/Juliet.vcxproj index 1d0f787..5e8ad2d 100644 --- a/Juliet/Juliet.vcxproj +++ b/Juliet/Juliet.vcxproj @@ -108,9 +108,11 @@ + + @@ -220,6 +222,7 @@ + diff --git a/Juliet/Juliet.vcxproj.filters b/Juliet/Juliet.vcxproj.filters index 0357371..0a25d60 100644 --- a/Juliet/Juliet.vcxproj.filters +++ b/Juliet/Juliet.vcxproj.filters @@ -172,6 +172,9 @@ include\Graphics + + include\Graphics + include\Graphics @@ -181,6 +184,9 @@ include\Graphics + + include\Graphics + include @@ -507,6 +513,9 @@ src\Graphics + + src\Graphics + src\UnitTest\Container diff --git a/Juliet/include/Core/Container/Vector.h b/Juliet/include/Core/Container/Vector.h index c63c7d7..6496b26 100644 --- a/Juliet/include/Core/Container/Vector.h +++ b/Juliet/include/Core/Container/Vector.h @@ -17,7 +17,7 @@ namespace Juliet DataFirst = DataLast = nullptr; 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) }; Arena = ArenaAllocate(params JULIET_DEBUG_PARAM(Name)); InternalArena = true; @@ -29,7 +29,7 @@ namespace Juliet { Assert(!Arena); - JULIET_DEBUG_ONLY(Name = name ? name : Name); + JULIET_DEBUG_ONLY(Name = name ? name : Name;) DataFirst = DataLast = nullptr; Count = 0; @@ -196,7 +196,7 @@ namespace Juliet size_t Count; size_t Capacity; 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 must have a standard layout to remain POD-like."); diff --git a/Juliet/include/Core/Memory/MemoryArena.h b/Juliet/include/Core/Memory/MemoryArena.h index 4f41918..987d53f 100644 --- a/Juliet/include/Core/Memory/MemoryArena.h +++ b/Juliet/include/Core/Memory/MemoryArena.h @@ -85,23 +85,17 @@ namespace Juliet [[nodiscard]] JULIET_API size_t ArenaPos(NonNullPtr arena); template - [[nodiscard]] Type* ArenaPushStruct(NonNullPtr arena) + [[nodiscard]] Type* ArenaPushStruct(NonNullPtr arena JULIET_DEBUG_PARAM(const char* tag = nullptr)) { return static_cast( - 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 - [[nodiscard]] Type* ArenaPushArray(NonNullPtr arena, size_t count JULIET_DEBUG_ONLY(, const char* tag)) - { - return static_cast(ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)), true JULIET_DEBUG_ONLY(, tag))); - } - - template - [[nodiscard]] Type* ArenaPushArray(NonNullPtr arena, size_t count) + [[nodiscard]] Type* ArenaPushArray(NonNullPtr arena, size_t count JULIET_DEBUG_PARAM(const char* tag = nullptr)) { return static_cast(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); diff --git a/Juliet/include/Graphics/Graphics.h b/Juliet/include/Graphics/Graphics.h index e353a47..0f0fed6 100644 --- a/Juliet/include/Graphics/Graphics.h +++ b/Juliet/include/Graphics/Graphics.h @@ -134,13 +134,11 @@ namespace Juliet extern JULIET_API void BindGraphicsPipeline(NonNullPtr renderPass, NonNullPtr graphicsPipeline); extern JULIET_API void DrawPrimitives(NonNullPtr renderPass, uint32 numVertices, uint32 numInstances, uint32 firstVertex, uint32 firstInstance); - extern JULIET_API void DrawIndexedPrimitives(NonNullPtr renderPass, uint32 numIndices, - uint32 numInstances, uint32 firstIndex, uint32 vertexOffset, - uint32 firstInstance); - - extern JULIET_API void SetIndexBuffer(NonNullPtr commandList, NonNullPtr buffer, IndexFormat format); - + extern JULIET_API void DrawIndexedPrimitives(NonNullPtr renderPass, uint32 numIndices, uint32 numInstances, + uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance); + extern JULIET_API void SetIndexBuffer(NonNullPtr commandList, NonNullPtr buffer, + IndexFormat format, size_t indexCount, index_t offset); extern JULIET_API void SetPushConstants(NonNullPtr commandList, ShaderStage stage, uint32 rootParameterIndex, uint32 numConstants, const void* constants); diff --git a/Juliet/include/Graphics/Mesh.h b/Juliet/include/Graphics/Mesh.h new file mode 100644 index 0000000..cbdd4be --- /dev/null +++ b/Juliet/include/Graphics/Mesh.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + +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); + JULIET_API Mesh* CreateQuadMesh(NonNullPtr arena); + JULIET_API void DestroyMesh(NonNullPtr mesh); +} // namespace Juliet diff --git a/Juliet/include/Graphics/VertexData.h b/Juliet/include/Graphics/VertexData.h new file mode 100644 index 0000000..10f714b --- /dev/null +++ b/Juliet/include/Graphics/VertexData.h @@ -0,0 +1,10 @@ +#pragma once + +namespace Juliet +{ + struct Vertex + { + float Position[3]; + float Color[4]; + }; +} // namespace Juliet diff --git a/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp b/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp index fc5ab4c..a0f7085 100644 --- a/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp @@ -361,30 +361,40 @@ namespace Juliet::D3D12 d3d12CommandList->GraphicsCommandList.CommandList->OMSetStencilRef(reference); } - void SetIndexBuffer(NonNullPtr commandList, NonNullPtr buffer, IndexFormat format) + void SetIndexBuffer(NonNullPtr commandList, NonNullPtr buffer, IndexFormat format, + size_t indexCount, index_t offset) { auto* d3d12CommandList = reinterpret_cast(commandList.Get()); auto* d3d12Buffer = reinterpret_cast(buffer.Get()); // 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 = {}; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barrier.Transition.pResource = d3d12Buffer->Handle; 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; 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; - ibView.BufferLocation = d3d12Buffer->Handle->GetGPUVirtualAddress(); - ibView.SizeInBytes = static_cast(d3d12Buffer->Size); - ibView.Format = (format == IndexFormat::UInt16) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; + ibView.BufferLocation = d3d12Buffer->Handle->GetGPUVirtualAddress() + offset; + if (format == IndexFormat::UInt16) + { + ibView.SizeInBytes = static_cast(indexCount * sizeof(uint16)); + ibView.Format = DXGI_FORMAT_R16_UINT; + } + else + { + ibView.SizeInBytes = static_cast(indexCount * sizeof(uint32)); + ibView.Format = DXGI_FORMAT_R32_UINT; + } d3d12CommandList->GraphicsCommandList.CommandList->IASetIndexBuffer(&ibView); } diff --git a/Juliet/src/Graphics/D3D12/D3D12CommandList.h b/Juliet/src/Graphics/D3D12/D3D12CommandList.h index c1c1b52..c246f6c 100644 --- a/Juliet/src/Graphics/D3D12/D3D12CommandList.h +++ b/Juliet/src/Graphics/D3D12/D3D12CommandList.h @@ -97,7 +97,8 @@ namespace Juliet::D3D12 extern void SetBlendConstants(NonNullPtr commandList, FColor blendConstants); extern void SetBlendConstants(NonNullPtr commandList, FColor blendConstants); extern void SetStencilReference(NonNullPtr commandList, uint8 reference); - extern void SetIndexBuffer(NonNullPtr commandList, NonNullPtr buffer, IndexFormat format); + extern void SetIndexBuffer(NonNullPtr commandList, NonNullPtr buffer, + IndexFormat format, index_t offset); extern void SetPushConstants(NonNullPtr commandList, ShaderStage stage, uint32 rootParameterIndex, uint32 numConstants, const void* constants); diff --git a/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp b/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp index e574786..6639864 100644 --- a/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp @@ -623,27 +623,6 @@ namespace Juliet::D3D12 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, uint32 numIndices, uint32 numInstances, - uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance) - { - auto* d3d12CommandList = reinterpret_cast(commandList.Get()); - d3d12CommandList->GraphicsCommandList.CommandList->DrawIndexedInstanced(numIndices, numInstances, firstIndex, - static_cast(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 driver, NonNullPtr pipeline) { auto* d3d12Driver = static_cast(driver.Get()); @@ -656,8 +635,6 @@ namespace Juliet::D3D12 } } - // Buffer functions are assigned directly from D3D12:: namespace - void CopyBufferToTexture(NonNullPtr commandList, NonNullPtr dst, NonNullPtr src) { auto* d3d12CommandList = reinterpret_cast(commandList.Get()); @@ -1053,7 +1030,7 @@ namespace Juliet::D3D12 device->SetStencilReference = D3D12::SetStencilReference; device->BindGraphicsPipeline = D3D12::BindGraphicsPipeline; device->DrawPrimitives = D3D12::DrawPrimitives; - device->DrawIndexedPrimitives = DrawIndexedPrimitives; + device->DrawIndexedPrimitives = D3D12::DrawIndexedPrimitives; device->SetIndexBuffer = D3D12::SetIndexBuffer; device->WaitUntilGPUIsIdle = D3D12::WaitUntilGPUIsIdle; diff --git a/Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp b/Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp index f2924e5..3a0810a 100644 --- a/Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp @@ -283,4 +283,12 @@ namespace Juliet::D3D12 d3d12CommandList->GraphicsCommandList.CommandList->DrawInstanced(numVertices, numInstances, firstVertex, firstInstance); } + + void DrawIndexedPrimitives(NonNullPtr commandList, uint32 numIndices, uint32 numInstances, + uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance) + { + auto* d3d12CommandList = reinterpret_cast(commandList.Get()); + d3d12CommandList->GraphicsCommandList.CommandList->DrawIndexedInstanced(numIndices, numInstances, firstIndex, + static_cast(vertexOffset), firstInstance); + } } // namespace Juliet::D3D12 diff --git a/Juliet/src/Graphics/D3D12/D3D12RenderPass.h b/Juliet/src/Graphics/D3D12/D3D12RenderPass.h index 62f8523..cf5f2f5 100644 --- a/Juliet/src/Graphics/D3D12/D3D12RenderPass.h +++ b/Juliet/src/Graphics/D3D12/D3D12RenderPass.h @@ -13,4 +13,6 @@ namespace Juliet::D3D12 extern void BindGraphicsPipeline(NonNullPtr commandList, NonNullPtr graphicsPipeline); extern void DrawPrimitives(NonNullPtr commandList, uint32 numVertices, uint32 numInstances, uint32 firstVertex, uint32 firstInstance); + void DrawIndexedPrimitives(NonNullPtr commandList, uint32 numIndices, uint32 numInstances, + uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance); } // namespace Juliet::D3D12 diff --git a/Juliet/src/Graphics/Graphics.cpp b/Juliet/src/Graphics/Graphics.cpp index b55c377..5fec4fa 100644 --- a/Juliet/src/Graphics/Graphics.cpp +++ b/Juliet/src/Graphics/Graphics.cpp @@ -1,11 +1,10 @@ #include #include +#include #include #include #include #include -#include - namespace Juliet { @@ -63,7 +62,6 @@ namespace Juliet newDevice->Name = chosenFactory->Name; return newDevice; } - } return nullptr; } @@ -263,13 +261,14 @@ namespace Juliet commandListHeader->Device->SetStencilReference(commandList, reference); } - void SetIndexBuffer(NonNullPtr commandList, NonNullPtr buffer, IndexFormat format) + void SetIndexBuffer(NonNullPtr commandList, NonNullPtr buffer, IndexFormat format, + size_t indexCount, index_t offset) { auto* commandListHeader = reinterpret_cast(commandList.Get()); - + 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) { - commandListHeader->Device->DrawIndexedPrimitives(commandList, numIndices, numInstances, firstIndex, vertexOffset, firstInstance); + commandListHeader->Device->DrawIndexedPrimitives(commandList, numIndices, numInstances, firstIndex, + vertexOffset, firstInstance); } } - - - void SetPushConstants(NonNullPtr commandList, ShaderStage stage, uint32 rootParameterIndex, uint32 numConstants, const void* constants) { @@ -399,8 +396,7 @@ namespace Juliet headers->Device->CopyBuffer(commandList, dst, src, size, dstOffset, srcOffset); } - void CopyBufferToTexture(NonNullPtr commandList, NonNullPtr dst, - NonNullPtr src) + void CopyBufferToTexture(NonNullPtr commandList, NonNullPtr dst, NonNullPtr src) { auto* headers = reinterpret_cast(commandList.Get()); if (headers->Device->CopyBufferToTexture) @@ -409,7 +405,6 @@ namespace Juliet } } - void TransitionBufferToReadable(NonNullPtr commandList, NonNullPtr buffer) { auto* header = reinterpret_cast(commandList.Get()); @@ -426,7 +421,6 @@ namespace Juliet return device->GetDescriptorIndexTexture(device, texture); } - void DestroyGraphicsBuffer(NonNullPtr device, NonNullPtr buffer) { device->DestroyGraphicsBuffer(buffer); diff --git a/Juliet/src/Graphics/GraphicsDevice.h b/Juliet/src/Graphics/GraphicsDevice.h index 7ce668e..60d1617 100644 --- a/Juliet/src/Graphics/GraphicsDevice.h +++ b/Juliet/src/Graphics/GraphicsDevice.h @@ -68,7 +68,8 @@ namespace Juliet void (*SetScissorRect)(NonNullPtr commandList, const Rectangle& viewPort); void (*SetBlendConstants)(NonNullPtr commandList, FColor blendConstants); void (*SetStencilReference)(NonNullPtr commandList, uint8 reference); - void (*SetIndexBuffer)(NonNullPtr commandList, NonNullPtr buffer, IndexFormat format); + void (*SetIndexBuffer)(NonNullPtr commandList, NonNullPtr buffer, + IndexFormat format, size_t indexCount, index_t offset); void (*BindGraphicsPipeline)(NonNullPtr commandList, NonNullPtr graphicsPipeline); void (*DrawPrimitives)(NonNullPtr commandList, uint32 numVertices, uint32 numInstances, diff --git a/Juliet/src/Graphics/ImGuiRenderer.cpp b/Juliet/src/Graphics/ImGuiRenderer.cpp index 99fa22b..eebe4ea 100644 --- a/Juliet/src/Graphics/ImGuiRenderer.cpp +++ b/Juliet/src/Graphics/ImGuiRenderer.cpp @@ -223,9 +223,7 @@ namespace Juliet DestroyShader(device, g_ImGuiState.VertexShader); } if (g_ImGuiState.FragmentShader) - { - DestroyShader(device, g_ImGuiState.FragmentShader); } if (g_ImGuiState.FontTexture) @@ -344,7 +342,7 @@ namespace Juliet TransitionBufferToReadable(cmdList, currentFrame.VertexBuffer); // 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 BindGraphicsPipeline(renderPass, g_ImGuiState.Pipeline); @@ -379,7 +377,7 @@ namespace Juliet const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback != nullptr) { - // pcmd->UserCallback(cmd_list, pcmd); + pcmd->UserCallback(cmd_list, pcmd); } else { diff --git a/Juliet/src/Graphics/Mesh.cpp b/Juliet/src/Graphics/Mesh.cpp new file mode 100644 index 0000000..af5d3fc --- /dev/null +++ b/Juliet/src/Graphics/Mesh.cpp @@ -0,0 +1,99 @@ +#include + +#include +#include + +namespace Juliet +{ + Mesh* CreateCubeMesh(NonNullPtr arena) + { + Mesh* result = ArenaPushStruct(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(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(arena.Get(), indexCubeCount JULIET_DEBUG_PARAM("Indices")); + MemCopy(result->Indices, indices, sizeof(uint16) * indexCubeCount); + + return result; + } + + Mesh* CreateQuadMesh(NonNullPtr arena) + { + Mesh* result = ArenaPushStruct(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(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(arena.Get(), triIndexCount JULIET_DEBUG_PARAM("Indices")); + MemCopy(result->Indices, indices, sizeof(uint16) * triIndexCount); + + return result; + } + +} // namespace Juliet diff --git a/JulietApp/main.cpp b/JulietApp/main.cpp index 90d722d..e9aadf6 100644 --- a/JulietApp/main.cpp +++ b/JulietApp/main.cpp @@ -20,7 +20,9 @@ #include #include #include +#include #include +#include #include #ifdef JULIET_ENABLE_IMGUI @@ -63,12 +65,6 @@ namespace const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" }; } // namespace -struct Vertex -{ - float Position[2]; - float Color[4]; -}; - void JulietApplication::Init() { Log(LogLevel::Message, LogCategory::Tool, "Initializing Juliet Application..."); @@ -88,7 +84,6 @@ void JulietApplication::Init() if (Running) { AttachToWindow(GraphicsDevice, MainWindow); - { // Create graphics pipeline String entryPoint = WrapString("main"); @@ -146,12 +141,12 @@ void JulietApplication::Init() // Create Buffers - Using StructuredBuffer for bindless SRV access in shader BufferCreateInfo bufferCI = {}; - bufferCI.Size = 256; + bufferCI.Size = 1024; bufferCI.Usage = BufferUsage::StructuredBuffer; // SRV for ResourceDescriptorHeap access ConstantBuffer = CreateGraphicsBuffer(GraphicsDevice, bufferCI); TransferBufferCreateInfo transferCI = {}; - transferCI.Size = 256; + transferCI.Size = 1024; transferCI.Usage = TransferBufferUsage::Upload; 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) { DestroyShader(GraphicsDevice, vertexShader); @@ -209,6 +208,8 @@ void JulietApplication::Shutdown() { Log(LogLevel::Message, LogCategory::Tool, "Shutting down Juliet Application..."); + ArenaRelease(CubeArena); + if (GameCode.IsValid) { Game.Shutdown(); @@ -283,10 +284,10 @@ void JulietApplication::Update() ImGui::ShowDemoWindow(); #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 }, { 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, 0.0f, 10.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_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, 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, 1.0f }, { 0.0f, 0.0f, 1.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); @@ -362,28 +363,49 @@ void JulietApplication::Update() void JulietApplication::OnPreRender(CommandList* cmd) { + index_t index = 0; + // Buffer uploads if (ConstantBuffer && TransferBuffer) { void* ptr = MapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer); if (ptr) { - auto vertices = static_cast(ptr); + Vertex* vertices = static_cast(ptr); - // Triangle 1 - vertices[0] = { { -0.5f, -0.5f }, { 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[2] = { { 0.5f, -0.5f }, { 0.0f, 0.0f, 1.0f, 1.0f } }; // Blue + // // Triangle 1 + // vertices[index++] = { { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }; // Red + // vertices[index++] = { { 0.0f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }; // Green + // 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 - 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 - vertices[5] = { { 0.5f, 0.5f }, { 1.0f, 0.0f, 1.0f, 1.0f } }; // Magenta + if (CubeMesh) + { + CubeMesh->VertexOffset = index; + 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(~255); + + size_t indexSize = CubeMesh->IndexCount * sizeof(uint16); + + CubeMesh->IndexOffset = 0; + + uint8* ptrOneByte = static_cast(ptr); + uint16* dst = reinterpret_cast(ptrOneByte + CubeMesh->IndexByteOffset); + MemCopy(dst, CubeMesh->Indices, indexSize); + } UnmapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer); } - CopyBuffer(cmd, ConstantBuffer, TransferBuffer, 256); + CopyBuffer(cmd, ConstantBuffer, TransferBuffer, CubeMesh->IndexByteOffset + (CubeMesh->IndexCount * sizeof(uint16))); TransitionBufferToReadable(cmd, ConstantBuffer); } } @@ -396,14 +418,19 @@ void JulietApplication::OnRender(RenderPass* pass, CommandList* cmd) struct PushData { - float ViewProjection[16]; + Matrix ViewProjection; uint32 BufferIndex; - } pushData = {}; - pushData.BufferIndex = descriptorIndex; + } pushData = {}; + pushData.BufferIndex = descriptorIndex; + pushData.ViewProjection = Camera_GetViewProjectionMatrix(GetDebugCamera()); 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(CubeMesh->IndexCount), 1, 0, 0, 0); + + DrawIndexedPrimitives(pass, static_cast(CubeMesh->IndexCount), 1, + static_cast(CubeMesh->IndexOffset), static_cast(CubeMesh->VertexOffset), 0); } ColorTargetInfo JulietApplication::GetColorTargetInfo(Texture* swapchainTexture) @@ -428,18 +455,32 @@ DepthStencilTargetInfo* JulietApplication::GetDepthTargetInfo() Camera JulietApplication::GetDebugCamera() { - static float orbitTime = 0.0f; - orbitTime += 0.016f; + static float time = 0.0f; + 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 = {}; - 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.Up = { 0.0f, 0.0f, 1.0f }; cam.FOV = 1.047f; cam.AspectRatio = 1200.0f / 800.0f; cam.NearPlane = 0.1f; cam.FarPlane = 1000.0f; + return cam; } @@ -447,7 +488,6 @@ bool JulietApplication::IsRunning() { return Running; } - namespace { JulietApplication EditorApplication; diff --git a/JulietApp/main.h b/JulietApp/main.h index 3a8b170..233bc61 100644 --- a/JulietApp/main.h +++ b/JulietApp/main.h @@ -8,6 +8,7 @@ namespace Juliet { + struct Mesh; struct GraphicsTransferBuffer; struct GraphicsBuffer; struct GraphicsDevice; @@ -45,11 +46,14 @@ class JulietApplication : public Juliet::IApplication Juliet::GraphicsTransferBuffer* TransferBuffer = {}; Juliet::Texture* DepthBuffer = {}; + Juliet::Mesh* CubeMesh = {}; + Juliet::Arena* CubeArena = nullptr; + Juliet::Arena* GameArena = nullptr; Juliet::Arena* GameScratchArena = nullptr; - bool Running = false; int AutoCloseFrameCount = -1; + bool Running = false; }; JulietApplication& GetEditorApplication();