Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
cb3ac76
Texture Atlases
kirides Mar 4, 2026
e50ea6a
rename to VobCulling
kirides Mar 5, 2026
d371a9c
resource streaming in and out of memory
kirides Mar 6, 2026
b7ba63c
remove streaming from engine for now, too expensive in the current fo…
kirides Mar 6, 2026
3684605
fix BC alignment issue
kirides Mar 9, 2026
7c12131
add Atlas support for world mesh drawing
kirides Mar 9, 2026
20e30a5
restore feature level dx10 "support" - shadows broken currently
kirides Mar 9, 2026
f6f533b
pass output RTV and DSV into lighting pass
kirides Mar 9, 2026
e45af34
implement PSO
kirides Mar 9, 2026
f7b9f3e
reduce interface level
kirides Mar 9, 2026
47cecd6
Init PipelinestateCache
kirides Mar 9, 2026
37131cd
begin to abstract DeviceContext
kirides Mar 9, 2026
cdfd4c5
remove "SetDIrty", instead hash the 3 states on "UpdateRendererStates"
kirides Mar 9, 2026
664391a
reduce memory fragmentation causes
kirides Mar 12, 2026
e521858
add toggles to disable atlas based drawing
kirides Mar 12, 2026
a2d6413
ensure correct Mip lod bias when upscaling when rendering using Atlas
kirides Mar 12, 2026
8cbf51c
don't hard-code atlas size
kirides Mar 12, 2026
f077a4f
reduce GodRay banding and visual artifacts by increasing samples to 6…
kirides Mar 14, 2026
03a6606
fallback textures
kirides Mar 14, 2026
3b2a119
note
kirides Mar 14, 2026
324ff5c
higher precision normals using 10-bit normals
kirides Mar 14, 2026
19c5439
increase precision of normals by using RG16_SNORM with octahedral enc…
kirides Mar 14, 2026
0ed892b
stuff
kirides Apr 2, 2026
8a59521
Extract atlas code to different passes
kirides Mar 15, 2026
98fdea5
more debugging
kirides Mar 15, 2026
f0c935f
for now disable VOB atlassing, as that leads to missing textures for …
kirides Mar 15, 2026
3554b04
atlas: reserve indirect args vectors
kirides Mar 15, 2026
33ddd5b
atlas: only mesh atlas if enabled
kirides Mar 15, 2026
3539892
throw out any cached textures after building the texture atlases
kirides Mar 15, 2026
318dff6
delete streaming manager code, as streaming only using main thread is…
kirides Mar 15, 2026
5073b34
atlas: use `Engine::GAPI->GetStaticMeshVisuals()` to ensure we collec…
kirides Mar 21, 2026
6aef15a
static vobs: also cache all Indoor-vobs
kirides Mar 21, 2026
39de835
rebase fix
kirides Mar 25, 2026
164c4dc
re-enable static vob atlas
kirides Mar 25, 2026
d624b83
rebase fix
kirides Apr 7, 2026
5c55707
adjust ConstantBuffer usages
kirides Apr 7, 2026
5ff3331
fix wind when drawing vobs using atlas approach
kirides Apr 7, 2026
d96d488
Fix Atlas shadow shader
kirides Apr 7, 2026
da715fc
optimize `DrawSkeletalMeshVobs` by drawing skeletals Inline and reduc…
kirides Apr 7, 2026
69be7e3
fix merge
kirides Apr 18, 2026
f6b2435
fix bad shader
kirides Apr 18, 2026
0320d94
Atlas fix bug where removed static visual was still drawn an possibly…
kirides Apr 18, 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
2 changes: 2 additions & 0 deletions D3D11Engine/BaseGraphicsEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,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() {};
};
109 changes: 98 additions & 11 deletions D3D11Engine/ConstantBufferStructs.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,104 @@ 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
float minHeight; // BBox.Min.y for per-vob wind calculations
float maxHeight; // BBox.Max.y for per-vob wind calculations
};

// 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
float minHeight; // BBox.Min.y for per-vob wind calculations
float maxHeight; // BBox.Max.y for per-vob wind calculations
UINT pad2;
};

// 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
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;
};
6 changes: 0 additions & 6 deletions D3D11Engine/D3D11Effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,12 @@ XRESULT D3D11Effect::DrawRain() {
// Set alphablending

state.BlendState.SetAlphaBlending();
state.BlendState.SetDirty();

// Disable depth-write
state.DepthState.DepthWriteEnabled = false;
state.DepthState.SetDirty();

// Disable culling
state.RasterizerState.CullMode = GothicRasterizerStateInfo::CM_CULL_NONE;
state.RasterizerState.SetDirty();

// Rendering instances only
e->GetContext()->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );
Expand Down Expand Up @@ -376,15 +373,12 @@ XRESULT D3D11Effect::DrawRain_CS() {
// Set alphablending

state.BlendState.SetAlphaBlending();
state.BlendState.SetDirty();

// Disable depth-write
state.DepthState.DepthWriteEnabled = false;
state.DepthState.SetDirty();

// Disable culling
state.RasterizerState.CullMode = GothicRasterizerStateInfo::CM_CULL_NONE;
state.RasterizerState.SetDirty();

// Rendering instances only
e->GetContext()->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );
Expand Down
Loading
Loading