From 8f580efa25054ea46994c63fce6d2b50ebcbde0c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 28 Mar 2019 13:45:41 +0100 Subject: [PATCH] [d3d11] Correctly handle out-of-bounds constant buffer ranges Otherwise we pass an invalid offset and length to the backend, which leads to invalid descriptor set updates in Vulkan. The D3D11 runtime does not report corrected constant offset and count parameters to the applicaion in *GetConstantBuffers1. Reported-by: Danylo Piliaiev --- src/d3d11/d3d11_context.cpp | 35 +++++++++++++++++++++++---------- src/d3d11/d3d11_context_state.h | 1 + 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 6867895ea..02d557281 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -3262,10 +3262,10 @@ namespace dxvk { const D3D11ConstantBufferBinding* pBufferBinding) { EmitCs([ cSlotId = Slot, - cBufferSlice = pBufferBinding->buffer != nullptr + cBufferSlice = pBufferBinding->constantBound ? pBufferBinding->buffer->GetBufferSlice( pBufferBinding->constantOffset * 16, - pBufferBinding->constantCount * 16) + pBufferBinding->constantBound * 16) : DxvkBufferSlice() ] (DxvkContext* ctx) { ctx->bindResourceBuffer(cSlotId, cBufferSlice); @@ -3371,14 +3371,28 @@ namespace dxvk { for (uint32_t i = 0; i < NumBuffers; i++) { auto newBuffer = static_cast(ppConstantBuffers[i]); - UINT constantOffset = 0; - UINT constantCount = newBuffer != nullptr - ? newBuffer->Desc()->ByteWidth / 16 - : 0; - - if (newBuffer != nullptr && pFirstConstant != nullptr && pNumConstants != nullptr) { - constantOffset = pFirstConstant[i]; - constantCount = pNumConstants [i]; + UINT constantOffset; + UINT constantCount; + UINT constantBound; + + if (likely(newBuffer != nullptr)) { + constantBound = newBuffer->Desc()->ByteWidth / 16; + + if (pFirstConstant && pNumConstants) { + constantOffset = pFirstConstant[i]; + constantCount = pNumConstants [i]; + + constantBound = (constantOffset + constantCount > constantBound) + ? constantBound - std::min(constantOffset, constantBound) + : constantCount; + } else { + constantOffset = 0; + constantCount = constantBound; + } + } else { + constantOffset = 0; + constantCount = 0; + constantBound = 0; } if (Bindings[StartSlot + i].buffer != newBuffer @@ -3387,6 +3401,7 @@ namespace dxvk { Bindings[StartSlot + i].buffer = newBuffer; Bindings[StartSlot + i].constantOffset = constantOffset; Bindings[StartSlot + i].constantCount = constantCount; + Bindings[StartSlot + i].constantBound = constantBound; BindConstantBuffer(slotId + i, &Bindings[StartSlot + i]); } diff --git a/src/d3d11/d3d11_context_state.h b/src/d3d11/d3d11_context_state.h index 277060519..fda4fb5c5 100644 --- a/src/d3d11/d3d11_context_state.h +++ b/src/d3d11/d3d11_context_state.h @@ -19,6 +19,7 @@ namespace dxvk { Com buffer = nullptr; UINT constantOffset = 0; UINT constantCount = 0; + UINT constantBound = 0; }; using D3D11ConstantBufferBindings = std::array<