Compare commits

..

15 Commits

Author SHA1 Message Date
446670bd29 Various debug to check lighting 2026-02-23 23:13:06 -05:00
581656568b Debug options: Stop moving light, camera and cubes.
F1 to have free camera
2026-02-23 22:05:46 -05:00
3277624ec2 Support lighting using a graphics buffer that is kep open! 2026-02-23 19:24:57 -05:00
4312ecd172 Fix crash on linux with proton 2026-02-22 22:22:42 -05:00
1056301981 Fix some errors with meshrenderer moving to engine that gemini didnt have time to fix
Will have to resync how to load more meshes. Probably need a command to do it but for now not needed.
2026-02-22 17:47:46 -05:00
932c45d844 New skyboxrenderer + moved meshrenderer inside engine and out from main to clean that up 2026-02-22 17:16:21 -05:00
a781facd48 Factorized Push Data 2026-02-22 15:54:09 -05:00
1e1ec84fa1 Added normals to vertexdata 2026-02-22 15:21:35 -05:00
f98be3c7f3 Made a ship version
Remove imgui from ship release, script to export fast. Can read assets from dev folder and ship folder.
2026-02-22 14:19:59 -05:00
bc6ce3afb6 remove log file 2026-02-22 12:22:34 -05:00
816fdc27b1 Fixed the weird stutter and added fps in title bar 2026-02-22 12:22:06 -05:00
b38cc5e3d5 Fix release 2026-02-22 12:08:03 -05:00
431015f009 Added rotation functions for matrix 2026-02-22 11:24:59 -05:00
a7947bfa17 Made MeshRenderer able to take a matrix transform for each mesh, and we are now able to draw 100 cubes.
Claude OPus helpes with implementation
2026-02-21 23:27:27 -05:00
8e83cd32f6 Fixed MeshRenderer, our cube is now totally drawn by mesh renderer ! 2026-02-21 22:45:20 -05:00
63 changed files with 1910 additions and 1033 deletions

3
.gitignore vendored
View File

@@ -13,6 +13,7 @@
.idea/
.vs/
[Ii]ntermediate/
[sS]hip/
# Logs
build_*.txt
@@ -51,3 +52,5 @@ launch_*.txt
*.out
*.app
misc/agent_error.log
misc/agent_output_ship.log

View File

