Partage
  • Partager sur Facebook
  • Partager sur Twitter

Abort trap: 6 avec la SDL2

Erreur générée par la fonction SDL_SetRenderTarget

Sujet résolu
13 février 2022 à 9:56:23

Bonjour,

J'ai commencé à apprendre à utiliser la SDL2 en C, et je suis en train de voir les textures. Le problème, c'est que dès que j'utilise la fonction ```SDL_SetRenderTarget```, le programme compile correctement, mais finit par afficher:

-[_MTLCommandBuffer presentDrawable:]:602: failed assertion `drawable must not be nil.'

Avant de se terminer par un beau:

Abort trap: 6

Je vous met mon code:

#include <SDL2/SDL.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
	if (SDL_Init(SDL_INIT_VIDEO) != 0){
	    fprintf(stderr, "Error while initializing video system: %s\n", SDL_GetError());
	}
	SDL_Window *HobbesWindow = SDL_CreateWindow("Hobbes", 0, 0, 640, 480, 0);
	if (HobbesWindow == NULL){
		fprintf(stderr, "Error while creating window: %s\n", SDL_GetError());
	}
	
	SDL_Renderer *HobbesRenderer = SDL_CreateRenderer(HobbesWindow, -1, 0);
	if (HobbesRenderer == NULL){
	    fprintf(stderr, "Error while creating renderer: %s\n", SDL_GetError());
	}
	
	
	
	
	
    SDL_Rect HobbesRect = {0, 0, 100, 100};
    SDL_SetRenderDrawColor(HobbesRenderer, 255, 0, 255, 255);
	
	SDL_Texture *HobbesTexture = SDL_CreateTexture(HobbesRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 100, 100);
	if (HobbesTexture == NULL){
		fprintf(stderr, "Error while creating texture: %s\n", SDL_GetError());
	}
	if (SDL_SetRenderTarget(HobbesRenderer, HobbesTexture) != 0){
		fprintf(stderr, "Error while setting render target to texture: %s\n", SDL_GetError());
	}
	
	if (SDL_RenderClear(HobbesRenderer) != 0){*/;
        fprintf(stderr, "Error while clearing window: %s\n", SDL_GetError());
    }
    
    
	SDL_Event HobbesEvent;
	SDL_bool quit = SDL_FALSE;
	int HobbesTimer = 0;
	
    while(!quit)
    {
    	if (HobbesTimer >= 5){
	    if (SDL_RenderDrawRect(HobbesRenderer, &HobbesRect) != 0){
    	    fprintf(stderr, "Error while drawing in rect: %s\n", SDL_GetError());
    	    }
	}
        SDL_RenderPresent(HobbesRenderer);
        SDL_WaitEvent(&HobbesEvent);
        if(HobbesEvent.type == SDL_KEYUP)
            quit = SDL_TRUE;

        SDL_Delay(10);
        HobbesTimer += 1;
	}
    SDL_DestroyTexture(HobbesTexture);
    SDL_DestroyRenderer(HobbesRenderer);
    SDL_DestroyWindow(HobbesWindow);
    SDL_Quit();
    return 0;
}

Quelqu'un peut-il m'aider?

-
Edité par UnknownUnknown18 13 février 2022 à 9:57:44

  • Partager sur Facebook
  • Partager sur Twitter
13 février 2022 à 11:25:14

Bonjour,

J' utilises moi aussi la SDL 2 pour des jeux, par contre je n'ai jamais utilisé la fonction 'SDL_SetRenderTarget(' . D' ailleurs je me demande pourquoi, dans le code proposé tu l' utilises, car tu dessines dans le pointeur sur SDL_Renderer* , HobbesRenderer . Et pas sur la texture. D' ailleurs tu ne nous dis pas d' où vient l' assertion, je n' en vois pas dans le code que tu nous postes. :)

P.S Edit :

Sur la doc officielle il y a bien l'impératif de créer la texture avec 'SDL_TEXTUREACCESS_TARGET' ce que tu as fait. Par contre il y a aussi de noté:

Before using this function, you should check the SDL_RENDERER_TARGETTEXTURE bit in the flags of SDL_RendererInfo to see if render targets are supported.

Peut-être une piste à étudier...

-
Edité par Warren79 13 février 2022 à 11:32:27

  • Partager sur Facebook
  • Partager sur Twitter

Mon site web de jeux SDL2 entre autres : https://www.ant01.fr

13 février 2022 à 12:11:27

Salut,

Quand tu dis qu'il fini par afficher, cela veut dire au bout d'un certain temps ?

Je ne fais jamais comme ça, pour moi tu ne peux pas afficher une texture en tant que render, tu mets ta texture en cible, tu dessines sur la cible, tu restitues le render (le vrai), tu appliques ta texture sur le render puis tu affiches le render. Les textures ne peuvent pas être affichées directement, même en se substituant au render.

Donc tu mets ton SDL_SetRenderTarget(HobbesRenderer, HobbesTexture) entre les lignes 45 et 46, puis SDL_SetRenderTarget(HobbesRenderer, NULL) entre 49 et 50, puis un renderCopy (HobbesRenderer, HobbesTexture, NULL, NULL), puis ton RenderPresent(HobbesRenderer).

Warren79 a écrit:

[...]je me demande pourquoi, dans le code proposé tu l' utilises, car tu dessines dans le pointeur sur SDL_Renderer*

Normal, la fonction substitue la texture au renderer, la texture devient le renderer. Quant à l'assertion je suppose qu'elle vient de la SDL.

Par contre lorsque tu fais la libération à la fin, il faut penser à restituer le contexte d'origine avec SDL_SetRenderTarget(HobbesRenderer, NULL) si ça n'a pas été fait.

Bonne continuation.

-
Edité par drx 13 février 2022 à 12:13:33

  • Partager sur Facebook
  • Partager sur Twitter

Bonhomme !! | Jeu de plateforme : Prototype.

13 février 2022 à 14:33:23

Warren79 a écrit:

D' ailleurs je me demande pourquoi, dans le code proposé tu l' utilises, car tu dessines dans le pointeur sur SDL_Renderer* , HobbesRenderer . Et pas sur la texture. D' ailleurs tu ne nous dis pas d' où vient l' assertion, je n' en vois pas dans le code que tu nous postes. :)

En fait, ce code était juste pour tester ce que mon tutoriel m'apprend, donc je l'édite au fur et à mesure et il n'est effectivement pas complet. Mais j'ai quand même posé ma question car le problème ne vient pas de là, mais de la fonction SDL_SetRenderTarget().

Pour l'assertion, elle est effectuée par la fonction SDL_SetRenderTarget(), ce n'est pas moi qui l'ai faite. Je vous ai mis le code dans son entièreté.

drx a écrit:

Quand tu dis qu'il fini par afficher, cela veut dire au bout d'un certain temps ?

Le message s'affiche tout d'un coup dès que j'appelle la fonction, ce qui donne au final:

-[_MTLCommandBuffer presentDrawable:]:602: failed assertion `drawable must not be nil.'
Abort trap: 6

