8
votes

Commande GLSL Break

J'apprends actuellement comment créer des shaders à GLSL pour un moteur de jeu que je travaille, et j'ai une question concernant la langue qui me puzzle. J'ai appris que dans les versions de Shader inférieures à 3.0, vous ne pouvez pas utiliser de variables uniformes dans la condition d'une boucle. Par exemple, le code suivant ne fonctionnerait pas dans les versions de Shader plus âgées de 3,0.

for (int i = 0; i < MAX_LIGHTS; i++)
{
    if(i >= uNumLights)
        break;
    ..............
}


0 commentaires

3 Réponses :


2
votes

(Je suppose que vous parlez de pixels shaders).
La deuxième variante ne fonctionnera que sur GPU qui prend en charge le modèle de shader> = 3. Étant donné que la ramification dynamique (telle que la mise à la variable nonumlights dans si condition) n'est pas prise en charge sur le modèle GPU Shader <3 non plus.

ici Vous pouvez comparer ce qui est et n'est pas pris en charge entre différents modèles de shader.


2 commentaires

Actuellement, j'écris des shader sur une ancienne carte vidéo, qui prend uniquement en charge le modèle 2.0 de Shader. L'étrange chose est que la deuxième variante fonctionne effectivement, ou au moins elle compile sans erreur. En ce qui concerne la fonctionnalité, je ne suis pas encore sûr si cela s'arrête lorsque la commande de pause est déclenchée. Le premier bien sûr ne compile pas du tout.


Mais comme @ dm.skt a expliqué la deuxième variante n'est pas efficace en raison du risque élevé de re-compilation de Shader. Donc, je ne dépendra pas des constructions de syntaxe qui ne sont supportées que sur HAL (mais pas dans le matériel) avec des hits de performance :-)



15
votes

GLSL peut être déroutant dans la mesure où pour () vous suggère qu'il doit y avoir une ramification conditionnelle, même si le matériel n'est pas incapable de le faire du tout (ce qui s'applique à < code> si () de la même manière).

Qu'est-ce que vraiment sur le matériel pré-SM3 est que le Hal à l'intérieur de votre implémentation OpenGL déroulera complètement votre boucle, donc il n'y a plus rien de saut. Et cela explique pourquoi il a des difficultés qui le font avec des non-constantes.

Bien que techniquement possible de le faire avec des non-constantes de toute façon, la mise en œuvre devrait recompiler la shader à chaque fois que vous modifiez cet uniforme, et il peut fonctionner contre le nombre maximal d'instructions si vous êtes juste autorisé à fournir n'importe quel nombre au hasard. .

C'est un problème parce que ... quoi alors? C'est une mauvaise situation.

Si vous fournissez une trop grande constante, elle vous donnera une erreur de compilateur "trop ​​nombreuses instructions" lorsque vous construisez le shader. Maintenant, si vous fournissez un numéro idiot dans un uniforme et que le HAL doit donc produire un nouveau code et fonctionne contre cette limite, que peut OpenGL faire?
Vous avez probablement validé votre programme après la compilation et la liaison, et vous avez probablement interrogé le journal des informations sur le shader, et OpenGL a continué à vous dire que tout allait bien. C'est, d'une certaine manière, une promesse contraignante, elle ne peut pas simplement décider au contraire tout d'un coup. Par conséquent, il doit s'assurer que cette situation ne peut pas se poser et que la seule solution réalisable est de ne pas permettre des uniformes dans des conditions dans des générations matérielles qui ne supportent pas la ramification dynamique.
Sinon, il faudrait une forme de validation à l'intérieur gluniforme qui rejette les valeurs mauvaises. Cependant, étant donné que cela dépend de la recompilation shader réussie (ou non), cela signifierait qu'il faudrait fonctionner de manière synchrone, ce qui en fait une approche "non go". En outre, considérons que GL_ARB_UNIFIFIFIFIFIFIFIFIFIFOR_Buffer_Object est exposé sur certains matériels SM2 (par exemple, geforce FX), ce qui signifie que vous pouvez lancer un objet tampon avec un contenu imprévisible à OpenGL et vous attendez toujours à ce que cela fonctionne en quelque sorte! La mise en œuvre devrait numériser la mémoire de la mémoire tampon pour des valeurs non valides après la déménagement, ce qui est fou.

Semblable à une boucle, une instruction si () ne branche pas sur le matériel SM2, même si cela ressemble à cela. Au lieu de cela, cela calculera les deux branches et effectuera un mouvement conditionnel.


2 commentaires

Je sais que l'explication d'une blague la ruine, mais "la hal à l'intérieur de ton OpenGL" est bien humoristique?


@ Steven2163712: HAL = Couche d'abstraction matérielle (au cas où vous pensiez que cela fait référence à un film de science-fiction, aucune blague n'était prévue). Je ne peux pas utiliser le mot officiellement correct (même si je crois que c'est techniquement correct). OpenGL est une chose abstraite qui est largement indépendante de la manière dont le matériel actuel est inférieur à celui-ci. Qui est à la fois géniale et dérangeante. Impressionnant dans la mesure où quelque chose n'est pas pris en charge, la couche d'abstraction ne fait que fonctionner (si possible du tout). Incarnant dans la mesure où vous avez du mal à trouver un chemin rapide de travailler, et un moment plus difficile connaissant .



0
votes

Il y a un travail amusant autour, je viens de comprendre. Semble stupide et je ne peux pas vous promettre que c'est un choix sain, mais il semble travailler pour moi en ce moment:

Définissez votre boucle au maximum que vous autorisez. Placez une condition à l'intérieur de la boucle pour sauter sur les routines lourdes, si le nombre va au-delà de votre valeur uniforme. xxx


0 commentaires