Assertion failure at SDL_GPU_BlitCommon

Environment:

  • SDL 3.1.6-preview
  • macOS 15.2
  • M4 CPU
  • Windows 11, ARM running in Parallels

I have a simple C program rendering an SVG into a window. This works nicely on macOS:

The same program compiles on Windows too, but gives me Assertion failure at SDL_GPU_BlitCommon (\playground\sdl\cmake-build-debug-windows-arm64\_deps\sdl3-src\src\gpu\SDL_gpu.c:303), triggered 1 time: 'blit_pipeline != ((void *)0)'

This is the code:

#include <SDL2/SDL.h>
#include <blend2d.h>
#include <iostream>

int main(int argc, char* argv[]) {
    // Initialize SDL
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        std::cerr << "SDL initialization failed: " << SDL_GetError() << std::endl;
        return 1;
    }

    // Create window
    const int WIDTH = 800;
    const int HEIGHT = 600;
    SDL_Window* window = SDL_CreateWindow(
        "SDL + Blend2D Example",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        WIDTH, HEIGHT,
        SDL_WINDOW_SHOWN
    );

    if (!window) {
        std::cerr << "Window creation failed: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    // Create surface
    SDL_Surface* surface = SDL_CreateRGBSurface(
        0, WIDTH, HEIGHT, 32,
        0x00FF0000,
        0x0000FF00,
        0x000000FF,
        0xFF000000
    );

    // Create Blend2D image
    BLImage img(WIDTH, HEIGHT, BL_FORMAT_PRGB32);
    BLContext ctx(img);

    // Fill background with white
    ctx.setCompOp(BL_COMP_OP_SRC_COPY);
    ctx.fillAll();

    // Draw red rectangle
    BLPath path;
    path.addRect(200, 150, 400, 300);
    
    ctx.setCompOp(BL_COMP_OP_SRC_OVER);
    ctx.setFillStyle(BLRgba32(255, 0, 0)); // Red color
    ctx.fillPath(path);

    // Copy Blend2D image data to SDL surface
    memcpy(surface->pixels, img.data(), img.stride() * img.height());

    // Create texture from surface
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);

    bool running = true;
    SDL_Event event;

    // Main loop
    while (running) {
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                running = false;
            }
        }

        // Render
        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);
    }

    // Cleanup
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_FreeSurface(surface);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

The offending call is SDL_RenderPresent(renderer);

Does anyone has an idea what Iā€™m doing wrong, or is this a bug in SDL?

So, after some investigation I changed the code to use

// Create surface
SDL_Surface *surface = SDL_GetWindowSurface(window);
...
SDL_UpdateWindowSurface(window);

This works now perfectly on Windows, and is anyway more efficient.

So, the original problem seems to be related to using a texture instead of working with the pixel-buffer directly.

1 Like

What are the strides of the SDL_Surface and BLImage?

SDL_Log("surface->pitch=%d", surface->pitch);
SDL_Log("img.stride()=%d", (int)img.stride());