@@ -0,0 +1,292 @@
# Lighting & Skybox Plan
## Current State
| Item | Current |
|------|---------|
| Vertex format | `float3 Position` + `float4 Color` (28 bytes, no normals) |
| Vertex shader | [Triangle.vert.hlsl](file:///w:/Classified/Juliet/Assets/source/Triangle.vert.hlsl) — bindless buffer read, `mul(VP, mul(Model, pos))` |
| Fragment shader | [SolidColor.frag.hlsl](file:///w:/Classified/Juliet/Assets/source/SolidColor.frag.hlsl) — passthrough `return Color` |
| Push constants | `ViewProjection` + `Model` + `BufferIndex` + extras |
| Texturing | None — no sampler usage, no texture reads |
---
## Phase 1: Add Normals to Vertex Data
Lighting requires normals. This is the foundation for everything else.
### Vertex Format Change
```diff
struct Vertex
{
float Position[3];
+ float Normal[3];
float Color[4];
};
```
- **Stride**: 28 → 40 bytes
- Update `Triangle.vert.hlsl` stride constant: `uint stride = 40;`
- Load normal after position: `float3 normal = asfloat(buffer.Load3(offset + 12));`
- Load color shifts to: `float4 col = asfloat(buffer.Load4(offset + 24));`
### Files to modify
| File | Change |
|------|--------|
| [VertexData.h](file:///w:/Classified/Juliet/Juliet/include/Graphics/VertexData.h) | Add `float Normal[3]` to `Vertex` |
| [MeshRenderer.cpp](file:///w:/Classified/Juliet/Juliet/src/Graphics/MeshRenderer.cpp) | Update `AddCube()` to include per-face normals |
| [Triangle.vert.hlsl](file:///w:/Classified/Juliet/Assets/source/Triangle.vert.hlsl) | Update stride, load normal, pass to fragment |
---
## Phase 2: Basic Directional Light (Diffuse)
Simple single directional light with diffuse (Lambert) shading.
### Approach: Push light data through RootConstants
Add light direction and color to `RootConstants.hlsl` and the C++ `PushData`:
```hlsl
// RootConstants.hlsl additions
float3 LightDirection; // Normalized, world-space
float _LightPad;
float3 LightColor;
float AmbientIntensity;
```
```cpp
// PushData additions
Vector3 LightDirection;
float _LightPad;
Vector3 LightColor;
float AmbientIntensity;
```
### Shader Changes
**Vertex shader** — transform normal to world space and pass it to fragment:
```hlsl
// Triangle.vert.hlsl output struct
struct Output
{
float4 Color : TEXCOORD0;
float3 WorldNormal : TEXCOORD1;
float4 Position : SV_Position;
};
// In main():
float3 worldNormal = mul((float3x3)Model, normal);
output.WorldNormal = worldNormal;
```
> [!NOTE]
> Using `(float3x3)Model` for normal transform is only correct for uniform-scale transforms. For non-uniform scale, you'd need the inverse-transpose. Fine for now with translation-only transforms.
**Fragment shader** — apply Lambert diffuse:
```hlsl
// SolidColor.frag.hlsl → rename to Lit.frag.hlsl
#include "RootConstants.hlsl"
float4 main(float4 Color : TEXCOORD0, float3 WorldNormal : TEXCOORD1) : SV_Target0
{
float3 N = normalize(WorldNormal);
float NdotL = saturate(dot(N, -LightDirection));
float3 diffuse = Color.rgb * LightColor * NdotL;
float3 ambient = Color.rgb * AmbientIntensity;
return float4(diffuse + ambient, Color.a);
}
```
### Files to modify
| File | Change |
|------|--------|
| [RootConstants.hlsl](file:///w:/Classified/Juliet/Assets/source/RootConstants.hlsl) | Add light params |
| [MeshRenderer.h](file:///w:/Classified/Juliet/Juliet/include/Graphics/MeshRenderer.h) | Add light params to `PushData` |
| [Triangle.vert.hlsl](file:///w:/Classified/Juliet/Assets/source/Triangle.vert.hlsl) | Pass world normal to fragment |
| [SolidColor.frag.hlsl](file:///w:/Classified/Juliet/Assets/source/SolidColor.frag.hlsl) | Lambert diffuse + ambient |
| [DebugDisplayRenderer.cpp](file:///w:/Classified/Juliet/Juliet/src/Graphics/DebugDisplayRenderer.cpp) | Update push data struct to match new layout |
| [main.cpp](file:///w:/Classified/Juliet/JulietApp/main.cpp) | Set `LightDirection`, `LightColor`, `AmbientIntensity` |
---
## Phase 3: Skybox
A skybox renders a cubemap texture behind all geometry, giving the scene a background.
### Approach: Fullscreen-triangle with inverse VP
Render a fullscreen triangle as the very last thing (or first with depth write off), sample a cubemap using the camera view direction reconstructed from screen coordinates.
### New Assets
- **Skybox cubemap texture** — a `.dds` or 6 `.png` face images loaded as a `TextureCube`
- **New shaders**: `Skybox.vert.hlsl` + `Skybox.frag.hlsl`
### Shader Design
**Vertex shader** — fullscreen triangle using `SV_VertexID`:
```hlsl
// Skybox.vert.hlsl
#include "RootConstants.hlsl"
struct Output
{
float3 ViewDir : TEXCOORD0;
float4 Position : SV_Position;
};
Output main(uint vertexID : SV_VertexID)
{
Output output;
// Fullscreen triangle
float2 uv = float2((vertexID << 1) & 2, vertexID & 2);
float4 clipPos = float4(uv * 2.0 - 1.0, 1.0, 1.0);
clipPos.y = -clipPos.y;
output.Position = clipPos;
// Reconstruct view direction from clip space
// InverseViewProjection needs to be added to RootConstants
float4 worldPos = mul(InverseViewProjection, clipPos);
output.ViewDir = worldPos.xyz / worldPos.w;
return output;
}
```
**Fragment shader** — sample cubemap:
```hlsl
// Skybox.frag.hlsl
#include "RootConstants.hlsl"
float4 main(float3 ViewDir : TEXCOORD0) : SV_Target0
{
TextureCube skybox = ResourceDescriptorHeap[TextureIndex];
SamplerState samp = SamplerDescriptorHeap[0]; // Linear clamp
return skybox.Sample(samp, normalize(ViewDir));
}
```
### Pipeline Requirements
| Setting | Value |
|---------|-------|
| Depth write | **Off** (skybox is infinitely far) |
| Depth test | **LessEqual** or **Off** (render behind everything) |
| Cull mode | **None** (fullscreen triangle) |
| Draw call | `Draw(3, 0)` — no vertex buffer needed |
### New C++ Components
1. **Cubemap loading** — need to create `TextureCube` from 6 face images or a `.dds` cubemap file
2. **Skybox pipeline** — new `GraphicsPipeline` with the skybox shaders and the pipeline settings above
3. **Sampler** — need at least one linear sampler in the sampler heap (may already exist for ImGui)
4. **`InverseViewProjection`** — add to `RootConstants` and compute in C++ via a `MatrixInverse` function
> [!IMPORTANT]
> `MatrixInverse` needs to be implemented in `Matrix.h`. This is a non-trivial 4×4 matrix inversion (adjugate/determinant method or Gauss-Jordan).
### Files to modify/create
| File | Change |
|------|--------|
| [NEW] `Skybox.vert.hlsl` | Fullscreen triangle + view direction |
| [NEW] `Skybox.frag.hlsl` | Cubemap sample |
| [RootConstants.hlsl](file:///w:/Classified/Juliet/Assets/source/RootConstants.hlsl) | Add `InverseViewProjection` |
| [Matrix.h](file:///w:/Classified/Juliet/Juliet/include/Core/Math/Matrix.h) | Add `MatrixInverse()` |
| [MeshRenderer.h](file:///w:/Classified/Juliet/Juliet/include/Graphics/MeshRenderer.h) | Add `InverseViewProjection` to `PushData` |
| [main.cpp](file:///w:/Classified/Juliet/JulietApp/main.cpp) | Create skybox pipeline, load cubemap, render skybox |
---
## Recommended Implementation Order
```mermaid
graph LR
A["Phase 1<br/>Add Normals"] --> B["Phase 2<br/>Directional Light"]
B --> C["Phase 3<br/>Skybox"]
```
1. **Phase 1** (normals) is the smallest and unblocks Phase 2
2. **Phase 2** (lighting) gives the cubes visible 3D depth immediately
3. **Phase 3** (skybox) is independent of lighting but benefits from having `MatrixInverse` and sampler infrastructure
> [!TIP]
> Phases 1+2 together are a single session of work (~8 files). Phase 3 is larger due to cubemap loading and new pipeline creation.
---
## Open Questions (Answered)
1. **Cubemap source****Procedural gradient skybox** chosen because asset loading infrastructure is not yet established.
2. **Sampler heap** — Evaluate what exists. However, with a procedural skybox, we won't need a sampler for Phase 3! (The sky color can be procedurally generated from the reconstructed view direction).
3. **Specular****Blinn-Phong** specular, structured in an agnostic way so PBR (physically based rendering) parameters can be plugged in later.
---
## Phase 4: Forward Rendered Entity Lights
A simple, fast forward renderer using a Global Structured Buffer for entity-based point lights.
### Approach: Bindless Global Lights Buffer
Instead of passing each light via PushConstants, we pass a `StructuredBuffer<PointLight>` index and iterate over the active lights in the fragment shader.
### New C++ Components
```cpp
struct PointLight
{
Vector3 Position;
float Radius;
Vector3 Color;
float Intensity;
};
```
1. **Lights Buffer Allocation**: Allocate a `StructuredBuffer` large enough for all potential lights (e.g., max 1024).
2. **Buffer Upload**: Loop through the active game entity lights every frame and upload them using the TransferBuffer system.
3. **PushData Update**:
- `uint32 LightsBufferIndex`
- `uint32 ActiveLightCount`
### Shader Design
**Fragment Shader Expansion** loop over all `ActiveLightCount` to compute the attenuation and diffuse, then accumulate.
```hlsl
StructuredBuffer<PointLight> lights = ResourceDescriptorHeap[LightsBufferIndex];
float3 totalDiffuse = Color.rgb * LightColor * NdotL; // Include Directional Sun
for (uint i = 0; i < ActiveLightCount; ++i)
{
PointLight light = lights[i];
float3 lightVector = light.Position - WorldPosition;
float distance = length(lightVector);
if (distance > light.Radius) continue;
float3 L = lightVector / distance;
float NdotL = saturate(dot(N, L));
float attenuation = 1.0 - saturate(distance / light.Radius);
attenuation *= attenuation; // inverse square-ish
totalDiffuse += Color.rgb * light.Color * light.Intensity * NdotL * attenuation;
}
```
> [!NOTE]
> Passing `WorldPosition` to the Fragment shader from the Vertex shader is required for positional lighting.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -13,8 +13,8 @@ Output main(uint vertexIndex : SV_VertexID)
// Retrieve the vertex buffer using SM6.6 bindless syntax
ByteAddressBuffer buffer = ResourceDescriptorHeap[BufferIndex];
// TextureIndex is used as vertex offset for consolidated buffer (depth-tested at 0, overlay at halfMax)
uint actualVertexIndex = vertexIndex + TextureIndex;
// VertexOffset is used as vertex offset for consolidated buffer (depth-tested at 0, overlay at halfMax)
uint actualVertexIndex = vertexIndex + VertexOffset;
// Vertex layout: float3 Position (12 bytes) + float4 Color (16 bytes) = 28 bytes stride
uint stride = 28;

View File

@@ -1,15 +1,39 @@
#ifndef ROOT_CONSTANTS_HLSL
#define ROOT_CONSTANTS_HLSL
struct PointLight
{
float3 Position;
float Radius;
float3 Color;
float Intensity;
};
struct TransformData
{
row_major float4x4 Model;
};
cbuffer RootConstants : register(b0, space0)
{
row_major float4x4 ViewProjection;
uint MeshIndex;
uint TransformsBufferIndex;
uint BufferIndex;
uint TextureIndex;
uint VertexOffset; // Base vertex for indexed drawing with bindless buffers
uint _Padding; // Padding for alignment
float2 Scale; // 2D scale factor
float2 Translate; // 2D translation
float2 _Padding2; // Explicit padding to align LightDirection to 16 bytes
float3 GlobalLightDirection; // Normalized, world-space
float GlobalLightPad;
float3 GlobalLightColor;
float GlobalAmbientIntensity;
uint LightBufferIndex;
uint ActiveLightCount;
};

View File

@@ -0,0 +1,26 @@
#include "RootConstants.hlsl"
float4 main(float3 ViewDir : TEXCOORD0) : SV_Target0
{
float3 dir = normalize(ViewDir);
// Simple Procedural Gradient Skybox Colors
float3 skyZenithColor = float3(0.05f, 0.15f, 0.45f); // Deep blue top
float3 skyHorizonColor = float3(0.4f, 0.6f, 0.9f); // Light blue horizon
float3 groundColor = float3(0.1f, 0.1f, 0.15f); // Dark ground
float t = dir.z; // -1 to 1 based on vertical alignment
float3 finalColor = groundColor;
if (t > 0.0f) {
// Blend from horizon to zenith
finalColor = lerp(skyHorizonColor, skyZenithColor, t);
} else {
// Ground - quick blend from horizon to ground
finalColor = lerp(skyHorizonColor, groundColor, saturate(-t * 2.0f));
}
// Combine with overall ambient lighting scale
return float4(finalColor, 1.0f);
}

View File

@@ -0,0 +1,74 @@
#include "RootConstants.hlsl"
struct Output
{
float3 ViewDir : TEXCOORD0;
float4 Position : SV_Position;
};
float4x4 Inverse(float4x4 m)
{
float n11 = m[0][0], n12 = m[1][0], n13 = m[2][0], n14 = m[3][0];
float n21 = m[0][1], n22 = m[1][1], n23 = m[2][1], n24 = m[3][1];
float n31 = m[0][2], n32 = m[1][2], n33 = m[2][2], n34 = m[3][2];
float n41 = m[0][3], n42 = m[1][3], n43 = m[2][3], n44 = m[3][3];
float t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44;
float t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44;
float t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44;
float t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
float det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
float idet = 1.0f / det;
float4x4 ret;
ret[0][0] = t11 * idet;
ret[0][1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * idet;
ret[0][2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * idet;
ret[0][3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * idet;
ret[1][0] = t12 * idet;
ret[1][1] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * idet;
ret[1][2] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * idet;
ret[1][3] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * idet;
ret[2][0] = t13 * idet;
ret[2][1] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * idet;
ret[2][2] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * idet;
ret[2][3] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * idet;
ret[3][0] = t14 * idet;
ret[3][1] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * idet;
ret[3][2] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * idet;
ret[3][3] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * idet;
return ret;
}
Output main(uint vertexID : SV_VertexID)
{
Output output;
// Fullscreen triangle properties
// vertexID 0 -> uv(0,0) -> pos(-1, 1)
// vertexID 1 -> uv(2,0) -> pos( 3, 1)
// vertexID 2 -> uv(0,2) -> pos(-1, -3)
float2 uv = float2((vertexID << 1) & 2, vertexID & 2);
// Map uv to clip space position.
// Z is set to 1.0 (far plane in reverse-Z or standard depth)
// Assuming standard Z projection ranges from 0 to 1, we use 1.0 for the far plane.
// Depending on reverse-z, this might need to be 0.0, but let's stick to standard 1.0
// depth for skyboxes.
float4 clipPos = float4(uv * 2.0 - 1.0, 1.0, 1.0);
clipPos.y = -clipPos.y; // Flip Y for D3D
output.Position = clipPos;
// Reconstruct view direction from clip space
float4x4 inverseVP = Inverse(ViewProjection);
float4 worldPos = mul(inverseVP, clipPos);
output.ViewDir = worldPos.xyz / worldPos.w;
return output;
}

View File

@@ -1,4 +1,46 @@
float4 main(float4 Color : TEXCOORD0) : SV_Target0
#include "RootConstants.hlsl"
struct Input
{
return Color;
float4 Color : TEXCOORD0;
float3 WorldNormal : TEXCOORD1;
float3 WorldPosition : TEXCOORD2;
};
float4 main(Input input) : SV_Target0
{
float3 normal = normalize(input.WorldNormal);
// Initial ambient component
float3 result = input.Color.rgb * GlobalLightColor * GlobalAmbientIntensity;
// Directional light contribution
float ndotl = max(dot(normal, -GlobalLightDirection), 0.0);
result += input.Color.rgb * GlobalLightColor * ndotl;
// Point lights
if (ActiveLightCount > 0)
{
StructuredBuffer<PointLight> pointLights = ResourceDescriptorHeap[LightBufferIndex];
for (uint i = 0; i < ActiveLightCount; ++i)
{
PointLight light = pointLights[i];
float3 lightDir = light.Position - input.WorldPosition;
float dist = length(lightDir);
if (dist < light.Radius)
{
lightDir = normalize(lightDir);
float attenuation = 1.0 - (dist / light.Radius);
attenuation = max(attenuation, 0.0);
float pndotl = max(dot(normal, lightDir), 0.0);
result += light.Color * input.Color.rgb * pndotl * attenuation * light.Intensity;
}
}
}
return float4(result, input.Color.a);
}

View File

@@ -1,6 +1,8 @@
struct Output
{
float4 Color : TEXCOORD0;
float3 WorldNormal : TEXCOORD1;
float3 WorldPosition : TEXCOORD2;
float4 Position : SV_Position;
};
@@ -12,14 +14,23 @@ Output main(uint vertexIndex : SV_VertexID)
ByteAddressBuffer buffer = ResourceDescriptorHeap[BufferIndex];
uint stride = 28;
uint stride = 40;
uint offset = vertexIndex * stride;
float3 pos = asfloat(buffer.Load3(offset));
float4 col = asfloat(buffer.Load4(offset + 12));
float3 normal = asfloat(buffer.Load3(offset + 12));
float4 col = asfloat(buffer.Load4(offset + 24));
//output.Position = float4(pos, 1.0f);
output.Position = mul(ViewProjection, float4(pos, 1.0f));
// Fetch Model Matrix
StructuredBuffer<TransformData> transformsBuffer = ResourceDescriptorHeap[TransformsBufferIndex];
float4x4 Model = transformsBuffer[MeshIndex].Model;
float4 worldPos = mul(Model, float4(pos, 1.0f));
output.Position = mul(ViewProjection, worldPos);
output.Color = col;
output.WorldPosition = worldPos.xyz;
float3 worldNormal = mul((float3x3)Model, normal);
output.WorldNormal = worldNormal;
return output;
}

View File

@@ -47,8 +47,11 @@
// --- DLL BUILD ---
DLL( '$ProjectName$-Lib-$Platform$-$BuildConfigName$' )
{
.Libraries = { '$ProjectName$-Objs-$Platform$-$BuildConfigName$',
'ImGui-Lib-$Platform$-$BuildConfigName$' }
.Libraries = { '$ProjectName$-Objs-$Platform$-$BuildConfigName$' }
If ( .BuildConfigName != 'Release' )
{
^Libraries + { 'ImGui-Lib-$Platform$-$BuildConfigName$' }
}
.LinkerOutput = '$BinPath$/$Platform$-$BuildConfigName$/$ProjectName$.dll' // Output .dll to Bin

View File

@@ -8,5 +8,6 @@ namespace Juliet
{
enum class JulietInit_Flags : uint8;
struct Arena;
extern JULIET_API void StartApplication(IApplication& app, JulietInit_Flags flags);
} // namespace Juliet

View File

@@ -1,5 +1,7 @@
#pragma once
#include <Core/Common/NonNullPtr.h>
namespace Juliet
{
struct RenderPass;
@@ -7,12 +9,13 @@ namespace Juliet
struct Texture;
struct ColorTargetInfo;
struct DepthStencilTargetInfo;
struct Arena;
class IApplication
{
public:
virtual ~IApplication() = default;
virtual void Init() = 0;
virtual void Init(NonNullPtr<Arena> arena) = 0;
virtual void Shutdown() = 0;
virtual void Update() = 0;
virtual bool IsRunning() = 0;

View File

@@ -193,11 +193,16 @@ namespace Juliet
{
Assert(Arena);
if (InternalArena)
{
ArenaClear(Arena);
DataFirst = DataLast = nullptr;
Data = nullptr;
Count = 0;
Capacity = 0;
Reserve(ReserveSize);
}
DataFirst = DataLast = nullptr;
Count = 0;
}
bool IsEmpty() const { return Count == 0; }

View File

@@ -2,6 +2,7 @@
#include <Core/Common/CoreTypes.h>
#include <Core/Common/NonNullPtr.h>
#include <Core/Common/String.h>
#include <Juliet.h>
namespace Juliet
@@ -16,4 +17,5 @@ namespace Juliet
extern JULIET_API void HideWindow(NonNullPtr<Window> window);
extern JULIET_API WindowID GetWindowID(NonNullPtr<Window> window);
extern JULIET_API void SetWindowTitle(NonNullPtr<Window> window, String title);
} // namespace Juliet

View File

@@ -5,7 +5,16 @@
namespace Juliet
{
// Returns the path to the application directory
extern JULIET_API String GetBasePath();
[[nodiscard]] extern JULIET_API String GetBasePath();
extern JULIET_API bool IsAbsolutePath(String path);
// Returns the resolved base path to the compiled shaders directory.
// In dev, this resolves to ../../Assets/compiled/ relative to the exe.
// In shipping, this resolves to Assets/Shaders/ next to the exe.
[[nodiscard]] extern JULIET_API String GetAssetBasePath();
// Builds a full path to an asset file given its filename (e.g. "Triangle.vert.dxil").
// The caller owns the returned buffer and must free it.
[[nodiscard]] extern JULIET_API String GetAssetPath(String filename);
[[nodiscard]]extern JULIET_API bool IsAbsolutePath(String path);
} // namespace Juliet

View File

@@ -3,6 +3,8 @@
#include <Core/Common/CoreTypes.h>
#include <Core/Common/NonNullPtr.h>
#ifdef JULIET_ENABLE_IMGUI
struct ImGuiContext;
namespace Juliet
@@ -25,3 +27,5 @@ namespace Juliet
JULIET_API void RunTests();
} // namespace ImGuiService
} // namespace Juliet
#endif // JULIET_ENABLE_IMGUI

View File

@@ -37,6 +37,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
(void)hPrev;
(void)szCmdLine;
(void)sw;
return Juliet::Bootstrap(JulietMain, __argc, __wargv);
}
}

View File

@@ -8,8 +8,9 @@ namespace Juliet
struct Matrix
{
float m[4][4];
};
static Matrix Identity()
[[nodiscard]] inline Matrix MatrixIdentity()
{
Matrix result = {};
result.m[0][0] = 1.0f;
@@ -19,7 +20,7 @@ namespace Juliet
return result;
}
Matrix operator*(const Matrix& rhs) const
[[nodiscard]] inline Matrix operator*(const Matrix& lhs, const Matrix& rhs)
{
Matrix result = {};
for (int i = 0; i < 4; ++i)
@@ -28,13 +29,78 @@ namespace Juliet
{
for (int k = 0; k < 4; ++k)
{
result.m[i][j] += m[i][k] * rhs.m[k][j];
result.m[i][j] += lhs.m[i][k] * rhs.m[k][j];
}
}
}
return result;
}
};
[[nodiscard]] inline Matrix MatrixTranslation(float x, float y, float z)
{
Matrix result = MatrixIdentity();
result.m[0][3] = x;
result.m[1][3] = y;
result.m[2][3] = z;
return result;
}
[[nodiscard]] inline Matrix MatrixScale(float x, float y, float z)
{
Matrix result = MatrixIdentity();
result.m[0][0] = x;
result.m[1][1] = y;
result.m[2][2] = z;
return result;
}
[[nodiscard]] inline Matrix MatrixRotationX(float radians)
{
float c = cosf(radians);
float s = sinf(radians);
Matrix result = MatrixIdentity();
result.m[1][1] = c;
result.m[1][2] = -s;
result.m[2][1] = s;
result.m[2][2] = c;
return result;
}
[[nodiscard]] inline Matrix MatrixRotationY(float radians)
{
float c = cosf(radians);
float s = sinf(radians);
Matrix result = MatrixIdentity();
result.m[0][0] = c;
result.m[0][2] = s;
result.m[2][0] = -s;
result.m[2][2] = c;
return result;
}
[[nodiscard]] inline Matrix MatrixRotationZ(float radians)
{
float c = cosf(radians);
float s = sinf(radians);
Matrix result = MatrixIdentity();
result.m[0][0] = c;
result.m[0][1] = -s;
result.m[1][0] = s;
result.m[1][1] = c;
return result;
}
inline void MatrixTranslate(Matrix& m, const Vector3& v)
{
m.m[0][3] += v.x;
m.m[1][3] += v.y;
m.m[2][3] += v.z;
}
[[nodiscard]] inline Matrix MatrixRotation(float x, float y, float z)
{
return MatrixRotationX(x) * MatrixRotationY(y) * MatrixRotationZ(z);
}
inline Matrix LookAt(const Vector3& eye, const Vector3& target, const Vector3& up)
{
@@ -83,4 +149,46 @@ namespace Juliet
result.m[3][3] = 0.0f;
return result;
}
[[nodiscard]] inline Matrix MatrixInverse(const Matrix& m)
{
Matrix out = {};
float m00 = m.m[0][0], m01 = m.m[0][1], m02 = m.m[0][2], m03 = m.m[0][3];
float m10 = m.m[1][0], m11 = m.m[1][1], m12 = m.m[1][2], m13 = m.m[1][3];
float m20 = m.m[2][0], m21 = m.m[2][1], m22 = m.m[2][2], m23 = m.m[2][3];
float m30 = m.m[3][0], m31 = m.m[3][1], m32 = m.m[3][2], m33 = m.m[3][3];
out.m[0][0] = m11 * m22 * m33 - m11 * m23 * m32 - m21 * m12 * m33 + m21 * m13 * m32 + m31 * m12 * m23 - m31 * m13 * m22;
out.m[1][0] = -m10 * m22 * m33 + m10 * m23 * m32 + m20 * m12 * m33 - m20 * m13 * m32 - m30 * m12 * m23 + m30 * m13 * m22;
out.m[2][0] = m10 * m21 * m33 - m10 * m23 * m31 - m20 * m11 * m33 + m20 * m13 * m31 + m30 * m11 * m23 - m30 * m13 * m21;
out.m[3][0] = -m10 * m21 * m32 + m10 * m22 * m31 + m20 * m11 * m32 - m20 * m12 * m31 - m30 * m11 * m22 + m30 * m12 * m21;
out.m[0][1] = -m01 * m22 * m33 + m01 * m23 * m32 + m21 * m02 * m33 - m21 * m03 * m32 - m31 * m02 * m23 + m31 * m03 * m22;
out.m[1][1] = m00 * m22 * m33 - m00 * m23 * m32 - m20 * m02 * m33 + m20 * m03 * m32 + m30 * m02 * m23 - m30 * m03 * m22;
out.m[2][1] = -m00 * m21 * m33 + m00 * m23 * m31 + m20 * m01 * m33 - m20 * m03 * m31 - m30 * m01 * m23 + m30 * m03 * m21;
out.m[3][1] = m00 * m21 * m32 - m00 * m22 * m31 - m20 * m01 * m32 + m20 * m02 * m31 + m30 * m01 * m22 - m30 * m02 * m21;
out.m[0][2] = m01 * m12 * m33 - m01 * m13 * m32 - m11 * m02 * m33 + m11 * m03 * m32 + m31 * m02 * m13 - m31 * m03 * m12;
out.m[1][2] = -m00 * m12 * m33 + m00 * m13 * m32 + m10 * m02 * m33 - m10 * m03 * m32 - m30 * m02 * m13 + m30 * m03 * m12;
out.m[2][2] = m00 * m11 * m33 - m00 * m13 * m31 - m10 * m01 * m33 + m10 * m03 * m31 + m30 * m01 * m13 - m30 * m03 * m11;
out.m[3][2] = -m00 * m11 * m32 + m00 * m12 * m31 + m10 * m01 * m32 - m10 * m02 * m31 - m30 * m01 * m12 + m30 * m02 * m11;
out.m[0][3] = -m01 * m12 * m23 + m01 * m13 * m22 + m11 * m02 * m23 - m11 * m03 * m22 - m21 * m02 * m13 + m21 * m03 * m12;
out.m[1][3] = m00 * m12 * m23 - m00 * m13 * m22 - m10 * m02 * m23 + m10 * m03 * m22 + m20 * m02 * m13 - m20 * m03 * m12;
out.m[2][3] = -m00 * m11 * m23 + m00 * m13 * m21 + m10 * m01 * m23 - m10 * m03 * m21 - m20 * m01 * m13 + m20 * m03 * m11;
out.m[3][3] = m00 * m11 * m22 - m00 * m12 * m21 - m10 * m01 * m22 + m10 * m02 * m21 + m20 * m01 * m12 - m20 * m02 * m11;
float det = m00 * out.m[0][0] + m01 * out.m[1][0] + m02 * out.m[2][0] + m03 * out.m[3][0];
if (det != 0.0f)
{
float invDet = 1.0f / det;
for (int r = 0; r < 4; ++r)
for (int c = 0; c < 4; ++c)
out.m[r][c] *= invDet;
}
return out;
}
} // namespace Juliet

View File

@@ -9,6 +9,7 @@ namespace Juliet
struct Engine
{
IApplication* Application = nullptr;
Arena* PlatformArena = nullptr;
};
void InitializeEngine(JulietInit_Flags flags);

View File

@@ -164,6 +164,8 @@ namespace Juliet
extern JULIET_API GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo);
extern JULIET_API GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device,
const TransferBufferCreateInfo& createInfo);
extern JULIET_API void* MapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
extern JULIET_API void UnmapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
extern JULIET_API void* MapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
extern JULIET_API void UnmapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
extern JULIET_API void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,

View File

@@ -8,7 +8,6 @@ namespace Juliet
IndexBuffer = 1 << 0,
ConstantBuffer = 1 << 1,
StructuredBuffer = 1 << 2,
VertexBuffer = 1 << 3,
};
enum class TransferBufferUsage : uint8
@@ -20,7 +19,9 @@ namespace Juliet
struct BufferCreateInfo
{
size_t Size;
size_t Stride;
BufferUsage Usage;
bool IsDynamic;
};
struct TransferBufferCreateInfo

View File

@@ -0,0 +1,15 @@
#pragma once
#include <Juliet.h>
#include <Core/Math/Vector.h>
namespace Juliet
{
struct PointLight
{
Vector3 Position;
float Radius;
Vector3 Color;
float Intensity;
};
} // namespace Juliet

View File

@@ -2,6 +2,7 @@
#include <Core/Common/CoreTypes.h>
#include <Core/Common/NonNullPtr.h>
#include <Core/Math/Matrix.h>
#include <Juliet.h>
namespace Juliet
@@ -16,5 +17,7 @@ namespace Juliet
index_t VertexOffset;
index_t IndexOffset;
Matrix Transform = MatrixIdentity();
};
} // namespace Juliet

View File

@@ -2,6 +2,8 @@
#include <Core/Container/Vector.h>
#include <Core/Math/Matrix.h>
#include <Graphics/Lighting.h>
#include <Graphics/PushConstants.h>
#include <Graphics/VertexData.h>
#include <Juliet.h>
@@ -17,12 +19,14 @@ namespace Juliet
struct Mesh;
using MeshID = index_t;
using LightID = 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
constexpr size_t kDefaultLightCount = 1024;
struct MeshRenderer
{
@@ -30,31 +34,39 @@ namespace Juliet
VectorArena<Mesh, kDefaultMeshNumber, false> Meshes;
VectorArena<Vertex, kDefaultVertexCount, false> Vertices;
VectorArena<Index, kDefaultIndexCount, false> Indices;
VectorArena<PointLight, kDefaultLightCount, false> PointLights;
GraphicsBuffer* VertexBuffer;
GraphicsBuffer* IndexBuffer;
GraphicsTransferBuffer* StreamCopyBuffer;
GraphicsTransferBuffer* LoadCopyBuffer;
GraphicsBuffer* LightsBuffer;
PointLight* MappedLights;
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 InitializeMeshRenderer(NonNullPtr<Arena> arena);
[[nodiscard]] JULIET_API bool InitializeMeshRendererGraphics(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window);
JULIET_API void ShutdownMeshRendererGraphics();
JULIET_API void ShutdownMeshRenderer();
JULIET_API void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList);
JULIET_API void RenderMeshes(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, PushData& pushData);
// Lights
[[nodiscard]] JULIET_API LightID AddPointLight(const PointLight& light);
JULIET_API void SetPointLightPosition(LightID id, const Vector3& position);
JULIET_API void SetPointLightColor(LightID id, const Vector3& color);
JULIET_API void SetPointLightRadius(LightID id, float radius);
JULIET_API void SetPointLightIntensity(LightID id, float intensity);
JULIET_API void ClearPointLights();
// Utils
[[nodiscard]] JULIET_API MeshID AddCube();
[[nodiscard]] JULIET_API MeshID AddQuad();
JULIET_API void SetMeshTransform(MeshID id, const Matrix& transform);
#if ALLOW_SHADER_HOT_RELOAD
JULIET_API void ReloadMeshRendererShaders();

View File

@@ -0,0 +1,30 @@
#pragma once
#include <Core/Math/Matrix.h>
#include <Core/Math/Vector.h>
#include <Juliet.h>
namespace Juliet
{
struct PushData
{
Matrix ViewProjection;
uint32 MeshIndex;
uint32 TransformsBufferIndex;
uint32 BufferIndex;
uint32 TextureIndex;
uint32 VertexOffset;
uint32 Padding;
float Scale[2];
float Translate[2];
float Padding2[2];
Vector3 GlobalLightDirection;
float GlobalLightPad;
Vector3 GlobalLightColor;
float GlobalAmbientIntensity;
uint32 LightBufferIndex;
uint32 ActiveLightCount;
};
} // namespace Juliet

View File

@@ -0,0 +1,29 @@
#pragma once
#include <Core/Math/Matrix.h>
#include <Juliet.h>
namespace Juliet
{
struct RenderPass;
struct CommandList;
struct Window;
struct GraphicsPipeline;
struct GraphicsDevice;
struct SkyboxRenderer
{
GraphicsDevice* Device;
GraphicsPipeline* Pipeline;
};
[[nodiscard]] JULIET_API bool InitializeSkyboxRenderer(NonNullPtr<GraphicsDevice> device,
NonNullPtr<Window> window);
JULIET_API void ShutdownSkyboxRenderer();
JULIET_API void RenderSkybox(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, const Matrix& viewProjection);
#if ALLOW_SHADER_HOT_RELOAD
JULIET_API void ReloadSkyboxShaders();
#endif
} // namespace Juliet

View File

@@ -5,6 +5,7 @@ namespace Juliet
struct Vertex
{
float Position[3];
float Normal[3];
float Color[4];
};

View File

@@ -123,7 +123,7 @@ namespace Juliet
{
// Find and destroy
VectorArena<Window>& windows = g_CurrentDisplayDevice->Windows;
for (index_t idx = windows.Size() - 1; idx != 0; --idx)
for (index_t idx = windows.Size(); idx-- > 0;)
{
Window& windowRef = windows[idx];
if (windowRef.ID == window->ID)
@@ -149,6 +149,11 @@ namespace Juliet
return window->ID;
}
void SetWindowTitle(NonNullPtr<Window> window, String title)
{
g_CurrentDisplayDevice->SetWindowTitle(g_CurrentDisplayDevice, window, title);
}
// Display Device Utils. Not exposed in the API
DisplayDevice* GetDisplayDevice()
{

View File

@@ -25,6 +25,7 @@ namespace Juliet
void (*DestroyPlatformWindow)(NonNullPtr<DisplayDevice> self, NonNullPtr<Window> window);
void (*ShowWindow)(NonNullPtr<DisplayDevice> self, NonNullPtr<Window> window);
void (*HideWindow)(NonNullPtr<DisplayDevice> self, NonNullPtr<Window> window);
void (*SetWindowTitle)(NonNullPtr<DisplayDevice> self, NonNullPtr<Window> window, String title);
// Events
void (*PumpEvents)(NonNullPtr<DisplayDevice> self);

View File

@@ -33,10 +33,11 @@ namespace Juliet::Win32
device->DestroyPlatformWindow = DestroyPlatformWindow;
device->ShowWindow = ShowWindow;
device->HideWindow = HideWindow;
device->SetWindowTitle = SetWindowTitle;
device->PumpEvents = PumpEvents;
device->Windows.Create(JULIET_DEBUG_ONLY("Display Windows"));
device->Windows.Create(arena JULIET_DEBUG_PARAM("Display Windows"));
return device;
}

View File

@@ -14,8 +14,10 @@
// For GET_X_LPARAM, GET_Y_LPARAM.
#include <windowsx.h>
#ifdef JULIET_ENABLE_IMGUI
#include <imgui.h> // Need For IMGUI_IMPL_API
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
#endif
namespace Juliet::Win32
{
@@ -145,10 +147,12 @@ namespace Juliet::Win32
LRESULT CALLBACK Win32MainWindowCallback(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
#ifdef JULIET_ENABLE_IMGUI
if (ImGui_ImplWin32_WndProcHandler(handle, message, wParam, lParam))
{
return true;
}
#endif
LRESULT returnCode = -1;

View File

@@ -92,4 +92,13 @@ namespace Juliet::Win32
auto& win32State = static_cast<Window32State&>(*window->State);
::ShowWindow(win32State.Handle, SW_HIDE);
}
void SetWindowTitle(NonNullPtr<DisplayDevice> /*self*/, NonNullPtr<Window> window, String title)
{
Assert(window);
Assert(window->State);
auto& win32State = static_cast<Window32State&>(*window->State);
SetWindowTextA(win32State.Handle, CStr(title));
}
} // namespace Juliet::Win32

View File

@@ -25,4 +25,5 @@ namespace Juliet::Win32
extern void DestroyPlatformWindow(NonNullPtr<DisplayDevice> self, NonNullPtr<Window> window);
extern void ShowWindow(NonNullPtr<DisplayDevice> self, NonNullPtr<Window> window);
extern void HideWindow(NonNullPtr<DisplayDevice> self, NonNullPtr<Window> window);
extern void SetWindowTitle(NonNullPtr<DisplayDevice> self, NonNullPtr<Window> window, String title);
} // namespace Juliet::Win32

View File

@@ -1,14 +1,29 @@
#include <Core/Common/CoreTypes.h>
#include <Core/Common/CoreUtils.h>
#include <Core/Common/String.h>
#include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/HAL/Filesystem/Filesystem_Platform.h>
#include <Core/HAL/Filesystem/Filesystem_Private.h>
#include <Core/HAL/Win32.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Memory/Allocator.h>
#include <cstdio>
namespace Juliet
{
namespace
{
String CachedBasePath = {};
String CachedAssetBasePath = {};
bool DirectoryExists(const char* path)
{
Assert(path);
DWORD attributes = GetFileAttributesA(path);
return (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY);
}
}
String GetBasePath()
@@ -20,6 +35,27 @@ namespace Juliet
return CachedBasePath;
}
String GetAssetBasePath()
{
return CachedAssetBasePath;
}
[[nodiscard]] String GetAssetPath(String filename)
{
Assert(IsValid(CachedAssetBasePath));
Assert(IsValid(filename));
size_t totalSize = CachedAssetBasePath.Size + filename.Size + 1;
auto* buffer = static_cast<char*>(Calloc(totalSize, sizeof(char)));
if (!buffer)
{
return {};
}
snprintf(buffer, totalSize, "%s%s", CStr(CachedAssetBasePath), CStr(filename));
return { buffer, totalSize - 1 };
}
bool IsAbsolutePath(String path)
{
if (!IsValid(path))
@@ -29,7 +65,40 @@ namespace Juliet
return Platform::IsAbsolutePath(path);
}
void InitFilesystem() {}
void InitFilesystem()
{
String basePath = GetBasePath();
Assert(IsValid(basePath));
// Probe candidate paths for compiled shader directory
// 1. Shipping layout: Assets/Shaders/ next to the exe
// 2. Dev layout: ../../Assets/compiled/ (exe is in bin/x64Clang-<Config>/)
constexpr const char* kCandidates[] = {
"Assets/Shaders/",
"../../Assets/compiled/"
};
for (const char* candidate : kCandidates)
{
char probePath[512];
snprintf(probePath, sizeof(probePath), "%s%s", CStr(basePath), candidate);
if (DirectoryExists(probePath))
{
size_t len = strlen(probePath);
auto* buffer = static_cast<char*>(Calloc(len + 1, sizeof(char)));
if (buffer)
{
snprintf(buffer, len + 1, "%s", probePath);
CachedAssetBasePath = { buffer, len };
Log(LogLevel::Message, LogCategory::Core, "Asset base path: %s", buffer);
}
return;
}
}
Log(LogLevel::Error, LogCategory::Core, "Filesystem: Could not find Assets/compiled/ directory!");
}
void ShutdownFilesystem()
{
@@ -38,5 +107,10 @@ namespace Juliet
CachedBasePath.Size = 0;
SafeFree(CachedBasePath.Data);
}
if (IsValid(CachedAssetBasePath))
{
CachedAssetBasePath.Size = 0;
SafeFree(CachedAssetBasePath.Data);
}
}
} // namespace Juliet

View File

@@ -58,7 +58,7 @@ namespace Juliet::Platform
bool IsAbsolutePath(String path)
{
if (path.Data || path.Size == 0)
if (!path.Data || path.Size == 0)
{
return false;
}

View File

@@ -3,6 +3,8 @@
#include <Core/HAL/OS/OS.h>
#include <Core/HAL/OS/OS_Private.h>
#include <Core/HAL/Win32.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
namespace Juliet
{
@@ -15,7 +17,7 @@ namespace Juliet
{
Byte* OS_Reserve(size_t size)
{
auto result = static_cast<Byte*>(VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE));
auto* result = static_cast<Byte*>(VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE));
return result;
}
@@ -25,8 +27,12 @@ namespace Juliet
Assert(size <= static_cast<size_t>(MaxValueOf<DWORD>()));
if (w32_rio_functions.RIORegisterBuffer != nullptr && w32_rio_functions.RIODeregisterBuffer != nullptr)
{
w32_rio_functions.RIODeregisterBuffer(
w32_rio_functions.RIORegisterBuffer(reinterpret_cast<PCHAR>(ptr), static_cast<DWORD>(size)));
}
return result;
}
@@ -62,8 +68,6 @@ namespace Juliet
{
int OS_Main(EntryPointFunc entryPointFunc, int argc, wchar_t** argv)
{
(void)argc;
(void)argv;
SetUnhandledExceptionFilter(&ExceptionFilter);
// Allow only one instance to be launched.
@@ -82,7 +86,7 @@ namespace Juliet
DWORD rio_byte = 0;
SOCKET Sock = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
WSAIoctl(Sock, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
(void**)&w32_rio_functions, sizeof(w32_rio_functions), &rio_byte, nullptr, nullptr);
reinterpret_cast<void**>(&w32_rio_functions), sizeof(w32_rio_functions), &rio_byte, nullptr, nullptr);
closesocket(Sock);
}

View File

@@ -3,9 +3,10 @@
#include <Core/ImGui/ImGuiService.h>
#include <Core/ImGui/ImGuiTests.h>
#include <Core/Logging/LogManager.h>
#include <Core/Memory/MemoryArena.h>
#ifdef JULIET_ENABLE_IMGUI
#include <backends/imgui_impl_win32.h>
#include <imgui.h>
@@ -102,3 +103,5 @@ namespace Juliet::ImGuiService
Juliet::UnitTest::TestImGui();
}
} // namespace Juliet::ImGuiService
#endif // JULIET_ENABLE_IMGUI

View File

@@ -10,6 +10,7 @@ namespace Juliet::UnitTest
{
void TestImGui()
{
#ifdef JULIET_ENABLE_IMGUI
ImGuiContext* ctx = ImGuiService::GetContext();
if (ImGui::GetCurrentContext() != ctx)
@@ -68,5 +69,6 @@ namespace Juliet::UnitTest
(void)drawList;
printf("ImGui tests passed (Exhaustive).\n");
#endif
}
} // namespace Juliet::UnitTest

View File

@@ -75,12 +75,12 @@ namespace Juliet
void ArenaRelease(NonNullPtr<Arena> arena)
{
JULIET_DEBUG_ONLY(DebugUnregisterArena(arena);)
// Release active blocks (Current chain)
for (Arena *node = arena->Current, *previous = nullptr; node != nullptr; node = previous)
{
previous = node->Previous;
JULIET_DEBUG_ONLY(DebugUnregisterArena(node);)
JULIET_DEBUG_ONLY(DebugArenaFreeBlock(node);)
Memory::OS_Release(node, node->Reserved);

View File

@@ -68,6 +68,8 @@ namespace Juliet
{
arena->GlobalNext->GlobalPrev = arena->GlobalPrev;
}
arena->GlobalPrev = nullptr;
arena->GlobalNext = nullptr;
}
void DebugArenaSetDebugName(NonNullPtr<Arena> arena, const char* name)

View File

@@ -6,7 +6,9 @@
#include <Engine/Engine.h>
#include <Graphics/DebugDisplay.h>
#include <Graphics/Graphics.h>
#include <Graphics/MeshRenderer.h>
#include <Graphics/RenderPass.h>
#include <Graphics/SkyboxRenderer.h>
#include <time.h>
#ifdef JULIET_ENABLE_IMGUI
@@ -37,6 +39,16 @@ namespace Juliet
if (device)
{
DebugDisplay_Initialize(device);
if (Window* window = EngineInstance.Application->GetPlatformWindow())
{
bool success = InitializeMeshRendererGraphics(device, window);
Assert(success);
(void)(success);
success = InitializeSkyboxRenderer(device, window);
Assert(success);
(void)(success);
}
}
#ifdef JULIET_ENABLE_IMGUI
@@ -73,6 +85,8 @@ namespace Juliet
if (device)
{
DebugDisplay_Shutdown(device);
ShutdownSkyboxRenderer();
ShutdownMeshRendererGraphics();
}
}
@@ -122,6 +136,9 @@ namespace Juliet
Camera debugCamera = EngineInstance.Application->GetDebugCamera();
DebugDisplay_Flush(cmdList, pass, debugCamera);
// Note: The MeshRenderer and SkyboxRenderer draw calls are still inside Application->OnRender
// They shouldn't be moved here directly without an interface since they require PushData.
#ifdef JULIET_ENABLE_IMGUI
// ImGui rendering (always last before EndRenderPass)
ImGuiRenderer_Render(cmdList, pass);
@@ -136,6 +153,8 @@ namespace Juliet
void InitializeEngine(JulietInit_Flags flags)
{
EngineInstance.PlatformArena = ArenaAllocate({ .AllowRealloc = true } JULIET_DEBUG_PARAM("Platform Arena"));
InitializeLogManager();
#if JULIET_DEBUG
@@ -153,12 +172,17 @@ namespace Juliet
ShutdownFilesystem();
ShutdownLogManager();
ArenaRelease(EngineInstance.PlatformArena);
}
void LoadApplication(IApplication& app)
{
EngineInstance.Application = &app;
EngineInstance.Application->Init();
InitializeMeshRenderer(EngineInstance.PlatformArena);
EngineInstance.Application->Init(EngineInstance.PlatformArena);
// Systems depending on Window/GraphicsDevice
InitializeDependentSystems();
@@ -170,6 +194,9 @@ namespace Juliet
ShutdownDependentSystems();
EngineInstance.Application->Shutdown();
ShutdownMeshRenderer();
EngineInstance.Application = nullptr;
}

View File

@@ -38,7 +38,6 @@ namespace Juliet::D3D12
case BufferUsage::ConstantBuffer: return "ConstantBuffer";
case BufferUsage::StructuredBuffer: return "StructuredBuffer";
case BufferUsage::IndexBuffer: return "IndexBuffer";
case BufferUsage::VertexBuffer: return "VertexBuffer";
}
return "Unknown";
}
@@ -62,96 +61,63 @@ namespace Juliet::D3D12
Free(buffer);
}
D3D12Buffer* CreateBuffer(NonNullPtr<D3D12Driver> d3d12Driver, size_t size, BufferUsage usage, D3D12BufferType type)
D3D12Buffer* CreateBuffer(NonNullPtr<D3D12Driver> d3d12Driver, size_t size, size_t stride, BufferUsage usage,
D3D12BufferType type, bool isDynamic)
{
auto buffer = static_cast<D3D12Buffer*>(Calloc(1, sizeof(D3D12Buffer)));
auto* buffer = static_cast<D3D12Buffer*>(Calloc(1, sizeof(D3D12Buffer)));
if (!buffer)
{
return nullptr;
}
if (type == D3D12BufferType::Base && usage == BufferUsage::None)
{
Assert(false, "Creating Base buffer with BufferUsage::None is invalid");
DestroyBuffer(buffer);
return nullptr;
}
// Align size for Constant Buffers
if (usage == BufferUsage::ConstantBuffer)
{
size = (size + 255U) & ~255U;
}
D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON;
D3D12_HEAP_PROPERTIES heapProperties = {};
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON;
D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
switch (type)
{
case D3D12BufferType::Base:
{
switch (usage)
{
case BufferUsage::None:
{
Assert(false, "Creating buffer with invalid usage");
DestroyBuffer(buffer);
return nullptr;
}
// Constant buffers or Dynamic buffers generally need to be uploaded every frame
const bool isUpload = isDynamic || (type == D3D12BufferType::TransferUpload) || (usage == BufferUsage::ConstantBuffer);
case BufferUsage::IndexBuffer:
case BufferUsage::StructuredBuffer:
case BufferUsage::VertexBuffer:
{
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapFlags = D3D12_HEAP_FLAG_NONE;
break;
}
case BufferUsage::ConstantBuffer:
{
if (d3d12Driver->GPUUploadHeapSupported)
{
heapProperties.Type = D3D12_HEAP_TYPE_GPU_UPLOAD;
}
else
{
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;
break;
}
}
break;
}
case D3D12BufferType::TransferDownload:
if (type == D3D12BufferType::TransferDownload)
{
heapProperties.Type = D3D12_HEAP_TYPE_READBACK;
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapFlags = D3D12_HEAP_FLAG_NONE;
initialState = D3D12_RESOURCE_STATE_COPY_DEST;
break;
}
case D3D12BufferType::TransferUpload:
else if (isUpload)
{
if (d3d12Driver->GPUUploadHeapSupported)
{
heapProperties.Type = D3D12_HEAP_TYPE_GPU_UPLOAD;
initialState = D3D12_RESOURCE_STATE_COMMON;
}
else
{
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;
break;
}
else
{
// Must be a static buffer (Base type)
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
initialState = D3D12_RESOURCE_STATE_COMMON;
}
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
D3D12_RESOURCE_DESC desc = {};
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Alignment = 0;
@@ -167,20 +133,22 @@ namespace Juliet::D3D12
Log(LogLevel::Message, LogCategory::Graphics, "CreateBuffer: Device=%p, Size=%zu, Type=%s Use=%s",
(void*)d3d12Driver->D3D12Device, size, D3D12BufferTypeToString(type), BufferUsageToString(usage));
ID3D12Resource* handle = nullptr;
HRESULT result = d3d12Driver->D3D12Device->CreateCommittedResource(&heapProperties, heapFlags, &desc,
initialState, nullptr, IID_ID3D12Resource,
reinterpret_cast<void**>(&handle));
if (FAILED(result))
{
Log(LogLevel::Error, LogCategory::Graphics, "Could not create buffer! HRESULT=0x%08X", (uint32)result);
Log(LogLevel::Error, LogCategory::Graphics, "Could not create buffer! HRESULT=0x%08X", static_cast<uint32>(result));
Log(LogLevel::Error, LogCategory::Graphics, "Failed Desc: Width=%llu Layout=%d HeapType=%d",
(unsigned long long)desc.Width, (int)desc.Layout, (int)heapProperties.Type);
HRESULT removeReason = d3d12Driver->D3D12Device->GetDeviceRemovedReason();
if (FAILED(removeReason))
{
Log(LogLevel::Error, LogCategory::Graphics, "Device Removed Reason: 0x%08X", (uint32)removeReason);
Log(LogLevel::Error, LogCategory::Graphics, "Device Removed Reason: 0x%08X", static_cast<uint32>(removeReason));
}
DestroyBuffer(buffer);
@@ -205,6 +173,7 @@ namespace Juliet::D3D12
if (usage == BufferUsage::ConstantBuffer)
{
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
cbvDesc.BufferLocation = handle->GetGPUVirtualAddress();
cbvDesc.SizeInBytes = static_cast<uint32>(size);
d3d12Driver->D3D12Device->CreateConstantBufferView(&cbvDesc, cpuHandle);
@@ -212,13 +181,25 @@ namespace Juliet::D3D12
else if (usage == BufferUsage::StructuredBuffer)
{
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Buffer.FirstElement = 0;
if (stride > 0)
{
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
srvDesc.Buffer.NumElements = static_cast<uint32>(size / stride);
srvDesc.Buffer.StructureByteStride = static_cast<uint32>(stride);
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
}
else
{
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
srvDesc.Buffer.NumElements = static_cast<uint32>(size / 4);
srvDesc.Buffer.StructureByteStride = 0;
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
}
d3d12Driver->D3D12Device->CreateShaderResourceView(handle, &srvDesc, cpuHandle);
Log(LogLevel::Message, LogCategory::Graphics, " -> SRV DescriptorIndex=%u", descriptor.Index);
}
@@ -233,10 +214,10 @@ namespace Juliet::D3D12
}
} // namespace
GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage)
GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, size_t stride, BufferUsage usage, bool isDynamic)
{
auto d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
return reinterpret_cast<GraphicsBuffer*>(CreateBuffer(d3d12Driver, size, usage, D3D12BufferType::Base));
return reinterpret_cast<GraphicsBuffer*>(CreateBuffer(d3d12Driver, size, stride, usage, D3D12BufferType::Base, isDynamic));
}
void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer)
@@ -248,8 +229,9 @@ namespace Juliet::D3D12
{
auto d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
return reinterpret_cast<GraphicsTransferBuffer*>(
CreateBuffer(d3d12Driver, size, BufferUsage::None,
usage == TransferBufferUsage::Upload ? D3D12BufferType::TransferUpload : D3D12BufferType::TransferDownload));
CreateBuffer(d3d12Driver, size, 0, BufferUsage::None,
usage == TransferBufferUsage::Upload ? D3D12BufferType::TransferUpload : D3D12BufferType::TransferDownload,
false));
}
void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsTransferBuffer> buffer)
@@ -276,6 +258,24 @@ namespace Juliet::D3D12
d3d12Buffer->Handle->Unmap(0, nullptr);
}
void* MapBuffer(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer)
{
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
void* ptr = nullptr;
D3D12_RANGE readRange = { 0, 0 };
if (FAILED(d3d12Buffer->Handle->Map(0, &readRange, &ptr)))
{
return nullptr;
}
return ptr;
}
void UnmapBuffer(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer)
{
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
d3d12Buffer->Handle->Unmap(0, nullptr);
}
uint32 GetDescriptorIndex(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer)
{
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());

