From 565fe17ba203a1421c52dcc8bf62445abb96d839 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 26 Jan 2026 15:43:51 +0000 Subject: [PATCH] Add API and usage documentation for custom annotations system --- docs/how/how_annotate_capture.rst | 34 ++-- docs/imgs/Screenshots/CommandAnnotations.png | Bin 0 -> 17564 bytes docs/imgs/Screenshots/EventAnnotFilter.png | Bin 0 -> 16503 bytes docs/imgs/Screenshots/EventAnnotHighlight.png | Bin 0 -> 15744 bytes docs/imgs/Screenshots/ResourceAnnotations.png | Bin 0 -> 5716 bytes docs/in_application_api.rst | 151 +++++++++++++++++- docs/python_api/qrenderdoc/windows.rst | 6 + docs/window/annotation_viewer.rst | 123 ++++++++++++++ docs/window/index.rst | 21 +-- docs/window/resource_inspector.rst | 9 ++ 10 files changed, 318 insertions(+), 26 deletions(-) create mode 100644 docs/imgs/Screenshots/CommandAnnotations.png create mode 100644 docs/imgs/Screenshots/EventAnnotFilter.png create mode 100644 docs/imgs/Screenshots/EventAnnotHighlight.png create mode 100644 docs/imgs/Screenshots/ResourceAnnotations.png create mode 100644 docs/window/annotation_viewer.rst diff --git a/docs/how/how_annotate_capture.rst b/docs/how/how_annotate_capture.rst index 4e8680ee4..f1f2187a0 100644 --- a/docs/how/how_annotate_capture.rst +++ b/docs/how/how_annotate_capture.rst @@ -1,16 +1,28 @@ How do I annotate a capture? ============================ -RenderDoc allows annotation of captures in two ways - annotations that you provide from your application along with the other graphics API calls that you make, and annotations that are made in the UI while analysing a capture and can be saved with it. - -The annotations provided with the graphics API calls from your application vary by the particular API and are documented below. - -Annotations made in the UI are also described below. These can be useful for example when investigating a bug or repro case and passing on your findings natively to someone else, instead of having to include additional text like 'texture 148 is the buggy texture' you can directly mark up the capture. +RenderDoc allows annotation of captures in multiple ways. Your application can call built-in debug functions in graphics APIs as well as custom RenderDoc APIs. You can also add extra annotations after opening the capture. All of the UI modifications can be saved with a capture. Pressing :kbd:`Ctrl-S` or :guilabel:`File` → :guilabel:`Save` will save the capture with any changes that have been made to it in the UI. If you haven't already saved a temporary capture, or the capture is on a remote context, this will need to you save it to a local path. +Application-provided data +------------------------- + +Rich custom annotations +^^^^^^^^^^^^^^^^^^^^^^^ + +RenderDoc's :doc:`../in_application_api` provides mechanisms for annotating both objects and commands with rich structured annotations, which can be used by the application for including complex custom data for additional context and debug information beyond what is provided via baseline graphics APIs. + +The specific implementation details of how to pass this information along can be found in the documentation for the :doc:`../in_application_api`, via the :cpp:func:`SetObjectAnnotation` and :cpp:func:`SetCommandAnnotation` functions. The exact details may vary slightly by graphics API. + +For a high-level explanation of how the feature works and how to inspect and use it in the UI, see the :doc:`../window/annotation_viewer` documentation. + +.. figure:: ../imgs/Screenshots/CommandAnnotations.png + + Annotation Viewer: Showing the custom annotations on a selected event. + Application provided marker regions ------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When calling graphics API functions from your code you can provide annotations to group regions of the frame under names, with a nested hierarchy. @@ -96,7 +108,7 @@ Example code for Vulkan using the ``VK_EXT_debug_utils`` extension: // queue-level markers can be provided similarly. Application provided object names ---------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Similar to the marker regions above, it is possible to give objects names via the graphics APIs and they will be displayed with those human-readable names instead of auto-generated names. @@ -183,9 +195,11 @@ On D3D12 there is a RenderDoc extension provided with this interface, queried fr This interface allows you to set a custom name for descriptors, if using SM6.6 style ``ResourceDescriptorHeap[]`` access for better debugging. +UI-side markup +-------------- Bookmarks ---------- +^^^^^^^^^ .. |asterisk_orange| image:: ../imgs/icons/asterisk_orange.png @@ -200,7 +214,7 @@ The |asterisk_orange| bookmark button will allow you to bookmark an event, the s When loading any capture with saved bookmarks they will be automatically populated into the UI. This will allow you to highlight particular problematic events and anyone opening the capture will be able to use the shortcuts above to jump immediately to where the problem is. Resource Renaming ------------------ +^^^^^^^^^^^^^^^^^ From within the :doc:`../window/resource_inspector` window, you can rename any resource in the capture. Whether the resource already had a custom-specified name, or if it had a default-generated name, you can provide overrides at any time. @@ -213,7 +227,7 @@ To do so, simply select the resource in question in the resource inspector - eit As with bookmarks, these renames can be saved with a capture and are automatically used when loading the capture subsequently. This can be useful to point the way to which resources are causing problems, or specifically how a given resource with a more general name is being used in this particular capture. Capture Comments ----------------- +^^^^^^^^^^^^^^^^ In the :doc:`../window/capture_comments` window there is a simple text field allowing you to store any arbitrary text you want within the capture. This could be notes on the environment or build version that was stored. diff --git a/docs/imgs/Screenshots/CommandAnnotations.png b/docs/imgs/Screenshots/CommandAnnotations.png new file mode 100644 index 0000000000000000000000000000000000000000..2d2388ef2ce2d3c24bf704805ad36dc87a764cfc GIT binary patch literal 17564 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 literal 0 HcmV?d00001 diff --git a/docs/imgs/Screenshots/EventAnnotFilter.png b/docs/imgs/Screenshots/EventAnnotFilter.png new file mode 100644 index 0000000000000000000000000000000000000000..91afb249a59f203d7925aacb5bedb43b8fd8b3ba GIT binary patch literal 16503 zcmdUXby$>L*Y7AQqLiY5)F_BFh;$AL2uMjwi*)zUgGozw4c!b4(jwhmLyUCyPy++! z#^-(B=l#z2UFSO2`S1K8bLZY`ul%jG_O1V01u23%6n8)%5P^)egfa+pof!nWmU;U+ za7A0^jT7*5!}O*6OAx3eO{1ztTY2M50j_>nI2Bdn z+=#KAL7<`%6Q{G}Dak+}v2xd?C=H!oBBub^N{d@nD5$m{&NUFoz@R6VQ{j#fbkh$8 z0zJ0czNg@ZJshw2HlN9OezFi^eOOlBo?bIsE#<*V;LOsJhQBk$QMbh}$^`oOu9+nP zx`i~?ue3#pzC{~CUw23!rbmCZmjrDs54lmxaGu4{!ms9T&%$;_7!`a_d&RzPy zxxTLGUI^yh-xNeq2+wJJb$0+KuhK1~dgDIu&}-DV<^Pw zcSRFD(qhcZY<5?I5B>A`Hu5)K^8ij`7JkG6lA^NT!~>8>067e`(E2;s69xseSN=K% z5E>c>1S)(3v2Dacr9hyMW_t(l%jrTmaQ`FYJSA(}CqT$o&#Y#~Tg7|sKa}865}4Q$t}9Snt2>%6@$L%bCIPK7 zWTCmtR*RWbOy%Nu(;cghXV)eswfXIK2V^3$< qw11s7t(#iUJxNXEBc)DKwKHwf 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 !&7zFP+7>F?Y7Q_CRI{XJ$`0wZhR*A~PZ{BON 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 literal 0 HcmV?d00001 diff --git a/docs/imgs/Screenshots/ResourceAnnotations.png b/docs/imgs/Screenshots/ResourceAnnotations.png new file mode 100644 index 0000000000000000000000000000000000000000..629473a09870901f8efd63f41bab9c7d4ac6850f GIT binary patch literal 5716 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 M-)v77AHNj)KRR*&rT_o{ literal 0 HcmV?d00001 diff --git a/docs/in_application_api.rst b/docs/in_application_api.rst index 298b1c389..f69fdeace 100644 --- a/docs/in_application_api.rst +++ b/docs/in_application_api.rst @@ -138,7 +138,7 @@ To do this you'll use your platforms dynamic library functions to see if the lib .. cpp:enumerator:: RENDERDOC_CaptureOption::eRENDERDOC_Option_DebugOutputMute - specifies whether to mute any API debug output messages when `APIValidation` is enabled, and not pass them along to the application. Default is on. + specifies whether to mute any API debug output messages when ``APIValidation`` is enabled, and not pass them along to the application. Default is on. .. cpp:function:: uint32_t GetCaptureOptionU32(RENDERDOC_CaptureOption opt) @@ -331,8 +331,8 @@ To do this you'll use your platforms dynamic library functions to see if the lib :param uint32_t idx: specifies which capture to return the details of. Must be less than the return value of :cpp:func:`GetNumCaptures`. :param char* filename: is an optional parameter filled with the UTF-8 null-terminated path to the file. There must be enough space in the array to contain all characters including the null terminator. If set to NULL, nothing is written. - :param uint32_t* pathlength: is an optional parameter filled with the byte length of the above `filename` including the null terminator. If set to NULL, nothing is written. - :param uint64_t* timestamp: is an optional parameter filled with the 64-bit timestamp of the file - equivalent to the `time()` system call. If set to NULL, nothing is written. + :param uint32_t* pathlength: is an optional parameter filled with the byte length of the above ``filename`` including the null terminator. If set to NULL, nothing is written. + :param uint64_t* timestamp: is an optional parameter filled with the 64-bit timestamp of the file - equivalent to the ``time()`` system call. If set to NULL, nothing is written. :return: Returns ``1`` if the capture index was valid, or ``0`` if it was out of range. .. note:: @@ -391,7 +391,7 @@ The path follows the template set in :cpp:func:`SetCaptureFilePathTemplate` so i * For D3D12 it must be the ``ID3D12Device`` device object. * For OpenGL it must be the ``HGLRC``, ``GLXContext``, or ``EGLContext`` context object. * For OpenGLES it must be the ``EGLContext`` context object. - * For Vulkan it must be the dispatch table pointer within the ``VkInstance``. This is a pointer-sized value at the location pointed to by the ``VkInstance``. NOTE - this is not the actual ``VkInstance`` pointer itself. You can use the RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE helper macro defined in the renderdoc header to obtain this pointer from any VkInstance. + * For Vulkan it must be the dispatch table pointer within the ``VkInstance``. This is a pointer-sized value at the location pointed to by the ``VkInstance``. NOTE - this is not the actual ``VkInstance`` pointer itself. You can use the ``RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE()`` helper macro defined in the renderdoc header to obtain this pointer from any VkInstance. ``RENDERDOC_WindowHandle`` is a typedef to ``void *``. It is the platform specific Windows ``HWND``, Xcb ``xcb_window_t``, Xlib ``Window`` / ``Drawable``, Wayland ``wl_surface*``, or Android ``ANativeWindow*``. @@ -433,7 +433,7 @@ The path follows the template set in :cpp:func:`SetCaptureFilePathTemplate` so i ``RENDERDOC_DevicePointer`` and ``RENDERDOC_WindowHandle`` are described above in :cpp:func:`SetActiveWindow`. ``device`` and ``wndHandle`` can either or both be set to ``NULL`` to wildcard match against active device/window combinations. This wildcard matching can be used if the handle is difficult to obtain where frame captures are triggered. - Wildcard matching of `device` and `wndHandle` is described above in :cpp:func:`StartFrameCapture`. + Wildcard matching of ``device`` and ``wndHandle`` is described above in :cpp:func:`StartFrameCapture`. There will be undefined results if there is not an active frame capture for the device/window combination. @@ -451,7 +451,7 @@ The path follows the template set in :cpp:func:`SetCaptureFilePathTemplate` so i ``RENDERDOC_DevicePointer`` and ``RENDERDOC_WindowHandle`` are described above in :cpp:func:`SetActiveWindow`. ``device`` and ``wndHandle`` can either or both be set to ``NULL`` to wildcard match against active device/window combinations. This wildcard matching can be used if the handle is difficult to obtain where frame captures are triggered. - Wildcard matching of `device` and `wndHandle` is described above in :cpp:func:`StartFrameCapture`. + Wildcard matching of ``device`` and ``wndHandle`` is described above in :cpp:func:`StartFrameCapture`. There will be undefined results if there is not an active frame capture for the device/window combination. @@ -495,3 +495,142 @@ The path follows the template set in :cpp:func:`SetCaptureFilePathTemplate` so i Added in API version 1.2.0 +.. cpp:function:: void SetObjectAnnotation(RENDERDOC_DevicePointer device, void* object, const char *key, RENDERDOC_AnnotationType valueType, uint32_t valueVectorWidth, const RENDERDOC_AnnotationValue* value) + + This function allows associating custom rich annotations with API objects. These annotations can be examined in the :doc:`window/resource_inspector`. + + See the :doc:`window/annotation_viewer` documentation for more detailed information on the annotation system. + + :param RENDERDOC_DevicePointer device: is a handle to the API 'device' object that will be set active. May be ``NULL`` to wildcard match. + :param void* object: is a handle to the API object that will be annotated. Must not be ``NULL``. + :param const char* key: is a dot separated path for the annotation to update. Must not be ``NULL`` or empty. + :param RENDERDOC_AnnotationType valueType: is the type of value to set, including basic scalar types as well as strings and API objects. + :param uint32_t valueVectorWidth: is the vector width of the value to set, or 0 for scalars. Must be no greater than 4. + :param const RENDERDOC_AnnotationValue* value: is a pointer to the value itself. + + :return: Returns ``0`` if the annotation was successfully set. + + Returns ``1`` if the device is unknown or invalid. + + Returns ``2`` if the device is valid but the annotation is not recognised or not supported for API-specific reasons, such as an unrecognised or invalid object or queue/commandbuffer. + + Returns ``3`` if the call is ill-formed or invalid e.g. empty is specified with a value pointer, or non-empty is specified with a NULL value pointer. + + Deleting an annotation can be done by setting a value with ``valueType`` equal to ``eRENDERDOC_Empty`` and ``value`` equal to ``NULL``. This deletes the annotation at the specific key, as well as any children of that key. + + You can set ``valueVectorWidth`` to 0 for single values, which is equivalent to setting 1. This is required for strings and API objects, which can't be vectors. + + There are C++ helper structs ``RDGLObjectHelper`` and ``RDAnnotationHelper`` that can simplify code for specifying single scalar values. + +.. note:: + + For Vulkan, annotating ``VkInstance``, ``VkPhysicalDevice``, or ``VkDevice`` objects may encounter problems due to loader wrapping. To address this, you can use ``vkSetDebugUtilsObjectTagEXT`` to set a tag with the ``tagName`` set to ``RENDERDOC_APIObjectAnnotationHelper`` and the ``pTag`` set to the handle of the object itself. After doing that once RenderDoc will be able to recognise those handles. + + For OpenGL as it lacks proper object handles, the ``object`` parameter and any ``apiObject`` value must be a pointer to an instance of ``RENDERDOC_GLResourceReference`` which contains both a ``GLenum`` identifier with the same meaning as the parameter in ``glObjectLabel`` as well as the integer handle itself. + +.. note:: + + ``RENDERDOC_DevicePointer`` is described above in :cpp:func:`SetActiveWindow`. + ``device`` can be set to ``NULL`` to wildcard match against active devices. This wildcard matching can be used if the handle is difficult to obtain where annotations are set. + + Wildcard matching of ``device`` is described above in :cpp:func:`StartFrameCapture`. + +.. note:: + + Added in API version 1.7.0 + +.. cpp:enum:: RENDERDOC_AnnotationType + +.. cpp:enumerator:: RENDERDOC_AnnotationType::eRENDERDOC_Empty + + ``eRENDERDOC_Empty`` is used to delete an annotation. All children are also deleted. + +.. cpp:enumerator:: RENDERDOC_AnnotationType::eRENDERDOC_Bool + + ``eRENDERDOC_Bool`` indicates that the ``boolean`` member of ``RENDERDOC_AnnotationValue`` (or ``RENDERDOC_AnnotationVectorValue``) is valid. + +.. cpp:enumerator:: RENDERDOC_AnnotationType::eRENDERDOC_Int32 + + ``eRENDERDOC_Int32`` indicates that the ``int32`` member of ``RENDERDOC_AnnotationValue`` (or ``RENDERDOC_AnnotationVectorValue``) is valid. + +.. cpp:enumerator:: RENDERDOC_AnnotationType::eRENDERDOC_UInt32 + + ``eRENDERDOC_UInt32`` indicates that the ``uint32`` member of ``RENDERDOC_AnnotationValue`` (or ``RENDERDOC_AnnotationVectorValue``) is valid. + +.. cpp:enumerator:: RENDERDOC_AnnotationType::eRENDERDOC_Int64 + + ``eRENDERDOC_Int64`` indicates that the ``int64`` member of ``RENDERDOC_AnnotationValue`` (or ``RENDERDOC_AnnotationVectorValue``) is valid. + +.. cpp:enumerator:: RENDERDOC_AnnotationType::eRENDERDOC_UInt64 + + ``eRENDERDOC_UInt64`` indicates that the ``uint64`` member of ``RENDERDOC_AnnotationValue`` (or ``RENDERDOC_AnnotationVectorValue``) is valid. + +.. cpp:enumerator:: RENDERDOC_AnnotationType::eRENDERDOC_Float + + ``eRENDERDOC_Float`` indicates that the ``float32`` member of ``RENDERDOC_AnnotationValue`` (or ``RENDERDOC_AnnotationVectorValue``) is valid. + +.. cpp:enumerator:: RENDERDOC_AnnotationType::eRENDERDOC_Double + + ``eRENDERDOC_Double`` indicates that the ``float64`` member of ``RENDERDOC_AnnotationValue`` (or ``RENDERDOC_AnnotationVectorValue``) is valid. + +.. cpp:enumerator:: RENDERDOC_AnnotationType::eRENDERDOC_String + + ``eRENDERDOC_String`` indicates that the ``string`` member of ``RENDERDOC_AnnotationValue`` is valid. + +.. cpp:enumerator:: RENDERDOC_AnnotationType::eRENDERDOC_APIObject + + ``eRENDERDOC_APIObject`` indicates that the ``apiObject`` member of ``RENDERDOC_AnnotationValue`` is valid. + +.. cpp:function:: void SetCommandAnnotation(RENDERDOC_DevicePointer device, void* queueOrCommandBuffer, const char* key, RENDERDOC_AnnotationType valueType, uint32_t valueVectorWidth, const RENDERDOC_AnnotationValue* value) + + This function allows adding custom rich annotations to command streams. These annotations can be examined in the :doc:`window/annotation_viewer` which has more information on the annotation system. + + For more information see the page on the :doc:`../window/annotation_viewer`. + + :param RENDERDOC_DevicePointer device: is a handle to the API 'device' object that will be set active. May be ``NULL`` to wildcard match. + :param void* queueOrCommandBuffer: is a handle to the API-specific command buffer or queue. + :param const char* key: is a dot separated path for the annotation to update. Must not be ``NULL`` or empty. + :param RENDERDOC_AnnotationType valueType: is the type of value to set, including basic scalar types as well as strings and API objects. + :param uint32_t valueVectorWidth: is the vector width of the value to set, or 0 for scalars. Must be no greater than 4. + :param const RENDERDOC_AnnotationValue* value: is a pointer to the value itself. + + :return: Returns ``0`` if the annotation was successfully set. + + Returns ``1`` if the device is unknown or invalid. + + Returns ``2`` if the device is valid but the annotation is not recognised or not supported for API-specific reasons, such as an unrecognised or invalid object or queue/commandbuffer. + + Returns ``3`` if the call is ill-formed or invalid e.g. empty is specified with a value pointer, or non-empty is specified with a NULL value pointer. + + Deleting an annotation can be done by setting a value with ``valueType`` equal to ``eRENDERDOC_Empty`` and ``value`` equal to ``NULL``. This deletes the annotation at the specific key, as well as any children of that key. + + You can set ``valueVectorWidth`` to 0 for single values, which is equivalent to setting 1. This is required for strings and API objects, which can't be vectors. + + There are C++ helper structs ``RDGLObjectHelper`` and ``RDAnnotationHelper`` that can simplify code for specifying single scalar values. + + The ``queueOrCommandBuffer`` parameter refers to a different object depending on the API: + + * On Vulkan, it can either be a ``VkCommandBuffer`` in the recording state, or a ``VkQueue``. + * On OpenGL, it must be ``NULL``. + * On D3D11 it must either be ``NULL`` or the immediate context ``ID3D11DeviceContext*``. + * On D3D12 it must either be an ``ID3D12GraphicsCommandList*`` or a ``ID3D12CommandQueue*``. + +.. note:: + + For Vulkan, annotating ``VkInstance``, ``VkPhysicalDevice``, or ``VkDevice`` objects may encounter problems due to loader wrapping. To address this, you can use ``vkSetDebugUtilsObjectTagEXT`` to set a tag with the ``tagName`` set to ``RENDERDOC_APIObjectAnnotationHelper`` and the ``pTag`` set to the handle of the object itself. After doing that once RenderDoc will be able to recognise those handles. + + For OpenGL as it lacks proper object handles, any ``apiObject`` values must be a pointer to an instance of ``RENDERDOC_GLResourceReference`` which contains both a ``GLenum`` identifier with the same meaning as the parameter in ``glObjectLabel`` as well as the integer handle itself. + The ``queueOrCommandBuffer`` parameter must be ``NULL``. + + For D3D11 the ``queueOrCommandBuffer`` parameter must be either the immediate context or ``NULL``. + +.. note:: + + ``RENDERDOC_DevicePointer`` is described above in :cpp:func:`SetActiveWindow`. + ``device`` can be set to ``NULL`` to wildcard match against active devices. This wildcard matching can be used if the handle is difficult to obtain where annotations are set. + + Wildcard matching of ``device`` is described above in :cpp:func:`StartFrameCapture`. + +.. note:: + + Added in API version 1.7.0 diff --git a/docs/python_api/qrenderdoc/windows.rst b/docs/python_api/qrenderdoc/windows.rst index a47757e90..b0ff66cc5 100644 --- a/docs/python_api/qrenderdoc/windows.rst +++ b/docs/python_api/qrenderdoc/windows.rst @@ -42,6 +42,12 @@ Descriptor Viewer .. autoclass:: qrenderdoc.DescriptorViewer :members: +Annotation Viewer +----------------- + +.. autoclass:: qrenderdoc.AnnotationViewer + :members: + Texture Viewer -------------- diff --git a/docs/window/annotation_viewer.rst b/docs/window/annotation_viewer.rst new file mode 100644 index 000000000..65044b9dc --- /dev/null +++ b/docs/window/annotation_viewer.rst @@ -0,0 +1,123 @@ +Annotation Viewer +================= + +The annotation viewer window provides information on the per-command annotations provided by the application. By default it is hidden, if loading a capture with annotations included the viewer will be shown if it has never previously been used. + +This page describes both the general annotation system as well as the specific viewer for per-command annotations. + +.. figure:: ../imgs/Screenshots/CommandAnnotations.png + + Annotation Viewer: Showing the custom annotations on a selected event. + +Individual annotations can be strings, scalar values (integers, floats, bools), up to 4-wide vectors of those same types, as well as other API objects. + +Annotations are set in an arbitrary user-specified hierarchy as determined by a dot-separated path. When displayed, paths are sorted with a natural sort so arrays can be created by using paths such as ``custom.list.0``, ``custom.list.1``, and so on. + +.. note:: + + It is also possible to associate the same annotations with an object itself which can be viewed in a section in the :doc:`resource_inspector`. + +Viewing command annotations +--------------------------- + +When opening a capture with annotations, if it hasn't been displayed before the Annotation Viewer will open and by default be docked onto the :doc:`api_inspector`. If you have closed the Annotation Viewer you will have to open it from the :guilabel:`Window` menu. + +The Annotation Viewer will then show the set of annotations for the current event. These can be expanded and examined at will, and as different events are selected the annotations for each of those events will be shown. + +When right clicking on an annotation, it can be selected for previewing in a column in the event browser. This is only possible for scalar values, but if a particular path is selected then a new column will be shown on the event browser that shows the value of that annotation (or nothing, if it is absent) at each event. + +.. figure:: ../imgs/Screenshots/EventAnnotHighlight.png + + Event Browser: Showing a given annotation as a column on each event. + +Viewing object annotations +-------------------------- + +Annotations set on objects rather than commands are visible via the :doc:`resource_inspector`, when a capture contains annotations a panel will be shown with any annotations for the selected resource. + +As different resources are selected, the same set of annotations will be displayed if there is overlap, so for example viewing a nested entry ``custom.nested.value`` it will stay expanded if a different resource is selected which also has that annotation. + +The display is the same as for command annotations above in the Annotation Viewer. + +.. figure:: ../imgs/Screenshots/ResourceAnnotations.png + + Resource Inspector: Viewing the annotations applied to an image in the resource inspector. + +API usage +------------------- + +The annotations are provided via the :doc:`../in_application_api` as the :cpp:func:`SetObjectAnnotation` and :cpp:func:`SetCommandAnnotation` functions, the documentation page for which provides the specific API reference. + +These can be wrapped in helper functions as desired to make it easier to integrate with an application's codebase. + +.. tip:: + To explicitly remove annotations, you can set a value with ``valueType`` equal to ``eRENDERDOC_Empty`` and ``value`` equal to ``NULL``. This will delete the annotation at that path and all children. + +Annotations can be set on objects at any time. The latest contents of these annotations are saved when the capture ends and do not vary depending on the current event. This means that any modifications to object annotations during a capture will be shown, but selecting different events will not change the annotations on an object. If you need annotations that vary by event, you can use command annotations. + +Annotations on commands begin empty at the start of a capture, and are stored per-event with each event able to have a unique set of annotations. + +Vulkan and D3D12 have both queue-level and command buffer-level annotations, OpenGL and D3D11 only having one immediate level of annotations. When dealing with both queue and command buffer annotations, the queue annotations persist globally on each queue, and command buffer annotations are layered on top for the duration of that command buffer. + +Examples +^^^^^^^^ + +As a simple example of adding an annotation to an object on D3D11, assuming an ``rdoc`` pointer to the 1.7 API function structure: + +.. highlight:: c++ +.. code:: c++ + + void AnnotateImage(ID3D11Device *dev, ID3D11Texture2D *tex, ID3D11Buffer *buf) + { + // using the RDAnnotationHelper to minimise typing for simple scalar values + rdoc->SetObjectAnnotation(dev, tex, "custom.texture_flags", eRENDERDOC_Int32, 0, RDAnnotationHelper(16)); + + // referring to an object, using the temporary value structure + RENDERDOC_AnnotationValue val; + val.apiObject = (void *)buf; + rdoc->SetObjectAnnotation(dev, tex, "custom.associated_buffer", eRENDERDOC_APIObject, 0, &val); + } + +And similarly an example of adding a command annotation on Vulkan: + +.. highlight:: c++ +.. code:: c++ + + void AnnotateCommand(VkInstance inst, VkCommandBuffer cmd) + { + void *dev = RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(inst); + rdoc->SetCommandAnnotation(dev, cmd, "draw_mesh.my_property", eRENDERDOC_Int32, 0, + RDAnnotationHelper(200)); + + rdoc->SetCommandAnnotation(dev, cmd, "draw_mesh.source_name", eRENDERDOC_String, 0, + RDAnnotationHelper("Default_Model.file")); + } + +Special object properties +------------------------- + +When specifying an object, certain properties can be provided for convenience of display. With a buffer resource you can specify both ``resource`` as the API object, as well as ``resource.__offset`` and ``resource.__size`` to specify a particular sub-range of that buffer. When opening the resource from the annotation viewer or resource inspector the buffer viewer will pre-fill this particular range. + +You can also specify ``resource.__rd__format`` as a string to provide a text-based buffer format to pre-fill in the buffer viewer, for more information see :doc:`../how/how_buffer_format`. You can also specify a ``__rd_format`` annotation on an object itself as well to provide a 'default' format. + +.. note:: + + These properties and any other properties prefixed with ``__`` will not be visible normally, and will only come into effect when applied in these ways. + +Event filtering +--------------- + +The event browser filtering system also has a function for filtering based on annotations ``$annot()``. + +This function can be used to filter the visible events, based on their annotation values. For example an expression like ``$annot(foo.bar > 5)`` will only display events where the annotation ``foo.bar`` is present, and stores a number greater than 5. Expressions can also filter based on strings using ``$annot(foo.bar contains "qux")`` or regular expression matching such as ``$annot(foo.bar =~ /qu[xz])``. + +.. figure:: ../imgs/Screenshots/EventAnnotFilter.png + + Event Browser: Filtering the visible events based on an annotation. + +Python access +------------- + +Annotations on commands can be accessed via :py:attr:`renderdoc.APIEvent.annotations`, which is an optional :py:class:`~renderdoc.SDObject` object that can be accessed recursively. Helper functions like :py:meth:`~renderdoc.SDObject.FindChildByKeyPath` can be used to speed up accessing a specific annotation. + +Annotations on objects are available in a similar way through :py:attr:`renderdoc.ResourceDescription.annotations`. \ No newline at end of file diff --git a/docs/window/index.rst b/docs/window/index.rst index 8b6f1ac37..b9d85c3ce 100644 --- a/docs/window/index.rst +++ b/docs/window/index.rst @@ -2,20 +2,21 @@ Window reference ================ .. toctree:: - texture_viewer + annotation_viewer api_inspector - mesh_viewer buffer_viewer capture_attach - event_browser - settings_window - pipeline_state - shader_viewer - shader_messages - timeline_bar + capture_comments capture_connection debug_messages + event_browser + mesh_viewer + performance_counter_viewer + pipeline_state python_shell resource_inspector - performance_counter_viewer - capture_comments + settings_window + shader_messages + shader_viewer + texture_viewer + timeline_bar \ No newline at end of file diff --git a/docs/window/resource_inspector.rst b/docs/window/resource_inspector.rst index 7b68f3bd9..0629c67c4 100644 --- a/docs/window/resource_inspector.rst +++ b/docs/window/resource_inspector.rst @@ -25,6 +25,15 @@ Some resources such as textures and buffers have information available about whe In this list, each entry lists an EID range and a type of usage. +Annotations +----------- + +Resources can optionally have deep structured annotations provided by the application via the :doc:`../in_application_api`. For annotations applied to objects, they are displayed here under the key paths provided. + +For more information on the annotation system in general see the :doc:`annotation_viewer`. + +This view is hidden if there are no annotations in the capture. + Resource Initialisation Parameters ----------------------------------