2017-12-21 2 views
0

Ich verwende C# mit OpenTK, um auf OpenGL-API zuzugreifen. Mein Projekt verwendet Tessellation zum Rendern einer Heightmap. Mein Tessellations-Kontroll-Shader teilt ein Quadrat in ein Raster von 64 Quadraten auf und mein Tessellations-Evaluations-Shader fügt diesen Punkten vertikale Offsets hinzu. Vertikale Versätze werden in einem einheitlichen Schwimmerpuffer wie folgt gespeichert:Einheitliche Puffergröße auf Nvidia-GPUs

uniform float HeightmapBuffer[65 * 65]; 

Alles funktioniert gut, wenn ich das Projekt auf meinem Laptop mit AMD Radeon 8250 GPU laufen. Die Probleme beginnen, wenn ich versuche, es auf Nvidia-Grafikkarten auszuführen. Ich habe versucht, eine ältere GT 430 und eine brandneue GTX 1060, aber die Ergebnisse sind gleich:

Tessellation evaluation info 
---------------------------- 
0(13) : error C5041: cannot locate suitable resource to bind variable "HeightmapBuffer". Possibly large array. 

Als ich dieses Problem erforscht, ich GL_MAX_UNIFORM_BLOCK_SIZE Variable gefunden, die auf dem AMD und 65.54 kB auf beiden Nvidia-Chips ~ 500 MB zurück. Es ist ein wenig seltsam, da mein Array tatsächlich nur 16,9 kB verwendet, also bin ich mir nicht einmal sicher, ob die "BLOCK SIZE" tatsächlich die Größe einer Variablen begrenzt. Vielleicht begrenzt es die Größe aller Uniformen, die an einen Shader übergeben werden? Trotzdem kann ich nicht glauben, dass mein Programm 65 kB verwenden würde.

Beachten Sie, dass ich auch versucht habe, den "üblichen" Weg zu gehen, indem ich eine Textur verwende, aber ich denke, es gab Probleme mit der Interpolation. Wenn zwei benachbarte Höhenmaps zusammengefügt wurden, passten die Ränder nicht zusammen. Mit einem einheitlichen Puffer-Array auf der anderen Seite funktionieren die Dinge perfekt.

Also was ist die eigentliche Bedeutung von GL_MAX_UNIFORM_BLOCK_SIZE? Warum ist dieser Wert bei Nvidia-GPUs so niedrig? Gibt es eine andere Möglichkeit, ein großes Array an meinen Shader zu übergeben?

+1

'float' Uniformen sind eigentlich die Größe eines' vec4' also hast du '4 Bytes * 4 * 65 * 65' =' 67.6 KiB'. – genpfault

+0

Hrm, ich habe es schwer, diese Informationen in der GL-Spezifikation zu finden, also nimm es mit einem Körnchen Salz. Ich erinnere mich vielleicht an die ES 2.0-Spezifikation. – genpfault

+0

Mögliches Duplikat von [Fehler im Geometrie-Shader aus großem Array] (https://StackOverflow.com/questions/29262469/error-in-Geometry-Shader-From-large-array) – Gusman

Antwort

3

Als ich dieses Problem erforschte, fand ich GL_MAX_UNIFORM_BLOCK_SIZE Variable, die ~ 500MB auf der AMD und 65,54 kB auf beiden Nvidia-Chips zurückgibt.

GL_MAX_UNIFORM_BLOCK_SIZE ist die falsche Grenze. Das gilt nur für Uniform Buffer Objects.

Sie erklären nur ein Array

uniform float HeightmapBuffer[65 * 65]; 

außerhalb eines einheitlichen Blocks. Da Sie dies in einem Tesselation-Evaluations-Shader zu verwenden scheinen, ist der relevante Grenzwert MAX_TESS_EVALUATION_UNIFORM_COMPONENTS (für jede programmierbare Stufe gibt es eine separate Begrenzung). Diese Komponente Limit zählt nur die Anzahl der Schwimmerkomponenten, so dass ein vec4 4 Komponenten verbraucht, eine float nur eine.

In Ihrem speziellen Fall, die neueste GL spec [GL 4.6 Kernprofil] (https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf) zum Zeitpunkt des Schreibens dieses Artikels garantiert nur einen Minimalwert von 1024 für die (= 4kiB), und Sie sind Weg über diese Grenze hinaus.

Es ist eigentlich eine sehr schlechte Idee, Uniformen für solche Datenmengen zu verwenden. Sie sollten in Betracht ziehen, UBOs, Texture Buffer Objects, Shader Storage Buffer Objects oder sogar einfache Texturen zu verwenden, um Ihr Array zu speichern. UBOs wären wahrscheinlich die natürlichste Wahl in Ihrem Szenario.

+0

@PeterMcG: Die Frage besagt eindeutig, dass dies der Fall ist geht es um den Tesselation-Evaluations-Shader, nicht um den Kontroll-Shader. Der Standard-Uniform-Block ist kein einheitlicher Block im Sinne von 'GL_MAX_UNIFORM_BLOCK_SIZE', der nur für UBOs gilt. Die Benennung könnte unglücklich sein, aber die Spezifikation ist sehr klar. – derhass