drx a écrit:

Je ne fais jamais comme ça, pour moi tu ne peux pas afficher une texture en tant que render, tu mets ta texture en cible, tu dessines sur la cible, tu restitues le render (le vrai), tu appliques ta texture sur le render puis tu affiches le render. Les textures ne peuvent pas être affichées directement, même en se substituant au render.

Donc tu mets ton SDL_SetRenderTarget(HobbesRenderer, HobbesTexture) entre les lignes 45 et 46, puis SDL_SetRenderTarget(HobbesRenderer, NULL) entre 49 et 50, puis un renderCopy (HobbesRenderer, HobbesTexture, NULL, NULL), puis ton RenderPresent(HobbesRenderer).

Par contre lorsque tu fais la libération à la fin, il faut penser à restituer le contexte d'origine avec SDL_SetRenderTarget(HobbesRenderer, NULL) si ça n'a pas été fait.

D'accord, je suivrai ces étapes la prochaine fois ^^. J'ai édité mon code comme tu me l'as conseillé, mais la fonction SDL_SetRenderTarget() n'a toujours pas fonctionné...

Warren79 a écrit:

Sur la doc officielle il y a bien l'impératif de créer la texture avec 'SDL_TEXTUREACCESS_TARGET' ce que tu as fait. Par contre il y a aussi de noté:

Before using this function, you should check the SDL_RENDERER_TARGETTEXTURE bit in the flags of SDL_RendererInfo to see if render targets are supported.

Peut-être une piste à étudier...

D'accord, je vais regarder de ce côté, ça me semble probable que ce soit ça :)