View File

@@ -20,7 +20,7 @@ namespace Juliet::D3D12
size_t Size;
};
extern GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage);
extern GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, size_t stride, BufferUsage usage, bool isDynamic);
extern void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer);
extern GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage);

View File

@@ -23,12 +23,6 @@
#define D3D12_CREATEDEVICE_FUNC "D3D12CreateDevice"
#define D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE_FUNC "D3D12SerializeVersionedRootSignature"
extern "C" {
// Used to enable the "Agility SDK" components
__declspec(dllexport) extern const unsigned int D3D12SDKVersion = 615;
__declspec(dllexport) extern const char* D3D12SDKPath = ".\\D3D12\\";
}
// TODO : Use LoadLibrary and not link to the lib. Allows failing earlier if Dx12 is not installed for some reason
// + Will load the dll when needed
// This will prevent us from using IID_ variables as they are defined in dxguid.lib
@@ -1040,6 +1034,8 @@ namespace Juliet::D3D12
device->DestroyGraphicsPipeline = DestroyGraphicsPipeline;
device->CreateGraphicsBuffer = CreateGraphicsBuffer;
device->DestroyGraphicsBuffer = DestroyGraphicsBuffer;
device->MapGraphicsBuffer = MapBuffer;
device->UnmapGraphicsBuffer = UnmapBuffer;
device->CreateGraphicsTransferBuffer = CreateGraphicsTransferBuffer;
device->DestroyGraphicsTransferBuffer = DestroyGraphicsTransferBuffer;
device->MapGraphicsTransferBuffer = MapBuffer;

View File

@@ -102,7 +102,9 @@ namespace Juliet::D3D12
events[i] = fence->Event;
}
LogDebug(LogCategory::Graphics, "Waiting for %d fences. Querier %s", numFences JULIET_DEBUG_PARAM(CStr(querier)));
#if JULIET_DEBUG
LogDebug(LogCategory::Graphics, "Waiting for %d fences. Querier %s", numFences, CStr(querier));
#endif
for (uint32 i = 0; i < numFences; ++i)
{
D3D12Fence* d3d12fence = reinterpret_cast<D3D12Fence*>(fences[i]);
@@ -152,8 +154,10 @@ namespace Juliet::D3D12
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
auto d3d12Fence = reinterpret_cast<D3D12Fence*>(fence.Get());
LogDebug(LogCategory::Graphics, "ReleaseFence Querier %s | %x fence. Handle %x | Event %x | Refcount %d",
CStr(querier), d3d12Fence, d3d12Fence->Handle, d3d12Fence->Event, d3d12Fence->ReferenceCount);
#if JULIET_DEBUG
LogDebug(LogCategory::Graphics, "ReleaseFence | %x fence. Handle %x | Event %x | Refcount %d | Querier %s", d3d12Fence,
d3d12Fence->Handle, d3d12Fence->Event, d3d12Fence->ReferenceCount, CStr(querier));
#endif
if (--d3d12Fence->ReferenceCount == 0)
{
ReleaseFenceToPool(d3d12driver, d3d12Fence);
@@ -224,21 +228,27 @@ namespace Juliet::D3D12
fence->Handle = handle;
fence->Event = CreateEvent(nullptr, false, false, nullptr);
fence->ReferenceCount = 0;
#if JULIET_DEBUG
LogDebug(LogCategory::Graphics, "Acquire Querier %s | Setting Signal to 0 NEW fence", CStr(querier));
#endif
}
else
{
fence = driver->AvailableFences[driver->AvailableFenceCount - 1];
driver->AvailableFenceCount -= 1;
fence->Handle->Signal(D3D12_FENCE_UNSIGNALED_VALUE);
#if JULIET_DEBUG
LogDebug(LogCategory::Graphics, "Acquire Querier %s | Setting Signal to 0, RECYCLING", CStr(querier));
#endif
}
fence->ReferenceCount += 1;
Assert(fence->ReferenceCount == 1);
#if JULIET_DEBUG
LogDebug(LogCategory::Graphics, "Acquire Querier %s | %x fence. Handle %x | Event %x | Refcount %d",
CStr(querier), fence, fence->Handle, fence->Event, fence->ReferenceCount);
#endif
return fence;
}

View File

