J'ai rencontré un problème lorsque GLSL Shader génère une image incorrecte sur le GPU suivant:
GT 430
GT 770
GTX 570
GTX 760
mais fonctionne normalement sur ceux-ci:
Intel HD Graphics 2500
Intel HD 4000
Intel 4400
GTX 740m de
Radeon HD 6310m de
Radeon HD 8850 P>
Le code de shader est comme suit: P>
if(ints[i].geomInt.point.z < ints[i].geomInt.point.z - 10.0) { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); return; ColoredIntersection tmp = ints[j]; ints[j] = ints[i]; ints[i] = tmp; }
3 Réponses :
Si quelqu'un est toujours intéressé, j'ai posé cette question sur de nombreux sites spécialisés, y compris OpenGL.org et DevTalk.nvidia.com. Je n'ai reçu aucune réponse concrète sur ce qui ne va pas avec mon shader, juste quelques suggestions comment travailler autour de mon problème. Comme utiliser si (condition == vrai) au lieu de si (condition), utilisez aussi des algorithmes simples que possible etc. À la fin, j'ai choisi l'une des rotations les plus faciles de mon code qui se débarrasse du problème: je viens de remplacer avec p>
Honnêtement, j'aurais essayé de mettre bool valide code> sandwichisé entre les deux
Vec3 code> S connaissant ce que je fais à propos de l'alignement des données préféré de GPU.
VEC3 CODE> aime commencer sur une limite de 16 octets et est essentiellement traitée de la même manière qu'un
Vec4 code>. Vous pouvez cram une variable de 4 octets (oui,
bool code> est 32 bits dans GLSL) entre deux
Vec3 code> s de manière assez efficace sans perturber l'alignement ni l'espace de gaspillage.
Je ne pense pas que rien ne soit faux avec votre shader. Le pipeline OpenGL rend une tramebuffer. Si vous utilisez cette tramebuffer avant que le rendu soit terminé, vous obtiendrez souvent ce que vous avez vu. Veuillez garder à l'esprit que GldraRaparrays et similaires sont asynchrones (la fonction renvoie avant que le GPU ait fini de dessiner les sommets.) P>
L'utilisation la plus courante pour ces artefacts carrés est lorsque vous utilisez la tramebuffer résultant comme texture qui utilise ensuite pour un rendu supplémentaire. p>
Le pilote OpenGL est censé garder une trace des dépendances et savoir comment attendre que les dépendances soient remplies. p>
Si vous partagez une tramebuffer à travers les threads, tous les paris sont éteints, vous pourriez alors avoir besoin de faire appel à des choses comme une synchronisation de clôture (GLFEFENSYNC) pour vous assurer que un fil attend un rendu qui se déroule sur une autre Fil. P>
En tant que solution de contournement, vous trouverez peut-être appeler GLFINISH ou même GlreadPixels (avec un pixel) trie le problème. P>
Veuillez également garder à l'esprit que ce problème est lié à la synchronisation et à simplifier une shader pourrait très bien faire disparaître le problème. P>
Nope, la synchronisation n'est pas la raison. Au moins, je n'ai pas réussi à supprimer les artefacts par aucune option de synchronisation (GLFLUSH () / GLFESYNC () / WGLSWAPITIVAL (), SLEEP ()). Et je rendu directement à la fenêtre afin que les problèmes de synchronisation de rendu de texture ne soient pas non pertinents. Si vous ne me croyez pas, vous pouvez facilement le tester vous-même si vous avez des fenêtres et NVIDIA GPU: toutes les sources et les libs sont inclus dans la pièce jointe.
Eh bien, alors cela pourrait bien être un bug dans les pilotes NVIDIA OpenGL.
J'ai vu cette chose exacte à GLSL lorsque les variables ne sont pas initialisées. Par exemple, un Vec3 sera (0,0,0) par défaut sur certaines cartes graphiques, mais sur d'autres cartes graphiques, ce sera une valeur différente. Êtes-vous sûr que vous n'utilisez pas une variable sans l'attribuer d'abord une valeur? Spécifiquement, vous n'initialisez-vous pas de colorifiant3InterSection.color si l'insisection.valid est faux, mais je pense que vous l'utilisez plus tard. P>
Artefacts intéressants. Sur les configurations, le problème reproduit, est-ce complètement reproductible? Dites que vous l'exécutez 10 fois de suite, obtenez-vous toujours les artefacts? Toujours exactement la même mauvaise sortie ou y a-t-il du hasard?
Il est 100% reproductible sur la plupart des GPU Nvidia Modern. Si j'exécute le shader sur des graphiques intégrés Intel, il n'y a pas d'artefacts, si sur GF640M, ils apparaissent. Les artefacts carrés eux-mêmes changent chaque image sans aucun motif notable.
Si vous supprimez le code> code> de votre succursale, cela change-t-il quelque chose?
J'ai ajouté ce retour comme une mesure de débogage pour montrer que la condition n'est jamais vraie. Et non, j'ai un double coché et ce retour n'affecte aucune image de résultat.
Ah, cela me rappelle essentiellement de lire / écrire non synchronisé sur le tampon de couleur. Vous pouvez produire un effet presque identique à l'aide de la charge d'image / stocker sans barrière de mémoire. Cependant, étant donné que certains de ces blocs à l'écran (en particulier dans le coin supérieur gauche) ne sont pas alignés carrément sur la fenêtre, je pense que c'est un problème avec le calcul plutôt que le stockage. Avez-vous essayé d'utiliser des pragmas pour désactiver les optimisations du compilateur? NV a de nombreuses exclusives, recherchez
#pragma optionnv code>.
Vous voudrez peut-être également utiliser des fonctions intégrées pour des éléments tels que la normalisation afin d'éviter tout problème difficile à suivre par le FP.
Mais aucune optimisation n'est censée optimiser le code sans changer sa logique? Le seul cas lorsque l'optimisation peut entraîner un comportement de code de code différemment est lorsque le code a une sorte de comportement non défini. Alors, pourquoi devrais-je désactiver toute optimisation si je souhaite réellement que mon code optimisé (Shader est effectivement assez coûteux)? Et merci de la normalisation intégrée, je l'ai oubliée.
Pas nécessairement, l'optimisation peut faire des choses drôles avec des arithmétiques de point flottant. Les GPU ne respectent pas complètement à IEEE 754, avec des modèles plus anciens encore moins. Le rendu est beaucoup plus fin lorsqu'il s'agit de ce type de choses que d'une application générale en cours d'exécution sur la CPU. Compiler des logiciels généraux avec Fast Math contre une FP précise ne montrera souvent aucune différence du tout, mais la compilation de shaders avec un FP rapide et précis peut avoir un monde de différence. Et plus vous mettez en œuvre certaines opérations fondamentales vous-même au lieu d'utiliser des intégrées, plus vous êtes susceptible de courir dans cette situation.
J'ai remplacé toutes les normalisations avec des fonctions intégrées et ajouté une sauvegarde de sauvegarde pour GL_FRAGCOLOR. Aucun effet sur les artefacts. Démo mise à jour téléchargée et évolution de la source dans le message d'origine.
En fait, l'utilisation de constantes comme 1E-5 peut certainement conduire à un tel cas. En fonction de la précision de la représentation à virgule flottante utilisée, ces nombres magiques ne peuvent même pas être représentables.
lowp code>, par exemple, garantit rien de plus petit que 2 ^ -8.