mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 17:40:39 +00:00
7149302680
* There's not a good accepted terminology for this kind of event, and for historical reasons 'drawcall' has been the accepted term, even though that can be quite confusing when a dispatch or a copy is a 'drawcall'. * This is particularly highlighted by the event browser filters where $draw() includes draws and dispatches, but $dispatch() only includes dispatches, it's hard to intuitively understand why $draw() matches all of these calls. * As a result we've defined the term 'action' to cover these types of events in the same way that we defined 'event' in the first place to mean a single atomic API call.
150 lines
5.7 KiB
ReStructuredText
150 lines
5.7 KiB
ReStructuredText
Display texture in window
|
|
=========================
|
|
|
|
In this example we will open a window and iterate through the capture on a loop, displaying the first colour output target on it.
|
|
|
|
.. note::
|
|
|
|
This is intended for use with the python module directly, as the UI already has a texture viewer panel to do this with much more control. The principle is the same though and it can be useful reference of how to iterate over a capture.
|
|
|
|
To create a window we use tkinter, since it is provided with the Python distribution.
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
# Use tkinter to create windows
|
|
import tkinter
|
|
|
|
# Create a simple window
|
|
window = tkinter.Tk()
|
|
window.geometry("1280x720")
|
|
|
|
Next we need to determine which windowing systems the RenderDoc implementation supports, and create a :py:class:`~renderdoc.WindowingData` object for the window we want to render to. For the purposes of this example we will look for Win32 since it's the simplest to set up - needing only a window handle that we can get from tkinter easily. XCB/XLib require a display connection, which would be possible to get from another library such as Qt.
|
|
|
|
Once we have the :py:class:`~renderdoc.WindowingData`, we can create a :py:class:`~renderdoc.ReplayOutput` using :py:meth:`~renderdoc.ReplayController.CreateOutput`.
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
# Create renderdoc windowing data.
|
|
winsystems = [rd.WindowingSystem(i) for i in controller.GetSupportedWindowSystems()]
|
|
|
|
# Pass window system specific data here, See:
|
|
# - renderdoc.CreateWin32WindowingData
|
|
# - renderdoc.CreateXlibWindowingData
|
|
# - renderdoc.CreateXCBWindowingData
|
|
|
|
# This example code works on windows as that's simple to integrate with tkinter
|
|
if not rd.WindowingSystem.Win32 in winsystems:
|
|
raise RuntimeError("Example requires Win32 windowing system: " + str(winsystems))
|
|
|
|
windata = rd.CreateWin32WindowingData(int(window.frame(), 16))
|
|
|
|
# Create a texture output on the window
|
|
out = controller.CreateOutput(windata, rd.ReplayOutputType.Texture)
|
|
|
|
In order to iterate over all actions we need some global state first from :py:meth:`~renderdoc.ReplayController.GetTextures` and :py:meth:`~renderdoc.ReplayController.GetRootActions`, and we'll also define a helper function to fetch a particular texture by resourceId, so that we can easily look up the details for a texture.
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
# Fetch the list of textures
|
|
textures = controller.GetTextures()
|
|
|
|
# Fetch the list of actions
|
|
actions = controller.GetRootActions()
|
|
|
|
# Function to look up the texture descriptor for a given resourceId
|
|
def getTexture(texid):
|
|
global textures
|
|
for tex in textures:
|
|
if tex.resourceId == texid:
|
|
return tex
|
|
return None
|
|
|
|
We now define two callback functions - ``paint`` and ``advance``. ``paint`` will be called every 33ms, it will display the output with the latest state using :py:meth:`~renderdoc.ReplayOutput.Display`. ``advance`` changes the current state to reflect a new action.
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
# Our paint function will be called ever 33ms, to display the output
|
|
def paint():
|
|
global out, window
|
|
out.Display()
|
|
window.after(33, paint)
|
|
|
|
Within ``advance`` we do a few things. First we move the current event to the current action's ``eventId``, using :py:meth:`~renderdoc.ReplayController.SetFrameEvent`. Then we set up the texture display configuration with :py:meth:`~renderdoc.ReplayOutput.SetTextureDisplay`, to point to the first colour output at that action.
|
|
|
|
When we update to a new texture, we fetch its details using our earlier ``getTexture`` and calculate a scale that keeps the texture fully visible on screen.
|
|
|
|
Finally we move to the next action in the list for the next time ``advance`` is called.
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
# Start on the first action
|
|
curact = actions[0]
|
|
|
|
loopcount = 0
|
|
|
|
# The advance function will be called every 50ms, to move to the next action
|
|
def advance():
|
|
global out, window, curact, actions, loopcount
|
|
|
|
# Move to the current action
|
|
controller.SetFrameEvent(curact.eventId, False)
|
|
|
|
# Initialise a default TextureDisplay object
|
|
disp = rd.TextureDisplay()
|
|
|
|
# Set the first colour output as the texture to display
|
|
disp.resourceId = curact.outputs[0]
|
|
|
|
if disp.resourceId != rd.ResourceId.Null():
|
|
# Get the details of this texture
|
|
texDetails = getTexture(disp.resourceId)
|
|
|
|
# Calculate the scale required in width and height
|
|
widthScale = window.winfo_width() / texDetails.width
|
|
heightScale = window.winfo_height() / texDetails.height
|
|
|
|
# Use the lower scale to fit the texture on the window
|
|
disp.scale = min(widthScale, heightScale)
|
|
|
|
# Update the texture display
|
|
out.SetTextureDisplay(disp)
|
|
|
|
# Set the next action
|
|
curact = curact.next
|
|
|
|
# If we have no next action, start again from the first
|
|
if curact is None:
|
|
loopcount = loopcount + 1
|
|
curact = actions[0]
|
|
|
|
# after 3 loops, quit
|
|
if loopcount == 3:
|
|
window.quit()
|
|
else:
|
|
window.after(50, advance)
|
|
|
|
Once we have the callbacks defined, we call them once to initialise the display and set up the repeated callbacks, and start the tkinter main window loop.
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
# Start the callbacks
|
|
advance()
|
|
paint()
|
|
|
|
# Start the main window loop
|
|
window.mainloop()
|
|
|
|
Example Source
|
|
--------------
|
|
|
|
.. only:: html and not htmlhelp
|
|
|
|
:download:`Download the example script <display_window.py>`.
|
|
|
|
.. literalinclude:: display_window.py |