@@ -2,8 +2,10 @@
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/Memory/Allocator.h>
#include <Graphics/GraphicsPipeline.h>
#include <Graphics/PushConstants.h>
namespace Juliet
{
@@ -84,11 +86,11 @@ namespace Juliet
ShaderCreateInfo shaderCI = {};
shaderCI.EntryPoint = entryPoint;
String vertPath = WrapString("../../Assets/compiled/Debug.vert.dxil");
String vertPath = GetAssetPath(WrapString("Debug.vert.dxil"));
shaderCI.Stage = ShaderStage::Vertex;
Shader* vertexShader = CreateShader(device, vertPath, shaderCI);
String fragPath = WrapString("../../Assets/compiled/Debug.frag.dxil");
String fragPath = GetAssetPath(WrapString("Debug.frag.dxil"));
shaderCI.Stage = ShaderStage::Fragment;
Shader* fragmentShader = CreateShader(device, fragPath, shaderCI);
@@ -298,19 +300,24 @@ namespace Juliet
// Render depth-tested primitives (vertices at offset 0 in buffer)
if (g_DebugState.DepthTestedVertexCount > 0 && g_DebugState.DepthTestedPipeline && g_DebugState.VertexBuffer)
{
BindGraphicsPipeline(renderPass, g_DebugState.DepthTestedPipeline);
// Pack VP matrix + buffer index into push constants
struct
{
Matrix vp;
uint32 bufferIndex;
uint32 vertexOffset; // Offset in vertices (not bytes)
uint32 padding[2];
} pushData;
pushData.vp = Camera_GetViewProjectionMatrix(camera);
pushData.bufferIndex = bufferIndex;
pushData.vertexOffset = 0; // Depth-tested vertices start at 0
PushData pushData = {};
pushData.ViewProjection = Camera_GetViewProjectionMatrix(camera);
pushData.MeshIndex = 0;
pushData.TransformsBufferIndex = 0; // Not used by debug shader but layout must match
pushData.BufferIndex = bufferIndex;
pushData.TextureIndex = 0;
pushData.VertexOffset = 0; // Depth-tested vertices start at 0
pushData.Padding = 0;
pushData.Scale[0] = 1.0f; pushData.Scale[1] = 1.0f;
pushData.Translate[0] = 0.0f; pushData.Translate[1] = 0.0f;
// Dummy light data as we don't light debug primitives
pushData.GlobalLightDirection = {0,0,-1};
pushData.GlobalLightPad = 0;
pushData.GlobalLightColor = {1,1,1};
pushData.GlobalAmbientIntensity = 1.0f;
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / sizeof(uint32), &pushData);
DrawPrimitives(renderPass, g_DebugState.DepthTestedVertexCount, 1, 0, 0);
@@ -322,16 +329,23 @@ namespace Juliet
BindGraphicsPipeline(renderPass, g_DebugState.OverlayPipeline);
// Pack VP matrix + buffer index into push constants
struct
{
Matrix vp;
uint32 bufferIndex;
uint32 vertexOffset; // Offset in vertices (not bytes)
uint32 padding[2];
} pushData;
pushData.vp = Camera_GetViewProjectionMatrix(camera);
pushData.bufferIndex = bufferIndex;
pushData.vertexOffset = kMaxDebugVertices / 2; // Overlay vertices start at half
PushData pushData = {};
pushData.ViewProjection = Camera_GetViewProjectionMatrix(camera);
pushData.MeshIndex = 0;
pushData.TransformsBufferIndex = 0;
pushData.BufferIndex = bufferIndex;
pushData.TextureIndex = 0;
pushData.VertexOffset = kMaxDebugVertices / 2; // Overlay vertices start at half
pushData.Padding = 0;
pushData.Scale[0] = 1.0f; pushData.Scale[1] = 1.0f;
pushData.Translate[0] = 0.0f; pushData.Translate[1] = 0.0f;
// Dummy light data as we don't light debug primitives
pushData.GlobalLightDirection = {0,0,-1};
pushData.GlobalLightPad = 0;
pushData.GlobalLightColor = {1,1,1};
pushData.GlobalAmbientIntensity = 1.0f;
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / sizeof(uint32), &pushData);
DrawPrimitives(renderPass, g_DebugState.OverlayVertexCount, 1, 0, 0);

View File

