D3D11: Check Map() results

Map fails after device removal, leaving pData garbage. Skip the upload or
draw instead of writing through it.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-09-29 13:16:59 -06:00
1 parent bc581349fd
commit ba37f327b0
3 files changed
+34 -8

No files matched your search

+13 -2
View File
@@ -46,7 +46,11 @@ public:
nextMapDiscard_ = true;
}
// Returns null if the buffer can't be mapped (after device removal, for example). Skip the draw then.
uint8_t *BeginPush(ID3D11DeviceContext *context, UINT *offset, size_t size, int align = 16) {
if (!buffer_) {
return nullptr;
}
D3D11_MAPPED_SUBRESOURCE map;
pos_ = (pos_ + align - 1) & ~(align - 1);
if (pos_ + size > size_) {
@@ -55,7 +59,10 @@ public:
pos_ = 0;
nextMapDiscard_ = true;
}
context->Map(buffer_.Get(), 0, nextMapDiscard_ ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map);
if (FAILED(context->Map(buffer_.Get(), 0, nextMapDiscard_ ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map))) {
return nullptr;
}
mapped_ = true;
nextMapDiscard_ = false;
*offset = (UINT)pos_;
uint8_t *retval = (uint8_t *)map.pData + pos_;
@@ -63,7 +70,10 @@ public:
return retval;
}
void EndPush(ID3D11DeviceContext *context) {
context->Unmap(buffer_.Get(), 0);
if (mapped_) {
context->Unmap(buffer_.Get(), 0);
mapped_ = false;
}
}
private:
@@ -71,6 +81,7 @@ private:
size_t pos_ = 0;
size_t size_;
bool nextMapDiscard_ = false;
bool mapped_ = false;
};
std::vector<uint8_t> CompileShaderToBytecodeD3D11(const char *code, size_t codeSize, const char *target, UINT flags, std::string *errorMessage = nullptr);
+12
View File
@@ -358,6 +358,9 @@ void DrawEngineD3D11::Flush() {
UINT vOffset;
int vSize = numDecodedVerts_ * dec_->GetDecVtxFmt().stride;
uint8_t *vptr = pushVerts_->BeginPush(context_, &vOffset, vSize);
if (!vptr) {
goto bail;
}
memcpy(vptr, decoded_, vSize);
pushVerts_->EndPush(context_);
ID3D11Buffer *buf = pushVerts_->Buf();
@@ -366,6 +369,9 @@ void DrawEngineD3D11::Flush() {
UINT iOffset;
int iSize = 2 * vertexCount;
uint8_t *iptr = pushInds_->BeginPush(context_, &iOffset, iSize);
if (!iptr) {
goto bail;
}
memcpy(iptr, decIndex_, iSize);
pushInds_->EndPush(context_);
context_->IASetIndexBuffer(pushInds_->Buf(), DXGI_FORMAT_R16_UINT, iOffset);
@@ -477,6 +483,9 @@ void DrawEngineD3D11::Flush() {
UINT vOffset = 0;
int vSize = result.drawVertexCount * stride;
uint8_t *vptr = pushVerts_->BeginPush(context_, &vOffset, vSize);
if (!vptr) {
goto bail;
}
memcpy(vptr, result.drawBuffer, vSize);
pushVerts_->EndPush(context_);
ID3D11Buffer *buf = pushVerts_->Buf();
@@ -484,6 +493,9 @@ void DrawEngineD3D11::Flush() {
UINT iOffset;
int iSize = sizeof(uint16_t) * result.drawIndexCount;
uint8_t *iptr = pushInds_->BeginPush(context_, &iOffset, iSize);
if (!iptr) {
goto bail;
}
memcpy(iptr, inds, iSize);
pushInds_->EndPush(context_);
context_->IASetIndexBuffer(pushInds_->Buf(), DXGI_FORMAT_R16_UINT, iOffset);
+9 -6
View File
@@ -147,15 +147,18 @@ uint64_t ShaderManagerD3D11::UpdateUniforms(bool useBufferedRendering, bool pixe
D3D11_MAPPED_SUBRESOURCE map;
if (dirty & DIRTY_BASE_UNIFORMS) {
BaseUpdateUniforms(&ub_base, dirty, useBufferedRendering, pixelMapped);
context_->Map(push_base.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, &ub_base, sizeof(ub_base));
context_->Unmap(push_base.Get(), 0);
// Map fails after device removal, and map.pData is garbage then.
if (SUCCEEDED(context_->Map(push_base.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &map))) {
memcpy(map.pData, &ub_base, sizeof(ub_base));
context_->Unmap(push_base.Get(), 0);
}
}
if (dirty & DIRTY_LIGHT_UNIFORMS) {
LightUpdateUniforms(&ub_lights, dirty);
context_->Map(push_lights.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, &ub_lights, sizeof(ub_lights));
context_->Unmap(push_lights.Get(), 0);
if (SUCCEEDED(context_->Map(push_lights.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &map))) {
memcpy(map.pData, &ub_lights, sizeof(ub_lights));
context_->Unmap(push_lights.Get(), 0);
}
}
}
gstate_c.CleanUniforms();