-
Edité par UnknownUnknown18 13 février 2022 à 14:50:14

  • Partager sur Facebook
  • Partager sur Twitter
13 février 2022 à 15:23:36

Re,

Qu'est-ce qui te fait dire que c'est la fonction SetRenderTaget() qui ne fonctionne pas?

Le message [_MTLCommandBuffer presentDrawable:]:602: failed assertion `drawable must not be nil.

Laisse entendre que c'est la fonction RenderPresent() qui foire.

Si ta carte graphique a moins de 20 ans, il n'y a aucune raison qu'elle ne supporte pas le SDL_RENDERER_TARGETTEXTURE.

while(!quit)
    {
        SDL_SetRenderTarget(HobbesRenderer, HobbesTexture);

        if (HobbesTimer >= 5){
        if (SDL_RenderDrawRect(HobbesRenderer, &HobbesRect) != 0){
            fprintf(stderr, "Error while drawing in rect: %s\n", SDL_GetError());
            }
    }
        SDL_SetRenderTarget(HobbesRenderer, NULL);
        SDL_RenderCopy(HobbesRenderer, HobbesTexture, NULL, NULL);
        SDL_RenderPresent(HobbesRenderer);
        SDL_WaitEvent(&HobbesEvent);
        if(HobbesEvent.type == SDL_KEYUP)
            quit = SDL_TRUE;
 
        SDL_Delay(10);
        HobbesTimer += 1;
    }


J'ai fait ce genre de manip 300 fois, si ça foire, c'est le code, pas la lib.

Il faut faire une sortie après tes fprintf, parce que dans ton cas, si un truc foire, tu dis juste que ça a foiré puis tu continues. Si ton soft bug trop vite, ton message pourrait ne pas apparaître tant que stderr n'est pas fermé correctement : c'est un fichier.

Bonne continuation.

-
Edité par drx 13 février 2022 à 15:24:38

  • Partager sur Facebook
  • Partager sur Twitter

Bonhomme !! | Jeu de plateforme : Prototype.

13 février 2022 à 17:59:00

drx a écrit:

J'ai fait ce genre de manip 300 fois, si ça foire, c'est le code, pas la lib.

Hélas, les po pensent que c'est la lib qui est en tort, pas leur programme (et commentaire suivant)

-
Edité par edgarjacobs 13 février 2022 à 18:02:00

  • Partager sur Facebook
  • Partager sur Twitter

On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

15 février 2022 à 10:14:24

drx a écrit:

Qu'est-ce qui te fait dire que c'est la fonction SetRenderTaget() qui ne fonctionne pas?

Je dis ça parce que quand je met en commentaire l'appel de cette fonction, je n'ai plus de message d'erreur. Mais je vais essayer de poursuivre mon apprentissage des textures et de voir ce que j'ai pu mal faire.

drx a écrit:

Il faut faire une sortie après tes fprintf, parce que dans ton cas, si un truc foire, tu dis juste que ça a foiré puis tu continues. Si ton soft bug trop vite, ton message pourrait ne pas apparaître tant que stderr n'est pas fermé correctement : c'est un fichier.

Ok, je vais faire ça. C'est bien fclose() qu'il faut utiliser, non?

edgarjacobs a écrit:

Hélas, les po pensent que c'est la lib qui est en tort, pas leur programme(et commentaire suivant)


Ok, j'avoue que j'ai pas vraiment vérifié mon code suffisamment en profondeur :D. Je fais ça avec mon tuto et les conseils de @drx et je vous dirais ce que ça donne.

Nouveau message:(sinon je dois attendre 24h avant de reposter)

edgarjacobs a écrit:

Hélas, les po pensent que c'est la lib qui est en tort, pas leur programme(et commentaire suivant)

drx a écrit:

Le message [_MTLCommandBuffer presentDrawable:]:602: failed assertion `drawable must not be nil.

Laisse entendre que c'est la fonction RenderPresent() qui foire.


J'ai fait ce genre de manip 300 fois, si ça foire, c'est le code, pas la lib.

Vous aviez complètement raison tous les deux, c'est moi qui ai fait complètement n'importe quoi :-°.

Effectivement, c'était bien SDL_RenderPresent(HobbesRenderer) qui ratait, parce que j'avais pas compris qu'il fallait remettre le renderer comme cible de rendu AVANT de l'appeler. Dans mon code de base, je ne le faisais même pas, puis quand je l'ai modifié, je l'ai fait à la toute fin du programme. Maintenant, je l'ai fait dans la boucle principale, juste avant d'appeler SDL_RenderPresent(), et tout fonctionne correctement!

