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 - Wrong rotation for Direct3D11 renderer.
Summary: Wrong rotation for Direct3D11 renderer.
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: render (show other bugs)
Version: 2.0.10
Hardware: x86_64 Windows 10
: P2 critical
Assignee: Ryan C. Gordon
QA Contact: Sam Lantinga
URL:
Keywords: target-2.0.12
Depends on:
Blocks:
 
Reported: 2019-11-13 21:18 UTC by Martin Vee
Modified: 2019-12-23 14:38 UTC (History)
2 users (show)

See Also:


Attachments
Comparison of Direct3D renderers with rotated arrow pointing up. (8.00 KB, image/png)
2019-11-13 21:18 UTC, Martin Vee
Details
Patch for SDL_render_d3d11.c to fix the rotation problem. (2.05 KB, patch)
2019-11-20 20:52 UTC, Martin Vee
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
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.)