Skip to content

Commit 11091f1

Browse files
committed
Tidy up python documentation and add examples
1 parent 45c3c27 commit 11091f1

32 files changed

+1860
-16
lines changed

docs/getting_started/faq.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ RenderDoc stores data in two folders:
7171

7272
The UI stores data in a ``qrenderdoc`` folder underneath your OS's user settings folder. On windows this is ``%APPDATA%`` and on linux this will be somewhere in your home directory, perhaps in ``~/.local/share``. Nothing in this data is machine specific aside from paths, so you can back up and restore this directory at will.
7373

74-
Deleting this folder will also reset QRenderDoc to the defaults - if you uninstall RenderDoc this folder will not be deleted.
74+
Deleting this folder will also reset the RenderDoc UI to the defaults - if you uninstall RenderDoc this folder will not be deleted.
7575

7676
The core code may save cached data in a ``renderdoc`` folder - either ``%APPDATA%/renderdoc`` or ``~/.renderdoc/`` but this doesn't contain settings, so is not important to back up.
7777

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Table of Contents
77
=================
88

99
.. toctree::
10+
:includehidden:
1011
:maxdepth: 2
1112

1213
introduction

docs/python_api/base/index.rst

Lines changed: 0 additions & 9 deletions
This file was deleted.

docs/python_api/examples/basics.rst

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
Basic Interfaces
2+
================
3+
4+
This document explains some common interfaces and their relationship, which can be useful as a primer to understand where to get started, as well as for reference to look back on from later examples.
5+
6+
Replay Basics
7+
-------------
8+
9+
ReplayController
10+
^^^^^^^^^^^^^^^^
11+
12+
The primary interface for accessing the low level of RenderDoc's replay analysis is :py:class:`~renderdoc.ReplayController`.
13+
14+
From this interface, information about the capture can be gathered, using e.g. :py:meth:`~renderdoc.ReplayController.GetDrawcalls` to return the list of root-level drawcalls in the frame, or :py:meth:`~renderdoc.ReplayController.GetResources` to return a list of all resources in the capture.
15+
16+
Some methods like the two above return information which is global and does not vary across the frame. Most functions however return information relative to the current point in the frame.
17+
18+
During RenderDoc's replay, you can imagine a cursor that moves back and forth between the start and end of the frame. All requests for information that varies - such as texture and buffer contents, pipeline state, and other information will be relative to the current event.
19+
20+
Every function call within a frame is assigned an ascending ``eventId``, from ``1`` up to as many events as are in the frame. Within the drawcall list returned by :py:meth:`~renderdoc.ReplayController.GetDrawcalls`, each drawcall contains a list of events in :py:attr:`~renderdoc.DrawcallDescription.events`. These contain all of the ``eventId`` that immediately preceeded the draw. The details of the function call can be found by using :py:attr:`~renderdoc.APIEvent.chunkIndex` as an index into the structured data returned from :py:meth:`~renderdoc.GetStructuredFile`. The structured data contains the function name and the complete set of parameters passed to it, with their values.
21+
22+
To change the current active event and move the cursor, you can call :py:meth:`~renderdoc.ReplayController.SetFrameEvent`. This will move the replay to represent the current state immediately after the given event has executed.
23+
24+
At this point you can use :py:meth:`~renderdoc.ReplayController.GetBufferData` and :py:meth:`~renderdoc.ReplayController.GetTextureData` to obtain the contents of a buffer or texture respectively. The pipeline state can be accessed via ``Get*PipelineState`` for each API - to determine the current capture's pipeline type you can fetch the API properties from :py:meth:`~renderdoc.ReplayController.GetAPIProperties`.
25+
26+
For more examples of how to fetch data, see the concrete examples below.
27+
28+
ReplayOutput
29+
^^^^^^^^^^^^
30+
31+
While :py:class:`~renderdoc.ReplayController` provides methods for obtaining data directly, it doesn't provide any functionality for displaying to a window. For this the :py:class:`~renderdoc.ReplayOutput` class allows you to bind to a window and configure the output.
32+
33+
First you need to gather the platform-specific windowing information in a :py:class:`~renderdoc.WindowingData`. This class is opaque to python, but you can create it using helper functions such as :py:func:`~renderdoc.CreateWin32WindowingData` and :py:func:`~renderdoc.CreateXlibWindowingData`. The parameters to these are platform specific, and are typically accepted as integers where they refer to a windowing handle.
34+
35+
To then create an output for a window, :py:meth:`~renderdoc.ReplayController.CreateOutput` can create different types of outputs.
36+
37+
Once created, you can configure the output with :py:meth:`~renderdoc.ReplayOutput.SetMeshDisplay` and :py:meth:`~renderdoc.ReplayOutput.SetTextureDisplay` to update the configuration, and then call :py:meth:`~renderdoc.ReplayOutput.Display` to display on screen.
38+
39+
.. _qrenderdoc-python-basics:
40+
41+
RenderDoc UI Basics
42+
-------------------
43+
44+
The RenderDoc UI provides a number of useful abstractions over the lower level API, which can be convenient when developing scripts. In addition it gives access to the different panels to allow limited control over them. The ``pyrenderdoc`` global is available to all scripts running within the RenderDoc UI, and it provides access to all of these things.
45+
46+
Each single-instance panel such as the :py:class:`~qrenderdoc.TextureViewer` or :py:class:`~qrenderdoc.PipelineStateViewer` has accessors within the :py:class:`~qrenderdoc.CaptureContext`.
47+
48+
Functions such as :py:meth:`~qrenderdoc.CaptureContext.GetTextureViewer` will return a valid handle to the texture viewer, but if the texture viewer was closed then although it will be created it will *not* be immediately visible. You need to call :py:meth:`~qrenderdoc.CaptureContext.ShowTextureViewer` first which will bring the texture viewer to the front and make sure it is visible and docked if it wasn't already.
49+
50+
You can also create new instances of windows such as buffer or shader viewers using :py:meth:`~qrenderdoc.CaptureContext.ViewBuffer` or :py:meth:`~qrenderdoc.CaptureContext.ViewShader`.
51+
52+
The :py:class:`~qrenderdoc.CaptureContext` interface also provides useful utility functions such as :py:meth:`~qrenderdoc.CaptureContext.GetTexture` or :py:meth:`~qrenderdoc.CaptureContext.GetDrawcall` to look up objects by id instead of needing your own caching and lookup from the lists returned by the lower level interface.
53+
54+
There is also an API-agnostic pipeline abstraction to return information that is the same across APIs. Using :py:meth:`~qrenderdoc.CaptureContext.CurPipelineState` returns a :py:class:`~qrenderdoc.CommonPipelineState` which has accessors for fetching the current vertex buffers, shaders, and colour outputs. This allows you to write generic code that will work on any API that RenderDoc supports. The API-specific pipelines are still available through ``Cur*PipelineState``.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
qrenderdoc examples
2+
===================
3+
4+
These examples are only relevant to the scripting available in the UI.
5+
6+
.. toctree::
7+
show_buffer
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
filename = "test.rdc"
2+
formatter = "float3 pos; half norms[16]; uint flags;"
3+
4+
pyrenderdoc.LoadCapture(filename, filename, False, True)
5+
6+
mybuf = renderdoc.ResourceId.Null()
7+
8+
for buf in pyrenderdoc.GetBuffers():
9+
print("buf %s is %s" % (buf.resourceId, pyrenderdoc.GetResourceName(buf.resourceId)))
10+
11+
# here put your actual selection criteria - i.e. look for a particular name
12+
if pyrenderdoc.GetResourceName(buf.resourceId) == "dataBuffer":
13+
mybuf = buf.resourceId
14+
break
15+
16+
print("selected %s" % pyrenderdoc.GetResourceName(mybuf))
17+
18+
# Open a new buffer viewer for this buffer, with the given format
19+
bufview = pyrenderdoc.ViewBuffer(0, 0, mybuf, formatter)
20+
21+
# Show the buffer viewer on the main tool area
22+
pyrenderdoc.AddDockWindow(bufview.Widget(), qrenderdoc.DockReference.MainToolArea, None)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
Display buffer with format
2+
==========================
3+
4+
This example shows an easy way to automate a repro case. It could be run as a command line argument when starting the UI, to avoid repetitive steps.
5+
6+
First the code opens a specified file, although this step could be omitted if the desired capture is already open.
7+
8+
.. highlight:: python
9+
.. code:: python
10+
11+
filename = "test.rdc"
12+
13+
pyrenderdoc.LoadCapture(filename, filename, False, True)
14+
15+
Next we iterate through the list of buffers to find the one we want. The selection criteria are up to you, in this case we look at the name provided and identify the buffer by that, however it could also be a particular size, or the buffer bound at a given event.
16+
17+
.. highlight:: python
18+
.. code:: python
19+
20+
mybuf = renderdoc.ResourceId.Null()
21+
22+
for buf in pyrenderdoc.GetBuffers():
23+
print("buf %s is %s" % (buf.resourceId, pyrenderdoc.GetResourceName(buf.resourceId)))
24+
25+
# here put your actual selection criteria - i.e. look for a particular name
26+
if pyrenderdoc.GetResourceName(buf.resourceId) == "dataBuffer":
27+
mybuf = buf.resourceId
28+
break
29+
30+
print("selected %s" % pyrenderdoc.GetResourceName(mybuf))
31+
32+
Once we've identified the buffer we want to view, we create a buffer viewer and display it on the main tool area.
33+
34+
.. highlight:: python
35+
.. code:: python
36+
37+
# Open a new buffer viewer for this buffer, with the given format
38+
bufview = pyrenderdoc.ViewBuffer(0, 0, mybuf, formatter)
39+
40+
# Show the buffer viewer on the main tool area
41+
pyrenderdoc.AddDockWindow(bufview.Widget(), qrenderdoc.DockReference.MainToolArea, None)
42+
43+
Example Source
44+
--------------
45+
46+
.. only:: html and not htmlhelp
47+
48+
:download:`Download the example script <show_buffer.py>`.
49+
50+
.. literalinclude:: show_buffer.py
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
Getting Started (RenderDoc UI)
2+
==============================
3+
4+
.. note::
5+
6+
This document is aimed at users getting started with scripting within the RenderDoc UI.
7+
8+
The module used here (``qrenderdoc``) is not available as a stand-alone module.
9+
10+
When working within the RenderDoc UI, the ``renderdoc`` and ``qrenderdoc`` modules are implicitly imported when any script runs. In addition to this, an additional global ``pyrenderdoc`` is always available. It is an instance of :py:class:`~qrenderdoc.CaptureContext` and it represents the interface into the UI interface.
11+
12+
Loading a Capture
13+
-----------------
14+
15+
Unlike :doc:`when using the base module directly <renderdoc_intro>`, within the UI it is strongly recommended that you load captures using the UI interfaces itself rather than doing it entirely within python code, otherwise there is a risk of conflict between the two loaded captures in the same program.
16+
17+
To load a capture programmatically, we can use the ``pyrenderdoc`` global variable and call :py:meth:`~qrenderdoc.CaptureContext.LoadCapture`. When loading a local capture some of the parameters are redundant - we don't need to specify a different "actual" file vs the loaded file, and it is not a temporary handle. These parameters are primarily used by the UI itself when loading captures from remote hosts or immediately after they are generated while they are still stored temporarily on disk and the user needs to be prompted to save or delete them on close.
18+
19+
.. highlight:: python
20+
.. code:: python
21+
22+
filename = 'test.rdc'
23+
24+
# Load a file, with the same 'original' name, that's not temporary, and is local
25+
pyrenderdoc.LoadCapture(filename, filename, False, True)
26+
27+
This will close any capture that is already loaded, but to just close an open capture you can use :py:meth:`~qrenderdoc.CaptureContext.CloseCapture`.
28+
29+
As part of opening the capture, RenderDoc will begin replay automatically and populate the various panels and internal data structures for easy access. It will also handle prompting the user if any errors happen or if replay isn't supported.
30+
31+
Once the capture is opened, all of the RenderDoc UI accessible data is immediately available and can be accessed directly, see :ref:`qrenderdoc-python-basics`.
32+
33+
Accessing Capture Analysis
34+
--------------------------
35+
36+
To access the :py:class:`~renderdoc.ReplayController` and any related core interfaces, a little bit of extra work is required. Within the UI, the replay work happens on a separate thread to prevent long-running tasks from causing the UI to become unresponsive. That means the :py:class:`~renderdoc.ReplayController` is not immediately available, but is provided to a callback on the right thread.
37+
38+
To invoke onto the right thread, you can use :py:meth:`~qrenderdoc.ReplayManager.BlockInvoke` and pass it a callback that will be called with a single parameter - the :py:class:`~renderdoc.ReplayController` instance for the currently open capture.
39+
40+
.. warning::
41+
42+
There is another invoke function :py:meth:`~qrenderdoc.ReplayManager.AsyncInvoke`, but due to Python's limited threading capability the callback can't be called while the script is executing, meaning this has limited use. For Python it is recommended to use :py:meth:`~qrenderdoc.ReplayManager.BlockInvoke`.
43+
44+
.. highlight:: python
45+
.. code:: python
46+
47+
def myCallback(controller):
48+
print("%d top-level drawcalls" % len(controller.GetDrawcalls()))
49+
50+
pyrenderdoc.Replay().BlockInvoke(myCallback)
51+
52+
If there is no replay active, the callback will be silently dropped.

0 commit comments

Comments
 (0)