@@ -371,7 +371,7 @@ namespace Juliet
GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo)
{
return device->CreateGraphicsBuffer(device->Driver, createInfo.Size, createInfo.Usage);
return device->CreateGraphicsBuffer(device->Driver, createInfo.Size, createInfo.Stride, createInfo.Usage, createInfo.IsDynamic);
}
GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, const TransferBufferCreateInfo& createInfo)
@@ -379,6 +379,16 @@ namespace Juliet
return device->CreateGraphicsTransferBuffer(device->Driver, createInfo.Size, createInfo.Usage);
}
void* MapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
{
return device->MapGraphicsBuffer(device->Driver, buffer);
}
void UnmapGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
{
device->UnmapGraphicsBuffer(device->Driver, buffer);
}
void* MapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer)
{
return device->MapGraphicsTransferBuffer(device->Driver, buffer);

View File

@@ -100,9 +100,12 @@ namespace Juliet
void (*DestroyTexture)(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture);
// Buffers
GraphicsBuffer* (*CreateGraphicsBuffer)(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage);
GraphicsBuffer* (*CreateGraphicsBuffer)(NonNullPtr<GPUDriver> driver, size_t size, size_t stride, BufferUsage usage, bool isDynamic);
void (*DestroyGraphicsBuffer)(NonNullPtr<GraphicsBuffer> buffer);
void* (*MapGraphicsBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsBuffer> buffer);
void (*UnmapGraphicsBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsBuffer> buffer);
GraphicsTransferBuffer* (*CreateGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage);
void (*DestroyGraphicsTransferBuffer)(NonNullPtr<GraphicsTransferBuffer> buffer);

View File

@@ -5,6 +5,7 @@
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/Memory/MemoryArena.h>
#include <Graphics/GraphicsPipeline.h>
@@ -127,11 +128,11 @@ namespace Juliet
ShaderCreateInfo shaderCI = {};
shaderCI.EntryPoint = entryPoint;
String vertPath = WrapString("../../Assets/compiled/ImGui.vert.dxil");
String vertPath = GetAssetPath(WrapString("ImGui.vert.dxil"));
shaderCI.Stage = ShaderStage::Vertex;
g_ImGuiState.VertexShader = CreateShader(device, vertPath, shaderCI);
String fragPath = WrapString("../../Assets/compiled/ImGui.frag.dxil");
String fragPath = GetAssetPath(WrapString("ImGui.frag.dxil"));
shaderCI.Stage = ShaderStage::Fragment;
g_ImGuiState.FragmentShader = CreateShader(device, fragPath, shaderCI);
@@ -149,8 +150,8 @@ namespace Juliet
TextureCreateInfo texCI = {};
texCI.Type = TextureType::Texture_2D;
texCI.Width = (uint32)width;
texCI.Height = (uint32)height;
texCI.Width = static_cast<uint32>(width);
texCI.Height = static_cast<uint32>(height);
texCI.Format = TextureFormat::R8G8B8A8_UNORM;
texCI.Flags = TextureUsageFlag::Sampler;
@@ -159,10 +160,10 @@ namespace Juliet
texCI.SampleCount = TextureSampleCount::One;
g_ImGuiState.FontTexture = CreateTexture(device, texCI);
io.Fonts->SetTexID((ImTextureID)g_ImGuiState.FontTexture);
io.Fonts->SetTexID(reinterpret_cast<ImTextureID>(g_ImGuiState.FontTexture));
// Upload data
uint32 rowPitch = (uint32)width * 4u;
uint32 rowPitch = static_cast<uint32>(width) * 4u;
uint32 alignedRowPitch = (rowPitch + 255u) & ~255u;
uint32 textureSize = alignedRowPitch * static_cast<uint32>(height);
@@ -176,7 +177,7 @@ namespace Juliet
return false;
}
auto dst = (uint8*)MapGraphicsTransferBuffer(device, tb);
auto* dst = static_cast<uint8*>(MapGraphicsTransferBuffer(device, tb));
for (uint32 y = 0; y < static_cast<uint32>(height); ++y)
{
@@ -314,13 +315,13 @@ namespace Juliet
FrameResources& currentFrame = g_ImGuiState.Frames[g_ImGuiState.FrameIndex];
// Upload Buffers
uint32 totalVtx = (uint32)drawData->TotalVtxCount;
uint32 totalIdx = (uint32)drawData->TotalIdxCount;
uint32 totalVtx = static_cast<uint32>(drawData->TotalVtxCount);
uint32 totalIdx = static_cast<uint32>(drawData->TotalIdxCount);
EnsureBufferSize(currentFrame, totalVtx * sizeof(ImDrawVert), totalIdx * sizeof(ImDrawIdx));
auto vtxDst = (ImDrawVert*)MapGraphicsTransferBuffer(g_ImGuiState.Device, currentFrame.VertexUpload);
auto idxDst = (ImDrawIdx*)MapGraphicsTransferBuffer(g_ImGuiState.Device, currentFrame.IndexUpload);
auto* vtxDst = static_cast<ImDrawVert*>(MapGraphicsTransferBuffer(g_ImGuiState.Device, currentFrame.VertexUpload));
auto* idxDst = static_cast<ImDrawIdx*>(MapGraphicsTransferBuffer(g_ImGuiState.Device, currentFrame.IndexUpload));
for (int n = 0; n < drawData->CmdListsCount; n++)
{
@@ -402,28 +403,18 @@ namespace Juliet
SetScissorRect(renderPass, scissorRect);
// Bind Texture
uint32 textureIndex = GetDescriptorIndex(g_ImGuiState.Device, (Texture*)pcmd->GetTexID());
uint32 textureIndex = GetDescriptorIndex(g_ImGuiState.Device, reinterpret_cast<Texture*>(pcmd->GetTexID()));
// Push Constants
// Layout: ViewProjection(64) + BufferIndex(4) + TextureIndex(4) + VertexOffset(4) + Padding(4) + Scale(8) + Translate(8)
struct
{
float dummyVP[16]; // Occupy VP slot
uint32 bufferIndex;
uint32 textureIndex;
uint32 vertexOffset; // Base vertex for indexed bindless drawing
uint32 padding; // Alignment padding
float scale[2];
float translate[2];
} pushData = {}; // Zero-initialize all fields
PushData pushData = {}; // Zero-initialize all fields
pushData.bufferIndex = GetDescriptorIndex(g_ImGuiState.Device, currentFrame.VertexBuffer);
pushData.textureIndex = textureIndex;
pushData.vertexOffset = pcmd->VtxOffset + globalVtxOffset; // Pass vertex offset for bindless
pushData.scale[0] = scale[0];
pushData.scale[1] = scale[1];
pushData.translate[0] = translate[0];
pushData.translate[1] = translate[1];
pushData.BufferIndex = GetDescriptorIndex(g_ImGuiState.Device, currentFrame.VertexBuffer);
pushData.TextureIndex = textureIndex;
pushData.VertexOffset = pcmd->VtxOffset + globalVtxOffset; // Pass vertex offset for bindless
pushData.Scale[0] = scale[0];
pushData.Scale[1] = scale[1];
pushData.Translate[0] = translate[0];
pushData.Translate[1] = translate[1];
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);

View File

@@ -1,5 +1,6 @@
#include <Graphics/MeshRenderer.h>
#include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Math/Matrix.h>
@@ -11,92 +12,172 @@ namespace Juliet
{
namespace
{
MeshRenderer g_MeshRenderer;
struct MeshRendererState
{
GraphicsDevice* Device = nullptr;
GraphicsPipeline* Pipeline = nullptr;
GraphicsBuffer* VertexBuffer = nullptr;
GraphicsBuffer* IndexBuffer = nullptr;
GraphicsBuffer* LightsBuffer = nullptr;
GraphicsBuffer* TransformsBuffer = nullptr;
GraphicsTransferBuffer* LoadCopyBuffer = nullptr;
VectorArena<Mesh, kDefaultMeshNumber, false> Meshes;
VectorArena<Vertex, kDefaultVertexCount, false> Vertices;
VectorArena<Index, kDefaultIndexCount, false> Indices;
VectorArena<PointLight, kDefaultLightCount, false> PointLights;
PointLight* MappedLights = nullptr;
Matrix* MappedTransforms = nullptr;
};
MeshRendererState g_MeshRenderer;
} // namespace
bool InitializeMeshRenderer(NonNullPtr<Arena> arena, NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
void InitializeMeshRenderer(NonNullPtr<Arena> arena)
{
(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;
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"));
g_MeshRenderer.PointLights.Create(arena JULIET_DEBUG_PARAM("PointLights"));
}
bool InitializeMeshRendererGraphics(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
{
bool result = true;
GraphicsDevice* graphicsDevice = g_MeshRenderer.Device = device.Get();
// Create graphics pipeline
String entryPoint = WrapString("main");
ShaderCreateInfo shaderCI = {};
shaderCI.EntryPoint = entryPoint;
String shaderPath = GetAssetPath(WrapString("Triangle.vert.dxil"));
shaderCI.Stage = ShaderStage::Vertex;
Shader* vertexShader = CreateShader(graphicsDevice, shaderPath, shaderCI);
shaderPath = GetAssetPath(WrapString("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.RasterizerState.CullMode = CullMode::None;
pipelineCI.RasterizerState.FrontFace = FrontFace::Clockwise;
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.Stride = 0;
vertexBufferCI.Usage = BufferUsage::StructuredBuffer;
g_MeshRenderer.VertexBuffer = CreateGraphicsBuffer(graphicsDevice, vertexBufferCI);
Assert(g_MeshRenderer.VertexBuffer != nullptr);
BufferCreateInfo indexBufferCI = {};
indexBufferCI.Size = kIndexPage;
indexBufferCI.Usage = BufferUsage::IndexBuffer;
g_MeshRenderer.IndexBuffer = CreateGraphicsBuffer(graphicsDevice, indexBufferCI);
Assert(g_MeshRenderer.IndexBuffer != nullptr);
// Lights Buffer
BufferCreateInfo lightsBufferCI = {};
lightsBufferCI.Size = 1024 * sizeof(PointLight); // Max 1024 lights for now
lightsBufferCI.Stride = sizeof(PointLight);
lightsBufferCI.Usage = BufferUsage::StructuredBuffer;
lightsBufferCI.IsDynamic = true;
g_MeshRenderer.LightsBuffer = CreateGraphicsBuffer(graphicsDevice, lightsBufferCI);
Assert(g_MeshRenderer.LightsBuffer != nullptr);
g_MeshRenderer.MappedLights = static_cast<PointLight*>(MapGraphicsBuffer(graphicsDevice, g_MeshRenderer.LightsBuffer));
Assert(g_MeshRenderer.MappedLights != nullptr);
// Transforms Buffer
BufferCreateInfo transformsBufferCI = {};
transformsBufferCI.Size = 10000 * sizeof(Matrix); // Max 10000 meshes for now
transformsBufferCI.Stride = sizeof(Matrix);
transformsBufferCI.Usage = BufferUsage::StructuredBuffer;
transformsBufferCI.IsDynamic = true;
g_MeshRenderer.TransformsBuffer = CreateGraphicsBuffer(graphicsDevice, transformsBufferCI);
Assert(g_MeshRenderer.TransformsBuffer != nullptr);
g_MeshRenderer.MappedTransforms =
static_cast<Matrix*>(MapGraphicsBuffer(graphicsDevice, g_MeshRenderer.TransformsBuffer));
Assert(g_MeshRenderer.MappedTransforms != nullptr);
// Sync existing lights that might have been added before graphics initialization
for (index_t i = 0; i < g_MeshRenderer.PointLights.Count; ++i)
{
g_MeshRenderer.MappedLights[i] = g_MeshRenderer.PointLights.Data[i];
}
if (vertexShader)
{
DestroyShader(graphicsDevice, vertexShader);
}
if (fragmentShader)
{
DestroyShader(graphicsDevice, fragmentShader);
}
// Load evereything that is already in the vectors
CommandList* loadCmd = AcquireCommandList(device);
LoadMeshesOnGPU(loadCmd);
SubmitCommandLists(loadCmd);
return result;
}
void ShutdownMeshRendererGraphics()
{
if (g_MeshRenderer.LoadCopyBuffer)
{
UnmapGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
DestroyGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
g_MeshRenderer.LoadCopyBuffer = nullptr;
}
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.IndexBuffer);
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
if (g_MeshRenderer.LightsBuffer)
{
UnmapGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer);
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer);
g_MeshRenderer.LightsBuffer = nullptr;
}
if (g_MeshRenderer.TransformsBuffer)
{
UnmapGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer);
DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer);
g_MeshRenderer.TransformsBuffer = nullptr;
}
}
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();
g_MeshRenderer.Indices.Destroy();
g_MeshRenderer.Vertices.Destroy();
g_MeshRenderer.Meshes.Destroy();
g_MeshRenderer.PointLights.Destroy();
}
void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList)
@@ -119,12 +200,18 @@ namespace Juliet
Vertex* vertices = g_MeshRenderer.Vertices.Data;
if (!vertices)
{
UnmapGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
DestroyGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
g_MeshRenderer.LoadCopyBuffer = nullptr;
return;
}
Index* indices = g_MeshRenderer.Indices.Data;
if (!indices)
{
UnmapGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
DestroyGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
g_MeshRenderer.LoadCopyBuffer = nullptr;
return;
}
@@ -140,20 +227,7 @@ namespace Juliet
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;
// }
UnmapGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
CopyBuffer(cmdList, g_MeshRenderer.VertexBuffer, g_MeshRenderer.LoadCopyBuffer, totalVertexBytes, 0, 0);
CopyBuffer(cmdList, g_MeshRenderer.IndexBuffer, g_MeshRenderer.LoadCopyBuffer, totalIndexBytes, 0, indexOfByteOffset);
@@ -177,58 +251,136 @@ namespace Juliet
BindGraphicsPipeline(pass, g_MeshRenderer.Pipeline);
uint32 vertexDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
uint32 lightDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer);
uint32 transformsDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer);
pushData.BufferIndex = vertexDescriptorIndex;
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
pushData.LightBufferIndex = lightDescriptorIndex;
pushData.TransformsBufferIndex = transformsDescriptorIndex;
pushData.ActiveLightCount = static_cast<uint32>(g_MeshRenderer.PointLights.Count);
SetIndexBuffer(cmdList, g_MeshRenderer.IndexBuffer, IndexFormat::UInt16, g_MeshRenderer.Indices.Count, 0);
uint32 meshIndex = 0;
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);
if (g_MeshRenderer.MappedTransforms)
{
g_MeshRenderer.MappedTransforms[meshIndex] = mesh.Transform;
}
pushData.MeshIndex = meshIndex;
pushData.TextureIndex = 0;
pushData.VertexOffset = static_cast<uint32>(mesh.VertexOffset);
pushData.Padding = 0;
pushData.Scale[0] = 1.0f;
pushData.Scale[1] = 1.0f;
pushData.Translate[0] = 0.0f;
pushData.Translate[1] = 0.0f;
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
DrawIndexedPrimitives(pass, static_cast<uint32>(mesh.IndexCount), 1, static_cast<uint32>(mesh.IndexOffset),
static_cast<uint32>(mesh.VertexOffset), 0);
meshIndex++;
}
}
LightID AddPointLight(const PointLight& light)
{
Assert(g_MeshRenderer.PointLights.Count < kDefaultLightCount);
LightID id = g_MeshRenderer.PointLights.Count;
g_MeshRenderer.PointLights.PushBack(light);
if (g_MeshRenderer.MappedLights)
{
g_MeshRenderer.MappedLights[id] = light;
}
return id;
}
void SetPointLightPosition(LightID id, const Vector3& position)
{
Assert(id < static_cast<LightID>(g_MeshRenderer.PointLights.Count));
g_MeshRenderer.PointLights.Data[id].Position = position;
if (g_MeshRenderer.MappedLights)
{
g_MeshRenderer.MappedLights[id].Position = position;
}
}
void SetPointLightColor(LightID id, const Vector3& color)
{
Assert(id < static_cast<LightID>(g_MeshRenderer.PointLights.Count));
g_MeshRenderer.PointLights.Data[id].Color = color;
if (g_MeshRenderer.MappedLights)
{
g_MeshRenderer.MappedLights[id].Color = color;
}
}
void SetPointLightRadius(LightID id, float radius)
{
Assert(id < static_cast<LightID>(g_MeshRenderer.PointLights.Count));
g_MeshRenderer.PointLights.Data[id].Radius = radius;
if (g_MeshRenderer.MappedLights)
{
g_MeshRenderer.MappedLights[id].Radius = radius;
}
}
void SetPointLightIntensity(LightID id, float intensity)
{
Assert(id < static_cast<LightID>(g_MeshRenderer.PointLights.Count));
g_MeshRenderer.PointLights.Data[id].Intensity = intensity;
if (g_MeshRenderer.MappedLights)
{
g_MeshRenderer.MappedLights[id].Intensity = intensity;
}
}
void ClearPointLights()
{
g_MeshRenderer.PointLights.Clear();
}
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
constexpr Vertex vertexData[] = { // Front Face (Z = -0.5f) — Red
{ { -0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// 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
// Back Face (Z = 0.5f) — Green
{ { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// 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
// Top Face (Y = 0.5f) — Blue
{ { -0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// 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
// Bottom Face (Y = -0.5f) — Yellow
{ { -0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// 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
// Right Face (X = 0.5f) — Cyan
{ { 0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// 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
// Left Face (X = -0.5f) — Magenta
{ { -0.5f, 0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, 0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }
};
constexpr size_t cubeVertexCount = ArraySize(vertexData);
result.VertexCount = cubeVertexCount;
@@ -283,6 +435,12 @@ namespace Juliet
return g_MeshRenderer.Meshes.Count - 1;
}
void SetMeshTransform(MeshID id, const Matrix& transform)
{
Assert(id < static_cast<MeshID>(g_MeshRenderer.Meshes.Count));
g_MeshRenderer.Meshes.Data[id].Transform = transform;
}
#if ALLOW_SHADER_HOT_RELOAD
void ReloadMeshRendererShaders()
{
@@ -292,11 +450,11 @@ namespace Juliet
String entryPoint = WrapString("main");
ShaderCreateInfo shaderCI = {};
shaderCI.EntryPoint = entryPoint;
String shaderPath = WrapString("../../Assets/compiled/Triangle.vert.dxil");
String shaderPath = GetAssetPath(WrapString("Triangle.vert.dxil"));
shaderCI.Stage = ShaderStage::Vertex;
Shader* vertexShader = CreateShader(device, shaderPath, shaderCI);
shaderPath = WrapString("../../Assets/compiled/SolidColor.frag.dxil");
shaderPath = GetAssetPath(WrapString("SolidColor.frag.dxil"));
shaderCI.Stage = ShaderStage::Fragment;
Shader* fragmentShader = CreateShader(device, shaderPath, shaderCI);

View File

@@ -0,0 +1,104 @@
#include <Graphics/SkyboxRenderer.h>
#include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Graphics/GraphicsDevice.h>
#include <Graphics/PushConstants.h>
namespace Juliet
{
namespace
{
SkyboxRenderer g_SkyboxRenderer;
} // namespace
bool InitializeSkyboxRenderer(NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
{
bool result = true;
GraphicsDevice* graphicsDevice = g_SkyboxRenderer.Device = device.Get();
String skyboxVSEntry = WrapString("main");
ShaderCreateInfo skyboxVSCI = {};
skyboxVSCI.EntryPoint = skyboxVSEntry;
skyboxVSCI.Stage = ShaderStage::Vertex;
String vsPath = GetAssetPath(WrapString("Skybox.vert.dxil"));
Shader* skyboxVS = CreateShader(graphicsDevice, vsPath, skyboxVSCI);
String skyboxFSEntry = WrapString("main");
ShaderCreateInfo skyboxFSCI = {};
skyboxFSCI.EntryPoint = skyboxFSEntry;
skyboxFSCI.Stage = ShaderStage::Fragment;
String fsPath = GetAssetPath(WrapString("Skybox.frag.dxil"));
Shader* skyboxFS = CreateShader(graphicsDevice, fsPath, skyboxFSCI);
ColorTargetDescription colorTargetDesc = {};
colorTargetDesc.Format = GetSwapChainTextureFormat(graphicsDevice, window);
GraphicsPipelineCreateInfo skyboxPipelineCI = {};
skyboxPipelineCI.VertexShader = skyboxVS;
skyboxPipelineCI.FragmentShader = skyboxFS;
skyboxPipelineCI.PrimitiveType = PrimitiveType::TriangleList;
skyboxPipelineCI.TargetInfo.ColorTargetDescriptions = &colorTargetDesc;
skyboxPipelineCI.TargetInfo.NumColorTargets = 1;
skyboxPipelineCI.TargetInfo.DepthStencilFormat = TextureFormat::D32_FLOAT;
skyboxPipelineCI.TargetInfo.HasDepthStencilTarget = true;
skyboxPipelineCI.RasterizerState.FillMode = FillMode::Solid;
skyboxPipelineCI.RasterizerState.CullMode = CullMode::None;
skyboxPipelineCI.RasterizerState.FrontFace = FrontFace::Clockwise;
skyboxPipelineCI.DepthStencilState.EnableDepthTest = true;
skyboxPipelineCI.DepthStencilState.EnableDepthWrite = false;
skyboxPipelineCI.DepthStencilState.CompareOperation = CompareOperation::LessOrEqual;
g_SkyboxRenderer.Pipeline = CreateGraphicsPipeline(graphicsDevice, skyboxPipelineCI);
if (g_SkyboxRenderer.Pipeline == nullptr)
{
LogError(LogCategory::Graphics, "Failed to create skybox pipeline!");
result = false;
}
if (skyboxVS) DestroyShader(graphicsDevice, skyboxVS);
if (skyboxFS) DestroyShader(graphicsDevice, skyboxFS);
return result;
}
void ShutdownSkyboxRenderer()
{
if (g_SkyboxRenderer.Pipeline)
{
DestroyGraphicsPipeline(g_SkyboxRenderer.Device, g_SkyboxRenderer.Pipeline);
g_SkyboxRenderer.Pipeline = nullptr;
}
g_SkyboxRenderer = {};
}
void RenderSkybox(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, const Matrix& viewProjection)
{
if (!g_SkyboxRenderer.Pipeline)
{
return;
}
PushData pushData = {};
pushData.ViewProjection = viewProjection;
pushData.MeshIndex = 0;
pushData.TransformsBufferIndex = 0;
pushData.BufferIndex = 0;
BindGraphicsPipeline(pass, g_SkyboxRenderer.Pipeline);
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
SetPushConstants(cmdList, ShaderStage::Fragment, 0, sizeof(pushData) / 4, &pushData);
DrawPrimitives(pass, 3, 1, 0, 0);
}
#if ALLOW_SHADER_HOT_RELOAD
void ReloadSkyboxShaders()
{
// TODO
}
#endif
} // namespace Juliet

View File

@@ -59,8 +59,11 @@
.Libraries = {
'JulietApp-Lib-$Platform$-$BuildConfigName$',
'Juliet-Lib-$Platform$-$BuildConfigName$',
'Game-Lib-$Platform$-$BuildConfigName$',
'ImGui-Lib-$Platform$-$BuildConfigName$'
'Game-Lib-$Platform$-$BuildConfigName$'
}
If ( .BuildConfigName != 'Release' )
{
^Libraries + { 'ImGui-Lib-$Platform$-$BuildConfigName$' }
}

View File

@@ -1,5 +1,20 @@
#include "main.h"
#ifdef global
#undef global
#endif
#include <algorithm>
#include <ios>
#include <iosfwd>
#define global static
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#endif
#include <Core/Application/ApplicationManager.h>
#include <Core/Common/EnumUtils.h>
#include <Core/Common/String.h>
@@ -23,14 +38,40 @@
#include <Graphics/Mesh.h>
#include <Graphics/MeshRenderer.h>
#include <Graphics/RenderPass.h>
#include <Graphics/SkyboxRenderer.h>
#include <Graphics/VertexData.h>
#include <Juliet.h>
#ifdef JULIET_ENABLE_IMGUI
#include <imgui.h>
#endif
static bool ShowMemoryDebugger = false;
static bool animateCubes = true;
static bool animateLights = true;
static bool animateCamera = true;
static bool freeCameraMode = false;
static float camYaw = 0.0f;
static float camPitch = 0.0f;
static Juliet::Vector3 camPos = { 25.0f, 0.0f, 12.5f };
static float animateCubesTime = 0.0f;
static float animateLightsTime = 0.0f;
static float animateCameraTime = 0.0f;
static float redLightRadius = 10.0f;
static float redLightIntensity = 5.0f;
static float redLightColor[3] = { 1.0f, 0.2f, 0.2f };
static bool redLightFollowsCamera = false;
static bool enableGlobalLight = true;
static float globalLightDir[3] = { 0.5f, -1.0f, -0.5f };
static float globalLightColor[3] = { 1.0f, 0.95f, 0.8f };
static float globalAmbientIntensity = 0.2f;
static float blueLightRadius = 15.0f;
static float blueLightIntensity = 8.0f;
static float blueLightColor[3] = { 0.2f, 0.2f, 1.0f };
// TODO : Replace with message box from framework + call main and not winmain + subsystem
// TODO : Think how to do the draw pipeline.
@@ -44,13 +85,6 @@ static bool ShowMemoryDebugger = false;
using namespace Juliet;
extern "C" {
__declspec(dllexport) extern const unsigned int D3D12SDKVersion = 615;
}
extern "C" {
__declspec(dllexport) extern const char* D3D12SDKPath = ".\\";
}
namespace
{
using GameInit_t = void (*)(GameInitParams*);
@@ -65,21 +99,20 @@ namespace
const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" };
Arena* PlatformArena = nullptr;
LightID RedLightID = 0;
LightID BlueLightID = 0;
} // namespace
void JulietApplication::Init()
void JulietApplication::Init(NonNullPtr<Arena>)
{
Log(LogLevel::Message, LogCategory::Tool, "Initializing Juliet Application...");
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;
#endif
GraphicsDevice = CreateGraphicsDevice(config);
MainWindow = CreatePlatformWindow("Juliet Editor", 1280, 720);
@@ -90,8 +123,6 @@ void JulietApplication::Init()
{
AttachToWindow(GraphicsDevice, MainWindow);
{
Running = InitializeMeshRenderer(PlatformArena, GraphicsDevice, MainWindow);
// Create Depth Buffer
TextureCreateInfo depthCI = {};
depthCI.Type = TextureType::Texture_2D;
@@ -109,18 +140,40 @@ void JulietApplication::Init()
Running = false;
}
// std::ignore = AddCube();
//
// CommandList* loadCmd = AcquireCommandList(GraphicsDevice);
// LoadMeshesOnGPU(loadCmd);
// SubmitCommandLists(loadCmd);
constexpr int kGridSize = 10;
constexpr float kSpacing = 2.5f;
constexpr float kOffset = (kGridSize - 1) * kSpacing * 0.5f;
if (Running == false)
for (int row = 0; row < kGridSize; ++row)
{
return;
for (int col = 0; col < kGridSize; ++col)
{
MeshID cube = AddCube();
float x = static_cast<float>(col) * kSpacing - kOffset;
float y = static_cast<float>(row) * kSpacing - kOffset;
float seed = static_cast<float>(row * kGridSize + col);
Matrix rotation = MatrixRotation(seed * 0.73f, seed * 1.17f, seed * 0.53f);
SetMeshTransform(cube, MatrixTranslation(x, y, 0.0f) * rotation);
}
}
// Start with some default test lights
PointLight redLight = {};
redLight.Position = { 5.0f, 5.0f, 2.0f };
redLight.Radius = redLightRadius;
redLight.Color = { redLightColor[0], redLightColor[1], redLightColor[2] };
redLight.Intensity = redLightIntensity;
RedLightID = AddPointLight(redLight);
PointLight blueLight = {};
blueLight.Position = { -5.0f, 0.0f, 2.0f };
blueLight.Radius = blueLightRadius;
blueLight.Color = { blueLightColor[0], blueLightColor[1], blueLightColor[2] };
blueLight.Intensity = blueLightIntensity;
BlueLightID = AddPointLight(blueLight);
}
GameCode.Functions = reinterpret_cast<void**>(&Game);
GameCode.FunctionCount = ArraySize(GameFunctionTable);
GameCode.FunctionNames = GameFunctionTable;
@@ -155,8 +208,6 @@ void JulietApplication::Shutdown()
DestroyTexture(GraphicsDevice, DepthBuffer);
}
ShutdownMeshRenderer();
if (MainWindow && GraphicsDevice)
{
DetachFromWindow(GraphicsDevice, MainWindow);
@@ -172,15 +223,44 @@ void JulietApplication::Shutdown()
DestroyGraphicsDevice(GraphicsDevice);
}
ArenaRelease(PlatformArena);
Log(LogLevel::Message, LogCategory::Tool, "Juliet App shutdown Completed");
}
void JulietApplication::Update()
{
static LARGE_INTEGER frequency = {};
static LARGE_INTEGER lastTime = {};
if (frequency.QuadPart == 0)
{
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&lastTime);
}
LARGE_INTEGER currentTime;
QueryPerformanceCounter(&currentTime);
float deltaTime = static_cast<float>(currentTime.QuadPart - lastTime.QuadPart) / static_cast<float>(frequency.QuadPart);
lastTime = currentTime;
CameraTime += deltaTime;
static float fpsTimer = 0.0f;
static int fpsFrames = 0;
fpsTimer += deltaTime;
fpsFrames++;
if (fpsTimer >= 0.5f)
{
float fps = static_cast<float>(fpsFrames) / fpsTimer;
float ms = (fpsTimer / static_cast<float>(fpsFrames)) * 1000.0f;
char title[64];
snprintf(title, sizeof(title), "Juliet | %.1f FPS | %.2f ms", static_cast<double>(fps), static_cast<double>(ms));
SetWindowTitle(MainWindow, WrapString(title));
fpsTimer = 0.0f;
fpsFrames = 0;
}
bool reloadShaders = false;
static bool reloadShadersDebounce = false;
static bool f1Debounce = false;
SystemEvent evt;
while (GetEvent(evt))
@@ -206,14 +286,216 @@ void JulietApplication::Update()
}
}
static bool firstFreeFrame = false;
if (IsKeyDown(ScanCode::F1))
{
if (!f1Debounce)
{
freeCameraMode = !freeCameraMode;
if (freeCameraMode)
{
firstFreeFrame = true;
}
f1Debounce = true;
}
}
else
{
f1Debounce = false;
}
// Confine and hide the mouse for Free Camera mode
if (freeCameraMode)
{
#ifdef JULIET_ENABLE_IMGUI
// ImGui::ShowDemoWindow();
ImGui::SetMouseCursor(ImGuiMouseCursor_None);
#endif
#ifdef _WIN32
HWND hwnd = GetForegroundWindow();
if (hwnd)
{
RECT rect;
GetClientRect(hwnd, &rect);
POINT ptCenterClient = { (rect.right - rect.left) / 2, (rect.bottom - rect.top) / 2 };
if (!firstFreeFrame)
{
POINT currentPos;
GetCursorPos(&currentPos);
ScreenToClient(hwnd, &currentPos);
float deltaX = static_cast<float>(currentPos.x - ptCenterClient.x);
float deltaY = static_cast<float>(currentPos.y - ptCenterClient.y);
float sensitivity = 0.005f;
// Plus because the mouse is inverted inherently by windows to screen coordinate
camYaw += deltaX * sensitivity;
camPitch -= deltaY * sensitivity;
camPitch = std::min(camPitch, 1.5f);
camPitch = std::max(camPitch, -1.5f);
}
firstFreeFrame = false;
POINT ptCenterScreen = ptCenterClient;
ClientToScreen(hwnd, &ptCenterScreen);
SetCursorPos(ptCenterScreen.x, ptCenterScreen.y);
}
#endif
}
if (freeCameraMode)
{
float speed = 10.0f * deltaTime;
if ((GetKeyModState() & KeyMod::Shift) != KeyMod::None)
{
speed *= 3.0f;
}
Vector3 forward = { cosf(camYaw) * cosf(camPitch), sinf(camYaw) * cosf(camPitch), sinf(camPitch) };
Vector3 right = { cosf(camYaw + 1.5708f), sinf(camYaw + 1.5708f), 0.0f };
Vector3 up = { 0.0f, 0.0f, 1.0f };
if (IsKeyDown(ScanCode::W))
{
camPos = camPos + forward * speed;
}
if (IsKeyDown(ScanCode::S))
{
camPos = camPos - forward * speed;
}
if (IsKeyDown(ScanCode::D))
{
camPos = camPos + right * speed;
}
if (IsKeyDown(ScanCode::A))
{
camPos = camPos - right * speed;
}
if (IsKeyDown(ScanCode::E))
{
camPos = camPos + up * speed;
}
if (IsKeyDown(ScanCode::Q))
{
camPos = camPos - up * speed;
}
}
if (animateCubes)
{
animateCubesTime += deltaTime;
}
if (animateLights)
{
animateLightsTime += deltaTime;
}
if (animateCamera)
{
animateCameraTime += deltaTime;
}
#ifdef JULIET_ENABLE_IMGUI
ImGui::Begin("Debug Controls");
ImGui::Checkbox("Animate Cubes", &animateCubes);
ImGui::Checkbox("Animate Lights", &animateLights);
ImGui::Checkbox("Animate Camera", &animateCamera);
ImGui::Separator();
ImGui::Text("Global Light");
ImGui::Checkbox("Enable Global Light", &enableGlobalLight);
if (enableGlobalLight)
{
ImGui::SliderFloat3("Direction", globalLightDir, -1.0f, 1.0f);
ImGui::ColorEdit3("Color", globalLightColor);
ImGui::SliderFloat("Ambient Intensity", &globalAmbientIntensity, 0.0f, 1.0f);
}
ImGui::Separator();
ImGui::Text("Red Point Light");
ImGui::ColorEdit3("Red Color", redLightColor);
ImGui::SliderFloat("Red Radius", &redLightRadius, 1.0f, 50.0f);
ImGui::SliderFloat("Red Intensity", &redLightIntensity, 0.0f, 50.0f);
ImGui::Checkbox("Red Light Follows Camera", &redLightFollowsCamera);
ImGui::Separator();
ImGui::Text("Blue Point Light");
ImGui::ColorEdit3("Blue Color", blueLightColor);
ImGui::SliderFloat("Blue Radius", &blueLightRadius, 1.0f, 50.0f);
ImGui::SliderFloat("Blue Intensity", &blueLightIntensity, 0.0f, 50.0f);
ImGui::End();
#endif
ArenaClear(GameScratchArena);
Vector3 redLightPos = { 5.0f, 5.0f, 2.0f };
Vector3 blueLightPos = { -5.0f, 0.0f, 2.0f };
if (animateLights || animateLightsTime > 0.0f)
{
redLightPos = { cosf(animateLightsTime * 2.0f) * 5.0f, sinf(animateLightsTime * 2.0f) * 5.0f, 2.0f };
blueLightPos = { -5.0f, cosf(animateLightsTime) * 3.0f, 2.0f };
}
if (redLightFollowsCamera)
{
Camera cam = GetDebugCamera();
redLightPos = cam.Position;
}
SetPointLightPosition(RedLightID, redLightPos);
SetPointLightPosition(BlueLightID, blueLightPos);
SetPointLightColor(RedLightID, { redLightColor[0], redLightColor[1], redLightColor[2] });
SetPointLightRadius(RedLightID, redLightRadius);
SetPointLightIntensity(RedLightID, redLightIntensity);
SetPointLightColor(BlueLightID, { blueLightColor[0], blueLightColor[1], blueLightColor[2] });
SetPointLightRadius(BlueLightID, blueLightRadius);
SetPointLightIntensity(BlueLightID, blueLightIntensity);
// Animate the 100 cubes (10x10 grid)
constexpr int kGridSize = 10;
constexpr float kSpacing = 2.5f;
constexpr float kOffset = (kGridSize - 1) * kSpacing * 0.5f;
for (int row = 0; row < kGridSize; ++row)
{
for (int col = 0; col < kGridSize; ++col)
{
MeshID cube = static_cast<MeshID>(row * kGridSize + col); // Assuming they were added first
float x = static_cast<float>(col) * kSpacing - kOffset;
float y = static_cast<float>(row) * kSpacing - kOffset;
float seed = static_cast<float>(cube);
float timeZ = animateCubesTime * 2.0f + seed * 0.5f;
float z = 0.0f;
float scaleF = 1.0f;
Matrix rotation = MatrixIdentity();
if (animateCubes || animateCubesTime > 0.0f)
{
z = sinf(timeZ) * 1.5f; // Oscillate up and down
scaleF = 1.0f + sinf(animateCubesTime * 1.5f + seed) * 0.3f; // Pulse scale
rotation = MatrixRotation(animateCubesTime * 1.2f + seed * 0.73f, animateCubesTime * 0.8f + seed * 1.17f,
animateCubesTime * 0.5f + seed * 0.53f);
}
Matrix scale = MatrixScale(scaleF, scaleF, scaleF);
SetMeshTransform(cube, MatrixTranslation(x, y, z) * rotation * scale);
}
}
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);
DebugDisplay_DrawSphere(blueLightPos, 0.5f, { 0.0f, 0.0f, 1.0f, 1.0f }, true);
DebugDisplay_DrawSphere(redLightPos, 0.5f, { 1.0f, 0.0f, 0.0f, 1.0f }, true);
Game.Update(0.0f);
@@ -269,14 +551,26 @@ void JulietApplication::Update()
void JulietApplication::OnPreRender(CommandList* /*cmd*/) {}
void JulietApplication::OnRender(RenderPass*, CommandList*)
void JulietApplication::OnRender(RenderPass* pass, CommandList* cmd)
{
// PushData pushData = {};
// pushData.ViewProjection = Camera_GetViewProjectionMatrix(GetDebugCamera());
PushData pushData = {};
pushData.ViewProjection = Camera_GetViewProjectionMatrix(GetDebugCamera());
// RenderMeshes(pass, cmd, pushData);
if (enableGlobalLight)
{
pushData.GlobalLightDirection = Normalize({ globalLightDir[0], globalLightDir[1], globalLightDir[2] });
pushData.GlobalLightColor = { globalLightColor[0], globalLightColor[1], globalLightColor[2] };
pushData.GlobalAmbientIntensity = globalAmbientIntensity;
}
else
{
pushData.GlobalLightDirection = { 0.0f, -1.0f, 0.0f };
pushData.GlobalLightColor = { 0.0f, 0.0f, 0.0f };
pushData.GlobalAmbientIntensity = 0.0f;
}
// SetPushConstants(cmd, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
RenderSkybox(pass, cmd, pushData.ViewProjection);
RenderMeshes(pass, cmd, pushData);
}
ColorTargetInfo JulietApplication::GetColorTargetInfo(Texture* swapchainTexture)
@@ -301,21 +595,33 @@ DepthStencilTargetInfo* JulietApplication::GetDepthTargetInfo()
Camera JulietApplication::GetDebugCamera()
{
static float time = 0.0f;
time += 0.016f;
float orbitSpeed = 0.5f;
float currentOrbitTime = time * orbitSpeed;
if (freeCameraMode)
{
Camera cam = {};
cam.Position = camPos;
cam.Target = camPos + Vector3{ cosf(camYaw) * cosf(camPitch), sinf(camYaw) * cosf(camPitch), sinf(camPitch) };
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;
}
// --- Adjusted for 1-Meter Scale ---
float baseRadius = 2.5f; // Hover 2.5 meters away (down from 15.0f)
float baseRadius = 25.0f; // Increased to see 10x10 cube grid
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);
*/
if (animateCamera || animateCameraTime > 0.0f)
{
float orbitSpeed = 0.5f;
float currentOrbitTime = animateCameraTime * orbitSpeed;
float zoomAmplitude = 15.0f;
float zoomSpeed = 0.5f;
radius = baseRadius + (sinf(animateCameraTime * zoomSpeed) * zoomAmplitude);
float zHeight = radius * 0.5f; // Keep a nice downward viewing angle
Camera cam = {};
@@ -330,6 +636,20 @@ Camera JulietApplication::GetDebugCamera()
return cam;
}
float zHeight = radius * 0.5f; // Keep a nice downward viewing angle
Camera cam = {};
cam.Position = { radius, 0.0f, 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;
}
bool JulietApplication::IsRunning()
{
return Running;

View File

@@ -18,7 +18,7 @@ namespace Juliet
class JulietApplication : public Juliet::IApplication
{
protected:
void Init() override;
void Init(Juliet::NonNullPtr<Juliet::Arena> arena) override;
void Shutdown() override;
void Update() override;
bool IsRunning() override;
@@ -48,6 +48,7 @@ class JulietApplication : public Juliet::IApplication
int AutoCloseFrameCount = -1;
bool Running = false;
float CameraTime = 0.0f;
};
JulietApplication& GetEditorApplication();

View File

View File

@@ -1,630 +0,0 @@
[2026-02-21 23:07:28.6894112] Starting Unit Tests...
Running Paged Memory Arena Tests...
[2026-02-21 23:07:28.6896698] Allocating from W:\Classified\Juliet\Juliet\src\Core\Memory\MemoryArenaTests.cpp : 23l
[2026-02-21 23:07:28.6897701] Allocating from W:\Classified\Juliet\Juliet\src\Core\Memory\MemoryArena.cpp : 181l
[2026-02-21 23:07:28.7003022] Allocating from W:\Classified\Juliet\Juliet\src\Core\Memory\MemoryArenaTests.cpp : 122l
[2026-02-21 23:07:28.7005045] Allocating from W:\Classified\Juliet\Juliet\src\Core\Memory\MemoryArenaTests.cpp : 141l
All Paged MemoryArena tests passed.
[2026-02-21 23:07:28.7006190] Allocating from Juliet/include\Core/Container/Vector.h : 22l
[2026-02-21 23:07:28.7007239] Allocating from Juliet/include\Core/Container/Vector.h : 22l
[2026-02-21 23:07:28.7008239] Allocating from Juliet/include\Core/Container/Vector.h : 22l
[2026-02-21 23:07:28.7009231] Allocating from Juliet/include\Core/Container/Vector.h : 22l
[2026-02-21 23:07:28.7010362] Allocating from W:\Classified\Juliet\Juliet\src\UnitTest\Container\VectorUnitTest.cpp : 152l
[2026-02-21 23:07:28.7011542] Allocating from W:\Classified\Juliet\Juliet\src\UnitTest\Container\VectorUnitTest.cpp : 212l
[2026-02-21 23:07:28.7013055] Allocating from W:\Classified\Juliet\Juliet\src\UnitTest\Container\VectorUnitTest.cpp : 231l
[2026-02-21 23:07:28.7014501] Allocating from W:\Classified\Juliet\Juliet\src\UnitTest\Container\VectorUnitTest.cpp : 258l
[2026-02-21 23:07:28.7015854] Allocating from W:\Classified\Juliet\Juliet\src\UnitTest\Container\VectorUnitTest.cpp : 275l
[2026-02-21 23:07:28.7017277] Unit Tests Completed Successfully.
[2026-02-21 23:07:28.7018198] Allocating from W:\Classified\Juliet\Juliet\src\Core\HAL\Display\Display.cpp : 26l
[2026-02-21 23:07:28.7019410] Allocating from Juliet/include\Core/Container/Vector.h : 22l
[2026-02-21 23:07:28.7020442] Initializing Juliet Application...
[2026-02-21 23:07:28.7021156] W:\Classified\Juliet\bin\x64Clang-Debug\
[2026-02-21 23:07:28.7021800] Allocating from W:\Classified\Juliet\JulietApp\main.cpp : 77l
[2026-02-21 23:07:28.9129941] Allocating from W:\Classified\Juliet\Juliet\src\Graphics\D3D12\D3D12GraphicsDevice.cpp : 710l
[2026-02-21 23:07:28.9142381] D3D12 Driver Infos:
[2026-02-21 23:07:28.9143146] D3D12 Adapter: AMD Radeon RX 5700 XT
[2026-02-21 23:07:28.9143699] D3D12 Driver Version: 32.0.21041.1000
[2026-02-21 23:07:29.0218143] DX12: D3D12Device Created: 000001E74B43C060
[2026-02-21 23:07:29.0219203] DX12: Debug Info Logger Initialized
[2026-02-21 23:07:29.0252979] Allocating from W:\Classified\Juliet\Juliet\src\Graphics\D3D12\D3D12Common.cpp : 52l
[2026-02-21 23:07:29.0255980] Allocating from W:\Classified\Juliet\Juliet\src\Graphics\D3D12\D3D12Common.cpp : 52l
[2026-02-21 23:07:29.0257980] Allocating from W:\Classified\Juliet\Juliet\src\Graphics\D3D12\D3D12Common.cpp : 52l
[2026-02-21 23:07:29.0260445] Allocating from W:\Classified\Juliet\Juliet\src\Graphics\D3D12\D3D12Common.cpp : 52l
[2026-02-21 23:07:29.0262559] Allocating from W:\Classified\Juliet\Juliet\src\Graphics\D3D12\D3D12DescriptorHeap.cpp : 15l
[2026-02-21 23:07:29.0329752] Allocating from W:\Classified\Juliet\Juliet\src\Core\HAL\Display\Display.cpp : 83l
[2026-02-21 23:07:29.0726746] Allocating from W:\Classified\Juliet\Juliet\src\Core\HotReload\HotReload.cpp : 14l
[2026-02-21 23:07:29.1009264] Allocating from W:\Classified\Juliet\JulietApp\main.cpp : 131l
[2026-02-21 23:07:29.1010784] Allocating from W:\Classified\Juliet\JulietApp\main.cpp : 132l
Game Arena Allocated: 000001E718000080
Door is Opened
Rock has 100 health points
[2026-02-21 23:07:29.1012934] CreateBuffer: Device=000001E74B43C060, Size=458752, Type=Base Use=StructuredBuffer
[2026-02-21 23:07:29.1021401] -> SRV DescriptorIndex=1
[2026-02-21 23:07:29.1022149] CreateBuffer: Device=000001E74B43C060, Size=458752, Type=TransferUpload Use=None
[2026-02-21 23:07:29.1039161] Acquire Querier SubmitCommandLists | Setting Signal to 0 NEW fence
[2026-02-21 23:07:29.1040168] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.1049359] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.1080351] Acquire Querier SubmitCommandLists | Setting Signal to 0 NEW fence
[2026-02-21 23:07:29.1081700] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.1086393] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.1094686] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.1095416] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.1096043] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.1096697] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.1100872] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.1101673] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.1115502] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.1116597] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.1117262] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.1117877] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.1119523] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.1120219] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.1219018] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.1220233] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.1548977] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.1550120] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.1550761] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.1552723] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.1553462] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.1556713] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.1557420] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.1883044] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.1884217] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.1884842] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.1886605] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.1887304] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.1890054] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.1890773] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.2217941] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.2219489] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.2220127] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.2221841] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.2222537] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.2225840] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.2229455] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.2383337] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.2384502] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.2385116] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.2386715] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.2387404] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.2390131] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.2390831] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.2550069] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.2551509] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.2552277] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.2554968] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.2555885] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.2559458] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.2560186] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.2716329] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.2717566] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.2718188] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.2719830] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.2720524] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.2723588] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.2724293] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.2883261] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.2884544] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.2885176] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.2886957] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.2887651] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.2890525] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.2891224] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.3049791] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.3051053] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.3051742] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.3053687] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.3054490] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.3057488] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.3058663] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.3217358] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.3221037] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.3221787] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.3223392] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.3224151] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.3226868] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.3227563] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.3384015] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.3385231] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.3385849] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.3387972] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.3388806] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.3391764] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.3392454] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.3549502] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.3550678] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.3551300] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.3553365] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.3554239] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.3557324] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.3558173] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.3718790] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.3720342] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.3720964] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.3722930] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.3723626] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.3727154] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.3727858] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.3883475] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.3884716] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.3885407] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.3887072] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.3887751] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.3890449] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.3891139] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.4050130] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.4051451] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.4052211] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.4057504] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.4058242] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.4061362] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.4062069] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.4220033] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.4221699] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.4222655] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.4224440] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.4225130] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.4228507] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.4230289] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.4383211] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.4384322] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.4384929] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.4386460] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.4387140] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.4389800] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.4390485] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.4551206] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.4552471] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.4553160] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.4555175] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.4555999] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.4559124] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.4559860] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.4716976] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.4718104] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.4718706] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.4720319] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.4720992] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.4723706] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.4724395] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.4885510] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.4886733] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.4887339] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.4889002] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.4889685] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.4897593] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.4898428] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.5050352] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.5051512] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.5052118] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.5053676] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.5054354] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.5057139] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.5057836] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.5217239] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.5218315] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.5218914] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.5220452] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.5221130] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.5223847] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.5224647] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.5386262] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.5387997] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.5388616] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.5391048] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.5391783] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.5395836] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.5396547] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.5551587] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.5552707] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.5553349] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.5554919] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.5555694] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.5558460] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.5559151] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.5718849] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.5720184] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.5720876] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.5722595] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.5723368] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.5725932] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.5726729] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.5884407] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.5888274] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.5889019] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.5890669] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.5891355] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.5894190] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.5894895] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.6050657] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.6051767] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.6052379] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.6053974] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.6054653] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.6057525] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.6058220] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.6219736] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.6221289] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.6221919] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.6223510] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.6224542] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.6228430] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.6229127] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.6384486] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.6385667] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.6386281] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.6387914] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.6388594] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.6391646] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.6392352] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.6552723] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.6554321] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.6555066] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.6556890] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.6557586] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.6561253] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.6561985] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.6718770] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.6719922] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.6723202] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.6725049] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.6725750] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.6728510] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.6729221] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.6885332] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.6886638] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.6887277] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.6888980] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.6889667] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.6892578] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.6893267] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.7051422] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.7052573] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.7053184] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.7054859] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.7055545] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.7058434] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.7059136] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.7218363] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.7219475] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.7220075] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.7221733] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.7222401] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.7225114] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.7225796] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.7385886] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.7387196] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.7388121] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.7389703] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.7390388] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.7394514] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.7395229] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.7552948] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.7554259] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.7554947] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.7557460] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.7558396] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.7564970] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.7565703] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.7721069] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.7722609] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.7723235] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.7725031] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.7725708] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.7728847] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.7729540] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.7884869] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.7886006] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.7886609] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.7888126] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.7888803] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.7891520] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.7892211] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.8051647] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.8052788] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.8053391] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.8054907] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.8055588] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.8058434] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.8059125] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.8221185] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.8222806] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.8223454] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.8225130] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.8225832] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.8228357] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.8229053] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.8385143] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.8386319] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.8387099] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.8388683] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.8389361] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.8392851] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.8393554] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.8554379] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.8556217] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.8556853] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.8558672] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.8559452] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.8562899] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.8563617] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.8718738] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.8719845] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.8720455] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.8721995] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.8722675] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.8725372] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.8726060] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.8888543] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.8890323] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.8890972] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.8892723] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.8893406] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.8896374] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.8897080] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.9053885] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.9055292] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.9056066] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.9057839] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.9058523] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.9061407] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.9062118] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.9219003] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.9220143] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.9220750] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.9222255] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.9222932] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.9225559] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.9226248] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.9385972] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.9387316] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.9391049] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.9393074] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.9393908] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.9396707] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.9397408] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.9552388] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.9553648] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.9554337] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.9556054] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.9556743] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.9559709] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.9560405] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.9720518] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:29.9722343] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.9723022] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:29.9724586] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.9725273] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:29.9728006] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.9728701] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.9886030] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:29.9887199] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.9887806] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:29.9889336] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:29.9890017] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:29.9892699] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:29.9893386] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.0053965] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.0055551] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.0056632] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.0058710] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.0059511] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.0065715] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.0066695] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.0220242] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.0221446] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.0222055] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.0223888] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.0226947] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.0229638] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.0230325] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.0385920] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.0387046] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.0387652] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.0389172] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.0389853] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.0393007] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.0393702] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.0553859] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.0555243] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.0555846] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.0557679] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.0558741] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.0561754] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.0562440] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.0719620] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.0720909] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.0721606] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.0723293] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.0724063] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.0727013] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.0727731] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.0886654] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.0887876] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.0888576] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.0890166] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.0890853] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.0893541] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.0894225] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.1053791] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.1054946] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.1055561] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.1057296] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.1057975] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.1060846] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.1064736] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.1219319] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.1220436] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.1221049] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.1222529] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.1223210] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.1225809] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.1226495] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.1387337] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.1388585] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.1389202] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.1390910] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.1391698] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.1394527] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.1395222] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.1552434] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.1553487] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.1554091] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.1555737] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.1556415] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.1559313] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.1560008] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.1721813] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.1723668] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.1724335] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.1725905] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.1726615] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.1729352] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.1730046] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.1887324] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.1888483] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.1889222] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.1890923] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.1891606] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.1894484] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.1895234] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.2053935] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.2057938] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.2058855] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.2061346] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.2062079] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.2065537] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.2066251] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.2222746] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.2224296] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.2224985] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.2226857] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.2227538] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.2230474] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.2231175] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.2387549] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.2388843] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.2389575] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.2391549] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.2392265] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.2394901] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.2395599] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.2555491] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.2557219] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.2558055] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.2560121] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.2560826] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.2563404] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.2564116] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.2721597] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.2722730] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.2723342] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.2724929] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.2725609] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.2729482] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.2730210] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.2887908] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.2889096] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.2889737] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.2895087] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.2896327] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.2899473] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.2900204] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.3054322] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.3055509] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.3056132] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.3057819] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.3058519] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.3061179] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.3062166] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.3220754] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.3221880] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.3222493] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.3224018] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.3224704] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.3226892] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.3227585] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.3389273] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.3390824] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.3391478] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.3393716] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.3394602] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.3397041] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.3397750] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.3555356] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.3556975] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.3557637] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.3559530] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.3560228] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.3563415] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.3564125] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.3721616] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.3722919] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.3723610] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.3725537] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.3726308] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.3731823] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.3732560] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.3887177] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.3888432] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.3889060] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.3890684] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.3891373] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.3894137] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.3894829] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.4055045] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.4056302] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.4057001] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.4058699] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.4059384] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.4062185] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.4062876] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.4221815] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.4223273] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.4224015] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.4225832] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.4226683] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.4229462] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.4230153] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.4387783] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.4388909] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.4389524] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.4391155] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.4391837] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.4394582] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.4395415] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.4556329] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.4557807] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.4558415] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.4560476] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.4561199] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.4564434] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.4565142] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.4722121] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.4725697] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.4726403] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.4728061] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.4728767] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.4731873] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.4732570] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.4889794] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.4891407] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.4892059] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.4893632] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.4894306] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.4897096] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.4897784] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.5055772] ReleaseFence Querier CleanCommandList | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2
[2026-02-21 23:07:30.5056931] ReleaseFence Querier AcquireSwapChainTexture | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.5057674] ReleaseFenceToPool 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 0
[2026-02-21 23:07:30.5059404] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.5060086] Acquire Querier SubmitCommandLists | 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 1
[2026-02-21 23:07:30.5062940] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.5063641] Waiting for 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.5222066] ReleaseFence Querier CleanCommandList | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 2
[2026-02-21 23:07:30.5223329] ReleaseFence Querier AcquireSwapChainTexture | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.5224054] ReleaseFenceToPool 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 0
[2026-02-21 23:07:30.5225742] Acquire Querier SubmitCommandLists | Setting Signal to 0, RECYCLING
[2026-02-21 23:07:30.5226521] Acquire Querier SubmitCommandLists | 71da7ca0 fence. Handle 7de99b70 | Event 464 | Refcount 1
[2026-02-21 23:07:30.5229129] Waiting for 1 fences. Querier AcquireSwapChainTexture
[2026-02-21 23:07:30.5229827] Waiting for 71da7640 fence. Handle 71e5a8b0 | Event 4a4 | Refcount 2

