Meshrenderer first step. Adding logs to debug a weird crash since the add of mesh renderer and some clean up.
This commit is contained in:
@@ -227,6 +227,10 @@
|
||||
<CustomBuild Include="src\UnitTest\RunUnitTests.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\Graphics\MeshRenderer.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\Graphics\MeshRenderer.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{ab9c7e88-6c94-4f93-bc2a-7f5284b7d434}</ProjectGuid>
|
||||
|
||||
@@ -98,6 +98,34 @@ namespace Juliet
|
||||
}
|
||||
}
|
||||
|
||||
void PushBack(const Type* buffer, size_t amount)
|
||||
{
|
||||
Assert(Arena);
|
||||
|
||||
if (Count + amount > Capacity)
|
||||
{
|
||||
if (Capacity == 0 && Count + amount < ReserveSize)
|
||||
{
|
||||
Reserve(ReserveSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t newCapacity = Max(Capacity * 2, AlignPow2(Capacity + amount, AlignOf(Type)));
|
||||
Reserve(newCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
Type* dst = Data + Count;
|
||||
MemCopy(dst, buffer, amount * sizeof(Type));
|
||||
|
||||
if (Count == 0)
|
||||
{
|
||||
DataFirst = dst;
|
||||
}
|
||||
DataLast = dst + amount;
|
||||
Count += amount;
|
||||
}
|
||||
|
||||
void PushBack(const Type& value)
|
||||
{
|
||||
Assert(Arena);
|
||||
@@ -172,6 +200,8 @@ namespace Juliet
|
||||
Capacity = 0;
|
||||
}
|
||||
|
||||
bool IsEmpty() const { return Count == 0; }
|
||||
|
||||
// C++ Accessors for loop supports and Index based access
|
||||
Type& operator[](size_t index) { return DataFirst[index]; }
|
||||
const Type& operator[](size_t index) const { return DataFirst[index]; }
|
||||
|
||||
@@ -11,18 +11,10 @@ namespace Juliet
|
||||
|
||||
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
|
||||
|
||||
63
Juliet/include/Graphics/MeshRenderer.h
Normal file
63
Juliet/include/Graphics/MeshRenderer.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/Container/Vector.h>
|
||||
#include <Core/Math/Matrix.h>
|
||||
#include <Graphics/VertexData.h>
|
||||
#include <Juliet.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
struct GraphicsTransferBuffer;
|
||||
struct RenderPass;
|
||||
struct CommandList;
|
||||
struct GraphicsBuffer;
|
||||
struct Window;
|
||||
struct GraphicsPipeline;
|
||||
struct GraphicsDevice;
|
||||
struct Mesh;
|
||||
|
||||
using MeshID = index_t;
|
||||
|
||||
constexpr size_t kGeometryPage = Megabytes(64);
|
||||
constexpr size_t kIndexPage = Megabytes(32);
|
||||
constexpr size_t kDefaultMeshNumber = 500;
|
||||
constexpr size_t kDefaultVertexCount = 2'000'000; // Fit less than one geometry page
|
||||
constexpr size_t kDefaultIndexCount = 16'000'000; // Fit less than one index page
|
||||
|
||||
struct MeshRenderer
|
||||
{
|
||||
// Note we prevent realloc for now.
|
||||
VectorArena<Mesh, kDefaultMeshNumber, false> Meshes;
|
||||
VectorArena<Vertex, kDefaultVertexCount, false> Vertices;
|
||||
VectorArena<Index, kDefaultIndexCount, false> Indices;
|
||||
|
||||
GraphicsBuffer* VertexBuffer;
|
||||
GraphicsBuffer* IndexBuffer;
|
||||
GraphicsTransferBuffer* StreamCopyBuffer;
|
||||
GraphicsTransferBuffer* LoadCopyBuffer;
|
||||
|
||||
GraphicsDevice* Device;
|
||||
GraphicsPipeline* Pipeline;
|
||||
};
|
||||
|
||||
struct PushData
|
||||
{
|
||||
Matrix ViewProjection;
|
||||
uint32 BufferIndex;
|
||||
};
|
||||
|
||||
[[nodiscard]] JULIET_API bool InitializeMeshRenderer(NonNullPtr<Arena> arena, NonNullPtr<GraphicsDevice> device,
|
||||
NonNullPtr<Window> window);
|
||||
JULIET_API void ShutdownMeshRenderer();
|
||||
JULIET_API void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList);
|
||||
JULIET_API void RenderMeshes(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, PushData& pushData);
|
||||
|
||||
// Utils
|
||||
[[nodiscard]] JULIET_API MeshID AddCube();
|
||||
[[nodiscard]] JULIET_API MeshID AddQuad();
|
||||
|
||||
#if ALLOW_SHADER_HOT_RELOAD
|
||||
JULIET_API void ReloadMeshRendererShaders();
|
||||
#endif
|
||||
|
||||
} // namespace Juliet
|
||||
@@ -7,4 +7,6 @@ namespace Juliet
|
||||
float Position[3];
|
||||
float Color[4];
|
||||
};
|
||||
|
||||
using Index = uint16;
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -42,15 +42,15 @@ namespace Juliet
|
||||
#ifdef JULIET_ENABLE_IMGUI
|
||||
if (NonNullPtr window = EngineInstance.Application->GetPlatformWindow())
|
||||
{
|
||||
ImGuiService::Initialize(window);
|
||||
ImGui::SetCurrentContext(ImGuiService::GetContext());
|
||||
// ImGuiService::Initialize(window);
|
||||
// ImGui::SetCurrentContext(ImGuiService::GetContext());
|
||||
|
||||
if (device)
|
||||
{
|
||||
ImGuiRenderer_Initialize(device);
|
||||
// ImGuiRenderer_Initialize(device);
|
||||
|
||||
// Run Unit Tests automatically
|
||||
ImGuiService::RunTests();
|
||||
// ImGuiService::RunTests();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -64,9 +64,9 @@ namespace Juliet
|
||||
#ifdef JULIET_ENABLE_IMGUI
|
||||
if (device)
|
||||
{
|
||||
ImGuiRenderer_Shutdown(device);
|
||||
// ImGuiRenderer_Shutdown(device);
|
||||
}
|
||||
ImGuiService::Shutdown();
|
||||
// ImGuiService::Shutdown();
|
||||
#endif
|
||||
|
||||
// DebugDisplay system
|
||||
@@ -107,7 +107,7 @@ namespace Juliet
|
||||
EngineInstance.Application->OnPreRender(cmdList);
|
||||
|
||||
// Prepare debug display data (before render pass)
|
||||
DebugDisplay_Prepare(cmdList);
|
||||
// DebugDisplay_Prepare(cmdList);
|
||||
|
||||
// Get render targets from application
|
||||
ColorTargetInfo colorInfo = EngineInstance.Application->GetColorTargetInfo(swapChainTexture);
|
||||
@@ -119,12 +119,12 @@ namespace Juliet
|
||||
EngineInstance.Application->OnRender(pass, cmdList);
|
||||
|
||||
// Debug display flush (inside render pass)
|
||||
Camera debugCamera = EngineInstance.Application->GetDebugCamera();
|
||||
DebugDisplay_Flush(cmdList, pass, debugCamera);
|
||||
// Camera debugCamera = EngineInstance.Application->GetDebugCamera();
|
||||
// DebugDisplay_Flush(cmdList, pass, debugCamera);
|
||||
|
||||
#ifdef JULIET_ENABLE_IMGUI
|
||||
// ImGui rendering (always last before EndRenderPass)
|
||||
ImGuiRenderer_Render(cmdList, pass);
|
||||
// ImGuiRenderer_Render(cmdList, pass);
|
||||
#endif
|
||||
|
||||
EndRenderPass(pass);
|
||||
@@ -178,7 +178,7 @@ namespace Juliet
|
||||
while (EngineInstance.Application->IsRunning())
|
||||
{
|
||||
#ifdef JULIET_ENABLE_IMGUI
|
||||
ImGuiRenderer_NewFrame();
|
||||
// ImGuiRenderer_NewFrame();
|
||||
#endif
|
||||
|
||||
// Logic tick
|
||||
|
||||
@@ -113,10 +113,10 @@ namespace Juliet::D3D12
|
||||
{
|
||||
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
||||
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||
}
|
||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -142,10 +142,10 @@ namespace Juliet::D3D12
|
||||
{
|
||||
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
||||
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||
}
|
||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +246,8 @@ namespace Juliet::D3D12
|
||||
d3d12Driver->GraphicsQueue->ExecuteCommandLists(1, ppCommandLists);
|
||||
|
||||
// Acquire a fence and set it to the in-flight fence
|
||||
d3d12CommandList->InFlightFence = Internal::AcquireFence(d3d12Driver);
|
||||
d3d12CommandList->InFlightFence =
|
||||
Internal::AcquireFence(d3d12Driver JULIET_DEBUG_PARAM(ConstString("SubmitCommandLists")));
|
||||
if (!d3d12CommandList->InFlightFence)
|
||||
{
|
||||
return false;
|
||||
@@ -487,7 +488,8 @@ namespace Juliet::D3D12
|
||||
// Release Fence if needed
|
||||
if (commandList->AutoReleaseFence)
|
||||
{
|
||||
ReleaseFence(driver.Get(), reinterpret_cast<Fence*>(commandList->InFlightFence));
|
||||
ReleaseFence(driver.Get(), reinterpret_cast<Fence*>(commandList->InFlightFence)
|
||||
JULIET_DEBUG_PARAM(ConstString("CleanCommandList")));
|
||||
commandList->InFlightFence = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -604,7 +604,8 @@ namespace Juliet::D3D12
|
||||
{
|
||||
if (windowData->InFlightFences[idx] != nullptr)
|
||||
{
|
||||
ReleaseFence(driver, windowData->InFlightFences[idx]);
|
||||
ReleaseFence(driver,
|
||||
windowData->InFlightFences[idx] JULIET_DEBUG_PARAM(ConstString("DeatchFromWindow")));
|
||||
windowData->InFlightFences[idx] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,8 @@ namespace Juliet::D3D12
|
||||
{
|
||||
// Wait until the fence for the frame is signaled.
|
||||
// In VSYNC this means waiting that the least recent presented frame is done
|
||||
if (!Wait(driver, true, &windowData->InFlightFences[windowData->WindowFrameCounter], 1))
|
||||
if (!Wait(driver, true, &windowData->InFlightFences[windowData->WindowFrameCounter],
|
||||
1 JULIET_DEBUG_PARAM(ConstString("AcquireSwapChainTexture"))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -155,7 +156,8 @@ namespace Juliet::D3D12
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseFence(driver, windowData->InFlightFences[windowData->WindowFrameCounter]);
|
||||
ReleaseFence(driver, windowData->InFlightFences[windowData->WindowFrameCounter] JULIET_DEBUG_PARAM(
|
||||
ConstString("AcquireSwapChainTexture")));
|
||||
windowData->InFlightFences[windowData->WindowFrameCounter] = nullptr;
|
||||
}
|
||||
|
||||
@@ -219,7 +221,8 @@ namespace Juliet::D3D12
|
||||
|
||||
if (windowData->InFlightFences[windowData->WindowFrameCounter] != nullptr)
|
||||
{
|
||||
if (!Wait(d3d12Driver, true, &windowData->InFlightFences[windowData->WindowFrameCounter], 1))
|
||||
if (!Wait(d3d12Driver, true, &windowData->InFlightFences[windowData->WindowFrameCounter],
|
||||
1 JULIET_DEBUG_PARAM(ConstString("WaitForSwapchain"))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -17,16 +17,21 @@ namespace Juliet::D3D12
|
||||
driver->AvailableFenceCapacity = driver->AvailableFenceCapacity * 2;
|
||||
driver->AvailableFences = static_cast<D3D12Fence**>(
|
||||
Realloc(driver->AvailableFences, sizeof(D3D12Fence*) * driver->AvailableFenceCapacity));
|
||||
|
||||
LogMessage(LogCategory::Core, "ReleaseFenceToPool With Realloc");
|
||||
}
|
||||
driver->AvailableFences[driver->AvailableFenceCount] = fence;
|
||||
driver->AvailableFenceCount += 1;
|
||||
|
||||
LogMessage(LogCategory::Core, "ReleaseFenceToPool %x fence. Handle %x | Event %x | Refcount %d",
|
||||
fence.Get(), fence->Handle, fence->Event, fence->ReferenceCount);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool WaitUntilGPUIsIdle(NonNullPtr<GPUDriver> driver)
|
||||
{
|
||||
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
||||
D3D12Fence* fence = Internal::AcquireFence(d3d12driver);
|
||||
D3D12Fence* fence = Internal::AcquireFence(d3d12driver JULIET_DEBUG_PARAM(ConstString("WaitUntilGPUIsIdle")));
|
||||
if (!fence)
|
||||
{
|
||||
return false;
|
||||
@@ -56,7 +61,7 @@ namespace Juliet::D3D12
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseFence(driver, reinterpret_cast<Fence*>(fence));
|
||||
ReleaseFence(driver, reinterpret_cast<Fence*>(fence) JULIET_DEBUG_PARAM(ConstString("WaitUntilGPUIsIdle")));
|
||||
|
||||
bool result = true;
|
||||
|
||||
@@ -71,16 +76,17 @@ namespace Juliet::D3D12
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Wait(NonNullPtr<GPUDriver> driver, bool waitForAll, Fence* const* fences, uint32 numFences)
|
||||
bool Wait(NonNullPtr<GPUDriver> driver, bool waitForAll, Fence* const* fences, uint32 numFences JULIET_DEBUG_PARAM(String querier))
|
||||
{
|
||||
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
||||
|
||||
// TODO: use scratch allocator for alloca (stack alloc)
|
||||
auto events = static_cast<HANDLE*>(alloca(sizeof(HANDLE) * numFences));
|
||||
HANDLE* events = static_cast<HANDLE*>(alloca(sizeof(HANDLE) * numFences));
|
||||
MemoryZero(events, sizeof(HANDLE) * numFences);
|
||||
|
||||
for (uint32 i = 0; i < numFences; ++i)
|
||||
{
|
||||
auto fence = reinterpret_cast<D3D12Fence*>(fences[i]);
|
||||
D3D12Fence* fence = reinterpret_cast<D3D12Fence*>(fences[i]);
|
||||
|
||||
HRESULT res = fence->Handle->SetEventOnCompletion(D3D12_FENCE_SIGNAL_VALUE, fence->Event);
|
||||
if (FAILED(res))
|
||||
@@ -91,6 +97,13 @@ namespace Juliet::D3D12
|
||||
|
||||
events[i] = fence->Event;
|
||||
}
|
||||
LogMessage(LogCategory::Core, "Waiting for %d fences. Querier %s", numFences, CStr(querier));
|
||||
for (uint32 i = 0; i < numFences; ++i)
|
||||
{
|
||||
D3D12Fence* d3d12fence = reinterpret_cast<D3D12Fence*>(fences[i]);
|
||||
LogMessage(LogCategory::Core, "Waiting for %x fence. Handle %x | Event %x | Refcount %d", d3d12fence,
|
||||
d3d12fence->Handle, d3d12fence->Event, d3d12fence->ReferenceCount);
|
||||
}
|
||||
|
||||
DWORD waitResult = WaitForMultipleObjects(numFences, events, waitForAll, INFINITE);
|
||||
if (waitResult == WAIT_FAILED)
|
||||
@@ -122,11 +135,13 @@ namespace Juliet::D3D12
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence)
|
||||
void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence JULIET_DEBUG_PARAM(String querier))
|
||||
{
|
||||
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
||||
auto d3d12Fence = reinterpret_cast<D3D12Fence*>(fence.Get());
|
||||
|
||||
LogMessage(LogCategory::Core, "ReleaseFence Querier %s | %x fence. Handle %x | Event %x | Refcount %d",
|
||||
CStr(querier), d3d12Fence, d3d12Fence->Handle, d3d12Fence->Event, d3d12Fence->ReferenceCount);
|
||||
if (--d3d12Fence->ReferenceCount == 0)
|
||||
{
|
||||
ReleaseFenceToPool(d3d12driver, d3d12Fence);
|
||||
@@ -170,7 +185,7 @@ namespace Juliet::D3D12
|
||||
}
|
||||
}
|
||||
|
||||
D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver)
|
||||
D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver JULIET_DEBUG_PARAM(String querier))
|
||||
{
|
||||
D3D12Fence* fence;
|
||||
ID3D12Fence* handle;
|
||||
@@ -180,7 +195,7 @@ namespace Juliet::D3D12
|
||||
if (driver->AvailableFenceCount == 0)
|
||||
{
|
||||
HRESULT result = driver->D3D12Device->CreateFence(D3D12_FENCE_UNSIGNALED_VALUE, D3D12_FENCE_FLAG_NONE,
|
||||
IID_ID3D12Fence, reinterpret_cast<void**>(&handle));
|
||||
IID_ID3D12Fence, reinterpret_cast<void**>(&handle));
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver->D3D12Device, "Failed to create fence!", result);
|
||||
@@ -197,15 +212,22 @@ namespace Juliet::D3D12
|
||||
fence->Handle = handle;
|
||||
fence->Event = CreateEvent(nullptr, false, false, nullptr);
|
||||
fence->ReferenceCount = 0;
|
||||
LogMessage(LogCategory::Core, "Acquire Querier %s | Setting Signal to 0 NEW fence", CStr(querier));
|
||||
}
|
||||
else
|
||||
{
|
||||
fence = driver->AvailableFences[driver->AvailableFenceCount - 1];
|
||||
driver->AvailableFenceCount -= 1;
|
||||
fence->Handle->Signal(D3D12_FENCE_UNSIGNALED_VALUE);
|
||||
LogMessage(LogCategory::Core, "Acquire Querier %s | Setting Signal to 0, RECYCLING", CStr(querier));
|
||||
}
|
||||
|
||||
fence->ReferenceCount += 1;
|
||||
Assert(fence->ReferenceCount == 1);
|
||||
|
||||
LogMessage(LogCategory::Core, "Acquire Querier %s | %x fence. Handle %x | Event %x | Refcount %d",
|
||||
CStr(querier), fence, fence->Handle, fence->Event, fence->ReferenceCount);
|
||||
|
||||
return fence;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,10 @@ namespace Juliet::D3D12
|
||||
};
|
||||
|
||||
extern bool WaitUntilGPUIsIdle(NonNullPtr<GPUDriver> driver);
|
||||
extern bool Wait(NonNullPtr<GPUDriver> driver, bool waitForAll, Fence* const* fences, uint32 numFences);
|
||||
extern bool Wait(NonNullPtr<GPUDriver> driver, bool waitForAll, Fence* const* fences,
|
||||
uint32 numFences JULIET_DEBUG_PARAM(String querier));
|
||||
extern bool QueryFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
extern void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
extern void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence JULIET_DEBUG_PARAM(String querier));
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
@@ -36,7 +37,7 @@ namespace Juliet::D3D12
|
||||
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource,
|
||||
uint32 subresourceIndex, bool needsUavBarrier);
|
||||
|
||||
extern D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver);
|
||||
extern D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver JULIET_DEBUG_PARAM(String querier));
|
||||
extern void DestroyFence(NonNullPtr<D3D12Fence> fence);
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -1,124 +1,124 @@
|
||||
#include <algorithm>
|
||||
#include <Core/Common/EnumUtils.h>
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Logging/LogTypes.h>
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Graphics/D3D12/D3D12CommandList.h>
|
||||
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
|
||||
#include <Graphics/D3D12/D3D12Synchronization.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
|
||||
{
|
||||
DXGI_FORMAT JulietToD3D12_TextureFormat[] = {
|
||||
DXGI_FORMAT_UNKNOWN, // INVALID
|
||||
DXGI_FORMAT_A8_UNORM, // A8_UNORM
|
||||
DXGI_FORMAT_R8_UNORM, // R8_UNORM
|
||||
DXGI_FORMAT_R8G8_UNORM, // R8G8_UNORM
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM
|
||||
DXGI_FORMAT_R16_UNORM, // R16_UNORM
|
||||
DXGI_FORMAT_R16G16_UNORM, // R16G16_UNORM
|
||||
DXGI_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM, // R10G10B10A2_UNORM
|
||||
DXGI_FORMAT_B5G6R5_UNORM, // B5G6R5_UNORM
|
||||
DXGI_FORMAT_B5G5R5A1_UNORM, // B5G5R5A1_UNORM
|
||||
DXGI_FORMAT_B4G4R4A4_UNORM, // B4G4R4A4_UNORM
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM
|
||||
DXGI_FORMAT_BC1_UNORM, // BC1_UNORM
|
||||
DXGI_FORMAT_BC2_UNORM, // BC2_UNORM
|
||||
DXGI_FORMAT_BC3_UNORM, // BC3_UNORM
|
||||
DXGI_FORMAT_BC4_UNORM, // BC4_UNORM
|
||||
DXGI_FORMAT_BC5_UNORM, // BC5_UNORM
|
||||
DXGI_FORMAT_BC7_UNORM, // BC7_UNORM
|
||||
DXGI_FORMAT_BC6H_SF16, // BC6H_FLOAT
|
||||
DXGI_FORMAT_BC6H_UF16, // BC6H_UFLOAT
|
||||
DXGI_FORMAT_R8_SNORM, // R8_SNORM
|
||||
DXGI_FORMAT_R8G8_SNORM, // R8G8_SNORM
|
||||
DXGI_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM
|
||||
DXGI_FORMAT_R16_SNORM, // R16_SNORM
|
||||
DXGI_FORMAT_R16G16_SNORM, // R16G16_SNORM
|
||||
DXGI_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM
|
||||
DXGI_FORMAT_R16_FLOAT, // R16_FLOAT
|
||||
DXGI_FORMAT_R16G16_FLOAT, // R16G16_FLOAT
|
||||
DXGI_FORMAT_R16G16B16A16_FLOAT, // R16G16B16A16_FLOAT
|
||||
DXGI_FORMAT_R32_FLOAT, // R32_FLOAT
|
||||
DXGI_FORMAT_R32G32_FLOAT, // R32G32_FLOAT
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT, // R32G32B32A32_FLOAT
|
||||
DXGI_FORMAT_R11G11B10_FLOAT, // R11G11B10_UFLOAT
|
||||
DXGI_FORMAT_R8_UINT, // R8_UINT
|
||||
DXGI_FORMAT_R8G8_UINT, // R8G8_UINT
|
||||
DXGI_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT
|
||||
DXGI_FORMAT_R16_UINT, // R16_UINT
|
||||
DXGI_FORMAT_R16G16_UINT, // R16G16_UINT
|
||||
DXGI_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT
|
||||
DXGI_FORMAT_R32_UINT, // R32_UINT
|
||||
DXGI_FORMAT_R32G32_UINT, // R32G32_UINT
|
||||
DXGI_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT
|
||||
DXGI_FORMAT_R8_SINT, // R8_INT
|
||||
DXGI_FORMAT_R8G8_SINT, // R8G8_INT
|
||||
DXGI_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT
|
||||
DXGI_FORMAT_R16_SINT, // R16_INT
|
||||
DXGI_FORMAT_R16G16_SINT, // R16G16_INT
|
||||
DXGI_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT
|
||||
DXGI_FORMAT_R32_SINT, // R32_INT
|
||||
DXGI_FORMAT_R32G32_SINT, // R32G32_INT
|
||||
DXGI_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, // R8G8B8A8_UNORM_SRGB
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, // B8G8R8A8_UNORM_SRGB
|
||||
DXGI_FORMAT_BC1_UNORM_SRGB, // BC1_UNORM_SRGB
|
||||
DXGI_FORMAT_BC2_UNORM_SRGB, // BC2_UNORM_SRGB
|
||||
DXGI_FORMAT_BC3_UNORM_SRGB, // BC3_UNORM_SRGB
|
||||
DXGI_FORMAT_BC7_UNORM_SRGB, // BC7_UNORM_SRGB
|
||||
DXGI_FORMAT_R16_TYPELESS, // D16_UNORM
|
||||
DXGI_FORMAT_R24G8_TYPELESS, // D24_UNORM
|
||||
DXGI_FORMAT_R32_TYPELESS, // D32_FLOAT
|
||||
DXGI_FORMAT_R24G8_TYPELESS, // D24_UNORM_S8_UINT
|
||||
DXGI_FORMAT_R32G8X24_TYPELESS, // D32_FLOAT_S8_UINT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // INVALID
|
||||
DXGI_FORMAT_A8_UNORM, // A8_UNORM
|
||||
DXGI_FORMAT_R8_UNORM, // R8_UNORM
|
||||
DXGI_FORMAT_R8G8_UNORM, // R8G8_UNORM
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM
|
||||
DXGI_FORMAT_R16_UNORM, // R16_UNORM
|
||||
DXGI_FORMAT_R16G16_UNORM, // R16G16_UNORM
|
||||
DXGI_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM, // R10G10B10A2_UNORM
|
||||
DXGI_FORMAT_B5G6R5_UNORM, // B5G6R5_UNORM
|
||||
DXGI_FORMAT_B5G5R5A1_UNORM, // B5G5R5A1_UNORM
|
||||
DXGI_FORMAT_B4G4R4A4_UNORM, // B4G4R4A4_UNORM
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM
|
||||
DXGI_FORMAT_BC1_UNORM, // BC1_UNORM
|
||||
DXGI_FORMAT_BC2_UNORM, // BC2_UNORM
|
||||
DXGI_FORMAT_BC3_UNORM, // BC3_UNORM
|
||||
DXGI_FORMAT_BC4_UNORM, // BC4_UNORM
|
||||
DXGI_FORMAT_BC5_UNORM, // BC5_UNORM
|
||||
DXGI_FORMAT_BC7_UNORM, // BC7_UNORM
|
||||
DXGI_FORMAT_BC6H_SF16, // BC6H_FLOAT
|
||||
DXGI_FORMAT_BC6H_UF16, // BC6H_UFLOAT
|
||||
DXGI_FORMAT_R8_SNORM, // R8_SNORM
|
||||
DXGI_FORMAT_R8G8_SNORM, // R8G8_SNORM
|
||||
DXGI_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM
|
||||
DXGI_FORMAT_R16_SNORM, // R16_SNORM
|
||||
DXGI_FORMAT_R16G16_SNORM, // R16G16_SNORM
|
||||
DXGI_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM
|
||||
DXGI_FORMAT_R16_FLOAT, // R16_FLOAT
|
||||
DXGI_FORMAT_R16G16_FLOAT, // R16G16_FLOAT
|
||||
DXGI_FORMAT_R16G16B16A16_FLOAT, // R16G16B16A16_FLOAT
|
||||
DXGI_FORMAT_R32_FLOAT, // R32_FLOAT
|
||||
DXGI_FORMAT_R32G32_FLOAT, // R32G32_FLOAT
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT, // R32G32B32A32_FLOAT
|
||||
DXGI_FORMAT_R11G11B10_FLOAT, // R11G11B10_UFLOAT
|
||||
DXGI_FORMAT_R8_UINT, // R8_UINT
|
||||
DXGI_FORMAT_R8G8_UINT, // R8G8_UINT
|
||||
DXGI_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT
|
||||
DXGI_FORMAT_R16_UINT, // R16_UINT
|
||||
DXGI_FORMAT_R16G16_UINT, // R16G16_UINT
|
||||
DXGI_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT
|
||||
DXGI_FORMAT_R32_UINT, // R32_UINT
|
||||
DXGI_FORMAT_R32G32_UINT, // R32G32_UINT
|
||||
DXGI_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT
|
||||
DXGI_FORMAT_R8_SINT, // R8_INT
|
||||
DXGI_FORMAT_R8G8_SINT, // R8G8_INT
|
||||
DXGI_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT
|
||||
DXGI_FORMAT_R16_SINT, // R16_INT
|
||||
DXGI_FORMAT_R16G16_SINT, // R16G16_INT
|
||||
DXGI_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT
|
||||
DXGI_FORMAT_R32_SINT, // R32_INT
|
||||
DXGI_FORMAT_R32G32_SINT, // R32G32_INT
|
||||
DXGI_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, // R8G8B8A8_UNORM_SRGB
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, // B8G8R8A8_UNORM_SRGB
|
||||
DXGI_FORMAT_BC1_UNORM_SRGB, // BC1_UNORM_SRGB
|
||||
DXGI_FORMAT_BC2_UNORM_SRGB, // BC2_UNORM_SRGB
|
||||
DXGI_FORMAT_BC3_UNORM_SRGB, // BC3_UNORM_SRGB
|
||||
DXGI_FORMAT_BC7_UNORM_SRGB, // BC7_UNORM_SRGB
|
||||
DXGI_FORMAT_R16_TYPELESS, // D16_UNORM
|
||||
DXGI_FORMAT_R24G8_TYPELESS, // D24_UNORM
|
||||
DXGI_FORMAT_R32_TYPELESS, // D32_FLOAT
|
||||
DXGI_FORMAT_R24G8_TYPELESS, // D24_UNORM_S8_UINT
|
||||
DXGI_FORMAT_R32G8X24_TYPELESS, // D32_FLOAT_S8_UINT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
|
||||
};
|
||||
static_assert(sizeof(JulietToD3D12_TextureFormat) / sizeof(JulietToD3D12_TextureFormat[0]) ==
|
||||
ToUnderlying(TextureFormat::Count));
|
||||
@@ -375,13 +375,9 @@ namespace Juliet::D3D12
|
||||
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_CubeArray: desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; break;
|
||||
case TextureType::Texture_3D:
|
||||
case TextureType::Texture_3DArray:
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
|
||||
break;
|
||||
case TextureType::Texture_3DArray: desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D; break;
|
||||
}
|
||||
|
||||
desc.Alignment = 0;
|
||||
@@ -396,17 +392,27 @@ namespace Juliet::D3D12
|
||||
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;
|
||||
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProps.CreationNodeMask = 0; // We don't do multi-adapter operation
|
||||
heapProps.VisibleNodeMask = 0; // We don't do multi-adapter operation
|
||||
|
||||
ID3D12Resource* resource = nullptr;
|
||||
D3D12_CLEAR_VALUE clearValue = {};
|
||||
ID3D12Resource* resource = nullptr;
|
||||
D3D12_CLEAR_VALUE clearValue = {};
|
||||
D3D12_CLEAR_VALUE* pClearValue = nullptr;
|
||||
|
||||
if (desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
|
||||
@@ -426,9 +432,10 @@ namespace Juliet::D3D12
|
||||
pClearValue = &clearValue;
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_STATES initialState = GetDefaultTextureResourceState(createInfo.Flags);
|
||||
HRESULT hr = d3d12Driver->D3D12Device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_COMMON, pClearValue, IID_ID3D12Resource,
|
||||
reinterpret_cast<void**>(&resource));
|
||||
initialState, pClearValue, IID_ID3D12Resource,
|
||||
reinterpret_cast<void**>(&resource));
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
@@ -451,10 +458,11 @@ namespace Juliet::D3D12
|
||||
texture->Resource = resource;
|
||||
texture->ReferenceCount = 1;
|
||||
|
||||
uint32 numLayers = std::max<uint32>(1, createInfo.LayerCount);
|
||||
uint32 numMips = std::max<uint32>(1, createInfo.MipLevelCount);
|
||||
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)));
|
||||
texture->Subresources =
|
||||
static_cast<D3D12TextureSubresource*>(Calloc(texture->SubresourceCount, sizeof(D3D12TextureSubresource)));
|
||||
|
||||
for (uint32 layer = 0; layer < numLayers; ++layer)
|
||||
{
|
||||
@@ -499,14 +507,14 @@ namespace Juliet::D3D12
|
||||
Internal::D3D12Descriptor descriptor;
|
||||
if (Internal::AssignDescriptor(d3d12Driver->BindlessDescriptorHeap, descriptor))
|
||||
{
|
||||
texture->SRVHandle = D3D12StagingDescriptor{};
|
||||
texture->SRVHandle = D3D12StagingDescriptor{};
|
||||
texture->SRVHandle.CpuHandleIndex = descriptor.Index;
|
||||
texture->SRVHandle.CpuHandle = descriptor.CpuHandle;
|
||||
texture->SRVHandle.Heap = descriptor.Heap;
|
||||
texture->SRVHandle.CpuHandle = descriptor.CpuHandle;
|
||||
texture->SRVHandle.Heap = descriptor.Heap;
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||
srvDesc.Format = desc.Format;
|
||||
|
||||
srvDesc.Format = desc.Format;
|
||||
|
||||
// Fix SRV format for Depth Buffers (TypeLess -> Typed)
|
||||
if (createInfo.Format == TextureFormat::D32_FLOAT)
|
||||
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
|
||||
@@ -517,11 +525,11 @@ namespace Juliet::D3D12
|
||||
else if (createInfo.Format == TextureFormat::D32_FLOAT_S8_UINT)
|
||||
srvDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
srvDesc.Texture2D.MipLevels = numMips;
|
||||
srvDesc.Texture2D.PlaneSlice = 0;
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
srvDesc.Texture2D.MipLevels = numMips;
|
||||
srvDesc.Texture2D.PlaneSlice = 0;
|
||||
srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||
|
||||
d3d12Driver->D3D12Device->CreateShaderResourceView(resource, &srvDesc, descriptor.CpuHandle);
|
||||
@@ -529,7 +537,6 @@ namespace Juliet::D3D12
|
||||
}
|
||||
|
||||
return reinterpret_cast<Texture*>(textureContainer);
|
||||
|
||||
}
|
||||
|
||||
void DestroyTexture(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture)
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace Juliet
|
||||
// Fences
|
||||
bool (*WaitUntilGPUIsIdle)(NonNullPtr<GPUDriver> driver);
|
||||
bool (*QueryFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
void (*ReleaseFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
void (*ReleaseFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence JULIET_DEBUG_PARAM(String querier));
|
||||
|
||||
// Shaders
|
||||
Shader* (*CreateShader)(NonNullPtr<GPUDriver> driver, ByteBuffer shaderByteCode, ShaderCreateInfo& shaderCreateInfo);
|
||||
|
||||
@@ -5,95 +5,5 @@
|
||||
|
||||
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
|
||||
|
||||
315
Juliet/src/Graphics/MeshRenderer.cpp
Normal file
315
Juliet/src/Graphics/MeshRenderer.cpp
Normal file
@@ -0,0 +1,315 @@
|
||||
#include <Graphics/MeshRenderer.h>
|
||||
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Logging/LogTypes.h>
|
||||
#include <Core/Math/Matrix.h>
|
||||
#include <Graphics/GraphicsDevice.h>
|
||||
#include <Graphics/Mesh.h>
|
||||
#include <Graphics/VertexData.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
namespace
|
||||
{
|
||||
MeshRenderer g_MeshRenderer;
|
||||
} // namespace
|
||||
|
||||
bool InitializeMeshRenderer(NonNullPtr<Arena> arena, NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
|
||||
{
|
||||
(void)arena;
|
||||
(void)device;
|
||||
(void)window;
|
||||
return true;
|
||||
// bool result = true;
|
||||
//
|
||||
// g_MeshRenderer.Meshes.Create(arena JULIET_DEBUG_PARAM("Meshes"));
|
||||
// g_MeshRenderer.Vertices.Create(arena JULIET_DEBUG_PARAM("Vertices"));
|
||||
// g_MeshRenderer.Indices.Create(arena JULIET_DEBUG_PARAM("Indices"));
|
||||
//
|
||||
// GraphicsDevice* graphicsDevice = g_MeshRenderer.Device = device.Get();
|
||||
//
|
||||
// // Create graphics pipeline
|
||||
// String entryPoint = WrapString("main");
|
||||
// ShaderCreateInfo shaderCI = {};
|
||||
// shaderCI.EntryPoint = entryPoint;
|
||||
//
|
||||
// // TODO: Assets management that handles path to assets or something.
|
||||
// String shaderPath = WrapString("../../Assets/compiled/Triangle.vert.dxil");
|
||||
// shaderCI.Stage = ShaderStage::Vertex;
|
||||
// Shader* vertexShader = CreateShader(graphicsDevice, shaderPath, shaderCI);
|
||||
//
|
||||
// shaderPath = WrapString("../../Assets/compiled/SolidColor.frag.dxil");
|
||||
// shaderCI.Stage = ShaderStage::Fragment;
|
||||
// Shader* fragmentShader = CreateShader(graphicsDevice, shaderPath, shaderCI);
|
||||
//
|
||||
// ColorTargetDescription colorTargetDescription = {};
|
||||
// colorTargetDescription.Format = GetSwapChainTextureFormat(graphicsDevice, window);
|
||||
//
|
||||
// GraphicsPipelineCreateInfo pipelineCI = {};
|
||||
// pipelineCI.VertexShader = vertexShader;
|
||||
// pipelineCI.FragmentShader = fragmentShader;
|
||||
// pipelineCI.PrimitiveType = PrimitiveType::TriangleList;
|
||||
// pipelineCI.TargetInfo = { .ColorTargetDescriptions = &colorTargetDescription,
|
||||
// .NumColorTargets = 1,
|
||||
// .DepthStencilFormat = TextureFormat::D32_FLOAT,
|
||||
// .HasDepthStencilTarget = true };
|
||||
// pipelineCI.RasterizerState.FillMode = FillMode::Solid;
|
||||
// pipelineCI.DepthStencilState.EnableDepthTest = true;
|
||||
// pipelineCI.DepthStencilState.EnableDepthWrite = true;
|
||||
// pipelineCI.DepthStencilState.CompareOperation = CompareOperation::Less;
|
||||
//
|
||||
// g_MeshRenderer.Pipeline = CreateGraphicsPipeline(graphicsDevice, pipelineCI);
|
||||
// if (g_MeshRenderer.Pipeline == nullptr)
|
||||
// {
|
||||
// LogError(LogCategory::Graphics, "Failed to create graphics pipeline!");
|
||||
// result = false;
|
||||
// }
|
||||
//
|
||||
// // Create the vertex and index buffers
|
||||
// BufferCreateInfo vertexBufferCI = {};
|
||||
// vertexBufferCI.Size = kGeometryPage;
|
||||
// vertexBufferCI.Usage = BufferUsage::VertexBuffer;
|
||||
// g_MeshRenderer.VertexBuffer = CreateGraphicsBuffer(graphicsDevice, vertexBufferCI);
|
||||
//
|
||||
// BufferCreateInfo indexBufferCI = {};
|
||||
// indexBufferCI.Size = kIndexPage;
|
||||
// indexBufferCI.Usage = BufferUsage::IndexBuffer;
|
||||
// g_MeshRenderer.IndexBuffer = CreateGraphicsBuffer(graphicsDevice, indexBufferCI);
|
||||
//
|
||||
// if (vertexShader)
|
||||
// {
|
||||
// DestroyShader(graphicsDevice, vertexShader);
|
||||
// }
|
||||
// if (fragmentShader)
|
||||
// {
|
||||
// DestroyShader(graphicsDevice, fragmentShader);
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
}
|
||||
|
||||
void ShutdownMeshRenderer()
|
||||
{
|
||||
return;
|
||||
// DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.IndexBuffer);
|
||||
// DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
|
||||
//
|
||||
// g_MeshRenderer.Indices.Destroy();
|
||||
// g_MeshRenderer.Vertices.Destroy();
|
||||
// g_MeshRenderer.Meshes.Destroy();
|
||||
}
|
||||
|
||||
void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList)
|
||||
{
|
||||
if (g_MeshRenderer.Meshes.IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Loading everything in one go.
|
||||
// Destroy the buffer at the end
|
||||
|
||||
TransferBufferCreateInfo uploadBCI = {};
|
||||
uploadBCI.Usage = TransferBufferUsage::Upload;
|
||||
uploadBCI.Size = kGeometryPage + kIndexPage;
|
||||
g_MeshRenderer.LoadCopyBuffer = CreateGraphicsTransferBuffer(g_MeshRenderer.Device, uploadBCI);
|
||||
|
||||
void* map = MapGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
|
||||
|
||||
Vertex* vertices = g_MeshRenderer.Vertices.Data;
|
||||
if (!vertices)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Index* indices = g_MeshRenderer.Indices.Data;
|
||||
if (!indices)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy all meshes! This supports only one page for now
|
||||
// Copy ALL Vertices in one block
|
||||
size_t totalVertexBytes = g_MeshRenderer.Vertices.Count * sizeof(Vertex);
|
||||
MemCopy(map, g_MeshRenderer.Vertices.Data, totalVertexBytes);
|
||||
|
||||
// Copy ALL Indices in one block
|
||||
size_t indexOfByteOffset = (kGeometryPage + 255) & static_cast<size_t>(~255);
|
||||
uint8* ptrOneByte = static_cast<uint8*>(map);
|
||||
size_t totalIndexBytes = g_MeshRenderer.Indices.Count * sizeof(Index);
|
||||
|
||||
MemCopy(ptrOneByte + indexOfByteOffset, g_MeshRenderer.Indices.Data, totalIndexBytes);
|
||||
|
||||
// index_t index = 0;
|
||||
// for (Mesh& mesh : g_MeshRenderer.Meshes)
|
||||
// {
|
||||
// // Vertices first
|
||||
// Vertex* mapVertices = static_cast<Vertex*>(map);
|
||||
// MemCopy(mapVertices + index, vertices + mesh.VertexOffset, mesh.VertexCount * sizeOfVertex);
|
||||
//
|
||||
// // Indices next
|
||||
// uint8* ptrOneByte = static_cast<uint8*>(map);
|
||||
// uint16* dst = reinterpret_cast<uint16*>(ptrOneByte + indexOfByteOffset);
|
||||
// MemCopy(dst, indices, mesh.IndexCount * sizeOfIndex);
|
||||
//
|
||||
// ++index;
|
||||
// }
|
||||
|
||||
CopyBuffer(cmdList, g_MeshRenderer.VertexBuffer, g_MeshRenderer.LoadCopyBuffer, totalVertexBytes, 0, 0);
|
||||
CopyBuffer(cmdList, g_MeshRenderer.IndexBuffer, g_MeshRenderer.LoadCopyBuffer, totalIndexBytes, 0, indexOfByteOffset);
|
||||
|
||||
// Transition vertex buffer to SRV state (this barrier waits for copy to complete)
|
||||
TransitionBufferToReadable(cmdList, g_MeshRenderer.VertexBuffer);
|
||||
TransitionBufferToReadable(cmdList, g_MeshRenderer.IndexBuffer);
|
||||
}
|
||||
|
||||
void RenderMeshes(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, PushData& pushData)
|
||||
{
|
||||
// First destroy any buffer that needs to be
|
||||
if (g_MeshRenderer.LoadCopyBuffer)
|
||||
{
|
||||
WaitUntilGPUIsIdle(g_MeshRenderer.Device);
|
||||
UnmapGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
|
||||
DestroyGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
|
||||
g_MeshRenderer.LoadCopyBuffer = nullptr;
|
||||
}
|
||||
|
||||
BindGraphicsPipeline(pass, g_MeshRenderer.Pipeline);
|
||||
|
||||
uint32 vertexDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
|
||||
|
||||
pushData.BufferIndex = vertexDescriptorIndex;
|
||||
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
|
||||
|
||||
for (Mesh& mesh : g_MeshRenderer.Meshes)
|
||||
{
|
||||
SetIndexBuffer(cmdList, g_MeshRenderer.IndexBuffer, IndexFormat::UInt16, mesh.IndexCount, 0);
|
||||
// DrawIndexedPrimitives(pass, static_cast<uint32>(mesh.IndexCount), 1, static_cast<uint32>(mesh.IndexOffset),
|
||||
// static_cast<uint32>(mesh.VertexOffset), 0);
|
||||
}
|
||||
}
|
||||
|
||||
MeshID AddCube()
|
||||
{
|
||||
Mesh result = {};
|
||||
|
||||
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.VertexOffset = g_MeshRenderer.Vertices.Count;
|
||||
g_MeshRenderer.Vertices.PushBack(vertexData, 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.IndexOffset = g_MeshRenderer.Indices.Count;
|
||||
g_MeshRenderer.Indices.PushBack(indices, indexCubeCount);
|
||||
|
||||
MeshID id = g_MeshRenderer.Meshes.Count;
|
||||
g_MeshRenderer.Meshes.PushBack(result);
|
||||
return id;
|
||||
}
|
||||
|
||||
MeshID AddQuad()
|
||||
{
|
||||
// Mesh result = {};
|
||||
|
||||
// // 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);
|
||||
//
|
||||
// g_MeshRenderer.Meshes.PushBack(std::move(result));
|
||||
return g_MeshRenderer.Meshes.Count - 1;
|
||||
}
|
||||
|
||||
#if ALLOW_SHADER_HOT_RELOAD
|
||||
void ReloadMeshRendererShaders()
|
||||
{
|
||||
auto* pipeline = g_MeshRenderer.Pipeline;
|
||||
auto* device = g_MeshRenderer.Device;
|
||||
|
||||
String entryPoint = WrapString("main");
|
||||
ShaderCreateInfo shaderCI = {};
|
||||
shaderCI.EntryPoint = entryPoint;
|
||||
String shaderPath = WrapString("../../Assets/compiled/Triangle.vert.dxil");
|
||||
shaderCI.Stage = ShaderStage::Vertex;
|
||||
Shader* vertexShader = CreateShader(device, shaderPath, shaderCI);
|
||||
|
||||
shaderPath = WrapString("../../Assets/compiled/SolidColor.frag.dxil");
|
||||
shaderCI.Stage = ShaderStage::Fragment;
|
||||
Shader* fragmentShader = CreateShader(device, shaderPath, shaderCI);
|
||||
|
||||
UpdateGraphicsPipelineShaders(device, pipeline, vertexShader, fragmentShader);
|
||||
|
||||
if (vertexShader)
|
||||
{
|
||||
DestroyShader(device, vertexShader);
|
||||
}
|
||||
if (fragmentShader)
|
||||
{
|
||||
DestroyShader(device, fragmentShader);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // namespace Juliet
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <Graphics/GraphicsConfig.h>
|
||||
#include <Graphics/GraphicsPipeline.h>
|
||||
#include <Graphics/Mesh.h>
|
||||
#include <Graphics/MeshRenderer.h>
|
||||
#include <Graphics/RenderPass.h>
|
||||
#include <Graphics/VertexData.h>
|
||||
#include <Juliet.h>
|
||||
@@ -63,6 +64,8 @@ namespace
|
||||
} Game;
|
||||
|
||||
const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" };
|
||||
|
||||
Arena* PlatformArena = nullptr;
|
||||
} // namespace
|
||||
|
||||
void JulietApplication::Init()
|
||||
@@ -71,6 +74,8 @@ void JulietApplication::Init()
|
||||
|
||||
Log(LogLevel::Message, LogCategory::Tool, "%s", CStr(GetBasePath()));
|
||||
|
||||
PlatformArena = ArenaAllocate({ .AllowRealloc = true } JULIET_DEBUG_PARAM("Platform Arena"));
|
||||
|
||||
GraphicsConfig config;
|
||||
#if JULIET_DEBUG
|
||||
config.EnableDebug = true;
|
||||
@@ -85,42 +90,7 @@ void JulietApplication::Init()
|
||||
{
|
||||
AttachToWindow(GraphicsDevice, MainWindow);
|
||||
{
|
||||
// Create graphics pipeline
|
||||
String entryPoint = WrapString("main");
|
||||
ShaderCreateInfo shaderCI = {};
|
||||
shaderCI.EntryPoint = entryPoint;
|
||||
|
||||
// TODO: Assets management that handles path to assets or something.
|
||||
String shaderPath = WrapString("../../Assets/compiled/Triangle.vert.dxil");
|
||||
shaderCI.Stage = ShaderStage::Vertex;
|
||||
Shader* vertexShader = CreateShader(GraphicsDevice, shaderPath, shaderCI);
|
||||
|
||||
shaderPath = WrapString("../../Assets/compiled/SolidColor.frag.dxil");
|
||||
shaderCI.Stage = ShaderStage::Fragment;
|
||||
Shader* fragmentShader = CreateShader(GraphicsDevice, shaderPath, shaderCI);
|
||||
|
||||
ColorTargetDescription colorTargetDescription = {};
|
||||
colorTargetDescription.Format = GetSwapChainTextureFormat(GraphicsDevice, MainWindow);
|
||||
|
||||
GraphicsPipelineCreateInfo pipelineCI = {};
|
||||
pipelineCI.VertexShader = vertexShader;
|
||||
pipelineCI.FragmentShader = fragmentShader;
|
||||
pipelineCI.PrimitiveType = PrimitiveType::TriangleList;
|
||||
pipelineCI.TargetInfo = { .ColorTargetDescriptions = &colorTargetDescription,
|
||||
.NumColorTargets = 1,
|
||||
.DepthStencilFormat = TextureFormat::D32_FLOAT,
|
||||
.HasDepthStencilTarget = true };
|
||||
pipelineCI.RasterizerState.FillMode = FillMode::Solid;
|
||||
pipelineCI.DepthStencilState.EnableDepthTest = true;
|
||||
pipelineCI.DepthStencilState.EnableDepthWrite = true;
|
||||
pipelineCI.DepthStencilState.CompareOperation = CompareOperation::Less;
|
||||
|
||||
GraphicsPipeline = CreateGraphicsPipeline(GraphicsDevice, pipelineCI);
|
||||
if (GraphicsPipeline == nullptr)
|
||||
{
|
||||
LogError(LogCategory::Game, "Failed to create graphics pipeline!");
|
||||
Running = false;
|
||||
}
|
||||
Running = InitializeMeshRenderer(PlatformArena, GraphicsDevice, MainWindow);
|
||||
|
||||
// Create Depth Buffer
|
||||
TextureCreateInfo depthCI = {};
|
||||
@@ -139,50 +109,11 @@ void JulietApplication::Init()
|
||||
Running = false;
|
||||
}
|
||||
|
||||
// Create Buffers - Using StructuredBuffer for bindless SRV access in shader
|
||||
BufferCreateInfo bufferCI = {};
|
||||
bufferCI.Size = 1024;
|
||||
bufferCI.Usage = BufferUsage::StructuredBuffer; // SRV for ResourceDescriptorHeap access
|
||||
StructuredBuffer = CreateGraphicsBuffer(GraphicsDevice, bufferCI);
|
||||
|
||||
TransferBufferCreateInfo transferCI = {};
|
||||
transferCI.Size = 1024;
|
||||
transferCI.Usage = TransferBufferUsage::Upload;
|
||||
TransferBuffer = CreateGraphicsTransferBuffer(GraphicsDevice, transferCI);
|
||||
|
||||
// Upload Static Data for Test
|
||||
if (TransferBuffer && StructuredBuffer)
|
||||
{
|
||||
void* data = MapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
||||
if (data)
|
||||
{
|
||||
Matrix projection = PerspectiveFov(60.0f * (3.14159f / 180.0f), 1200.0f / 800.0f, 0.1f, 1000.0f);
|
||||
Matrix view = LookAt({ 30.0f, 0.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f });
|
||||
Matrix model = Matrix::Identity();
|
||||
Matrix mvp = projection * view * model;
|
||||
|
||||
MemCopy(data, &mvp, sizeof(Matrix));
|
||||
UnmapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
||||
|
||||
CommandList* initCmd = AcquireCommandList(GraphicsDevice);
|
||||
CopyBuffer(initCmd, StructuredBuffer, TransferBuffer, 256);
|
||||
TransitionBufferToReadable(initCmd, StructuredBuffer);
|
||||
SubmitCommandLists(initCmd);
|
||||
}
|
||||
}
|
||||
|
||||
CubeArena = ArenaAllocate({ .ReserveSize = Kilobytes(1llu), .CommitSize = Kilobytes(1llu) } JULIET_DEBUG_PARAM("CubeArena"));
|
||||
CubeMesh = CreateCubeMesh(CubeArena);
|
||||
// CubeMesh = CreateQuadMesh(CubeArena);
|
||||
|
||||
if (vertexShader)
|
||||
{
|
||||
DestroyShader(GraphicsDevice, vertexShader);
|
||||
}
|
||||
if (fragmentShader)
|
||||
{
|
||||
DestroyShader(GraphicsDevice, fragmentShader);
|
||||
}
|
||||
// std::ignore = AddCube();
|
||||
//
|
||||
// CommandList* loadCmd = AcquireCommandList(GraphicsDevice);
|
||||
// LoadMeshesOnGPU(loadCmd);
|
||||
// SubmitCommandLists(loadCmd);
|
||||
|
||||
if (Running == false)
|
||||
{
|
||||
@@ -208,8 +139,6 @@ void JulietApplication::Shutdown()
|
||||
{
|
||||
Log(LogLevel::Message, LogCategory::Tool, "Shutting down Juliet Application...");
|
||||
|
||||
ArenaRelease(CubeArena);
|
||||
|
||||
if (GameCode.IsValid)
|
||||
{
|
||||
Game.Shutdown();
|
||||
@@ -220,19 +149,14 @@ void JulietApplication::Shutdown()
|
||||
{
|
||||
DestroyGraphicsPipeline(GraphicsDevice, GraphicsPipeline);
|
||||
}
|
||||
if (StructuredBuffer)
|
||||
{
|
||||
DestroyGraphicsBuffer(GraphicsDevice, StructuredBuffer);
|
||||
}
|
||||
if (TransferBuffer)
|
||||
{
|
||||
DestroyGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
||||
}
|
||||
|
||||
if (DepthBuffer)
|
||||
{
|
||||
DestroyTexture(GraphicsDevice, DepthBuffer);
|
||||
}
|
||||
|
||||
ShutdownMeshRenderer();
|
||||
|
||||
if (MainWindow && GraphicsDevice)
|
||||
{
|
||||
DetachFromWindow(GraphicsDevice, MainWindow);
|
||||
@@ -248,6 +172,8 @@ void JulietApplication::Shutdown()
|
||||
DestroyGraphicsDevice(GraphicsDevice);
|
||||
}
|
||||
|
||||
ArenaRelease(PlatformArena);
|
||||
|
||||
Log(LogLevel::Message, LogCategory::Tool, "Juliet App shutdown Completed");
|
||||
}
|
||||
|
||||
@@ -281,7 +207,7 @@ void JulietApplication::Update()
|
||||
}
|
||||
|
||||
#ifdef JULIET_ENABLE_IMGUI
|
||||
ImGui::ShowDemoWindow();
|
||||
// ImGui::ShowDemoWindow();
|
||||
#endif
|
||||
|
||||
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false);
|
||||
@@ -301,27 +227,7 @@ void JulietApplication::Update()
|
||||
WaitUntilGPUIsIdle(GraphicsDevice);
|
||||
|
||||
#if ALLOW_SHADER_HOT_RELOAD
|
||||
String entryPoint = WrapString("main");
|
||||
ShaderCreateInfo shaderCI = {};
|
||||
shaderCI.EntryPoint = entryPoint;
|
||||
String shaderPath = WrapString("../../Assets/compiled/Triangle.vert.dxil");
|
||||
shaderCI.Stage = ShaderStage::Vertex;
|
||||
Shader* vertexShader = CreateShader(GraphicsDevice, shaderPath, shaderCI);
|
||||
|
||||
shaderPath = WrapString("../../Assets/compiled/SolidColor.frag.dxil");
|
||||
shaderCI.Stage = ShaderStage::Fragment;
|
||||
Shader* fragmentShader = CreateShader(GraphicsDevice, shaderPath, shaderCI);
|
||||
|
||||
UpdateGraphicsPipelineShaders(GraphicsDevice, GraphicsPipeline, vertexShader, fragmentShader);
|
||||
|
||||
if (vertexShader)
|
||||
{
|
||||
DestroyShader(GraphicsDevice, vertexShader);
|
||||
}
|
||||
if (fragmentShader)
|
||||
{
|
||||
DestroyShader(GraphicsDevice, fragmentShader);
|
||||
}
|
||||
ReloadMeshRendererShaders();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -361,76 +267,16 @@ void JulietApplication::Update()
|
||||
ArenaClear(GameScratchArena);
|
||||
}
|
||||
|
||||
void JulietApplication::OnPreRender(CommandList* cmd)
|
||||
void JulietApplication::OnPreRender(CommandList* /*cmd*/) {}
|
||||
|
||||
void JulietApplication::OnRender(RenderPass*, CommandList*)
|
||||
{
|
||||
index_t index = 0;
|
||||
// PushData pushData = {};
|
||||
// pushData.ViewProjection = Camera_GetViewProjectionMatrix(GetDebugCamera());
|
||||
|
||||
// Buffer uploads
|
||||
if (StructuredBuffer && TransferBuffer)
|
||||
{
|
||||
void* ptr = MapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
||||
if (ptr)
|
||||
{
|
||||
Vertex* vertices = static_cast<Vertex*>(ptr);
|
||||
// RenderMeshes(pass, cmd, pushData);
|
||||
|
||||
// // 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
|
||||
|
||||
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<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);
|
||||
}
|
||||
|
||||
CopyBuffer(cmd, StructuredBuffer, TransferBuffer, CubeMesh->IndexByteOffset + (CubeMesh->IndexCount * sizeof(uint16)));
|
||||
TransitionBufferToReadable(cmd, StructuredBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void JulietApplication::OnRender(RenderPass* pass, CommandList* cmd)
|
||||
{
|
||||
BindGraphicsPipeline(pass, GraphicsPipeline);
|
||||
|
||||
uint32 descriptorIndex = GetDescriptorIndex(GraphicsDevice, StructuredBuffer);
|
||||
|
||||
struct PushData
|
||||
{
|
||||
Matrix ViewProjection;
|
||||
uint32 BufferIndex;
|
||||
} pushData = {};
|
||||
pushData.BufferIndex = descriptorIndex;
|
||||
pushData.ViewProjection = Camera_GetViewProjectionMatrix(GetDebugCamera());
|
||||
|
||||
SetPushConstants(cmd, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
|
||||
|
||||
SetIndexBuffer(cmd, StructuredBuffer, 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);
|
||||
// SetPushConstants(cmd, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
|
||||
}
|
||||
|
||||
ColorTargetInfo JulietApplication::GetColorTargetInfo(Texture* swapchainTexture)
|
||||
|
||||
@@ -38,19 +38,13 @@ class JulietApplication : public Juliet::IApplication
|
||||
int GetAutoCloseFrameCount() const { return AutoCloseFrameCount; }
|
||||
|
||||
private:
|
||||
Juliet::Window* MainWindow = {};
|
||||
Juliet::GraphicsDevice* GraphicsDevice = {};
|
||||
Juliet::HotReloadCode GameCode = {};
|
||||
Juliet::GraphicsPipeline* GraphicsPipeline = {};
|
||||
Juliet::GraphicsBuffer* StructuredBuffer = {};
|
||||
Juliet::GraphicsTransferBuffer* TransferBuffer = {};
|
||||
Juliet::Texture* DepthBuffer = {};
|
||||
|
||||
Juliet::Mesh* CubeMesh = {};
|
||||
Juliet::Arena* CubeArena = nullptr;
|
||||
|
||||
Juliet::Arena* GameArena = nullptr;
|
||||
Juliet::Arena* GameScratchArena = nullptr;
|
||||
Juliet::Window* MainWindow = {};
|
||||
Juliet::GraphicsDevice* GraphicsDevice = {};
|
||||
Juliet::HotReloadCode GameCode = {};
|
||||
Juliet::GraphicsPipeline* GraphicsPipeline = {};
|
||||
Juliet::Texture* DepthBuffer = {};
|
||||
Juliet::Arena* GameArena = nullptr;
|
||||
Juliet::Arena* GameScratchArena = nullptr;
|
||||
|
||||
int AutoCloseFrameCount = -1;
|
||||
bool Running = false;
|
||||
|
||||
Reference in New Issue
Block a user