This commit is contained in:
elwrcl committed 2026-06-06 13:25:15 +03:00
1 parent 04d4dc8b09
commit 818cab85dc
12511 files changed
+6156641

No files matched your search

+415
View File
@@ -0,0 +1,415 @@
Buffer mapping patterns
-----------------------
There are two main strategies the driver has for CPU access to GL buffer
objects. One is that the GL calls allocate temporary storage and blit to the GPU
at
``glBufferSubData()``/``glBufferData()``/``glFlushMappedBufferRange()``/``glUnmapBuffer()``
time. This makes the behavior easily match. However, this may be more costly
than direct mapping of the GL BO on some platforms, and is essentially not
available to tiling GPUs (since tiling involves running through the command
stream multiple times). Thus, GL has additional interfaces to help make it so
apps can directly access memory while avoiding implicit blocking on the GPU
rendering from those BOs.
Rendering engines have a variety of knobs to set on those GL interfaces for data
upload, and as a whole they seem to take just about every path available. Let's
look at some examples to see how they might constrain GL driver buffer upload
behavior.
Portal 2
========
.. code-block:: text
1030842 glXSwapBuffers(dpy = 0x82a8000, drawable = 20971540)
1030876 glBufferDataARB(target = GL_ELEMENT_ARRAY_BUFFER, size = 65536, data = NULL, usage = GL_DYNAMIC_DRAW)
1030877 glBufferSubData(target = GL_ELEMENT_ARRAY_BUFFER, offset = 0, size = 576, data = blob(576))
1030896 glDrawRangeElementsBaseVertex(mode = GL_TRIANGLES, start = 0, end = 526, count = 252, type = GL_UNSIGNED_SHORT, indices = NULL, basevertex = 0)
1030915 glDrawRangeElementsBaseVertex(mode = GL_TRIANGLES, start = 0, end = 19657, count = 36, type = GL_UNSIGNED_SHORT, indices = 0x1f8, basevertex = 0)
1030917 glBufferDataARB(target = GL_ARRAY_BUFFER, size = 1572864, data = NULL, usage = GL_DYNAMIC_DRAW)
1030918 glBufferSubData(target = GL_ARRAY_BUFFER, offset = 0, size = 128, data = blob(128))
1030919 glBufferSubData(target = GL_ELEMENT_ARRAY_BUFFER, offset = 576, size = 12, data = blob(12))
1030936 glDrawRangeElementsBaseVertex(mode = GL_TRIANGLES, start = 0, end = 3, count = 6, type = GL_UNSIGNED_SHORT, indices = 0x240, basevertex = 0)
1030937 glBufferSubData(target = GL_ARRAY_BUFFER, offset = 128, size = 128, data = blob(128))
1030938 glBufferSubData(target = GL_ELEMENT_ARRAY_BUFFER, offset = 588, size = 12, data = blob(12))
1030940 glDrawRangeElementsBaseVertex(mode = GL_TRIANGLES, start = 4, end = 7, count = 6, type = GL_UNSIGNED_SHORT, indices = 0x24c, basevertex = 0)
[... repeated draws at increasing offsets]
1033097 glXSwapBuffers(dpy = 0x82a8000, drawable = 20971540)
From this sequence, we can see that it is important that the driver either
implement ``glBufferSubData()`` as a blit from a streaming uploader in sequence with
the ``glDraw*()`` calls (a common behavior for non-tiled GPUs, particularly those with
dedicated memory), or that you:
1) Track the valid range of the buffer so that you don't have to flush the draws
and synchronize on each following ``glBufferSubData()``.
2) Reallocate the buffer storage on ``glBufferData`` so that your first
``glBufferSubData()`` of the frame doesn't stall on the last frame's
rendering completing.
You can't just empty your valid range on ``glBufferData()`` unless you know that
the GPU access from the previous frame has completed. This pattern of
incrementing ``glBufferSubData()`` offsets interleaved with draws from that data
is common among newer Valve games.
.. code-block:: text
[ during setup ]
679259 glGenBuffersARB(n = 1, buffers = &1314)
679260 glBindBufferARB(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 1314)
679261 glBufferDataARB(target = GL_ELEMENT_ARRAY_BUFFER, size = 3072, data = NULL, usage = GL_STATIC_DRAW)
679264 glMapBufferRange(target = GL_ELEMENT_ARRAY_BUFFER, offset = 0, length = 3072, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT) = 0xd7384000
679269 glFlushMappedBufferRange(target = GL_ELEMENT_ARRAY_BUFFER, offset = 0, length = 3072)
679270 glUnmapBuffer(target = GL_ELEMENT_ARRAY_BUFFER) = GL_TRUE
[... setup of other buffers on this binding point]
679343 glBindBufferARB(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 1314)
679344 glMapBufferRange(target = GL_ELEMENT_ARRAY_BUFFER, offset = 0, length = 768, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT) = 0xd7384000
679346 glFlushMappedBufferRange(target = GL_ELEMENT_ARRAY_BUFFER, offset = 0, length = 768)
679347 glUnmapBuffer(target = GL_ELEMENT_ARRAY_BUFFER) = GL_TRUE
679348 glMapBufferRange(target = GL_ELEMENT_ARRAY_BUFFER, offset = 768, length = 768, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT) = 0xd7384300
679350 glFlushMappedBufferRange(target = GL_ELEMENT_ARRAY_BUFFER, offset = 0, length = 768)
679351 glUnmapBuffer(target = GL_ELEMENT_ARRAY_BUFFER) = GL_TRUE
679352 glMapBufferRange(target = GL_ELEMENT_ARRAY_BUFFER, offset = 1536, length = 768, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT) = 0xd7384600
679354 glFlushMappedBufferRange(target = GL_ELEMENT_ARRAY_BUFFER, offset = 0, length = 768)
679355 glUnmapBuffer(target = GL_ELEMENT_ARRAY_BUFFER) = GL_TRUE
679356 glMapBufferRange(target = GL_ELEMENT_ARRAY_BUFFER, offset = 2304, length = 768, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT) = 0xd7384900
679358 glFlushMappedBufferRange(target = GL_ELEMENT_ARRAY_BUFFER, offset = 0, length = 768)
679359 glUnmapBuffer(target = GL_ELEMENT_ARRAY_BUFFER) = GL_TRUE
[... setup completes and we start drawing later]
761845 glBindBufferARB(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 1314)
761846 glDrawRangeElementsBaseVertex(mode = GL_TRIANGLES, start = 0, end = 323, count = 384, type = GL_UNSIGNED_SHORT, indices = NULL, basevertex = 0)
This suggests that, for non-blitting drivers, resetting your "might be used on
the GPU" range after a stall could save you a bunch of additional GPU stalls
during setup.
Terraria
========
.. code-block:: text
167581 glXSwapBuffers(dpy = 0x3004630, drawable = 25165844)
167585 glBufferData(target = GL_ARRAY_BUFFER, size = 196608, data = NULL, usage = GL_STREAM_DRAW)
167586 glBufferSubData(target = GL_ARRAY_BUFFER, offset = 0, size = 1728, data = blob(1728))
167588 glDrawRangeElementsBaseVertex(mode = GL_TRIANGLES, start = 0, end = 71, count = 108, type = GL_UNSIGNED_SHORT, indices = NULL, basevertex = 0)
167589 glBufferData(target = GL_ARRAY_BUFFER, size = 196608, data = NULL, usage = GL_STREAM_DRAW)
167590 glBufferSubData(target = GL_ARRAY_BUFFER, offset = 0, size = 27456, data = blob(27456))
167592 glDrawRangeElementsBaseVertex(mode = GL_TRIANGLES, start = 0, end = 7, count = 12, type = GL_UNSIGNED_SHORT, indices = NULL, basevertex = 0)
167594 glDrawRangeElementsBaseVertex(mode = GL_TRIANGLES, start = 0, end = 3, count = 6, type = GL_UNSIGNED_SHORT, indices = NULL, basevertex = 8)
167596 glDrawRangeElementsBaseVertex(mode = GL_TRIANGLES, start = 0, end = 3, count = 6, type = GL_UNSIGNED_SHORT, indices = NULL, basevertex = 12)
[...]
In this game, we can see ``glBufferData()`` being used on the same array buffer
throughout, to get new storage so that the ``glBufferSubData()`` doesn't cause
synchronization.
Don't Starve
============
.. code-block:: text
7251917 glGenBuffers(n = 1, buffers = &115052)
7251918 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 115052)
7251919 glBufferData(target = GL_ARRAY_BUFFER, size = 144, data = blob(144), usage = GL_STREAM_DRAW)
7251921 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 115052)
7251928 glDrawArrays(mode = GL_TRIANGLES, first = 0, count = 6)
7251930 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 114872)
7251936 glDrawArrays(mode = GL_TRIANGLES, first = 0, count = 18)
7251938 glGenBuffers(n = 1, buffers = &115053)
7251939 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 115053)
7251940 glBufferData(target = GL_ARRAY_BUFFER, size = 144, data = blob(144), usage = GL_STREAM_DRAW)
7251942 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 115053)
7251949 glDrawArrays(mode = GL_TRIANGLES, first = 0, count = 6)
7251973 glXSwapBuffers(dpy = 0x86dd860, drawable = 20971540)
[... drawing next frame]
7252388 glDeleteBuffers(n = 1, buffers = &115052)
7252389 glDeleteBuffers(n = 1, buffers = &115053)
7252390 glXSwapBuffers(dpy = 0x86dd860, drawable = 20971540)
In this game we have a lot of tiny ``glBufferData()`` calls, suggesting that we
could see working set wins and possibly CPU overhead reduction by packing small
GL buffers in the same BO. Interestingly, the deletes of the temporary buffers
always happen at the end of the next frame.
Euro Truck Simulator
====================
.. code-block:: text
[usage of VBO 14,15]
[...]
885199 glXSwapBuffers(dpy = 0x379a3e0, drawable = 20971527)
885203 glInvalidateBufferData(buffer = 14)
885204 glInvalidateBufferData(buffer = 15)
[...]
889330 glXSwapBuffers(dpy = 0x379a3e0, drawable = 20971527)
889334 glInvalidateBufferData(buffer = 12)
889335 glInvalidateBufferData(buffer = 16)
[...]
893461 glXSwapBuffers(dpy = 0x379a3e0, drawable = 20971527)
893462 glClientWaitSync(sync = 0x77eee10, flags = 0x0, timeout = 0) = GL_ALREADY_SIGNALED
893463 glDeleteSync(sync = 0x780a630)
893464 glFenceSync(condition = GL_SYNC_GPU_COMMANDS_COMPLETE, flags = 0) = 0x78ec730
893465 glInvalidateBufferData(buffer = 13)
893466 glInvalidateBufferData(buffer = 17)
893505 glBindBuffer(target = GL_COPY_READ_BUFFER, buffer = 14)
893506 glMapBufferRange(target = GL_COPY_READ_BUFFER, offset = 0, length = 788, access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0x7b034efd1000
893508 glUnmapBuffer(target = GL_COPY_READ_BUFFER) = GL_TRUE
893509 glBindBuffer(target = GL_COPY_READ_BUFFER, buffer = 15)
893510 glMapBufferRange(target = GL_COPY_READ_BUFFER, offset = 0, length = 32, access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0x7b034e5df000
893512 glUnmapBuffer(target = GL_COPY_READ_BUFFER) = GL_TRUE
893532 glBindVertexBuffers(first = 0, count = 2, buffers = {10, 15}, offsets = {0, 0}, strides = {52, 16})
893552 glDrawElementsInstancedBaseVertex(mode = GL_TRIANGLES, count = 18, type = GL_UNSIGNED_SHORT, indices = 0x13f280, instancecount = 1, basevertex = 25131)
893609 glDrawArrays(mode = GL_TRIANGLES, first = 0, count = 6)
893732 glBindVertexBuffers(first = 0, count = 1, buffers = &14, offsets = &0, strides = &48)
893733 glBindBuffer(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 14)
893744 glDrawElementsBaseVertex(mode = GL_TRIANGLES, count = 6, type = GL_UNSIGNED_SHORT, indices = 0xf0, basevertex = 0)
893759 glDrawElementsBaseVertex(mode = GL_TRIANGLES, count = 24, type = GL_UNSIGNED_SHORT, indices = 0x2e0, basevertex = 6)
893786 glDrawElementsBaseVertex(mode = GL_TRIANGLES, count = 600, type = GL_UNSIGNED_SHORT, indices = 0xe87b0, basevertex = 21515)
893822 glDrawArrays(mode = GL_TRIANGLES, first = 0, count = 6)
893845 glBindBuffer(target = GL_COPY_READ_BUFFER, buffer = 14)
893846 glMapBufferRange(target = GL_COPY_READ_BUFFER, offset = 788, length = 788, access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0x7b034efd1314
893848 glUnmapBuffer(target = GL_COPY_READ_BUFFER) = GL_TRUE
893886 glDrawElementsInstancedBaseVertex(mode = GL_TRIANGLES, count = 18, type = GL_UNSIGNED_SHORT, indices = 0x13f280, instancecount = 1, basevertex = 25131)
893943 glDrawArrays(mode = GL_TRIANGLES, first = 0, count = 6)
At the start of this frame, buffer 14 and 15 haven't been used in the previous 2
frames, and the :ext:`GL_ARB_sync` fence has ensured that the GPU has at least started
frame n-1 as the CPU starts the current frame. The first map is ``offset = 0,
INVALIDATE_BUFFER | UNSYNCHRONIZED``, which suggests that the driver should
reallocate storage for the mapping even in the ``UNSYNCHRONIZED`` case, except
that the buffer is definitely going to be idle, making reallocation unnecessary
(you may need to empty your valid range, though, to prevent unnecessary batch
flushes).
Also note the use of a totally unrelated binding point for the mapping of the
vertex array -- you can't effectively use it as a hint for any buffer placement
in memory. The game does also use ``glCopyBufferSubData()``, but only on a
different buffer.
Plague Inc
==========
.. code-block:: text
1640732 glXSwapBuffers(dpy = 0xb218f20, drawable = 23068674)
1640733 glClientWaitSync(sync = 0xb4141430, flags = 0x0, timeout = 0) = GL_ALREADY_SIGNALED
1640734 glDeleteSync(sync = 0xb4141430)
1640735 glFenceSync(condition = GL_SYNC_GPU_COMMANDS_COMPLETE, flags = 0) = 0xb4141430
1640780 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 78)
1640787 glBindBuffer(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 79)
1640788 glDrawElements(mode = GL_TRIANGLES, count = 9636, type = GL_UNSIGNED_SHORT, indices = NULL)
1640795 glDrawElements(mode = GL_TRIANGLES, count = 9636, type = GL_UNSIGNED_SHORT, indices = NULL)
1640813 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 1096)
1640814 glMapBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 67584, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0xbfef4000
1640815 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 1091)
1640816 glMapBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 12, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0xc3998000
1640817 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 1096)
1640819 glFlushMappedBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 352)
1640820 glUnmapBuffer(target = GL_COPY_WRITE_BUFFER) = GL_TRUE
1640821 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 1091)
1640823 glFlushMappedBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 12)
1640824 glUnmapBuffer(target = GL_COPY_WRITE_BUFFER) = GL_TRUE
1640825 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 1096)
1640831 glBindBuffer(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 1091)
1640832 glDrawElements(mode = GL_TRIANGLES, count = 6, type = GL_UNSIGNED_SHORT, indices = NULL)
1640847 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 1096)
1640848 glMapBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 352, length = 67584, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0xbfef4160
1640849 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 1091)
1640850 glMapBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 88, length = 12, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0xc3998058
1640851 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 1096)
1640853 glFlushMappedBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 352)
1640854 glUnmapBuffer(target = GL_COPY_WRITE_BUFFER) = GL_TRUE
1640855 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 1091)
1640857 glFlushMappedBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 12)
1640858 glUnmapBuffer(target = GL_COPY_WRITE_BUFFER) = GL_TRUE
1640863 glDrawElementsBaseVertex(mode = GL_TRIANGLES, count = 6, type = GL_UNSIGNED_SHORT, indices = 0x58, basevertex = 4)
At the start of this frame, the VBOs haven't been used in about 6 frames, and
the :ext:`GL_ARB_sync` fence has ensured that the GPU has started frame n-1.
Note the use of ``glFlushMappedBufferRange()`` on a small fraction of the size
of the VBO -- it is important that a blitting driver make use of the flush
ranges when in explicit mode.
Darkest Dungeon
===============
.. code-block:: text
938384 glXSwapBuffers(dpy = 0x377fcd0, drawable = 23068692)
938385 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 2)
938386 glBufferData(target = GL_ARRAY_BUFFER, size = 1048576, data = NULL, usage = GL_STREAM_DRAW)
938511 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 2)
938512 glMapBufferRange(target = GL_ARRAY_BUFFER, offset = 0, length = 1048576, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0x7a73fcaa7000
938514 glFlushMappedBufferRange(target = GL_ARRAY_BUFFER, offset = 0, length = 512)
938515 glUnmapBuffer(target = GL_ARRAY_BUFFER) = GL_TRUE
938523 glBindBuffer(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 1)
938524 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 2)
938525 glDrawElements(mode = GL_TRIANGLES, count = 24, type = GL_UNSIGNED_SHORT, indices = NULL)
938527 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 2)
938528 glMapBufferRange(target = GL_ARRAY_BUFFER, offset = 0, length = 1048576, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0x7a73fcaa7000
938530 glFlushMappedBufferRange(target = GL_ARRAY_BUFFER, offset = 512, length = 512)
938531 glUnmapBuffer(target = GL_ARRAY_BUFFER) = GL_TRUE
938539 glBindBuffer(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 1)
938540 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 2)
938541 glDrawElements(mode = GL_TRIANGLES, count = 24, type = GL_UNSIGNED_SHORT, indices = 0x30)
[... more maps and draws at increasing offsets]
Interesting note for this game, after the initial ``glBufferData()`` in the
frame to reallocate the storage, it unsync maps the whole buffer each time, and
just changes which region it flushes. The same GL buffer name is used in every
frame.
Tabletop Simulator
==================
.. code-block:: text
1287594 glXSwapBuffers(dpy = 0x3e10810, drawable = 23068692)
1287595 glClientWaitSync(sync = 0x7abf554e37b0, flags = 0x0, timeout = 0) = GL_ALREADY_SIGNALED
1287596 glDeleteSync(sync = 0x7abf554e37b0)
1287597 glFenceSync(condition = GL_SYNC_GPU_COMMANDS_COMPLETE, flags = 0) = 0x7abf56647490
1287614 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 480)
1287615 glMapBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 384, access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0x7abf2e79a000
1287642 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 614)
1287650 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 5)
1287651 glBufferSubData(target = GL_COPY_WRITE_BUFFER, offset = 0, size = 1088, data = blob(1088))
1287652 glBindBuffer(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 615)
1287653 glDrawElements(mode = GL_TRIANGLES, count = 1788, type = GL_UNSIGNED_SHORT, indices = NULL)
[... more draw calls]
1289055 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 480)
1289057 glFlushMappedBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 384)
1289058 glUnmapBuffer(target = GL_COPY_WRITE_BUFFER) = GL_TRUE
1289059 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 480)
1289066 glDrawArrays(mode = GL_TRIANGLE_STRIP, first = 12, count = 4)
1289068 glDrawArrays(mode = GL_TRIANGLE_STRIP, first = 8, count = 4)
1289553 glXSwapBuffers(dpy = 0x3e10810, drawable = 23068692)
In this app, buffer 480 gets used like this every other frame. The :ext:`GL_ARB_sync`
fence ensures that frame n-1 has started on the GPU before CPU work starts on
the current frame, so the unsynchronized access to the buffers is safe.
Hollow Knight
=============
.. code-block:: text
1873034 glXSwapBuffers(dpy = 0x28609d0, drawable = 23068692)
1873035 glClientWaitSync(sync = 0x7b1a5ca6e130, flags = 0x0, timeout = 0) = GL_ALREADY_SIGNALED
1873036 glDeleteSync(sync = 0x7b1a5ca6e130)
1873037 glFenceSync(condition = GL_SYNC_GPU_COMMANDS_COMPLETE, flags = 0) = 0x7b1a5ca6e130
1873038 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 29)
1873039 glMapBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 8640, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0x7b1a04c7e000
1873040 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 30)
1873041 glMapBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 720, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0x7b1a07430000
1873065 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 29)
1873067 glFlushMappedBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 8640)
1873068 glUnmapBuffer(target = GL_COPY_WRITE_BUFFER) = GL_TRUE
1873069 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 30)
1873071 glFlushMappedBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 720)
1873072 glUnmapBuffer(target = GL_COPY_WRITE_BUFFER) = GL_TRUE
1873073 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 29)
1873074 glMapBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 8640, length = 576, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0x7b1a04c801c0
1873075 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 30)
1873076 glMapBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 720, length = 72, access = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT) = 0x7b1a074302d0
1873077 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 29)
1873079 glFlushMappedBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 576)
1873080 glUnmapBuffer(target = GL_COPY_WRITE_BUFFER) = GL_TRUE
1873081 glBindBuffer(target = GL_COPY_WRITE_BUFFER, buffer = 30)
1873083 glFlushMappedBufferRange(target = GL_COPY_WRITE_BUFFER, offset = 0, length = 72)
1873084 glUnmapBuffer(target = GL_COPY_WRITE_BUFFER) = GL_TRUE
1873085 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 29)
1873096 glBindBuffer(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 30)
1873097 glDrawElementsBaseVertex(mode = GL_TRIANGLES, count = 36, type = GL_UNSIGNED_SHORT, indices = 0x2d0, basevertex = 240)
In this app, buffer 29/30 get used like this starting from offset 0 every other
frame. The :ext:`GL_ARB_sync` fence is used to make sure that the GPU has reached the
start of the previous frame before we go unsynchronized writing over the n-2
frame's buffer.
Borderlands 2
=============
.. code-block:: text
3561998 glFlush()
3562004 glXSwapBuffers(dpy = 0xbaf0f90, drawable = 23068705)
3562006 glClientWaitSync(sync = 0x231c2ab0, flags = GL_SYNC_FLUSH_COMMANDS_BIT, timeout = 10000000000) = GL_ALREADY_SIGNALED
3562007 glDeleteSync(sync = 0x231c2ab0)
3562008 glFenceSync(condition = GL_SYNC_GPU_COMMANDS_COMPLETE, flags = 0) = 0x231aadc0
3562050 glBindBufferARB(target = GL_ARRAY_BUFFER, buffer = 1193)
3562051 glMapBufferRange(target = GL_ARRAY_BUFFER, offset = 0, length = 1792, access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT) = 0xde056000
3562053 glUnmapBufferARB(target = GL_ARRAY_BUFFER) = GL_TRUE
3562054 glBindBufferARB(target = GL_ARRAY_BUFFER, buffer = 1194)
3562055 glMapBufferRange(target = GL_ARRAY_BUFFER, offset = 0, length = 1280, access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT) = 0xd9426000
3562057 glUnmapBufferARB(target = GL_ARRAY_BUFFER) = GL_TRUE
[... unrelated draws]
3563051 glBindBufferARB(target = GL_ARRAY_BUFFER, buffer = 1193)
3563064 glBindBufferARB(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 875)
3563065 glDrawElementsInstancedARB(mode = GL_TRIANGLES, count = 72, type = GL_UNSIGNED_SHORT, indices = NULL, instancecount = 28)
The :ext:`GL_ARB_sync` fence ensures that the GPU has started frame n-1 before the CPU
starts on the current frame.
This sequence of buffer uploads appears in each frame with the same buffer
names, so you do need to handle the ``GL_MAP_INVALIDATE_BUFFER_BIT`` as a
reallocate if the buffer is GPU-busy (it wasn't in this trace capture) to avoid
stalls on the n-1 frame completing.
Note that this is just one small buffer. Most of the vertex data goes through a
``glBufferSubData()``/``glDraw*()`` path with the VBO used across multiple
frames, with a ``glBufferData()`` when needing to wrap.
Buffer mapping conclusions
--------------------------
* Non-blitting drivers must track the valid range of a freshly allocated buffer
as it gets uploaded in ``pipe_transfer_map()`` and avoid stalling on the GPU
when mapping an undefined portion of the buffer when ``glBufferSubData()`` is
interleaved with drawing.
* Non-blitting drivers must reallocate storage on ``glBufferData(NULL)`` so that
the following ``glBufferSubData()`` won't stall. That ``glBufferData(NULL)``
call will appear in the driver as an ``invalidate_resource()`` call if
``pipe_caps.invalidate_buffer`` is available. (If that flag is not set, then
mesa/st will create a new pipe_resource for you). Storage reallocation may be
skipped if you for some reason know that the buffer is idle, in which case you
can just empty the valid region.
* Blitting drivers must use the ``transfer_flush_region()`` region
instead of the mapped range when ``PIPE_MAP_FLUSH_EXPLICIT`` is set, to avoid
blitting too much data. (When that bit is unset, you just blit the whole
mapped range at unmap time.)
* Buffer valid range tracking in non-blitting drivers must use the
``transfer_flush_region()`` region instead of the mapped range when
``PIPE_MAP_FLUSH_EXPLICIT`` is set, to avoid excess stalls.
* Buffer valid range tracking doesn't need to be fancy, "number of bytes
valid starting from 0" is sufficient for all examples found.
* Use the ``util_debug_callback`` to report stalls on buffer mapping to ease
debug.
* Buffer binding points are not useful for tuning buffer placement (See all the
``PIPE_COPY_WRITE_BUFFER`` instances), you have to track the actual usage
history of a GL BO name. mesa/st does this for optimizing its state updates
on reallocation in the ``!pipe_caps.invalidate_buffer`` case, and if you set
``pipe_caps.invalidate_buffer`` then you have to flag your own internal state
updates (VBO addresses, XFB addresses, texture buffer addresses, etc.) on
reallocation based on usage history.
+976
View File
@@ -0,0 +1,976 @@
.. _context:
Context
=======
A Gallium rendering context encapsulates the state which effects 3D
rendering such as blend state, depth/stencil state, texture samplers,
etc.
Note that resource/texture allocation is not per-context but per-screen.
Methods
-------
CSO State
^^^^^^^^^
All Constant State Object (CSO) state is created, bound, and destroyed,
with triplets of methods that all follow a specific naming scheme.
For example, ``create_blend_state``, ``bind_blend_state``, and
``destroy_blend_state``.
CSO objects handled by the context object:
* :ref:`Blend`: ``*_blend_state``
* :ref:`Sampler`: Texture sampler states are bound separately for fragment,
vertex, geometry and compute shaders with the ``bind_sampler_states``
function. The ``start`` and ``num_samplers`` parameters indicate a range
of samplers to change. NOTE: at this time, start is always zero and
the CSO module will always replace all samplers at once (no sub-ranges).
This may change in the future.
* :ref:`Rasterizer`: ``*_rasterizer_state``
* :ref:`depth-stencil-alpha`: ``*_depth_stencil_alpha_state``
* :ref:`Shader`: These are create, bind and destroy methods for vertex,
fragment and geometry shaders.
* :ref:`vertexelements`: ``*_vertex_elements_state``
Resource Binding State
^^^^^^^^^^^^^^^^^^^^^^
This state describes how resources in various flavors (textures,
buffers, surfaces) are bound to the driver.
* ``set_constant_buffer`` sets a constant buffer to be used for a given shader
type. index is used to indicate which buffer to set (some APIs may allow
multiple ones to be set, and binding a specific one later, though drivers
are mostly restricted to the first one right now).
If take_ownership is true, the buffer reference is passed to the driver, so
that the driver doesn't have to increment the reference count.
* ``set_inlinable_constants`` sets inlinable constants for constant buffer 0.
These are constants that the driver would like to inline in the IR
of the current shader and recompile it. Drivers can determine which
constants they prefer to inline in finalize_nir and store that
information in shader_info::*inlinable_uniform*. When the state tracker
or frontend uploads constants to a constant buffer, it can pass
inlinable constants separately via this call.
Any ``set_constant_buffer`` call invalidates inlinable constants, so
``set_inlinable_constants`` must be called after it. Binding a shader also
invalidates this state.
There is no ``PIPE_CAP`` for this. Drivers shouldn't set the shader_info
fields if they don't implement ``set_inlinable_constants``.
* ``set_framebuffer_state``
* ``set_vertex_buffers``
Non-CSO State
^^^^^^^^^^^^^
These pieces of state are too small, variable, and/or trivial to have CSO
objects. They all follow simple, one-method binding calls, e.g.
``set_blend_color``.
* ``set_stencil_ref`` sets the stencil front and back reference values
which are used as comparison values in stencil test.
* ``set_blend_color``
* ``set_sample_mask`` sets the per-context multisample sample mask. Note
that this takes effect even if multisampling is not explicitly enabled if
the framebuffer surface(s) are multisampled. Also, this mask is AND-ed
with the optional fragment shader sample mask output (when emitted).
* ``set_sample_locations`` sets the sample locations used for rasterization.
```get_sample_position``` still returns the default locations. When NULL,
the default locations are used.
* ``set_min_samples`` sets the minimum number of samples that must be run.
* ``set_clip_state``
* ``set_polygon_stipple``
* ``set_scissor_states`` sets the bounds for the scissor test, which culls
pixels before blending to render targets. If the :ref:`Rasterizer` does
not have the scissor test enabled, then the scissor bounds never need to
be set since they will not be used. Note that scissor xmin and ymin are
inclusive, but xmax and ymax are exclusive. The inclusive ranges in x
and y would be [xmin..xmax-1] and [ymin..ymax-1]. The number of scissors
should be the same as the number of set viewports and can be up to
PIPE_MAX_VIEWPORTS.
* ``set_viewport_states``
* ``set_window_rectangles`` sets the window rectangles to be used for
rendering, as defined by :ext:`GL_EXT_window_rectangles`. There are two
modes - include and exclude, which define whether the supplied
rectangles are to be used for including fragments or excluding
them. All of the rectangles are ORed together, so in exclude mode,
any fragment inside any rectangle would be culled, while in include
mode, any fragment outside all rectangles would be culled. xmin/ymin
are inclusive, while xmax/ymax are exclusive (same as scissor states
above). Note that this only applies to draws, not clears or
blits. (Blits have their own way to pass the requisite rectangles
in.)
* ``set_tess_state`` configures the default tessellation parameters:
* ``default_outer_level`` is the default value for the outer tessellation
levels. This corresponds to GL's ``PATCH_DEFAULT_OUTER_LEVEL``.
* ``default_inner_level`` is the default value for the inner tessellation
levels. This corresponds to GL's ``PATCH_DEFAULT_INNER_LEVEL``.
* ``set_patch_vertices`` sets the number of vertices per input patch
for tessellation.
* ``set_debug_callback`` sets the callback to be used for reporting
various debug messages, eventually reported via :ext:`GL_KHR_debug` and
similar mechanisms.
Samplers
^^^^^^^^
pipe_sampler_state objects control how textures are sampled (coordinate wrap
modes, interpolation modes, etc). Samplers are only required for texture
instructions for which nir_tex_instr_need_sampler returns true. Drivers must
ignore samplers for other texture instructions. Frontends may or may not bind
samplers when no texture instruction use them. Notably, frontends may not bind
samplers for texture buffer objects, which are never accessed with samplers.
Sampler Views
^^^^^^^^^^^^^
These are the means to bind textures to shader stages. To create one, specify
its format, swizzle and LOD range in sampler view template.
If texture format is different than template format, it is said the texture
is being cast to another format. Casting can be done only between compatible
formats, that is formats that have matching component order and sizes.
Swizzle fields specify the way in which fetched texel components are placed
in the result register. For example, ``swizzle_r`` specifies what is going to be
placed in first component of result register.
The ``first_level`` and ``last_level`` fields of sampler view template specify
the LOD range the texture is going to be constrained to. Note that these
values are in addition to the respective min_lod, max_lod values in the
pipe_sampler_state (that is if min_lod is 2.0, and first_level 3, the first mip
level used for sampling from the resource is effectively the fifth).
The ``first_layer`` and ``last_layer`` fields specify the layer range the
texture is going to be constrained to. Similar to the LOD range, this is added
to the array index which is used for sampling.
* ``set_sampler_views`` binds an array of sampler views to a shader stage.
Every binding point acquires a reference
to a respective sampler view and releases a reference to the previous
sampler view.
Sampler views outside of ``[start_slot, start_slot + num_views)`` are
unmodified. If ``views`` is NULL, the behavior is the same as if
``views[n]`` was NULL for the entire range, i.e. releasing the reference
for all the sampler views in the specified range.
* ``create_sampler_view`` creates a new sampler view. ``texture`` is associated
with the sampler view which results in sampler view holding a reference
to the texture. Format specified in template must be compatible
with texture format.
* ``sampler_view_destroy`` destroys a sampler view and releases its reference
to associated texture.
Hardware Atomic buffers
^^^^^^^^^^^^^^^^^^^^^^^
Buffers containing HW atomics are required to support the feature
on some drivers.
Drivers that require this need to fill the ``set_hw_atomic_buffers`` method.
Shader Resources
^^^^^^^^^^^^^^^^
Shader resources are textures or buffers that may be read or written
from a shader without an associated sampler. This means that they
have no support for floating point coordinates, address wrap modes or
filtering.
There are 2 types of shader resources: buffers and images.
Buffers are specified using the ``set_shader_buffers`` method.
Images are specified using the ``set_shader_images`` method. When binding
images, the ``level``, ``first_layer`` and ``last_layer`` pipe_image_view
fields specify the mipmap level and the range of layers the image will be
constrained to.
Surfaces
^^^^^^^^
These are the means to use resources as color render targets or depthstencil
attachments. To create one, specify the mip level, the range of layers, and
the bind flags (either PIPE_BIND_DEPTH_STENCIL or PIPE_BIND_RENDER_TARGET).
Note that layer values are in addition to what is indicated by the geometry
shader output variable XXX_FIXME (that is if first_layer is 3 and geometry
shader indicates index 2, the 5th layer of the resource will be used). These
first_layer and last_layer parameters will only be used for 1d array, 2d array,
cube, and 3d textures otherwise they are 0.
* ``create_surface`` creates a new surface.
* ``surface_destroy`` destroys a surface and releases its reference to the
associated resource.
Stream output targets
^^^^^^^^^^^^^^^^^^^^^
Stream output, also known as transform feedback, allows writing the primitives
produced by the vertex pipeline to buffers. This is done after the geometry
shader or vertex shader if no geometry shader is present.
The stream output targets are views into buffer resources which can be bound
as stream outputs and specify a memory range where it's valid to write
primitives. The pipe driver must implement memory protection such that any
primitives written outside of the specified memory range are discarded.
Two stream output targets can use the same resource at the same time, but
with a disjoint memory range.
Additionally, the stream output target internally maintains the offset
into the buffer which is incremented every time something is written to it.
The internal offset is equal to how much data has already been written.
It can be stored in device memory and the CPU actually doesn't have to query
it.
The stream output target can be used in a draw command to provide
the vertex count. The vertex count is derived from the internal offset
discussed above.
* ``create_stream_output_target`` create a new target.
* ``stream_output_target_destroy`` destroys a target. Users of this should
use pipe_so_target_reference instead.
* ``set_stream_output_targets`` binds stream output targets. The parameter
offset is an array which specifies the internal offset of the buffer. The
internal offset is, besides writing, used for reading the data during the
draw_auto stage, i.e. it specifies how much data there is in the buffer
for the purposes of the draw_auto stage. -1 means the buffer should
be appended to, and everything else sets the internal offset.
* ``stream_output_target_offset`` Retrieve the internal stream offset from
an streamout target. This is used to implement Vulkan pause/resume support
which needs to pass the internal offset to the API.
NOTE: The currently-bound vertex or geometry shader must be compiled with
the properly-filled-in structure pipe_stream_output_info describing which
outputs should be written to buffers and how. The structure is part of
pipe_shader_state.
Clearing
^^^^^^^^
Clear is one of the most difficult concepts to nail down to a single
interface (due to both different requirements from APIs and also driver/HW
specific differences).
``clear`` initializes some or all of the surfaces currently bound to
the framebuffer to particular RGBA, depth, or stencil values.
Currently, this does not take into account color or stencil write masks (as
used by GL), and always clears the whole surfaces (no scissoring as used by
GL clear or explicit rectangles like d3d9 uses). It can, however, also clear
only depth or stencil in a combined depth/stencil surface.
If a surface includes several layers then all layers will be cleared.
``clear_render_target`` clears a single color rendertarget with the specified
color value. While it is only possible to clear one surface at a time (which can
include several layers), this surface need not be bound to the framebuffer.
If render_condition_enabled is false, any current rendering condition is ignored
and the clear will be unconditional.
``clear_depth_stencil`` clears a single depth, stencil or depth/stencil surface
with the specified depth and stencil values (for combined depth/stencil buffers,
it is also possible to only clear one or the other part). While it is only
possible to clear one surface at a time (which can include several layers),
this surface need not be bound to the framebuffer.
If render_condition_enabled is false, any current rendering condition is ignored
and the clear will be unconditional.
``clear_texture`` clears a non-PIPE_BUFFER resource's specified level
and bounding box with a clear value provided in that resource's native
format.
``clear_buffer`` clears a PIPE_BUFFER resource with the specified clear value
(which may be multiple bytes in length). Logically this is a memset with a
multi-byte element value starting at offset bytes from resource start, going
for size bytes. It is guaranteed that size % clear_value_size == 0.
Evaluating Depth Buffers
^^^^^^^^^^^^^^^^^^^^^^^^
``evaluate_depth_buffer`` is a hint to decompress the current depth buffer
assuming the current sample locations to avoid problems that could arise when
using programmable sample locations.
If a depth buffer is rendered with different sample location state than
what is current at the time of reading the depth buffer, the values may differ
because depth buffer compression can depend the sample locations.
Uploading
^^^^^^^^^
For simple single-use uploads, use ``pipe_context::stream_uploader`` or
``pipe_context::const_uploader``. The latter should be used for uploading
constants, while the former should be used for uploading everything else.
PIPE_USAGE_STREAM is implied in both cases, so don't use the uploaders
for static allocations.
Usage:
Call u_upload_alloc or u_upload_data as many times as you want. After you are
done, call u_upload_unmap. If the driver doesn't support persistent mappings,
u_upload_unmap makes sure the previously mapped memory is unmapped.
Gotchas:
- Always fill the memory immediately after u_upload_alloc. Any following call
to u_upload_alloc and u_upload_data can unmap memory returned by previous
u_upload_alloc.
- Don't interleave calls using stream_uploader and const_uploader. If you use
one of them, do the upload, unmap, and only then can you use the other one.
Drawing
^^^^^^^
``draw_vbo`` draws a specified primitive. The primitive mode and other
properties are described by ``pipe_draw_info``.
The ``mode``, ``start``, and ``count`` fields of ``pipe_draw_info`` specify the
the mode of the primitive and the vertices to be fetched, in the range between
``start`` to ``start``+``count``-1, inclusive.
Every instance with instanceID in the range between ``start_instance`` and
``start_instance``+``instance_count``-1, inclusive, will be drawn.
If ``index_size`` != 0, all vertex indices will be looked up from the index
buffer.
In indexed draw, ``min_index`` and ``max_index`` respectively provide a lower
and upper bound of the indices contained in the index buffer inside the range
between ``start`` to ``start``+``count``-1. This allows the driver to
determine which subset of vertices will be referenced during the draw call
without having to scan the index buffer. Providing a over-estimation of the
the true bounds, for example, a ``min_index`` and ``max_index`` of 0 and
0xffffffff respectively, must give exactly the same rendering, albeit with less
performance due to unreferenced vertex buffers being unnecessarily DMA'ed or
processed. Providing a underestimation of the true bounds will result in
undefined behavior, but should not result in program or system failure.
In case of non-indexed draw, ``min_index`` should be set to
``start`` and ``max_index`` should be set to ``start``+``count``-1.
``index_bias`` is a value added to every vertex index after lookup and before
fetching vertex attributes.
When drawing indexed primitives, the primitive restart index can be
used to draw disjoint primitive strips. For example, several separate
line strips can be drawn by designating a special index value as the
restart index. The ``primitive_restart`` flag enables/disables this
feature. The ``restart_index`` field specifies the restart index value.
When primitive restart is in use, array indexes are compared to the
restart index before adding the index_bias offset.
If a given vertex element has ``instance_divisor`` set to 0, it is said
it contains per-vertex data and effective vertex attribute address needs
to be recalculated for every index.
attribAddr = ``stride`` * index + ``src_offset``
If a given vertex element has ``instance_divisor`` set to non-zero,
it is said it contains per-instance data and effective vertex attribute
address needs to recalculated for every ``instance_divisor``-th instance.
attribAddr = ``stride`` * instanceID / ``instance_divisor`` + ``src_offset``
In the above formulas, ``src_offset`` is taken from the given vertex element
and ``stride`` is taken from a vertex buffer associated with the given
vertex element.
The calculated attribAddr is used as an offset into the vertex buffer to
fetch the attribute data.
The value of ``instanceID`` can be read in a vertex shader through a system
value register declared with INSTANCEID semantic name.
Queries
^^^^^^^
Queries gather some statistic from the 3D pipeline over one or more
draws. Queries may be nested, though not all gallium frontends exercise this.
Queries can be created with ``create_query`` and deleted with
``destroy_query``. To start a query, use ``begin_query``, and when finished,
use ``end_query`` to end the query.
``create_query`` takes a query type (``PIPE_QUERY_*``), as well as an index,
which is the vertex stream for ``PIPE_QUERY_PRIMITIVES_GENERATED`` and
``PIPE_QUERY_PRIMITIVES_EMITTED``, and allocates a query structure.
``begin_query`` will clear/reset previous query results.
``get_query_result`` is used to retrieve the results of a query. If
the ``wait`` parameter is TRUE, then the ``get_query_result`` call
will block until the results of the query are ready (and TRUE will be
returned). Otherwise, if the ``wait`` parameter is FALSE, the call
will not block and the return value will be TRUE if the query has
completed or FALSE otherwise.
``get_query_result_resource`` is used to store the result of a query into
a resource without synchronizing with the CPU. This write will optionally
wait for the query to complete, and will optionally write whether the value
is available instead of the value itself.
``set_active_query_state`` Set whether all current non-driver queries except
TIME_ELAPSED are active or paused.
The interface currently includes the following types of queries:
``PIPE_QUERY_OCCLUSION_COUNTER`` counts the number of fragments which
are written to the framebuffer without being culled by
:ref:`depth-stencil-alpha` testing or shader KILL instructions.
The result is an unsigned 64-bit integer.
This query can be used with ``render_condition``.
In cases where a boolean result of an occlusion query is enough,
``PIPE_QUERY_OCCLUSION_PREDICATE`` should be used. It is just like
``PIPE_QUERY_OCCLUSION_COUNTER`` except that the result is a boolean
value of FALSE for cases where COUNTER would result in 0 and TRUE
for all other cases.
This query can be used with ``render_condition``.
In cases where a conservative approximation of an occlusion query is enough,
``PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE`` should be used. It behaves
like ``PIPE_QUERY_OCCLUSION_PREDICATE``, except that it may return TRUE in
additional, implementation-dependent cases.
This query can be used with ``render_condition``.
``PIPE_QUERY_TIME_ELAPSED`` returns the amount of time, in nanoseconds,
the context takes to perform operations.
The result is an unsigned 64-bit integer.
``PIPE_QUERY_TIMESTAMP`` returns a device/driver internal timestamp,
scaled to nanoseconds, recorded after all commands issued prior to
``end_query`` have been processed.
This query does not require a call to ``begin_query``.
The result is an unsigned 64-bit integer.
``PIPE_QUERY_TIMESTAMP_RAW`` returns a device/driver timestamp, recorded
after all commands issued prior to ``end_query`` have been processed.
This query does not require a call to ``begin_query``.
The result is an unsigned 64-bit integer. ``pipe_screen::convert_timestamp()``
should be implemented, to covert the raw timestamp to nanoseconds, if
this query type is supported.
``PIPE_QUERY_TIMESTAMP_DISJOINT`` can be used to check the
internal timer resolution and whether the timestamp counter has become
unreliable due to things like throttling etc. - only if this is FALSE
a timestamp query (within the timestamp_disjoint query) should be trusted.
The result is a 64-bit integer specifying the timer resolution in Hz,
followed by a boolean value indicating whether the timestamp counter
is discontinuous or disjoint.
``PIPE_QUERY_PRIMITIVES_GENERATED`` returns a 64-bit integer indicating
the number of primitives processed by the pipeline (regardless of whether
stream output is active or not).
``PIPE_QUERY_PRIMITIVES_EMITTED`` returns a 64-bit integer indicating
the number of primitives written to stream output buffers.
``PIPE_QUERY_SO_STATISTICS`` returns 2 64-bit integers corresponding to
the result of
``PIPE_QUERY_PRIMITIVES_EMITTED`` and
the number of primitives that would have been written to stream output buffers
if they had infinite space available (primitives_storage_needed), in this order.
XXX the 2nd value is equivalent to ``PIPE_QUERY_PRIMITIVES_GENERATED`` but it is
unclear if it should be increased if stream output is not active.
``PIPE_QUERY_SO_OVERFLOW_PREDICATE`` returns a boolean value indicating
whether a selected stream output target has overflowed as a result of the
commands issued between ``begin_query`` and ``end_query``.
This query can be used with ``render_condition``. The output stream is
selected by the stream number passed to ``create_query``.
``PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE`` returns a boolean value indicating
whether any stream output target has overflowed as a result of the commands
issued between ``begin_query`` and ``end_query``. This query can be used
with ``render_condition``, and its result is the logical OR of multiple
``PIPE_QUERY_SO_OVERFLOW_PREDICATE`` queries, one for each stream output
target.
``PIPE_QUERY_GPU_FINISHED`` returns a boolean value indicating whether
all commands issued before ``end_query`` have completed. However, this
does not imply serialization.
This query does not require a call to ``begin_query``.
``PIPE_QUERY_PIPELINE_STATISTICS`` returns an array of the following
64-bit integers:
Number of vertices read from vertex buffers.
Number of primitives read from vertex buffers.
Number of vertex shader threads launched.
Number of geometry shader threads launched.
Number of primitives generated by geometry shaders.
Number of primitives forwarded to the rasterizer.
Number of primitives rasterized.
Number of fragment shader threads launched.
Number of tessellation control shader threads launched.
Number of tessellation evaluation shader threads launched.
If a shader type is not supported by the device/driver,
the corresponding values should be set to 0.
``PIPE_QUERY_PIPELINE_STATISTICS_SINGLE`` returns a single counter from
the ``PIPE_QUERY_PIPELINE_STATISTICS`` group. The specific counter must
be selected when calling ``create_query`` by passing one of the
``PIPE_STAT_QUERY`` enums as the query's ``index``.
Gallium does not guarantee the availability of any query types; one must
always check the capabilities of the :ref:`Screen` first.
Conditional Rendering
^^^^^^^^^^^^^^^^^^^^^
A drawing command can be skipped depending on the outcome of a query
(typically an occlusion query, or streamout overflow predicate).
The ``render_condition`` function specifies the query which should be checked
prior to rendering anything. Functions always honoring render_condition include
(and are limited to) draw_vbo and clear.
The blit, clear_render_target and clear_depth_stencil functions (but
not resource_copy_region, which seems inconsistent) can also optionally honor
the current render condition.
If ``render_condition`` is called with ``query`` = NULL, conditional
rendering is disabled and drawing takes place normally.
If ``render_condition`` is called with a non-null ``query`` subsequent
drawing commands will be predicated on the outcome of the query.
Commands will be skipped if ``condition`` is equal to the predicate result
(for non-boolean queries such as OCCLUSION_QUERY, zero counts as FALSE,
non-zero as TRUE).
If ``mode`` is PIPE_RENDER_COND_WAIT the driver will wait for the
query to complete before deciding whether to render.
If ``mode`` is PIPE_RENDER_COND_NO_WAIT and the query has not yet
completed, the drawing command will be executed normally. If the query
has completed, drawing will be predicated on the outcome of the query.
If ``mode`` is PIPE_RENDER_COND_BY_REGION_WAIT or
PIPE_RENDER_COND_BY_REGION_NO_WAIT rendering will be predicated as above
for the non-REGION modes but in the case that an occlusion query returns
a non-zero result, regions which were occluded may be omitted by subsequent
drawing commands. This can result in better performance with some GPUs.
Normally, if the occlusion query returned a non-zero result subsequent
drawing happens normally so fragments may be generated, shaded and
processed even where they're known to be obscured.
The ''render_condition_mem'' function specifies the drawing is dependent
on a value in memory. A buffer resource and offset denote which 32-bit
value to use for the query. This is used for Vulkan API.
Flushing
^^^^^^^^
``flush``
PIPE_FLUSH_END_OF_FRAME: Whether the flush marks the end of frame.
PIPE_FLUSH_DEFERRED: It is not required to flush right away, but it is required
to return a valid fence. If fence_finish is called with the returned fence
and the context is still unflushed, and the ctx parameter of fence_finish is
equal to the context where the fence was created, fence_finish will flush
the context.
PIPE_FLUSH_ASYNC: The flush is allowed to be asynchronous. Unlike
``PIPE_FLUSH_DEFERRED``, the driver must still ensure that the returned fence
will finish in finite time. However, subsequent operations in other contexts of
the same screen are no longer guaranteed to happen after the flush. Drivers
which use this flag must implement pipe_context::fence_server_sync.
PIPE_FLUSH_HINT_FINISH: Hints to the driver that the caller will immediately
wait for the returned fence.
Additional flags may be set together with ``PIPE_FLUSH_DEFERRED`` for even
finer-grained fences. Note that as a general rule, GPU caches may not have been
flushed yet when these fences are signaled. Drivers are free to ignore these
flags and create normal fences instead. At most one of the following flags can
be specified:
PIPE_FLUSH_TOP_OF_PIPE: The fence should be signaled as soon as the next
command is ready to start executing at the top of the pipeline, before any of
its data is actually read (including indirect draw parameters).
PIPE_FLUSH_BOTTOM_OF_PIPE: The fence should be signaled as soon as the previous
command has finished executing on the GPU entirely (but data written by the
command may still be in caches and inaccessible to the CPU).
``flush_resource``
Flush the resource cache, so that the resource can be used
by an external client. Possible usage:
- flushing a resource before presenting it on the screen
- flushing a resource if some other process or device wants to use it
This shouldn't be used to flush caches if the resource is only managed
by a single pipe_screen and is not shared with another process.
(i.e. you shouldn't use it to flush caches explicitly if you want to e.g.
use the resource for texturing)
Fences
^^^^^^
``pipe_fence_handle``, and related methods, are used to synchronize
execution between multiple parties. Examples include CPU <-> GPU synchronization,
renderer <-> windowing system, multiple external APIs, etc.
A ``pipe_fence_handle`` can either be 'one time use' or 're-usable'. A 'one time use'
fence behaves like a traditional GPU fence. Once it reaches the signaled state it
is forever considered to be signaled.
Once a re-usable ``pipe_fence_handle`` becomes signaled, it can be reset
back into an unsignaled state. The ``pipe_fence_handle`` will be reset to
the unsignaled state by performing a wait operation on said object, i.e.
``fence_server_sync``. As a corollary to this behavior, a re-usable
``pipe_fence_handle`` can only have one waiter.
This behavior is useful in producer <-> consumer chains. It helps avoid
unnecessarily sharing a new ``pipe_fence_handle`` each time a new frame is
ready. Instead, the fences are exchanged once ahead of time, and access is synchronized
through GPU signaling instead of direct producer <-> consumer communication.
``fence_server_sync`` inserts a wait command into the GPU's command stream.
``fence_server_signal`` inserts a signal command into the GPU's command stream.
There are no guarantees that the wait/signal commands will be flushed when
calling ``fence_server_sync`` or ``fence_server_signal``. An explicit
call to ``flush`` is required to make sure the commands are emitted to the GPU.
The Gallium implementation may implicitly ``flush`` the command stream during a
``fence_server_sync`` or ``fence_server_signal`` call if necessary.
Gallium frontends must ensure that ``fence_server_signal`` returns before calling
``fence_server_sync`` on the same ``pipe_fence_handle`` even if those calls are made on
a different ``pipe_context``.
Resource Busy Queries
^^^^^^^^^^^^^^^^^^^^^
``is_resource_referenced``
Blitting
^^^^^^^^
These methods emulate classic blitter controls.
These methods operate directly on ``pipe_resource`` objects, and stand
apart from any 3D state in the context. Each method is assumed to have an
implicit memory barrier around itself. They do not need any explicit
``memory_barrier``. Blitting functionality may be moved to a separate
abstraction at some point in the future.
``resource_copy_region`` blits a region of a resource to a region of another
resource, provided that both resources have the same format, or compatible
formats, i.e., formats for which copying the bytes from the source resource
unmodified to the destination resource will achieve the same effect of a
textured quad blitter.. The source and destination may be the same resource,
but overlapping blits are not permitted.
This can be considered the equivalent of a CPU memcpy.
``blit`` blits a region of a resource to a region of another resource, including
scaling, format conversion, and up-/downsampling, as well as a destination clip
rectangle (scissors) and window rectangles. It can also optionally honor the
current render condition (but either way the blit itself never contributes
anything to queries currently gathering data).
As opposed to manually drawing a textured quad, this lets the pipe driver choose
the optimal method for blitting (like using a special 2D engine), and usually
offers, for example, accelerated stencil-only copies even where
pipe_caps.shader_stencil_export is not available.
Transfers
^^^^^^^^^
These methods are used to get data to/from a resource.
``transfer_map`` creates a memory mapping and the transfer object
associated with it.
The returned pointer points to the start of the mapped range according to
the box region, not the beginning of the resource. If transfer_map fails,
the returned pointer to the buffer memory is NULL, and the pointer
to the transfer object remains unchanged (i.e. it can be non-NULL).
When mapping an MSAA surface, the samples are implicitly resolved to
single-sampled for reads (returning the first sample for depth/stencil/integer,
averaged for others). See u_transfer_helper's U_TRANSFER_HELPER_MSAA_MAP for a
way to get that behavior using a resolve blit.
``transfer_unmap`` remove the memory mapping for and destroy
the transfer object. The pointer into the resource should be considered
invalid and discarded.
``texture_subdata`` and ``buffer_subdata`` perform a simplified
transfer for simple writes. Basically transfer_map, data write, and
transfer_unmap all in one.
The box parameter to some of these functions defines a 1D, 2D or 3D
region of pixels. This is self-explanatory for 1D, 2D and 3D texture
targets.
For PIPE_TEXTURE_1D_ARRAY and PIPE_TEXTURE_2D_ARRAY, the box::z and box::depth
fields refer to the array dimension of the texture.
For PIPE_TEXTURE_CUBE, the box:z and box::depth fields refer to the
faces of the cube map (z + depth <= 6).
For PIPE_TEXTURE_CUBE_ARRAY, the box:z and box::depth fields refer to both
the face and array dimension of the texture (face = z % 6, array = z / 6).
.. _transfer_flush_region:
transfer_flush_region
%%%%%%%%%%%%%%%%%%%%%
If a transfer was created with ``FLUSH_EXPLICIT``, it will not automatically
be flushed on write or unmap. Flushes must be requested with
``transfer_flush_region``. Flush ranges are relative to the mapped range, not
the beginning of the resource.
.. _texture_barrier:
texture_barrier
%%%%%%%%%%%%%%%
This function flushes all pending writes to the currently-set surfaces and
invalidates all read caches of the currently-set samplers. This can be used
for both regular textures as well as for framebuffers read via FBFETCH.
.. _memory_barrier:
memory_barrier
%%%%%%%%%%%%%%%
This function flushes caches according to which of the PIPE_BARRIER_* flags
are set.
.. _resource_commit:
resource_commit
%%%%%%%%%%%%%%%
This function changes the commit state of a part of a sparse resource. Sparse
resources are created by setting the ``PIPE_RESOURCE_FLAG_SPARSE`` flag when
calling ``resource_create``. Initially, sparse resources only reserve a virtual
memory region that is not backed by memory (i.e., it is uncommitted). The
``resource_commit`` function can be called to commit or uncommit parts (or all)
of a resource. The driver manages the underlying backing memory.
The contents of newly committed memory regions are undefined. Calling this
function to commit an already committed memory region is allowed and leaves its
content unchanged. Similarly, calling this function to uncommit an already
uncommitted memory region is allowed.
For buffers, the given box must be aligned to multiples of
``pipe_caps.sparse_buffer_page_size``. As an exception to this rule, if the size
of the buffer is not a multiple of the page size, changing the commit state of
the last (partial) page requires a box that ends at the end of the buffer
(i.e., box->x + box->width == buffer->width0).
.. _pipe_transfer:
PIPE_MAP
^^^^^^^^^^^^^
These flags control the behavior of a transfer object.
``PIPE_MAP_READ``
Resource contents read back (or accessed directly) at transfer create time.
``PIPE_MAP_WRITE``
Resource contents will be written back at transfer_unmap time (or modified
as a result of being accessed directly).
``PIPE_MAP_DIRECTLY``
a transfer should directly map the resource. May return NULL if not supported.
``PIPE_MAP_DISCARD_RANGE``
The memory within the mapped region is discarded. Cannot be used with
``PIPE_MAP_READ``.
``PIPE_MAP_DISCARD_WHOLE_RESOURCE``
Discards all memory backing the resource. It should not be used with
``PIPE_MAP_READ``.
``PIPE_MAP_DONTBLOCK``
Fail if the resource cannot be mapped immediately.
``PIPE_MAP_UNSYNCHRONIZED``
Do not synchronize pending operations on the resource when mapping. The
interaction of any writes to the map and any operations pending on the
resource are undefined. Cannot be used with ``PIPE_MAP_READ``.
``PIPE_MAP_FLUSH_EXPLICIT``
Written ranges will be notified later with :ref:`transfer_flush_region`.
Cannot be used with ``PIPE_MAP_READ``.
``PIPE_MAP_PERSISTENT``
Allows the resource to be used for rendering while mapped.
PIPE_RESOURCE_FLAG_MAP_PERSISTENT must be set when creating
the resource.
If COHERENT is not set, memory_barrier(PIPE_BARRIER_MAPPED_BUFFER)
must be called to ensure the device can see what the CPU has written.
``PIPE_MAP_COHERENT``
If PERSISTENT is set, this ensures any writes done by the device are
immediately visible to the CPU and vice versa.
PIPE_RESOURCE_FLAG_MAP_COHERENT must be set when creating
the resource.
Compute kernel execution
^^^^^^^^^^^^^^^^^^^^^^^^
A compute program can be defined, bound or destroyed using
``create_compute_state``, ``bind_compute_state`` or
``destroy_compute_state`` respectively.
Any of the subroutines contained within the compute program can be
executed on the device using the ``launch_grid`` method. This method
will execute as many instances of the program as elements in the
specified N-dimensional grid, hopefully in parallel.
The compute program has access to four special resources:
* ``GLOBAL`` represents a memory space shared among all the threads
running on the device. An arbitrary buffer created with the
``PIPE_BIND_GLOBAL`` flag can be mapped into it using the
``set_global_binding`` method.
* ``LOCAL`` represents a memory space shared among all the threads
running in the same working group. The initial contents of this
resource are undefined.
* ``PRIVATE`` represents a memory space local to a single thread.
The initial contents of this resource are undefined.
* ``INPUT`` represents a read-only memory space that can be
initialized at ``launch_grid`` time.
These resources use a byte-based addressing scheme, and they can be
accessed from the compute program by means of the LOAD/STORE TGSI
opcodes.
In addition, normal texture sampling is allowed from the compute
program: ``bind_sampler_states`` may be used to set up texture
samplers for the compute stage and ``set_sampler_views`` may
be used to bind a number of sampler views to it.
Compute kernel queries
^^^^^^^^^^^^^^^^^^^^^^
.. _get_compute_state_info:
get_compute_state_info
%%%%%%%%%%%%%%%%%%%%%%
This function allows frontends to query kernel information defined inside
``pipe_compute_state_object_info``.
.. _get_compute_state_subgroup_size:
get_compute_state_subgroup_size
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
This function returns the choosen subgroup size when ``launch_grid`` is
called with the given block size. This doesn't need to be implemented when
only one size is reported through ``pipe_compute_caps.subgroup_sizes`` or
``pipe_compute_state_object_info::simd_sizes``.
Mipmap generation
^^^^^^^^^^^^^^^^^
If pipe_caps.generate_mipmap is true, ``generate_mipmap`` can be used
to generate mipmaps for the specified texture resource.
It replaces texel image levels base_level+1 through
last_level for layers range from first_layer through last_layer.
It returns TRUE if mipmap generation succeeds, otherwise it
returns FALSE. Mipmap generation may fail when it is not supported
for particular texture types or formats.
Device resets
^^^^^^^^^^^^^
Gallium frontends can query or request notifications of when the GPU
is reset for whatever reason (application error, driver error). When
a GPU reset happens, the context becomes unusable and all related state
should be considered lost and undefined. Despite that, context
notifications are single-shot, i.e. subsequent calls to
``get_device_reset_status`` will return PIPE_NO_RESET.
* ``get_device_reset_status`` queries whether a device reset has happened
since the last call or since the last notification by callback.
* ``set_device_reset_callback`` sets a callback which will be called when
a device reset is detected. The callback is only called synchronously.
Bindless
^^^^^^^^
If pipe_caps.bindless_texture is TRUE, the following ``pipe_context`` functions
are used to create/delete bindless handles, and to make them resident in the
current context when they are going to be used by shaders.
* ``create_texture_handle`` creates a 64-bit unsigned integer texture handle
that is going to be directly used in shaders.
* ``delete_texture_handle`` deletes a 64-bit unsigned integer texture handle.
* ``make_texture_handle_resident`` makes a 64-bit unsigned texture handle
resident in the current context to be accessible by shaders for texture
mapping.
* ``create_image_handle`` creates a 64-bit unsigned integer image handle that
is going to be directly used in shaders.
* ``delete_image_handle`` deletes a 64-bit unsigned integer image handle.
* ``make_image_handle_resident`` makes a 64-bit unsigned integer image handle
resident in the current context to be accessible by shaders for image loads,
stores and atomic operations.
Using several contexts
----------------------
Several contexts from the same screen can be used at the same time. Objects
created on one context cannot be used in another context, but the objects
created by the screen methods can be used by all contexts.
Transfers
^^^^^^^^^
A transfer on one context is not expected to synchronize properly with
rendering on other contexts, thus only areas not yet used for rendering should
be locked.
A flush is required after transfer_unmap to expect other contexts to see the
uploaded data, unless:
* Using persistent mapping. Associated with coherent mapping, unmapping the
resource is also not required to use it in other contexts. Without coherent
mapping, memory_barrier(PIPE_BARRIER_MAPPED_BUFFER) should be called on the
context that has mapped the resource. No flush is required.
* Mapping the resource with PIPE_MAP_DIRECTLY.
+14
View File
@@ -0,0 +1,14 @@
CSO
===
CSO, Constant State Objects, are a core part of Gallium's API.
CSO work on the principle of reusable state; they are created by filling
out a state object with the desired properties, then passing that object
to a context. The context returns an opaque context-specific handle which
can be bound at any time for the desired effect.
.. toctree::
:glob:
cso/*
+124
View File
@@ -0,0 +1,124 @@
.. _blend:
Blend
=====
This state controls blending of the final fragments into the target rendering
buffers.
Blend Factors
-------------
The blend factors largely follow the same pattern as their counterparts
in other modern and legacy drawing APIs.
Dual source blend factors are supported for up to 1 MRT, although
you can advertise > 1 MRT, the stack cannot handle them for a few reasons.
There is no definition on how the 1D array of shader outputs should be mapped
to something that would be a 2D array (location, index). No current hardware
exposes > 1 MRT, and we should revisit this issue if anyone ever does.
Logical Operations
------------------
Logical operations, also known as logicops, LOPs, or ROPs, are supported.
Only two-operand logicops are available. When logicops are enabled, all other
blend state is ignored, including per-render-target state, so logicops are
performed on all render targets.
.. warning::
The blend_enable flag is ignored for all render targets when logical
operations are enabled.
For a source component ``s`` and destination component ``d``, the logical
operations are defined as taking the bits of each channel of each component,
and performing one of the following operations per-channel:
================== =========================
Operation Equation
================== =========================
``CLEAR`` :math:`0`
``NOR`` :math:`\lnot(s \lor d)`
``AND_INVERTED`` :math:`\lnot s \land d`
``COPY_INVERTED`` :math:`\lnot s`
``AND_REVERSE`` :math:`s \land \lnot d`
``INVERT`` :math:`\lnot d`
``XOR`` :math:`s \oplus d`
``NAND`` :math:`\lnot(s \land d)`
``AND`` :math:`s \land d`
``EQUIV`` :math:`\lnot(s \oplus d)`
``NOOP`` :math:`d`
``OR_INVERTED`` :math:`\lnot s \lor d`
``COPY`` :math:`s`
``OR_REVERSE`` :math:`s \lor \lnot d`
``OR`` :math:`s \lor d`
``SET`` :math:`1`
================== =========================
.. note::
The logical operation names and definitions match those of the OpenGL API,
and are similar to the ROP2 and ROP3 definitions of GDI. This is
intentional, to ease transitions to Gallium.
Members
-------
These members affect all render targets.
dither
Whether dithering is enabled.
.. note::
Dithering is completely implementation-dependent. It may be ignored by
drivers for any reason, and some render targets may always or never be
dithered depending on their format or usage flags.
logicop_enable
Whether the blender should perform a logicop instead of blending.
logicop_func
The logicop to use. One of ``PIPE_LOGICOP``.
independent_blend_enable
If enabled, blend state is different for each render target, and
for each render target set in the respective member of the rt array.
If disabled, blend state is the same for all render targets, and only
the first member of the rt array contains valid data.
rt
Contains the per-rendertarget blend state.
alpha_to_coverage
If enabled, the fragment's alpha value is used to override the fragment's
coverage mask. The coverage mask will be all zeros if the alpha value is
zero. The coverage mask will be all ones if the alpha value is one.
Otherwise, the number of bits set in the coverage mask will be proportional
to the alpha value. Note that this step happens regardless of whether
multisample is enabled or the destination buffer is multisampled.
alpha_to_one
If enabled, the fragment's alpha value will be set to one. As with
alpha_to_coverage, this step happens regardless of whether multisample
is enabled or the destination buffer is multisampled.
max_rt
The index of the max render target (irrespective of whether independent
blend is enabled), i.e. the number of MRTs minus one. This is provided
so that the driver can avoid the overhead of programming unused MRTs.
Per-rendertarget Members
------------------------
blend_enable
If blending is enabled, perform a blend calculation according to blend
functions and source/destination factors. Otherwise, the incoming fragment
color gets passed unmodified (but colormask still applies).
rgb_func
The blend function to use for RGB channels. One of PIPE_BLEND.
rgb_src_factor
The blend source factor to use for RGB channels. One of PIPE_BLENDFACTOR.
rgb_dst_factor
The blend destination factor to use for RGB channels. One of PIPE_BLENDFACTOR.
alpha_func
The blend function to use for the alpha channel. One of PIPE_BLEND.
alpha_src_factor
The blend source factor to use for the alpha channel. One of PIPE_BLENDFACTOR.
alpha_dst_factor
The blend destination factor to use for alpha channel. One of PIPE_BLENDFACTOR.
colormask
Bitmask of which channels to write. Combination of PIPE_MASK bits.
+61
View File
@@ -0,0 +1,61 @@
.. _depth-stencil-alpha:
Depth, Stencil, & Alpha
=======================
These three states control the depth, stencil, and alpha tests, used to
discard fragments that have passed through the fragment shader.
Traditionally, these three tests have been clumped together in hardware, so
they are all stored in one structure.
During actual execution, the order of operations done on fragments is always:
* Alpha
* Stencil
* Depth
Depth Members
-------------
enabled
Whether the depth test is enabled.
writemask
Whether the depth buffer receives depth writes.
func
The depth test function. One of PIPE_FUNC.
Stencil Members
---------------
enabled
Whether the stencil test is enabled. For the second stencil, whether the
two-sided stencil is enabled. If two-sided stencil is disabled, the other
fields for the second array member are not valid.
func
The stencil test function. One of PIPE_FUNC.
valuemask
Stencil test value mask; this is ANDed with the value in the stencil
buffer and the reference value before doing the stencil comparison test.
writemask
Stencil test writemask; this controls which bits of the stencil buffer
are written.
fail_op
The operation to carry out if the stencil test fails. One of
PIPE_STENCIL_OP.
zfail_op
The operation to carry out if the stencil test passes but the depth test
fails. One of PIPE_STENCIL_OP.
zpass_op
The operation to carry out if the stencil test and depth test both pass.
One of PIPE_STENCIL_OP.
Alpha Members
-------------
enabled
Whether the alpha test is enabled.
func
The alpha test function. One of PIPE_FUNC.
ref_value
Alpha test reference value; used for certain functions.
+352
View File
@@ -0,0 +1,352 @@
.. _rasterizer:
Rasterizer
==========
The rasterizer state controls the rendering of points, lines and triangles.
Attributes include polygon culling state, line width, line stipple,
multisample state, scissoring and flat/smooth shading.
Linkage
-------
clamp_vertex_color
If set, TGSI_SEMANTIC_COLOR registers are clamped to the [0, 1] range after
the execution of the vertex shader, before being passed to the geometry
shader or fragment shader.
OpenGL: glClampColor(GL_CLAMP_VERTEX_COLOR) in GL 3.0 or
:ext:`GL_ARB_color_buffer_float`
D3D11: seems always disabled
Note pipe_caps.vertex_color_clamped indicates whether or not the
driver supports this control. If it's not supported, gallium frontends may
have to insert extra clamping code.
clamp_fragment_color
Controls whether TGSI_SEMANTIC_COLOR outputs of the fragment shader
are clamped to [0, 1].
OpenGL: glClampColor(GL_CLAMP_FRAGMENT_COLOR) in GL 3.0 or
:ext:`GL_ARB_color_buffer_float`
D3D11: seems always disabled
Note pipe_caps.fragment_color_clamped indicates whether or not the
driver supports this control. If it's not supported, gallium frontends may
have to insert extra clamping code.
Shading
-------
flatshade
If set, the provoking vertex of each polygon is used to determine the color
of the entire polygon. If not set, fragment colors will be interpolated
between the vertex colors.
The actual interpolated shading algorithm is obviously
implementation-dependent, but will usually be Gouraud for most hardware.
.. note::
This is separate from the fragment shader input attributes
CONSTANT, LINEAR and PERSPECTIVE. The flatshade state is needed at
clipping time to determine how to set the color of new vertices.
Draw can implement flat shading by copying the provoking vertex
color to all the other vertices in the primitive.
flatshade_first
Whether the first vertex should be the provoking vertex, for most primitives.
If not set, the last vertex is the provoking vertex.
There are a few important exceptions to the specification of this rule.
* ``PIPE_PRIMITIVE_POLYGON``: The provoking vertex is always the first
vertex. If the caller wishes to change the provoking vertex, they merely
need to rotate the vertices themselves.
* ``PIPE_PRIMITIVE_QUAD``, ``PIPE_PRIMITIVE_QUAD_STRIP``: The option only has
an effect if ``pipe_caps.quads_follow_provoking_vertex_convention`` is true.
If it is not, the provoking vertex is always the last vertex.
* ``PIPE_PRIMITIVE_TRIANGLE_FAN``: When set, the provoking vertex is the
second vertex, not the first. This permits each segment of the fan to have
a different color.
Polygons
--------
light_twoside
If set, there are per-vertex back-facing colors. The hardware
(perhaps assisted by Draw) should be set up to use this state
along with the front/back information to set the final vertex colors
prior to rasterization.
The front-face vertex shader color output is marked with TGSI semantic
COLOR[0], and back-face COLOR[1].
front_ccw
Indicates whether the window order of front-facing polygons is
counter-clockwise (TRUE) or clockwise (FALSE).
cull_mode
Indicates which faces of polygons to cull, either PIPE_FACE_NONE
(cull no polygons), PIPE_FACE_FRONT (cull front-facing polygons),
PIPE_FACE_BACK (cull back-facing polygons), or
PIPE_FACE_FRONT_AND_BACK (cull all polygons).
fill_front
Indicates how to fill front-facing polygons, either
PIPE_POLYGON_MODE_FILL, PIPE_POLYGON_MODE_LINE or
PIPE_POLYGON_MODE_POINT.
fill_back
Indicates how to fill back-facing polygons, either
PIPE_POLYGON_MODE_FILL, PIPE_POLYGON_MODE_LINE or
PIPE_POLYGON_MODE_POINT.
poly_stipple_enable
Whether polygon stippling is enabled.
poly_smooth
Controls OpenGL-style polygon smoothing/antialiasing
offset_point
If set, point-filled polygons will have polygon offset factors applied
offset_line
If set, line-filled polygons will have polygon offset factors applied
offset_tri
If set, filled polygons will have polygon offset factors applied
offset_units
Specifies the polygon offset bias
offset_scale
Specifies the polygon offset scale
offset_clamp
Upper (if > 0) or lower (if < 0) bound on the polygon offset result
Lines
-----
line_width
The width of lines.
line_smooth
Whether lines should be smoothed. Line smoothing is simply anti-aliasing.
line_stipple_enable
Whether line stippling is enabled.
line_stipple_pattern
16-bit bitfield of on/off flags, used to pattern the line stipple.
line_stipple_factor
When drawing a stippled line, each bit in the stipple pattern is
repeated N times, where N = line_stipple_factor + 1.
line_last_pixel
Controls whether the last pixel in a line is drawn or not. OpenGL
omits the last pixel to avoid double-drawing pixels at the ends of lines
when drawing connected lines.
Points
------
sprite_coord_enable
The effect of this state depends on pipe_caps.tgsi_texcoord !
Controls automatic texture coordinate generation for rendering sprite points.
If pipe_caps.tgsi_texcoord is false:
When bit k in the sprite_coord_enable bitfield is set, then generic
input k to the fragment shader will get an automatically computed
texture coordinate.
If pipe_caps.tgsi_texcoord is true:
The bitfield refers to inputs with TEXCOORD semantic instead of generic inputs.
The texture coordinate will be of the form (s, t, 0, 1) where s varies
from 0 to 1 from left to right while t varies from 0 to 1 according to
the state of 'sprite_coord_mode' (see below).
If any bit is set, then point_smooth MUST be disabled (there are no
round sprites) and point_quad_rasterization MUST be true (sprites are
always rasterized as quads). Any mismatch between these states should
be considered a bug in the gallium frontend.
This feature is implemented in the Draw module but may also be
implemented natively by GPUs or implemented with a geometry shader.
sprite_coord_mode
Specifies how the value for each shader output should be computed when drawing
point sprites. For PIPE_SPRITE_COORD_LOWER_LEFT, the lower-left vertex will
have coordinates (0,0,0,1). For PIPE_SPRITE_COORD_UPPER_LEFT, the upper-left
vertex will have coordinates (0,0,0,1).
This state is used by Draw to generate texcoords.
point_quad_rasterization
Determines if points should be rasterized according to quad or point
rasterization rules.
(Legacy-only) OpenGL actually has quite different rasterization rules
for points and point sprites - hence this indicates if points should be
rasterized as points or according to point sprite (which decomposes them
into quads, basically) rules. Newer GL versions no longer support the old
point rules at all.
Additionally Direct3D will always use quad rasterization rules for
points, regardless of whether point sprites are enabled or not.
If this state is enabled, point smoothing and antialiasing are
disabled. If it is disabled, point sprite coordinates are not
generated.
.. note::
Some renderers always internally translate points into quads; this state
still affects those renderers by overriding other rasterization state.
point_tri_clip
Determines if clipping of points should happen after they are converted
to "rectangles" (required by d3d) or before (required by OpenGL, though
this rule is ignored by some IHVs).
It is not valid to set this to enabled but have point_quad_rasterization
disabled.
point_smooth
Whether points should be smoothed. Point smoothing turns rectangular
points into circles or ovals.
point_size_per_vertex
Whether the vertex shader is expected to have a point size output.
Undefined behavior is permitted if there is disagreement between
this flag and the actual bound shader.
point_size
The size of points, if not specified per-vertex.
Other Members
-------------
scissor
Whether the scissor test is enabled.
multisample
Whether :term:`MSAA` is enabled.
half_pixel_center
When true, the rasterizer should use (0.5, 0.5) pixel centers for
determining pixel ownership (e.g, OpenGL, D3D10 and higher)::
0 0.5 1
0 +-----+
| |
0.5 | X |
| |
1 +-----+
When false, the rasterizer should use (0, 0) pixel centers for determining
pixel ownership (e.g., D3D9 or earlier)::
-0.5 0 0.5
-0.5 +-----+
| |
0 | X |
| |
0.5 +-----+
bottom_edge_rule
Determines what happens when a pixel sample lies precisely on a triangle
edge.
When true, a pixel sample is considered to lie inside of a triangle if it
lies on the *bottom edge* or *left edge* (e.g., OpenGL drawables)::
0 x
0 +--------------------->
|
| +-------------+
| | |
| | |
| | |
| +=============+
|
y V
When false, a pixel sample is considered to lie inside of a triangle if it
lies on the *top edge* or *left edge* (e.g., OpenGL FBOs, D3D)::
0 x
0 +--------------------->
|
| +=============+
| | |
| | |
| | |
| +-------------+
|
y V
Where:
- a *top edge* is an edge that is horizontal and is above the other edges;
- a *bottom edge* is an edge that is horizontal and is below the other
edges;
- a *left edge* is an edge that is not horizontal and is on the left side of
the triangle.
.. note::
Actually all graphics APIs use a top-left rasterization rule for pixel
ownership, but their notion of top varies with the axis origin (which
can be either at y = 0 or at y = height). Gallium instead always
assumes that top is always at y=0.
See also:
- https://learn.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-rasterizer-stage-rules
- https://learn.microsoft.com/en-us/windows/win32/direct3d9/rasterization-rules
clip_halfz
When true clip space in the z axis goes from [0..1] (D3D). When false
[-1, 1] (GL)
depth_clip_near
When false, the near depth clipping plane of the view volume is disabled.
depth_clip_far
When false, the far depth clipping plane of the view volume is disabled.
depth_clamp
Whether the depth value will be clamped to the interval defined by the
near and far depth range at the per-pixel level, after polygon offset has
been applied and before depth testing. Note that a clamp to [0,1] according
to GL rules should always happen even if this is disabled.
clip_plane_enable
For each k in [0, PIPE_MAX_CLIP_PLANES), if bit k of this field is set,
clipping half-space k is enabled, if it is clear, it is disabled.
The clipping half-spaces are defined either by the user clip planes in
``pipe_clip_state``, or by the clip distance outputs of the shader stage
preceding the fragment shader.
If any clip distance output is written, those half-spaces for which no
clip distance is written count as disabled; i.e. user clip planes and
shader clip distances cannot be mixed, and clip distances take precedence.
conservative_raster_mode
The conservative rasterization mode. For PIPE_CONSERVATIVE_RASTER_OFF,
conservative rasterization is disabled. For PIPE_CONSERVATIVE_RASTER_POST_SNAP
or PIPE_CONSERVATIVE_RASTER_PRE_SNAP, conservative rasterization is enabled.
When conservative rasterization is enabled, the polygon smooth, line smooth,
point smooth and line stipple settings are ignored.
With the post-snap mode, unlike the pre-snap mode, fragments are never
generated for degenerate primitives. Degenerate primitives, when rasterized,
are considered back-facing and the vertex attributes and depth are that of
the provoking vertex.
If the post-snap mode is used with an unsupported primitive, the pre-snap
mode is used, if supported. Behavior is similar for the pre-snap mode.
If the pre-snap mode is used, fragments are generated with respect to the primitive
before vertex snapping.
conservative_raster_dilate
The amount of dilation during conservative rasterization.
subpixel_precision_x
A bias added to the horizontal subpixel precision during conservative rasterization.
subpixel_precision_y
A bias added to the vertical subpixel precision during conservative rasterization.
+116
View File
@@ -0,0 +1,116 @@
.. _sampler:
Sampler
=======
Texture units have many options for selecting texels from loaded textures;
this state controls an individual texture unit's texel-sampling settings.
Texture coordinates are always treated as four-dimensional, and referred to
with the traditional (S, T, R, Q) notation.
Members
-------
wrap_s
How to wrap the S coordinate. One of PIPE_TEX_WRAP_*.
wrap_t
How to wrap the T coordinate. One of PIPE_TEX_WRAP_*.
wrap_r
How to wrap the R coordinate. One of PIPE_TEX_WRAP_*.
The wrap modes are:
* ``PIPE_TEX_WRAP_REPEAT``: Standard coord repeat/wrap-around mode.
* ``PIPE_TEX_WRAP_CLAMP_TO_EDGE``: Clamp coord to edge of texture, the border
color is never sampled.
* ``PIPE_TEX_WRAP_CLAMP_TO_BORDER``: Clamp coord to border of texture, the
border color is sampled when coords go outside the range [0,1].
* ``PIPE_TEX_WRAP_CLAMP``: The coord is clamped to the range [0,1] before
scaling to the texture size. This corresponds to the legacy OpenGL GL_CLAMP
texture wrap mode. Historically, this mode hasn't acted consistently across
all graphics hardware. It sometimes acts like CLAMP_TO_EDGE or
CLAMP_TO_BORDER. The behavior may also vary depending on linear vs.
nearest sampling mode.
* ``PIPE_TEX_WRAP_MIRROR_REPEAT``: If the integer part of the coordinate
is odd, the coord becomes (1 - coord). Then, normal texture REPEAT is
applied to the coord.
* ``PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE``: First, the absolute value of the
coordinate is computed. Then, regular CLAMP_TO_EDGE is applied to the coord.
* ``PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER``: First, the absolute value of the
coordinate is computed. Then, regular CLAMP_TO_BORDER is applied to the
coord.
* ``PIPE_TEX_WRAP_MIRROR_CLAMP``: First, the absolute value of the coord is
computed. Then, regular CLAMP is applied to the coord.
min_img_filter
The image filter to use when minifying texels. One of PIPE_TEX_FILTER_*.
mag_img_filter
The image filter to use when magnifying texels. One of PIPE_TEX_FILTER_*.
The texture image filter modes are:
* ``PIPE_TEX_FILTER_NEAREST``: One texel is fetched from the texture image
at the texture coordinate.
* ``PIPE_TEX_FILTER_LINEAR``: Two, four or eight texels (depending on the
texture dimensions; 1D/2D/3D) are fetched from the texture image and
linearly weighted and blended together.
min_mip_filter
The filter to use when minifying mipmapped textures. One of
PIPE_TEX_MIPFILTER_*.
The texture mip filter modes are:
* ``PIPE_TEX_MIPFILTER_NEAREST``: A single mipmap level/image is selected
according to the texture LOD (lambda) value.
* ``PIPE_TEX_MIPFILTER_LINEAR``: The two mipmap levels/images above/below
the texture LOD value are sampled from. The results of sampling from
those two images are blended together with linear interpolation.
* ``PIPE_TEX_MIPFILTER_NONE``: Mipmap filtering is disabled. All texels
are taken from the level 0 image.
compare_mode
If set to PIPE_TEX_COMPARE_R_TO_TEXTURE, the result of texture sampling
is not a color but a true/false value which is the result of comparing the
sampled texture value (typically a Z value from a depth texture) to the
texture coordinate's R component.
If set to PIPE_TEX_COMPARE_NONE, no comparison calculation is performed.
compare_func
The inequality operator used when compare_mode=1. One of PIPE_FUNC_x.
unnormalized_coords
If set, incoming texture coordinates are used as-is to compute
texel addresses. When set, only a subset of the texture wrap
modes are allowed: PIPE_TEX_WRAP_CLAMP, PIPE_TEX_WRAP_CLAMP_TO_EDGE,
and PIPE_TEX_WRAP_CLAMP_TO_BORDER. If unset, the incoming texture
coordinates are assumed to be normalized to the range [0, 1],
and will be scaled by the texture dimensions to compute texel
addresses.
lod_bias
Bias factor which is added to the computed level of detail.
The normal level of detail is computed from the partial derivatives of
the texture coordinates and/or the fragment shader TEX/TXB/TXL
instruction.
min_lod
Minimum level of detail, used to clamp LOD after bias. The LOD values
correspond to mipmap levels where LOD=0 is the level 0 mipmap image.
max_lod
Maximum level of detail, used to clamp LOD after bias.
border_color
Color union used for texel coordinates that are outside the [0,width-1],
[0, height-1] or [0, depth-1] ranges. Interpreted according to sampler
view format, unless the driver reports
pipe_caps.texture_border_color_quirk, in which case special care has to be
taken (see description of the cap).
max_anisotropy
Maximum anisotropy ratio to use when sampling from textures. For example,
if max_anisotropy=4, a region of up to 1 by 4 texels will be sampled.
Set to zero to disable anisotropic filtering. Any other setting enables
anisotropic filtering, however it's not unexpected some drivers only will
change their filtering with a setting of 2 and higher.
seamless_cube_map
If set, the bilinear filter of a cube map may take samples from adjacent
cube map faces when sampled near a texture border to produce a seamless
look.
+12
View File
@@ -0,0 +1,12 @@
.. _shader:
Shader
======
One of the two types of shaders supported by Gallium.
Members
-------
tokens
A list of tgsi_tokens.
+60
View File
@@ -0,0 +1,60 @@
.. _vertexelements:
Vertex Elements
===============
This state controls the format of the input attributes contained in
pipe_vertex_buffers. There is one pipe_vertex_element array member for each
input attribute.
Input Formats
-------------
Gallium supports a diverse range of formats for vertex data. Drivers are
guaranteed to support 32-bit floating-point vectors of one to four components.
Additionally, they may support the following formats:
* Integers, signed or unsigned, normalized or non-normalized, 8, 16, or 32
bits wide
* Floating-point, 16, 32, or 64 bits wide
At this time, support for varied vertex data formats is limited by driver
deficiencies. It is planned to support a single uniform set of formats for all
Gallium drivers at some point.
Rather than attempt to specify every small nuance of behavior, Gallium uses a
very simple set of rules for padding out unspecified components. If an input
uses less than four components, it will be padded out with the constant vector
``(0, 0, 0, 1)``.
Fog, point size, the facing bit, and edge flags, all are in the standard
format of ``(x, 0, 0, 1)``, and so only the first component of those inputs is
used.
Position
%%%%%%%%
Vertex position may be specified with two to four components. Using less than
two components is not allowed.
Colors
%%%%%%
Colors, both front- and back-facing, may omit the alpha component, only using
three components. Using less than three components is not allowed.
Members
-------
src_offset
The byte offset of the attribute in the buffer given by
vertex_buffer_index for the first vertex.
instance_divisor
The instance data rate divisor, used for instancing.
0 means this is per-vertex data, n means per-instance data used for
n consecutive instances (n > 0).
vertex_buffer_index
The vertex buffer this attribute lives in. Several attributes may
live in the same vertex buffer.
src_format
The format of the attribute data. One of the PIPE_FORMAT tokens.
+15
View File
@@ -0,0 +1,15 @@
Debugging
=========
Debugging utilities in gallium.
Debug Variables
^^^^^^^^^^^^^^^
All drivers respond to a set of common debug environment variables, as well as
some driver-specific variables. Set them as normal environment variables for
the platform or operating system you are running. For example, for Linux this
can be done by typing "export var=value" into a console and then running the
program from that console.
See :doc:`../envvars` for details.
+66
View File
@@ -0,0 +1,66 @@
Formats in gallium
==================
Gallium format names mostly follow D3D10 conventions, with some extensions.
Format names like XnYnZnWn have the X component in the lowest-address n bits
and the W component in the highest-address n bits; for B8G8R8A8, byte 0 is
blue and byte 3 is alpha. Note that platform endianness is not considered
in this definition. In C::
struct x8y8z8w8 { uint8_t x, y, z, w; };
Format aliases like XYZWstrq are (s+t+r+q)-bit integers in host endianness,
with the X component in the s least-significant bits of the integer. In C::
uint32_t xyzw8888 = (x << 0) | (y << 8) | (z << 16) | (w << 24);
Format suffixes affect the interpretation of the channel:
- ``SINT``: N bit signed integer [-2^(N-1) ... 2^(N-1) - 1]
- ``SNORM``: N bit signed integer normalized to [-1 ... 1]
- ``SSCALED``: N bit signed integer [-2^(N-1) ... 2^(N-1) - 1]
- ``FIXED``: Signed fixed point integer, (N/2 - 1) bits of mantissa
- ``FLOAT``: N bit IEEE754 float
- ``NORM``: Normalized integers, signed or unsigned per channel
- ``UINT``: N bit unsigned integer [0 ... 2^N - 1]
- ``UNORM``: N bit unsigned integer normalized to [0 ... 1]
- ``USCALED``: N bit unsigned integer [0 ... 2^N - 1]
The difference between ``SINT`` and ``SSCALED`` is that the former are pure
integers in shaders, while the latter are floats; likewise for ``UINT`` versus
``USCALED``.
There are two exceptions for ``FLOAT``. ``R9G9B9E5_FLOAT`` is nine bits
each of red green and blue mantissa, with a shared five bit exponent.
``R11G11B10_FLOAT`` is five bits of exponent and five or six bits of mantissa
for each color channel.
For the ``NORM`` suffix, the signedness of each channel is indicated with an
S or U after the number of channel bits, as in ``R5SG5SB6U_NORM``.
The ``SRGB`` suffix is like ``UNORM`` in range, but in the sRGB colorspace.
Compressed formats are named first by the compression format string (``DXT1``,
``ETC1``, etc), followed by a format-specific subtype. Refer to the
appropriate compression spec for details.
Formats used in video playback are named by their FOURCC code.
Format names with an embedded underscore are subsampled. ``R8G8_B8G8`` is a
single 32-bit block of two pixels, where the R and B values are repeated in
both pixels.
Index buffers do not have a natural format in Gallium structures. For purposes
of ``is_format_supported`` queries, the formats ``R8_UINT``, ``R16_UINT``, and
``R32_UINT`` are used with ``PIPE_BIND_INDEX_BUFFER`` for 8-bit, 16-bit, and
32-bit index buffers respectively.
References
----------
DirectX Graphics Infrastructure documentation on DXGI_FORMAT enum:
https://learn.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format
FOURCC codes for YUV formats:
http://web.archive.org/web/20220523043110/https://www.fourcc.org/yuv/
+35
View File
@@ -0,0 +1,35 @@
Glossary
========
.. glossary::
:sorted:
MSAA
Multi-Sampled Anti-Aliasing. A basic anti-aliasing technique that takes
multiple samples of the depth buffer, and uses this information to
smooth the edges of polygons.
TCL
Transform, Clipping, & Lighting. The three stages of preparation in a
rasterizing pipeline prior to the actual rasterization of vertices into
fragments.
NPOT
Non-power-of-two. Usually applied to textures which have at least one
dimension which is not a power of two.
LOD
Level of Detail. Also spelled "LoD". The value that determines when the
switches between mipmaps occur during texture sampling.
layer
This term is used as the name of the "3rd coordinate" of a resource.
3D textures have zslices, cube maps have faces, 1D and 2D array textures
have array members (other resources do not have multiple layers).
Since the functions only take one parameter no matter what type of
resource is used, use the term "layer" instead of a resource type
specific one.
GLSL
GL Shading Language. The official, common high-level shader language used
in GL 2.0 and above.
+24
View File
@@ -0,0 +1,24 @@
Gallium
=======
Contents:
.. toctree::
:maxdepth: 2
intro
debugging
tgsi
screen
resources
format
context
cso
buffermapping
glossary
Indices and tables
------------------
* :ref:`genindex`
* :ref:`search`
+9
View File
@@ -0,0 +1,9 @@
Introduction
============
What is Gallium?
----------------
Gallium is essentially an API for writing graphics drivers in a largely
device-agnostic fashion. It provides several objects which encapsulate the
core services of graphics hardware in a straightforward manner.
+128
View File
@@ -0,0 +1,128 @@
XXX this could be converted/formatted for Sphinx someday.
XXX do not use tabs in this file.
position ]
primary/secondary colors ]
generics (normals, ]
texcoords, fog) ] User vertices / arrays
point size ]
edge flag ]
primitive ID } System-generated values
vertex ID }
| | |
V V V
+-------------------+
| Vertex shader |
+-------------------+
| | |
V V V
position
clip distance
generics
front/back & primary/secondary colors
point size
edge flag
primitive ID
| | |
V V V
+------------------------+
| Geometry shader |
| (consume vertex ID) |
| (may change prim type) |
+------------------------+
| | |
V V V
[...]
fb layer
| | |
V V V
+--------------------------+
| Clipper |
| (consume clip distances) |
+--------------------------+
| | |
V V V
+-------------------+
| Polygon Culling |
+-------------------+
| | |
V V V
+-----------------------+
| Choose front or |
| back face color |
| (consume other color) |
+-----------------------+
| | |
V V V
[...]
primary/secondary colors only
| | |
V V V
+-------------------+
| Polygon Offset |
+-------------------+
| | |
V V V
+----------------------+
| Unfilled polygons |
| (consume edge flags) |
| (change prim type) |
+----------------------+
| | |
V V V
position
generics
primary/secondary colors
point size
primitive ID
fb layer
| | |
V V V
+---------------------------------+
| Optional Draw module helpers |
| * Polygon Stipple |
| * Line Stipple |
| * Line AA/smooth (as tris) |
| * Wide lines (as tris) |
| * Wide points/sprites (as tris) |
| * Point AA/smooth (as tris) |
| (NOTE: these stages may emit |
| new/extra generic attributes |
| such as texcoords) |
+---------------------------------+
| | |
V V V
position ]
generics (+ new/extra ones) ]
primary/secondary colors ] Software rast vertices
point size ]
primitive ID ]
fb layer ]
| | |
V V V
+---------------------+
| Triangle/Line/Point |
| Rasterization |
+---------------------+
| | |
V V V
generic attribs
primary/secondary colors
primitive ID
fragment win coord pos } System-generated values
front/back face flag }
| | |
V V V
+-------------------+
| Fragment shader |
+-------------------+
| | |
V V V
zero or more colors
zero or one Z value
NOTE: The instance ID is not shown. It can be imagined to be a global variable
accessible to all shader stages.
+208
View File
@@ -0,0 +1,208 @@
.. _resource:
Resources and derived objects
=============================
Resources represent objects that hold data: textures and buffers.
They are mostly modelled after the resources in Direct3D 10/11, but with a
different transfer/update mechanism, and more features for OpenGL support.
Resources can be used in several ways, and it is required to specify all planned uses through an appropriate set of bind flags.
TODO: write much more on resources
Transfers
---------
Transfers are the mechanism used to access resources with the CPU.
OpenGL: OpenGL supports mapping buffers and has inline transfer functions for both buffers and textures
D3D11: D3D11 lacks transfers, but has special resource types that are mappable to the CPU address space
TODO: write much more on transfers
Resource targets
----------------
Resource targets determine the type of a resource.
Note that drivers may not actually have the restrictions listed regarding
coordinate normalization and wrap modes, and in fact efficient OpenCL
support will probably require drivers that don't have any of them, which
will probably be advertised with an appropriate cap.
TODO: document all targets. Note that both 3D and cube have restrictions
that depend on the hardware generation.
PIPE_BUFFER
^^^^^^^^^^^
Buffer resource: can be used as a vertex, index, constant buffer
(appropriate bind flags must be requested).
Buffers do not really have a format, it's just bytes, but they are required
to have their type set to a R8 format (without a specific "just byte" format,
R8_UINT would probably make the most sense, but for historic reasons R8_UNORM
is OK too). (This is just to make some shared buffer/texture code easier so
format size can be queried.)
width0 serves as size, most other resource properties don't apply but must be
set appropriately (depth0/height0/array_size must be 1, last_level 0).
They can be bound to stream output if supported.
TODO: what about the restrictions lifted by the several later GL transform feedback extensions? How does one advertise that in Gallium?
They can be also be bound to a shader stage (for sampling) as usual by
creating an appropriate sampler view, if the driver supports pipe_caps.texture_buffer_objects.
This supports larger width than a 1d texture would
(TODO limit currently unspecified, minimum must be at least 65536).
Only the "direct fetch" sample opcodes are supported (TGSI_OPCODE_TXF,
TGSI_OPCODE_SAMPLE_I) so the sampler state (coord wrapping etc.)
is mostly ignored (with SAMPLE_I there's no sampler state at all).
They can be also be bound to the framebuffer (only as color render target, not
depth buffer, also there cannot be a depth buffer bound at the same time) as usual
by creating an appropriate view (this is not usable in OpenGL).
TODO there's no CAP bit currently for this, there's also unspecified size etc. limits
TODO: is there any chance of supporting GL pixel buffer object acceleration with this?
OpenGL: vertex buffers in GL 1.5 or :ext:`GL_ARB_vertex_buffer_object`
- Binding to stream out requires GL 3.0 or :ext:`GL_NV_transform_feedback`
- Binding as constant buffers requires GL 3.1 or :ext:`GL_ARB_uniform_buffer_object`
- Binding to a sampling stage requires GL 3.1 or :ext:`GL_ARB_texture_buffer_object`
D3D11: buffer resources
- Binding to a render target requires D3D_FEATURE_LEVEL_10_0
PIPE_TEXTURE_1D / PIPE_TEXTURE_1D_ARRAY
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1D surface accessed with normalized coordinates.
1D array textures are supported depending on pipe_caps.max_texture_array_layers.
- If pipe_caps.npot_textures is not supported,
width must be a power of two
- height0 must be 1
- depth0 must be 1
- array_size must be 1 for PIPE_TEXTURE_1D
- Mipmaps can be used
- Must use normalized coordinates
OpenGL: GL_TEXTURE_1D in GL 1.0
- pipe_caps.npot_textures is equivalent to GL 2.0 or :ext:`GL_ARB_texture_non_power_of_two`
D3D11: 1D textures in D3D_FEATURE_LEVEL_10_0
PIPE_TEXTURE_RECT
^^^^^^^^^^^^^^^^^
2D surface with OpenGL GL_TEXTURE_RECTANGLE semantics.
- depth0 must be 1
- array_size must be 1
- last_level must be 0
- Must use unnormalized coordinates
- Must use a clamp wrap mode
OpenGL: GL_TEXTURE_RECTANGLE in GL 3.1 or :ext:`GL_ARB_texture_rectangle` or
:ext:`GL_NV_texture_rectangle`
OpenCL: can create OpenCL images based on this, that can then be sampled arbitrarily
D3D11: not supported (only PIPE_TEXTURE_2D with normalized coordinates is supported)
PIPE_TEXTURE_2D / PIPE_TEXTURE_2D_ARRAY
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2D surface accessed with normalized coordinates.
2D array textures are supported depending on pipe_caps.max_texture_array_layers.
- If pipe_caps.npot_textures is not supported,
width and height must be powers of two
- depth0 must be 1
- array_size must be 1 for PIPE_TEXTURE_2D
- Mipmaps can be used
- Must use normalized coordinates
- No special restrictions on wrap modes
OpenGL: GL_TEXTURE_2D in GL 1.0
- pipe_caps.npot_textures is equivalent to GL 2.0 or :ext:`GL_ARB_texture_non_power_of_two`
OpenCL: can create OpenCL images based on this, that can then be sampled arbitrarily
D3D11: 2D textures
- pipe_caps.npot_textures is equivalent to D3D_FEATURE_LEVEL_9_3
PIPE_TEXTURE_3D
^^^^^^^^^^^^^^^
3-dimensional array of texels.
Mipmap dimensions are reduced in all 3 coordinates.
- If pipe_caps.npot_textures is not supported,
width, height and depth must be powers of two
- array_size must be 1
- Must use normalized coordinates
OpenGL: GL_TEXTURE_3D in GL 1.2 or :ext:`GL_EXT_texture3D`
- pipe_caps.npot_textures is equivalent to GL 2.0 or :ext:`GL_ARB_texture_non_power_of_two`
D3D11: 3D textures
- pipe_caps.npot_textures is equivalent to D3D_FEATURE_LEVEL_10_0
PIPE_TEXTURE_CUBE / PIPE_TEXTURE_CUBE_ARRAY
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Cube maps consist of 6 2D faces.
The 6 surfaces form an imaginary cube, and sampling happens by mapping an
input 3-vector to the point of the cube surface in that direction.
Cube map arrays are supported depending on pipe_caps.cube_map_array.
Sampling may be optionally seamless if a driver supports it (pipe_caps.seamless_cube_map),
resulting in filtering taking samples from multiple surfaces near to the edge.
- Width and height must be equal
- depth0 must be 1
- array_size must be a multiple of 6
- If pipe_caps.npot_textures is not supported,
width and height must be powers of two
- Must use normalized coordinates
OpenGL: GL_TEXTURE_CUBE_MAP in GL 1.3 or :ext:`GL_EXT_texture_cube_map`
- pipe_caps.npot_textures is equivalent to GL 2.0 or :ext:`GL_ARB_texture_non_power_of_two`
- Seamless cube maps require GL 3.2 or :ext:`GL_ARB_seamless_cube_map` or :ext:`GL_AMD_seamless_cubemap_per_texture`
- Cube map arrays require GL 4.0 or :ext:`GL_ARB_texture_cube_map_array`
D3D11: 2D array textures with the D3D11_RESOURCE_MISC_TEXTURECUBE flag
- pipe_caps.npot_textures is equivalent to D3D_FEATURE_LEVEL_10_0
- Cube map arrays require D3D_FEATURE_LEVEL_10_1
Surfaces
--------
Surfaces are views of a resource that can be bound as a framebuffer to serve as the render target or depth buffer.
TODO: write much more on surfaces
OpenGL: FBOs are collections of surfaces in GL 3.0 or :ext:`GL_ARB_framebuffer_object`
D3D11: render target views and depth/stencil views
Sampler views
-------------
Sampler views are views of a resource that can be bound to a pipeline stage to be sampled from shaders.
TODO: write much more on sampler views
OpenGL: texture objects are actually sampler view and resource in a single unit
D3D11: shader resource views
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff