Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3c2d85c
Texture Atlases
kirides Mar 4, 2026
8ece5f9
rename to VobCulling
kirides Mar 5, 2026
3cfd109
resource streaming in and out of memory
kirides Mar 6, 2026
b17c6c7
remove streaming from engine for now, too expensive in the current fo…
kirides Mar 6, 2026
f9a00d8
improve shadow rendering with TAA by introducing frame-counter
kirides Mar 9, 2026
8bcccf7
fix BC alignment issue
kirides Mar 9, 2026
b8eaca1
add Atlas support for world mesh drawing
kirides Mar 9, 2026
e8f5ce4
restore feature level dx10 "support" - shadows broken currently
kirides Mar 9, 2026
a87c0d0
pass output RTV and DSV into lighting pass
kirides Mar 9, 2026
1482d9f
implement PSO
kirides Mar 9, 2026
3cfd8b1
reduce interface level
kirides Mar 9, 2026
71a83aa
Init PipelinestateCache
kirides Mar 9, 2026
fa33ca1
begin to abstract DeviceContext
kirides Mar 9, 2026
4e9cd01
remove "SetDIrty", instead hash the 3 states on "UpdateRendererStates"
kirides Mar 9, 2026
fcdaef0
reduce memory fragmentation causes
kirides Mar 12, 2026
4275562
add toggles to disable atlas based drawing
kirides Mar 12, 2026
db00847
ensure correct Mip lod bias when upscaling when rendering using Atlas
kirides Mar 12, 2026
1b50556
don't hard-code atlas size
kirides Mar 12, 2026
e355f42
optimize-out position-from-depth by using linear math instead of matr…
kirides Mar 14, 2026
f14155c
reduce GodRay banding and visual artifacts by increasing samples to 6…
kirides Mar 14, 2026
c72e965
fallback textures
kirides Mar 14, 2026
a5c7044
note
kirides Mar 14, 2026
59bbccc
higher precision normals using 10-bit normals
kirides Mar 14, 2026
76b4f75
increase precision of normals by using RG16_SNORM with octahedral enc…
kirides Mar 14, 2026
b354276
Extract atlas code to different passes
kirides Mar 15, 2026
9344963
perf: dont copy string for extension
kirides Mar 15, 2026
ece2aee
perf: reserve buffer size for verticies
kirides Mar 15, 2026
1849ec8
more debugging
kirides Mar 15, 2026
0367d5e
for now disable VOB atlassing, as that leads to missing textures for …
kirides Mar 15, 2026
8dbab70
reserve more vectors
kirides Mar 15, 2026
fedd9f0
atlas: reserve indirect args vectors
kirides Mar 15, 2026
13bb84e
atlas: only mesh atlas if enabled
kirides Mar 15, 2026
9fc09bc
throw out any cached textures after building the texture atlases
kirides Mar 15, 2026
fecf40a
delete streaming manager code, as streaming only using main thread is…
kirides Mar 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion D3D11Engine/BaseGraphicsEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class BaseGraphicsEngine {
virtual BaseLineRenderer* GetLineRenderer() PURE;

/** Returns the graphics-device this is running on */
virtual std::string GetGraphicsDeviceName() PURE;
virtual const std::string& GetGraphicsDeviceName() PURE;

/** Draws a screen fade effects */
virtual XRESULT DrawScreenFade( void* camera ) { return XR_SUCCESS; };
Expand Down Expand Up @@ -227,4 +227,6 @@ class BaseGraphicsEngine {
virtual XRESULT UpdateRenderStates() { return XR_SUCCESS; };

virtual std::unique_ptr<GraphicsEventRecord> RecordGraphicsEvent( LPCWSTR region ) { return std::make_unique<GraphicsEventRecord>(); }

virtual void OnWorldLoaded() {};
};
121 changes: 101 additions & 20 deletions D3D11Engine/ConstantBufferStructs.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,100 @@ struct VobInstanceInfo {
DWORD GP_Slot;
};

/** Remap-index for the static vobs */
struct VobInstanceRemapInfo {
bool operator < ( const VobInstanceRemapInfo& b ) const {
return InstanceRemapIndex < b.InstanceRemapIndex;
}

bool operator == ( const VobInstanceRemapInfo& o ) const {
return InstanceRemapIndex == o.InstanceRemapIndex;
}

DWORD InstanceRemapIndex;
struct VobInstanceInfoAtlas {
XMFLOAT4X4 world;
XMFLOAT4X4 prevWorld; // Previous frame's world matrix for motion vectors
DWORD color;
float windStrenth;
float canBeAffectedByPlayer;
// Texture Atlas information, directly stored in the instance data for easy access in shader without needing an extra StructuredBuffer
int slice;
float uStart;
float vStart;
float uEnd;
float vEnd;
UINT globalSourceIndex; // global source index into feedback texture
};

// Descriptor returned for use with shader
// Points to a specific slice in the Texture2DArray atlas, along with UV coordinates for sampling that slice
// this is pointed to from VobInstanceInfo GP_Slot into a StructuredBuffer, which is then indexed in the shader to get the correct slice/UVs for each instance
struct TextureDescriptor {
int slice;
float uStart;
float vStart;
float uEnd;
float vEnd;
};

// CPU-side lookup: maps a zCTexture* to its atlas placement
struct TextureAtlasLookup {
DXGI_FORMAT atlasFormat;
TextureDescriptor descriptor;
};

// Per-vob data uploaded once at world load, read by GPU cull compute shader
struct VobGPUData {
XMFLOAT3 aabbCenter;
float pad0;
XMFLOAT3 aabbExtent;
float pad1;
XMFLOAT4X4 world;
XMFLOAT4X4 prevWorld;
DWORD color;
float aniModeStrength;
float canBeAffectedByPlayer;
UINT submeshStart; // index into SubmeshGPUData[]
UINT submeshCount; // how many submeshes this vob maps to
UINT pad2[3];
};

// Per-submesh lookup, shared across all vobs with the same visual
struct SubmeshGPUData {
int slice;
float uStart, vStart, uEnd, vEnd;
UINT argIndex; // index into merged indirect args
UINT instanceBaseOffset; // fixed write offset in instance buffer
UINT globalSourceIndex; // global source index into feedback texture
};

// Per-submesh data for the world mesh atlas indirect draw path.
// Read by VS_ExWorldAtlas via StructuredBuffer<WorldMeshSubmeshGPUData>.
struct WorldMeshSubmeshGPUData {
// Diffuse atlas
int diffuseSlice;
float dUStart, dVStart, dUEnd, dVEnd;
// Normal atlas
int normalSlice;
float nUStart, nVStart, nUEnd, nVEnd;
// FX atlas
int fxSlice;
float fUStart, fVStart, fUEnd, fVEnd;
// Flags: 1 = HAS_NORMAL, 2 = HAS_FX, 4 = ALPHA_TEST
UINT flags;
};

// Constant buffer for the GPU cull compute shader
struct CullConstants {
XMFLOAT4 frustumPlanes[6];
XMFLOAT3 cameraPosition;
float drawDistance;
float globalWindStrength;
UINT windAdvanced;
UINT numVobs;
UINT feedbackFrameNumber; // >0 = write feedback in CS; 0 = disabled (e.g. shadow pass)
UINT enableHiZ; // 1 = Hi-Z occlusion culling enabled
UINT hiZMipCount;
float hiZWidth; // Hi-Z mip 0 dimensions (full depth buffer size)
float hiZHeight;
XMFLOAT4X4 viewProjection; // Current frame view-projection matrix for Hi-Z reprojection
};

struct HiZBuildConstants {
UINT outputWidth;
UINT outputHeight;
UINT inputMipLevel;
UINT isCopyPass; // 1 = copy from depth buffer (mip 0), 0 = downsample from previous mip
};

#pragma pack (push, 1)
Expand Down Expand Up @@ -61,11 +144,11 @@ struct PerObjectState {
};

struct PFXVS_ConstantBuffer {
XMFLOAT4X4 PFXVS_InvProj;
float4 PFXVS_ProjParams; // x = 1/P._11, y = 1/P._22, z = P._43, w = P._33
};

struct HeightfogConstantBuffer {
XMFLOAT4X4 InvProj;
float4 HF_ProjParams; // x = 1/P._11, y = 1/P._22, z = P._43, w = P._33
XMFLOAT4X4 InvView;
float3 CameraPosition;
float HF_FogHeight;
Expand Down Expand Up @@ -120,7 +203,7 @@ struct DS_PointLightConstantBuffer {
float2 PL_ViewportSize;
float2 PL_Pad2;

XMFLOAT4X4 PL_InvProj; // Optimize out!
float4 PL_ProjParams; // x = 1/P._11, y = 1/P._22, z = P._43, w = P._33
XMFLOAT4X4 PL_InvView;

float3 PL_LightScreenPos;
Expand All @@ -130,7 +213,7 @@ struct DS_PointLightConstantBuffer {
constexpr int MAX_CSM_CASCADES = 4;

struct DS_ScreenQuadConstantBuffer {
XMFLOAT4X4 SQ_InvProj; // Optimize out!
float4 SQ_ProjParams; // x = 1/P._11, y = 1/P._22, z = P._43, w = P._33
XMFLOAT4X4 SQ_InvView;
XMFLOAT4X4 SQ_View;

Expand All @@ -142,16 +225,14 @@ struct DS_ScreenQuadConstantBuffer {
float4 SQ_LightColor;

// CSM: Cascade 0 (f�r Kompatibilit�t mit bestehenden Shadern)
XMFLOAT4X4 SQ_ShadowView[MAX_CSM_CASCADES];
XMFLOAT4X4 SQ_ShadowProj[MAX_CSM_CASCADES];

XMFLOAT4X4 SQ_RainView;
XMFLOAT4X4 SQ_RainProj;
XMFLOAT4X4 SQ_ShadowViewProj[MAX_CSM_CASCADES];

float SQ_ShadowStrength;
float SQ_ShadowAOStrength;
float SQ_WorldAOStrength;
float SQ_ShadowSoftness;
uint32_t SQ_FrameIndex;
float3 SQ_Pad;
};

struct CloudConstantBuffer {
Expand Down
31 changes: 31 additions & 0 deletions D3D11Engine/D3D11AtlasTypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once
#include "D3D11TextureAtlasManager.h"
#include "D3D11IndirectBuffer.h"
#include "ConstantBufferStructs.h"

#include <d3d11.h>
#include <vector>
#include <memory>

// Shared atlas constants
constexpr size_t TEXTURE_ATLAS_MAX = DXGI_FORMAT_V408 + 1;
struct MeshVisualInfo;

// Tracks one unique submesh in the global geometry buffer
struct StaticSubmeshEntry {
UINT indexCount;
UINT startIndexLocation; // offset into global IB
int baseVertexLocation; // offset into global VB
TextureDescriptor atlasDesc;
MeshVisualInfo* visual; // which visual owns this submesh
};

// Groups all submeshes that share one atlas (same DXGI_FORMAT)
struct AtlasDrawGroup {
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
std::vector<StaticSubmeshEntry> submeshes;
std::vector<D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS> indirectArgs;
std::unique_ptr<D3D11IndirectBuffer> indirectBuffer;
UINT mergedArgsOffset = 0; // byte offset into merged indirect args buffer
UINT mergedArgsCount = 0; // number of args in this group
};
4 changes: 2 additions & 2 deletions D3D11Engine/D3D11CascadedShadowMapBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,13 @@ ID3D11ShaderResourceView* D3D11CascadedShadowMapBuffer::GetShaderResourceView()
return m_srv.Get();
}

void D3D11CascadedShadowMapBuffer::BindToPixelShader( ID3D11DeviceContext1* context, UINT slot ) const {
void D3D11CascadedShadowMapBuffer::BindToPixelShader( ID3D11DeviceContext* context, UINT slot ) const {
if ( m_srv ) {
context->PSSetShaderResources( slot, 1, m_srv.GetAddressOf() );
}
}

void D3D11CascadedShadowMapBuffer::BindToVertexShader( ID3D11DeviceContext1* context, UINT slot ) const {
void D3D11CascadedShadowMapBuffer::BindToVertexShader( ID3D11DeviceContext* context, UINT slot ) const {
if ( m_srv ) {
context->VSSetShaderResources( slot, 1, m_srv.GetAddressOf() );
}
Expand Down
4 changes: 2 additions & 2 deletions D3D11Engine/D3D11CascadedShadowMapBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ class D3D11CascadedShadowMapBuffer {
* @param context Device context
* @param slot Shader resource slot
*/
void BindToPixelShader( ID3D11DeviceContext1* context, UINT slot ) const;
void BindToPixelShader( ID3D11DeviceContext* context, UINT slot ) const;

/**
* Bind the texture array to a vertex shader slot.
* @param context Device context
* @param slot Shader resource slot
*/
void BindToVertexShader( ID3D11DeviceContext1* context, UINT slot ) const;
void BindToVertexShader( ID3D11DeviceContext* context, UINT slot ) const;

/** Get the size of each cascade (width = height) */
UINT GetSize() const { return m_size; }
Expand Down
11 changes: 11 additions & 0 deletions D3D11Engine/D3D11CommandList.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "pch.h"
#include "D3D11CommandList.h"
#include "D3D11VertexBuffer.h"

void D3D11CommandList::IASetVertexBuffer( D3D11VertexBuffer* vb, UINT stride, UINT offset ) {
m_Context->IASetVertexBuffers( 0, 1, vb->GetVertexBuffer().GetAddressOf(), &stride, &offset );
}

void D3D11CommandList::IASetIndexBuffer( D3D11VertexBuffer* ib, DXGI_FORMAT format, UINT offset ) {
m_Context->IASetIndexBuffer( ib->GetVertexBuffer().Get(), format, offset );
}
140 changes: 140 additions & 0 deletions D3D11Engine/D3D11CommandList.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#pragma once
#include "pch.h"
#include "D3D11PipelineStateObject.h"

class D3D11VertexBuffer;

/**
* Slim command-list wrapper around an ID3D11DeviceContext1 and the
* D3D11PipelineStateCache.
*
* Provides SetPipelineState() plus the commonly used Draw / IA / OM
* helpers so that call-sites read like a modern graphics API without
* touching the raw context or the engine's global render-state machine.
*
* The object is intentionally cheap to construct (two pointers) and
* does not own any resources.
*/
struct D3D11CommandList {

D3D11CommandList() = default;
D3D11CommandList( ID3D11DeviceContext* context, D3D11PipelineStateCache* cache )
: m_Context( context ), m_Cache( cache ) {}

// --- Pipeline state ------------------------------------------------------

void SetPipelineState( const D3D11PipelineStateObject& pso ) {
m_Cache->SetPipelineState( pso );
}

/** Force the cache to re-bind everything on next SetPipelineState. */
void InvalidatePipelineState() {
m_Cache->Invalidate();
}

// --- Input assembly ------------------------------------------------------

void IASetVertexBuffer( D3D11VertexBuffer* vb, UINT stride, UINT offset = 0 );

void IASetVertexBuffers( UINT startSlot,
UINT numBuffers,
ID3D11Buffer* const* buffers,
const UINT* strides,
const UINT* offsets ) {
m_Context->IASetVertexBuffers( startSlot, numBuffers, buffers, strides, offsets );
}

void IASetIndexBuffer( ID3D11Buffer* buffer, DXGI_FORMAT format, UINT offset = 0 ) {
m_Context->IASetIndexBuffer( buffer, format, offset );
}

void IASetIndexBuffer( D3D11VertexBuffer* ib, DXGI_FORMAT format, UINT offset = 0 );

// --- Draw calls ----------------------------------------------------------

void Draw( UINT vertexCount, UINT startVertexLocation = 0 ) {
m_Context->Draw( vertexCount, startVertexLocation );
m_DrawnTriangles += vertexCount / 3;
}

void DrawIndexed( UINT indexCount,
UINT startIndexLocation = 0,
INT baseVertexLocation = 0 ) {
m_Context->DrawIndexed( indexCount, startIndexLocation, baseVertexLocation );
m_DrawnTriangles += indexCount / 3;
}

void DrawInstanced( UINT vertexCountPerInstance,
UINT instanceCount,
UINT startVertexLocation = 0,
UINT startInstanceLocation = 0 ) {
m_Context->DrawInstanced( vertexCountPerInstance, instanceCount,
startVertexLocation, startInstanceLocation );
m_DrawnTriangles += ( vertexCountPerInstance / 3 ) * instanceCount;
}

void DrawIndexedInstanced( UINT indexCountPerInstance,
UINT instanceCount,
UINT startIndexLocation = 0,
INT baseVertexLocation = 0,
UINT startInstanceLocation = 0 ) {
m_Context->DrawIndexedInstanced( indexCountPerInstance, instanceCount,
startIndexLocation, baseVertexLocation,
startInstanceLocation );
m_DrawnTriangles += ( indexCountPerInstance / 3 ) * instanceCount;
}

void DrawIndexedInstancedIndirect( ID3D11Buffer* argsBuffer,
UINT alignedByteOffsetForArgs ) {
m_Context->DrawIndexedInstancedIndirect( argsBuffer, alignedByteOffsetForArgs );
// Triangle count unknown for indirect draws
}

// --- Render target / viewport helpers ------------------------------------

void OMSetRenderTargets( UINT numViews,
ID3D11RenderTargetView* const* rtvs,
ID3D11DepthStencilView* dsv ) {
m_Context->OMSetRenderTargets( numViews, rtvs, dsv );
}

void RSSetViewports( UINT numViewports, const D3D11_VIEWPORT* viewports ) {
m_Context->RSSetViewports( numViewports, viewports );
}

void RSGetViewports( UINT* numViewports, D3D11_VIEWPORT* viewports ) {
m_Context->RSGetViewports( numViewports, viewports );
}

void ClearDepthStencilView( ID3D11DepthStencilView* dsv,
UINT clearFlags,
float depth,
UINT8 stencil ) {
m_Context->ClearDepthStencilView( dsv, clearFlags, depth, stencil );
}

void ClearRenderTargetView( ID3D11RenderTargetView* rtv, const float color[4] ) {
m_Context->ClearRenderTargetView( rtv, color );
}

// --- Stats ---------------------------------------------------------------

/** Return triangles drawn since last ResetStats() and reset counter. */
UINT FlushDrawnTriangles() {
UINT t = m_DrawnTriangles;
m_DrawnTriangles = 0;
return t;
}

UINT GetDrawnTriangles() const { return m_DrawnTriangles; }

// --- Raw access (escape hatch) -------------------------------------------

ID3D11DeviceContext* GetContext() const { return m_Context; }
D3D11PipelineStateCache* GetPSOCache() const { return m_Cache; }

private:
ID3D11DeviceContext* m_Context = nullptr;
D3D11PipelineStateCache* m_Cache = nullptr;
UINT m_DrawnTriangles = 0;
};
Loading
Loading