After experiencing that problem for a while, I decided to get my feet wet. I successfully built a debug version of SDL2 with MSYS2, and I traced the problem back to SDL_SetRenderTarget()
.
Here’s the technical explanation.
- Line 1833, SDL_render.c : SDL_SetRenderTarget is called with a valid renderer and a valid texture.
- Line 1843, SDL_render.c : FlushRenderCommands() is called, emptying the command queue.
- Line 1900, SDL_render.c : QueueCmdSetViewport called, one command queued.
- Line 1903, SDL_render.c : QueueCmdSetClipRect called, two commands queued.
- Line 1908, SDL_render.c : FlushRenderCommandsIfNotBatching. Since batching is disabled for me, it tries to empty the command queue, which contains the two above commands.
- Line 257, SDL_render.c : FlushRenderCommands called.
- Line 218, SDL_render.c : RunCommandQueue called, with renderer->vertex_data_used at 0 (there's no vertex data, since the only two commands in the command queue are SetViewport and SetClipRect).
- Line 2189, SDL_render_d3d11.c : D3D11_UpdateVertexBuffer, passing vertsize with a value of 0.
- Line 1814, SDL_render_d3d11.c : The entire D3D11_UpdateVertexBuffer never validates that dataSizeInBytes value is 0, so it tries to call ID3D11Device_CreateBuffer with a vertexBufferDesc's ByteWidth at 0. The call fails. The function returns -1.
- Line 2190, SDL_render_d3d11.c : Because D3D11_UpdateVertexBuffer returned -1, D3D11_RunCommandQueue also return -1 immediately, never processing the command queue (which still contains SetViewport and SetClipRect.
- Line 228, SDL_render.c : FlushRenderCommands empties the command queue, never executing the SetViewport and SetClipRect, and then returns -1 because of the RunCommandQueue call.
- Line 1908, SDL_render.c : Even though the render target is now set, SDL_SetRenderTarget() will report that it failed. Also, since the SetViewport and SetCliprect command did not execute, the renderer will render to the new target, but the viewport and the clipping will be invalid.
Since, I don’t know much about the SDL source code (I just started debugging it yesterday), I’m not completely confident that I understood the problem.
Here’s what I’m proposing as a fix. Can someone confirm that it’s correct?
static int
D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
const void * vertexData, size_t dataSizeInBytes)
{
D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
HRESULT result = S_OK;
const int vbidx = rendererData->currentVertexBuffer;
/* *** BEGIN OF PATCH */
if(dataSizeInBytes == 0)
return 0; // nothing to be done.
/* *** END OF PATCH */
if (rendererData->vertexBuffers[vbidx] && rendererData->vertexBufferSizes[vbidx] >= dataSizeInBytes) {
D3D11_MAPPED_SUBRESOURCE mappedResource;
result = ID3D11DeviceContext_Map(rendererData->d3dContext,