2

In my project I must use SDL_BLENDOPERATION_MAXIMUM via SDL_ComposeCustomBlendMode() which is supported in SDL 2.0.9 by direct3d11 renderer only. I have Windows 8.1 and GeForce GTX750 Ti with updated drivers. My system should support DirectX 11 renderending.

Changing defines in SDL_config.h or SDL_config_windows.h (SDL_VIDEO_RENDER_D3D11 to 1 and SDL_VIDEO_RENDER_D3D to 0) doesn't help. I tried to fill preprocessor difinitions with defines SDL_VIDEO_RENDER_D3D11 or WINRT according to SDL source code. But it doesn't help.

What should I do to activate direct3d11 renderer so I can use blend mode max?

My test code:

#include "SDL.h"
#include "SDL_image.h"
#include <string>

using namespace std;

int main( int argc, char *argv[] ) {
    SDL_Init( SDL_INIT_VIDEO );
    IMG_Init( IMG_INIT_PNG );
    SDL_SetHintWithPriority( SDL_HINT_RENDER_DRIVER, "direct3d11", SDL_HINT_OVERRIDE );
    SDL_Window *window = SDL_CreateWindow( "Testing", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                             1200, 600, SDL_WINDOW_RESIZABLE );
    SDL_Renderer *renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
    SDL_RendererInfo *rendererInfo = new SDL_RendererInfo();
    SDL_RendererInfo *driverInfo = new SDL_RendererInfo();
    SDL_GetRendererInfo( renderer, rendererInfo );
    int drivers = SDL_GetNumRenderDrivers();
    string availableDrivers = " (";
    for ( int i = 0; i < drivers; ++i ) {
        SDL_GetRenderDriverInfo( i, driverInfo );
        string driverName = driverInfo->name;
        if ( i == drivers - 1 ) {
            availableDrivers += driverName;
        }
        else {
            availableDrivers += driverName + ", ";
        }
    }
    availableDrivers += ")";
    string path = SDL_GetBasePath();
    SDL_Surface *surfRed = IMG_Load( (path + "\\Red.png").c_str() );
    SDL_Texture *textRed = SDL_CreateTextureFromSurface( renderer, surfRed );
    SDL_FreeSurface( surfRed );
    SDL_Surface *surfBlue = IMG_Load( ( path + "\\Blue.png" ).c_str() );
    SDL_Texture *textBlue = SDL_CreateTextureFromSurface( renderer, surfBlue );
    SDL_FreeSurface( surfBlue );
    SDL_Rect destRed, destBlue;
    destRed.x = 128;
    destRed.y = 128;
    destBlue.x = 196;
    destBlue.y = 196;
    SDL_QueryTexture( textRed, NULL, NULL, &destRed.w, &destRed.h );
    SDL_QueryTexture( textBlue, NULL, NULL, &destBlue.w, &destBlue.h );
    SDL_BlendMode blendMode = SDL_ComposeCustomBlendMode( SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_MAXIMUM,
        SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_MAXIMUM );         
    SDL_SetTextureBlendMode( textRed, blendMode );
    SDL_SetTextureBlendMode( textBlue, blendMode );
//  SDL_SetRenderDrawBlendMode( renderer, blendMode );
    string info = rendererInfo->name + availableDrivers + " " + SDL_GetError();
    SDL_SetWindowTitle( window, info.c_str() );
    SDL_SetRenderDrawColor( renderer, 0, 0, 0, 255 );
    SDL_Event event;
    bool isRunning = true;
    while ( isRunning ) {
        if ( SDL_PollEvent( &event ) ) {
            if ( event.type == SDL_QUIT ) {
                isRunning = false;
            }
        }
        SDL_RenderClear( renderer );
        SDL_RenderCopy( renderer, textRed, NULL, &destRed );
        SDL_RenderCopy( renderer, textBlue, NULL, &destBlue );
        SDL_RenderPresent( renderer );
    }
    delete driverInfo;
    delete rendererInfo;
    SDL_DestroyTexture( textRed );
    SDL_DestroyTexture( textBlue );
    SDL_DestroyRenderer( renderer );
    SDL_DestroyWindow( window );
    IMG_Quit();
    SDL_Quit();
    return 0;
}

Window title is "direct3d (direct3d, opengl, opengles2, software) This operration is not supported". It works fine when I change to SDL_BLENDOPERATION_ADD, but it's not what I want. If I uncomment renderer blend mode it doesn't help too.

