Bug - buffered commands lost (with possible fix) (also fixes "ID3D11Device1::CreateBuffer [vertex buffer]")


#1

Hi,

I’ll try to give as much information as possible while trying to stay concise.

I’m building a game using SDL2 2.0.10. The game uses two windows (and thus, two renderers). The renderer type for both renderers is set to “direct3d11”.

Sometimes, when I create my textures, I get the following message in the console :

Line 2757 : __FUNCTION__, ID3D11Device1::CreateBuffer [vertex buffer]: Paramètre incorrect.
(The french part of the message would translate as “invalid/incorrect parameter”).

I’m getting that a lot, but not for all textures. The line number changes from message to message (I’ve also seen 2786, 2713, 1940, 1944, 2732…).

My textures are created with the format SDL_PIXELFORMAT_ARGB8888 and a texture access of SDL_TEXTUREACCESS_TARGET.

Can someone explain what’s causing that message, and if that’s an important error, how can I prevent it from happening?

Thanks!


#2

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,

#3

Sorry for the bump, but in my opinion, that’s a serious problem which impacts functionality. I need to know what to do with that, as SDL2 just became our renderer for all our new games.