Fix binding missing vertex buffer slots to zero data on D3D11 and D3D12

This commit is contained in:
Wojtek Figat
2025-03-26 22:54:00 +01:00
parent f94543aac8
commit fa1469514b
8 changed files with 39 additions and 3 deletions

View File

@@ -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[] =

View File

@@ -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);

View File

@@ -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:

View File

@@ -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);

View File

@@ -15,9 +15,9 @@
#include <d3d12.h>
#include <ThirdParty/WinPixEventRuntime/pix3.h>
#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();
}

View File

@@ -797,6 +797,7 @@ void GPUDeviceDX12::Dispose()
updateRes2Dispose();
// Clear pipeline objects
SAFE_DELETE_GPU_RESOURCE(DummyVB);
for (auto& srv : _nullSrv)
srv.Release();
_nullUav.Release();

View File

@@ -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;

View File

@@ -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;
}