We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 4860

Summary: Wrong rotation for Direct3D11 renderer.
Product: SDL Reporter: Martin Vee <martin.veronneau>
Component: renderAssignee: Ryan C. Gordon <icculus>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: critical    
Priority: P2 CC: iryont, martin.veronneau
Version: 2.0.10Keywords: target-2.0.12
Hardware: x86_64   
OS: Windows 10   
Attachments: Comparison of Direct3D renderers with rotated arrow pointing up.
Patch for SDL_render_d3d11.c to fix the rotation problem.

Description Martin Vee 2019-11-13 21:18:30 UTC
Created attachment 4046 [details]
Comparison of Direct3D renderers with rotated arrow pointing up.

Using the Direct3D 11 render driver, the rotations produced by SDL_RenderCopyEx() seem to be offseted by 180 degrees.

All other renderers that I tested (sofftware, opengl, direct3d) behave like expected.

See forum for more details :
https://discourse.libsdl.org/t/rotation-angle-for-sdl-rendercopyex/26840

Here's a minimum example reproducing the problem :

=====================

#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <stdbool.h>

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;

SDL_Event e;

SDL_Texture* loadTexture( const char* path )
{
  SDL_Texture* newTexture = NULL;

  SDL_Surface* loadedSurface = IMG_Load(path);
  if( loadedSurface != NULL )
  {
    newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface );
    SDL_FreeSurface( loadedSurface );
  }

  return newTexture;
}


bool Init(void)
{
  bool success = false;

  if(SDL_Init(SDL_INIT_VIDEO) == 0)
  {
    // CHANGE RENDER DRIVER HERE
    char* RenderDriver = "direct3d11"; // software, opengl, direct3d, direct3d11
    SDL_SetHint(SDL_HINT_RENDER_DRIVER, RenderDriver );

    gWindow = SDL_CreateWindow( RenderDriver , SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
    if( gWindow != NULL )
    {
      gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED );
      if( gRenderer != NULL )
      {
        success = true;
      }
    }
  }

  return success;
}

void Finit(void)
{
  SDL_DestroyRenderer( gRenderer );
  SDL_DestroyWindow( gWindow );
  SDL_Quit();
}

// ******************************

int main( int argc, char* args[] )
{
  if(!Init())
  {
    printf("Init() failed\n");
  }
  else
  {
    SDL_Texture* arrowTexture = loadTexture(".\\images\\UpArrow.png");
    SDL_Rect destination;

    if(!arrowTexture )
    {
      printf("No texture");
    }
    else
    {
      bool exit = false;
      SDL_QueryTexture(arrowTexture, NULL, NULL, &destination.w, &destination.h);
      destination.x = (SCREEN_WIDTH /2) - (destination.w /2) ;
      destination.y = (SCREEN_HEIGHT /2) - (destination.h /2) ;

      while(!exit)
      {
        SDL_RenderCopyEx(gRenderer, arrowTexture, NULL, &destination, 90.0f, NULL, SDL_FLIP_NONE);
        SDL_RenderPresent(gRenderer);

        while( SDL_PollEvent( &e ) != 0 )
        {
          if( e.type == SDL_QUIT )
          {
            exit = true;
          }
        }
      }
      SDL_DestroyTexture(arrowTexture);
    }
  }

  Finit();
  return 0;
}

=====================
Comment 1 Martin Vee 2019-11-20 20:51:52 UTC
That problem was blocking the production here, so I lookde at the code in SDL_render_d3d11.c to try to debug it.

I realized that the horizontal and vertical flip code in D3D11_QueueCopyEx() was reversed.

I'm submitting a patch that works for us (see attached files).

Please note that the patch also includes changes that are not necessarly important, but that brings the code closer to what the D3D_QueueCopyEx() function looks like. The relevant part, though, is the SDL_FLIP part at the beginning of the function.
Comment 2 Martin Vee 2019-11-20 20:52:55 UTC
Created attachment 4063 [details]
Patch for SDL_render_d3d11.c to fix the rotation problem.
Comment 3 Ryan C. Gordon 2019-12-03 08:08:00 UTC
This patch is now https://hg.libsdl.org/SDL/rev/805a3b5cdcc8, thanks!

--ryan.
Comment 4 Konrad 2019-12-22 14:38:17 UTC
This fix actually made Direct3D11 renderer behave erratically with texture coordinates "jumping around".

I haven't actually looked at what caused it exactly in texture coordinates, but since recently I was implementing SDL2 renderer into my game I've noticed that as soon as I updated to 2.0.11 from hg the renderer with Direct3D 11 driver behaves erratically while other drivers have no such issues.

This is how texture coordinates behave:

https://youtu.be/hIu01zdC8hc

It renders normally in SDL 2.0.10 and I did confirm (by replacing SDL_render_d3d11.c in 2.0.11-hg from 2.0.10-stable) that this fix actually brought this behavior.
Comment 5 Konrad 2019-12-22 16:06:33 UTC
My bad actually, I did incorrectly assume this was the issue since this patch was messing around with texture UV, but I had some time to check all commits and this one is actually fine.

The one that caused the behavior was this one:

https://hg.libsdl.org/SDL/rev/44b0a095f4b7

If I comment this line it works fine.

I'm marking this one as resolved back again
Comment 6 Ryan C. Gordon 2019-12-23 14:38:47 UTC
(For record keeping purposes, the bug Konrad described is Bug #4913, which he kindly fixed for us.)