diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp index c2e0007aa..ae641b97b 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp @@ -114,6 +114,12 @@ void GPUContextDX11::FrameBegin() CurrentPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; CurrentStencilRef = 0; CurrentBlendFactor = Float4::One; + + // Bind dummy vertex buffer (used by missing bindings) + auto dummyVB = (GPUBufferDX11*)_device->GetDummyVB(); + ID3D11Buffer* dummyVBBuffer = dummyVB->GetBuffer(); + UINT stride = dummyVB->GetStride(), offset = 0; + _context->IASetVertexBuffers(GPU_MAX_VB_BINDED, 1, &dummyVBBuffer, &stride, &offset); // Bind static samplers ID3D11SamplerState* samplers[] = diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index f6dff7b44..db81b2a4d 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -14,6 +14,7 @@ #include "GPUSwapChainDX11.h" #include "Engine/Core/Log.h" #include "Engine/Core/Utilities.h" +#include "Engine/Core/Math/Color32.h" #include "Engine/Threading/Threading.h" #include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h" #include "Engine/Graphics/PixelFormatExtensions.h" @@ -403,6 +404,17 @@ ID3D11BlendState* GPUDeviceDX11::GetBlendState(const BlendingMode& blending) return state; } +GPUBuffer* GPUDeviceDX11::GetDummyVB() +{ + if (!_dummyVB) + { + _dummyVB = CreateBuffer(TEXT("DummyVertexBuffer")); + auto* layout = GPUVertexLayout::Get({{ VertexElement::Types::Attribute3, 0, 0, 0, PixelFormat::R8G8B8A8_UNorm }}); + _dummyVB->Init(GPUBufferDescription::Vertex(layout, sizeof(Color32), 1, &Color32::Transparent)); + } + return _dummyVB; +} + bool GPUDeviceDX11::Init() { HRESULT result; @@ -560,6 +572,7 @@ bool GPUDeviceDX11::Init() D3D11_MESSAGE_ID_DEVICE_DRAW_INDEX_BUFFER_TOO_SMALL, D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET, D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, + D3D11_MESSAGE_ID_DEVICE_DRAW_VERTEX_BUFFER_TOO_SMALL, }; filter.DenyList.NumIDs = ARRAY_COUNT(disabledMessages); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h index 066f02863..20813d184 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h @@ -59,6 +59,7 @@ private: GPUContextDX11* _mainContext = nullptr; bool _allowTearing = false; + GPUBuffer* _dummyVB = nullptr; // Static Samplers ID3D11SamplerState* _samplerLinearClamp = nullptr; @@ -106,6 +107,7 @@ public: ID3D11DepthStencilState* GetDepthStencilState(const void* descriptionPtr); ID3D11BlendState* GetBlendState(const BlendingMode& blending); + GPUBuffer* GetDummyVB(); public: diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp index 3b78882ae..baea52720 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp @@ -29,8 +29,9 @@ ID3D11InputLayout* GPUShaderProgramVSDX11::GetInputLayout(GPUVertexLayoutDX11* v GPUVertexLayoutDX11* mergedVertexLayout = vertexLayout; if (!mergedVertexLayout) mergedVertexLayout = (GPUVertexLayoutDX11*)Layout; // Fallback to shader-specified layout (if using old APIs) + int32 missingSlotOverride = GPU_MAX_VB_BINDED; // Use additional slot with empty VB if (InputLayout) - mergedVertexLayout = (GPUVertexLayoutDX11*)GPUVertexLayout::Merge(mergedVertexLayout, InputLayout); + mergedVertexLayout = (GPUVertexLayoutDX11*)GPUVertexLayout::Merge(mergedVertexLayout, InputLayout, false, true, missingSlotOverride); LOG_DIRECTX_RESULT(vertexLayout->GetDevice()->GetDevice()->CreateInputLayout(mergedVertexLayout->InputElements, mergedVertexLayout->InputElementsCount, Bytecode.Get(), Bytecode.Length(), &inputLayout)); } _cache.Add(vertexLayout, inputLayout); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp index 49576d8c4..11ac84482 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp @@ -15,9 +15,9 @@ #include #include #endif - #include "GPUContextDX12.h" #include "Engine/Core/Log.h" +#include "Engine/Core/Math/Color32.h" #include "Engine/Core/Math/Viewport.h" #include "Engine/Core/Math/Rectangle.h" #include "GPUShaderDX12.h" @@ -250,6 +250,17 @@ void GPUContextDX12::Reset() Platform::MemoryClear(&_cbHandles, sizeof(_cbHandles)); Platform::MemoryClear(&_samplers, sizeof(_samplers)); _swapChainsUsed = 0; + + // Bind dummy vertex buffer (used by missing bindings) + D3D12_VERTEX_BUFFER_VIEW dummyVBView; + if (!_device->DummyVB) + { + _device->DummyVB = _device->CreateBuffer(TEXT("DummyVertexBuffer")); + auto* layout = GPUVertexLayout::Get({{ VertexElement::Types::Attribute3, 0, 0, 0, PixelFormat::R8G8B8A8_UNorm }}); + _device->DummyVB->Init(GPUBufferDescription::Vertex(layout, sizeof(Color32), 1, &Color32::Transparent)); + } + ((GPUBufferDX12*)_device->DummyVB)->GetVBView(dummyVBView); + _commandList->IASetVertexBuffers(GPU_MAX_VB_BINDED, 1, &dummyVBView); ForceRebindDescriptors(); } diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index e646dd650..cc997bf1d 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -797,6 +797,7 @@ void GPUDeviceDX12::Dispose() updateRes2Dispose(); // Clear pipeline objects + SAFE_DELETE_GPU_RESOURCE(DummyVB); for (auto& srv : _nullSrv) srv.Release(); _nullUav.Release(); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.h index 81c42070f..013087f17 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.h @@ -85,6 +85,7 @@ public: CommandSignatureDX12* DispatchIndirectCommandSignature = nullptr; CommandSignatureDX12* DrawIndexedIndirectCommandSignature = nullptr; CommandSignatureDX12* DrawIndirectCommandSignature = nullptr; + GPUBuffer* DummyVB = nullptr; D3D12_CPU_DESCRIPTOR_HANDLE NullSRV(D3D12_SRV_DIMENSION dimension) const; D3D12_CPU_DESCRIPTOR_HANDLE NullUAV() const; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.cpp index ae8e29918..009534d2c 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUPipelineStateDX12.cpp @@ -87,8 +87,9 @@ ID3D12PipelineState* GPUPipelineStateDX12::GetState(GPUTextureViewDX12* depth, i vertexLayout = VertexBufferLayout; // Fallback to shader-specified layout (if using old APIs) if (vertexLayout) { + int32 missingSlotOverride = GPU_MAX_VB_BINDED; // Use additional slot with empty VB if (VertexInputLayout) - vertexLayout = (GPUVertexLayoutDX12*)GPUVertexLayout::Merge(vertexLayout, VertexInputLayout); + vertexLayout = (GPUVertexLayoutDX12*)GPUVertexLayout::Merge(vertexLayout, VertexInputLayout, false, true, missingSlotOverride); _desc.InputLayout.pInputElementDescs = vertexLayout->InputElements; _desc.InputLayout.NumElements = vertexLayout->InputElementsCount; }