web-dev-qa-db-fra.com

Quelle est la précision des flotteurs highp dans GLSL ES 2.0 (pour iPhone / iPod touch / iPad)?

J'ai un shader qui a idéalement besoin de 28 bits de mantisse, même si je peux en utiliser moins et dégrader les performances. Comment puis-je déterminer la précision de "highp" dans OpenGL ES? C'est probablement un FP24, avec une mantisse 16 bits, mais je ne peux pas comprendre avec certitude ni comment demander à OpenGL. Des idées?

31
gonzojive

Vous voulez que GetShaderPrecisionFormat interroge la plage et la précision des types de shader

int range[2], precision;
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision);

vous donnera la gamme et la précision du flotteur highp.

12
Chris Dodd

À partir de Référence OpenGL ES Shading Language :

  • highp - 16 bits, plage à virgule flottante: -2 ^ 62 à 2 ^ 62, plage d'entiers: -2 ^ 16 à 2 ^ 16
  • mediump - 10 bits, plage de virgule flottante: -2 ^ 14 à 2 ^ 14, plage d'entiers: -2 ^ 10 à 2 ^ 10
  • lowp - 8 bits, plage à virgule flottante: -2 à 2, plage entière: -2 ^ 8 à 2 ^ 8
32
Brad Larson

Dans mes tests sur ma gamme de jouets coûteux:

Pour les entiers et les flottants, les précisions et les plages entre les shaders de fragment et de sommet sont les mêmes.

Je ne listerai donc pas toutes les combinaisons de manière exhaustive.

Notez également que la précision des ints est définie pour être toujours 0.

PowerVR SGX543MP3 (iPhone 5):

  • Flottants
    • Faible: précision = 8, intervalle = 0 à 0 (Pas sûr, mais je pense que cela signifie que nous ne pouvons pas nous attendre à ce qu'un lowp puisse réellement représenter une valeur atteignant exactement 2 ou -2, Je ne connais pas vraiment un excellent moyen de tester cela, et nous ne devrions pas non plus nous préoccuper de ces limitations, utilisez simplement mediump lorsque cela pourrait être un problème)
    • Moyenne: précision = 10, plage = 15 à 15 (conforme aux spécifications)
    • Élevé: précision = 23, plage = 127 à 127 (dépasse les spécifications)
  • Ints
    • Faible: plage = 23 à 23 (dépasse les spécifications)
    • Moyenne: plage = 23 à 23 (dépasse les spécifications)
    • Élevé: plage = 23 à 23 (dépasse les spécifications)

A7 et PowerVR G6430 (iPad Air):

  • Flottants
    • Faible: précision = 10, plage = 15 à 15 (dépasse les spécifications)
    • Moyenne: précision = 10, plage = 15 à 15 (conforme aux spécifications)
    • Haute: précision = 23, plage = 127 à 127 (dépasse les spécifications ES 2.0, répond aux spécifications 3.0)
  • Ints
    • Faible: plage = 15 à 14 (dépasse les spécifications)
    • Moyenne: plage = 15 à 14 (dépasse les spécifications ES 2.0, répond aux spécifications ES 3.0)
    • Haut: plage = 31 à 30 (dépasse les spécifications ES 2.0, répond aux spécifications ES 3.0)

A8 et PowerVR GX6450 (iPhone 6 Plus):

  • Flottants
    • Faible: précision = 10, plage = 15 à 15 (dépasse les spécifications)
    • Moyenne: précision = 10, plage = 15 à 15 (conforme aux spécifications)
    • Haute: précision = 23, plage = 127 à 127 (dépasse les spécifications ES 2.0, répond aux spécifications 3.0)
  • Ints
    • Faible: plage = 15 à 14 (dépasse les spécifications)
    • Moyenne: plage = 15 à 14 (dépasse les spécifications ES 2.0, répond aux spécifications ES 3.0)
    • Haut: plage = 31 à 30 (dépasse les spécifications ES 2.0, répond aux spécifications ES 3.0)

Voici un exemple de la façon dont vous pouvez interroger les valeurs.

int range[2], precision;
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision);
NSLog(@"Fragment shader high precision float range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, range, &precision);
NSLog(@"Fragment shader medium precision float range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_LOW_FLOAT, range, &precision);
NSLog(@"Fragment shader low precision float range: %d %d precision: %d", range[0], range[1], precision);

glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_INT, range, &precision);
NSLog(@"Fragment shader high precision int range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_INT, range, &precision);
NSLog(@"Fragment shader medium precision int range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_LOW_INT, range, &precision);
NSLog(@"Fragment shader low precision int range: %d %d precision: %d", range[0], range[1], precision);

glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_HIGH_FLOAT, range, &precision);
NSLog(@"Vertex shader high precision float range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_MEDIUM_FLOAT, range, &precision);
NSLog(@"Vertex shader medium precision float range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_LOW_FLOAT, range, &precision);
NSLog(@"Vertex shader low precision float range: %d %d precision: %d", range[0], range[1], precision);

glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_HIGH_INT, range, &precision);
NSLog(@"Vertex shader high precision int range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_MEDIUM_INT, range, &precision);
NSLog(@"Vertex shader medium precision int range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_LOW_INT, range, &precision);
NSLog(@"Vertex shader low precision int range: %d %d precision: %d", range[0], range[1], precision);

Il n'est pas encore clair pour moi si vous pouvez vous attendre à des améliorations de performances tangibles en choisissant un type de moindre précision (même sur certains téléphones qui ont maintenant 3 ans).

Il est clair que la tendance est à la convergence avec le matériel de bureau car on peut voir que les GPU récents ont complètement éliminé les types 8 bits et recyclent les mediump pour lowp.

15
Steven Lu