Je vous met mon code tout neuf (il est pas évolué, hein, c'est juste pour apprendre :)):

#include <SDL2/SDL.h>
#include <stdio.h>

void HobbesQuit(SDL_Renderer *renderer, SDL_Window *window, SDL_Texture *texture){
	SDL_DestroyTexture(texture);
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
    SDL_Quit();
    printf("End of the program!\n");
}


int main(int argc, char *argv[]){
	if (SDL_Init(SDL_INIT_VIDEO) != 0){
	    fprintf(stderr, "Error while initializing video system: %s\n", SDL_GetError());
	    fclose(stderr);
	    HobbesQuit(NULL, NULL, NULL);
	}

	SDL_Window *HobbesWindow = SDL_CreateWindow("Hobbes", 0, 0, 640, 480, 0);
	if (HobbesWindow == NULL){
		fprintf(stderr, "Error while creating window: %s\n", SDL_GetError());
		fclose(stderr);
		HobbesQuit(NULL, HobbesWindow, NULL);
	}
	
	SDL_Renderer *HobbesRenderer = SDL_CreateRenderer(HobbesWindow, -1, 0);
	if (HobbesRenderer == NULL){
		fprintf(stderr, "Error while creating renderer: %s\n", SDL_GetError());
		fclose(stderr);
		HobbesQuit(HobbesRenderer, HobbesWindow, NULL);
	}
	
	SDL_Texture *HobbesTexture = SDL_CreateTexture(	HobbesRenderer,SDL_PIXELFORMAT_RGBA8888,
													SDL_TEXTUREACCESS_TARGET,
													100, 100);
	if (HobbesTexture == NULL){
		fprintf(stderr, "Error while creating texture: %s\n", SDL_GetError());
		fclose(stderr);
		HobbesQuit(HobbesRenderer, HobbesWindow, HobbesTexture);
	}
	
	if (SDL_SetRenderTarget(HobbesRenderer, HobbesTexture) != 0){
		fprintf(stderr, "Error while setting renderer target: %s\n", SDL_GetError());
		fclose(stderr);
		HobbesQuit(HobbesRenderer, HobbesWindow, HobbesTexture);
	}
	
	
	
	SDL_Rect HobbesRect = {0, 0, 100, 100};
	if (SDL_SetRenderDrawColor(HobbesRenderer, 255, 0, 255, 255) != 0){
		fprintf(stderr, "Error while setting draw color: %s\n", SDL_GetError());
		fclose(stderr);
		HobbesQuit(HobbesRenderer, HobbesWindow, HobbesTexture);
	}
    
	SDL_Event HobbesEvent;
	SDL_bool quit = SDL_FALSE;
	int HobbesTimer = 0;
	
    while(!quit)
    {
    	if (SDL_SetRenderTarget(HobbesRenderer, HobbesTexture) != 0){
			fprintf(stderr, "Error while setting renderer target: %s\n", SDL_GetError());
			fclose(stderr);
			HobbesQuit(HobbesRenderer, HobbesWindow, HobbesTexture);
		}
    	if (HobbesTimer >= 5){
    		if (SDL_RenderFillRect(HobbesRenderer, &HobbesRect) != 0){
    			fprintf(stderr, "Error while filling rect: %s\n", SDL_GetError());
				fclose(stderr);
				HobbesQuit(HobbesRenderer, HobbesWindow, HobbesTexture);
    		}
		}
		SDL_SetRenderTarget(HobbesRenderer, NULL);
		SDL_RenderCopy(HobbesRenderer, HobbesTexture, NULL, &HobbesRect);
        SDL_RenderPresent(HobbesRenderer);
        SDL_WaitEvent(&HobbesEvent);
        if(HobbesEvent.type == SDL_KEYUP)
            quit = SDL_TRUE;

        SDL_Delay(1000);
        HobbesTimer += 1;
	}
	
	HobbesQuit(HobbesRenderer, HobbesWindow, HobbesTexture);

    return 0;
}



Merci à tous pour votre grande patience à mon égard! ^^

-
Edité par UnknownUnknown18 15 février 2022 à 11:46:42

  • Partager sur Facebook
  • Partager sur Twitter