m5willmax
  • 41
  • 1
  • 3
  • 1
    you should post the code with how you instantiate your renderer if the solutions below didnt work for you. – Brad Allred Nov 13 '18 at 05:36
  • Thanks, I've loaded my code:) – m5willmax Nov 14 '18 at 14:25
  • This Windows 10 box with an AMD FirePro W4100 is showing the `direct3d11` backend in the titlebar with your code. Does `dxdiag` corroborate your "My system should support DirectX 11" theory? Is your system some sort of wonky laptop-style [Optimus](https://en.wikipedia.org/wiki/Nvidia_Optimus) thing? – genpfault Nov 14 '18 at 16:40
  • Now that you've added your code its clear that your system does not support the d3d11 renderer. assuming you used the officially provided SDL (and not self built or 3rd party) this would indicate our system does not in fact support d3d11. Are you sure you are using your GTX750 and not the integrated graphics? – Brad Allred Nov 14 '18 at 17:37
  • Yep, it's a desktop computer and I initially checked this things by myself. Dxdiad showed the DirectX version as 11 and Nvidia specification showed that GTX 750 Ti supports DX11. I was sure that I do something wrong with my coding. You answer has approved that I do right. Thanks a lot for help! – m5willmax Nov 15 '18 at 12:01

2 Answers2

3
  1. Enumerate the supported renderer backends via SDL_GetNumRenderDrivers() and SDL_GetRenderDriverInfo().
  2. Note the index of the direct3d11 driver, if it exists.
  3. Pass index into SDL_CreateRenderer().

All together:

SDL_Init( SDL_INIT_VIDEO );
SDL_Window* window = SDL_CreateWindow( "SDL2", 0, 0, 640, 480, SDL_WINDOW_SHOWN );

SDL_Renderer* renderer = nullptr;
for( int i = 0; i < SDL_GetNumRenderDrivers(); ++i )
{
    SDL_RendererInfo rendererInfo = {};
    SDL_GetRenderDriverInfo( i, &rendererInfo );
    if( rendererInfo.name != std::string( "direct3d11" ) )
    {
        continue;
    }

    renderer = SDL_CreateRenderer( window, i, 0 );
    break;
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
1

Note that what you are setting with SDL_VIDEO_RENDER_D3D and friends are compile time definitions for building SDL with D3D support.

To do this at runtime:

Sometime after SDL_Init() and before creating your window/renderer set a hint for it.

// returns true on success or false on failure
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "direct3d11");

However, this will only work on Windows, and I believe d3d is already the default renderer for windows. If your version of windows supports d3d11 that is what SDL should use. I strongly suspect you already have a d3d11 renderer and your problem is with how you instantiate or use your custom blend mode.

To verify you have a d3d11 renderer:

SDL_RendererInfo info;
SDL_GetRendererInfo(renderer, &info);
printf("%s", info.name);

To create a custom blend mode with SDL_BLENDOPERATION_MAXIMUM

SDL_BlendMode blender = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA, // change this to suit your needs
                                                   SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, // change this to suit your needs
                                                   SDL_BLENDOPERATION_MAXIMUM,
                                                   SDL_BLENDFACTOR_ONE, // change this to suit your needs
                                                   SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, // change this to suit your needs
                                                   SDL_BLENDOPERATION_MAXIMUM);

SDL_SetTextureBlendMode(texture, blender); // blender is your custom mode
SDL_SetRenderDrawBlendMode(renderer, blender); // blender is your custom mode

I cant imagine the above blender is actually the combination of factors/operations you want, but you didn't post your actual code to work off.

Community
  • 1
  • 1
Brad Allred
  • 7,323
  • 1
  • 30
  • 49
  • Setting hints doesn't help :( – m5willmax Nov 13 '18 at 03:16
  • @m5willmax you're going to have to be more specific if you want more help. Tell us what you tried (ex "direct3d" or "direct3d11") and the result. You are on Windows right? – Brad Allred Nov 13 '18 at 05:32
  • Yep, I use Windows 8.1. My system should support DirectX 11 renderending. SDL supports directx 11 and directx 9/10 renderers. And wiki says that blend mode maximum is supported by direct3d11 renderer only. Before creating renderer I set SDL_SetHintWithPriority( SDL_HINT_RENDER_DRIVER, "direct3d11", SDL_HINT_OVERRIDE ). – m5willmax Nov 13 '18 at 13:25
  • Then I create renderer with SDL_CreateRenderer( m_window, -1, SDL_RENDERER_ACCELERATED ). Changing renderer index doesn’t help. I load textures from pngs without transparency, pixel format is SDL_PIXELFORMAT_RGB24. My custom blend operation is SDL_BLENDOPERATION_MAXIMUM. SDL_GetError() says that “That operation is not supported”. I tried to fill preprocessor difinitions with defines SDL_VIDEO_RENDER_D3D11 or __WINRT__ according to SDL source code. But it doesn't help. – m5willmax Nov 13 '18 at 13:30
  • @m5willmax you should update your answer with the code creating and using your blend mode. from your description it sounds like you are doing it wrong and passing `SDL_BLENDOPERATION_MAXIMUM` as a parameter to `SDL_SetTextureBlendMode` which is _not_ how you do it. Again, preprocessor defines wont help you here. – Brad Allred Nov 13 '18 at 15:51