62
misc/ship.bat Normal file
View File

@@ -0,0 +1,62 @@
@echo off
setlocal
REM ============================================================
REM ship.bat - Build clang-Release and prepare Ship/ folder
REM ============================================================
set ROOT=%~dp0..
set BUILD_DIR=%ROOT%\bin\x64Clang-Release
set SHIP_DIR=%ROOT%\Ship
REM Step 0: Build Shader Compiler
echo [Ship] Building Shader Compiler...
call "%~dp0fbuild" JulietShaderCompiler-x64Clang-Release -cache
if errorlevel 1 (
echo [Ship] SHADER COMPILER BUILD FAILED
exit /b 1
)
REM Step 1: Compile shaders
echo [Ship] Compiling shaders...
call "%~dp0recompile_shaders.bat"
if errorlevel 1 (
echo [Ship] SHADER COMPILATION FAILED
exit /b 1
)
REM Step 2: Build clang-Release
echo [Ship] Building clang-Release...
call "%~dp0fbuild" clang-Release -cache
if errorlevel 1 (
echo [Ship] BUILD FAILED
exit /b 1
)
REM Step 3: Prepare Ship folder
echo [Ship] Preparing Ship folder: %SHIP_DIR%
if exist "%SHIP_DIR%" rd /s /q "%SHIP_DIR%"
mkdir "%SHIP_DIR%"
REM Copy only the required binaries
echo [Ship] Copying binaries...
copy "%BUILD_DIR%\JulietApp.exe" "%SHIP_DIR%\" >nul
copy "%BUILD_DIR%\Juliet.dll" "%SHIP_DIR%\" >nul
copy "%BUILD_DIR%\Game.dll" "%SHIP_DIR%\" >nul
REM Copy compiled shaders into Assets\Shaders\
echo [Ship] Copying shaders...
mkdir "%SHIP_DIR%\Assets\Shaders"
copy "%ROOT%\Assets\compiled\*.dxil" "%SHIP_DIR%\Assets\Shaders\" >nul
del "%SHIP_DIR%\Assets\Shaders\ImGui*.dxil" >nul 2>&1
echo.
echo [Ship] Done!
echo [Ship] Ship folder: %SHIP_DIR%
echo.
echo [Ship] Contents:
dir /b "%SHIP_DIR%"
echo.
echo [Ship] Shaders:
dir /b "%SHIP_DIR%\Assets\Shaders"