Skip to content

Render Target Concept

Stefan Zellmann edited this page Sep 11, 2017 · 13 revisions

Content of this page: This page describes the render target concept.

Note that the current version of Visionaray is an early preview. At this stage, the framework, including the API, are likely to undergo frequent changes.

Rationale

Render targets provide abstract storage for color and depth images resulting from ray tracing. Color and depth images have a consecutive storage representation that is compatible with C++ random access iterator semantics. Render targets may optionally provide means to display those images to the screen. Render targets interoperate with schedulers to provide an abstract interface to the hardware. While schedulers allow for kernel execution on multi-threaded hardware or on an accelerator, render targets provide cross-platform means to store, access, and display ray tracing results.

Interface

Visionaray comes with a number of built-in render targets. Visionaray's schedulers are however also compatible with user-provided render targets, as far as the data region they manage is accessible to the execution model implemented by the scheduler (CUDA-compatible schedulers may e.g. only access memory regions that were allocated using the CUDA runtime API). In order for a class to implement the render target concept, it must provide the following public interface.

class CustomRenderTarget
{
public:

    //-----------------------------------------------------

    // Types.

    // Render target reference type.
    // CF := color format
    // DF := depth format
    // See the section on pixel format constants
    // below for a list of supported formats.
    typedef render_target_ref<CF, DF> ref_type;

    // Type that can store a single color value.
    // Can e.g. be determined from CF through
    // pixel_traits (see below).
    typedef <...> color_type;

    // Type that can store a single depth value.
    // Can e.g. be determined from DF through
    // pixel_traits (see below).
    typedef <...> depth_type;

    //-----------------------------------------------------

    // Public functions.

    // Return the width in pixels of the color and depth
    // images stored by the render target.
    int width() const;

    // Return the height in pixels of the color and depth
    // images stored by the render target.
    int height() const;

    // Resize the color and depth images stored by the
    // render target.
    void resize(int w, int h);

    // Return a pointer to the first element of the color
    // buffer.
    color_type color();

    // Return a pointer to the first element of the depth
    // buffer.
    depth_type depth();

    // Return a lightweight reference to the render target.
    // The template render_target_ref<> stores unmanaged
    // pointers to the color buffer and the depth buffer.
    // Refs are used to share render targets between
    // contexts, e.g. between a CUDA host program and a
    // CUDA Visionaray kernel executed using cuda_sched.
    ref_type ref();

    // Set each element of the color buffer to color.
    // color is specified in the PF_RGBA32F format
    // (clamped [0..1] 32-bit floating point RGBA).
    // Convert if necessary.
    void clear_color_buffer(vec4 color = vec4(0,0,0,0));

    // Set each element of the depth buffer to depth.
    // depth is specified in the PF_DEPTH32F format
    // (clamped [0..1] 32-bit floating point).
    // Convert if necessary.
    void clear_color_buffer(float color = 1.0f);

    // Perform actions before a frame is rendered.
    // (Provide an empty implementation if not
    // applicable.)
    void begin_frame();

    // Perform actions after a frame was rendered.
    // (Provide an empty implementation if not
    // applicable.)
    void end_frame();

    //-----------------------------------------------------

    // Optional functions.

    // Display the color buffer to the screen.
    void display_color_buffer() const;
};

Visionaray render targets store color and depth images whose type is identified by pixel format constants (see the section on pixel formats for a list of applicable values). Pixel format constants and their corresponding pixel formats have a storage type defined with them, that can be deduced by using the traits class template pixel_traits in the following way.

//---------------------------------------------------------

// Deduce C++ type for storing PF_RGBA32F colors.
typedef typename pixel_traits<PF_RGBA32F>::type color_type;

// Deduce C++ type for storing PF_DEPTH32F values.
typedef typename pixel_traits<PF_DEPTH32F>::type depth_type;


//---------------------------------------------------------

// color_type is vec4
static_assert(std::is_same<color_type, vec4>::value, "...");

// depth_type is float
static_assert(std::is_same<depth_type, float>::value, "...");

In the case that the depth format constant has the value PF_UNSPECIFIED, the render target does not manage storage for a depth buffer, the corresponding call to depth() should return a nullptr in this case.

Render Target References

Render target references provide lightweight access to the buffers managed by the render target itself. Such lightweight access is e.g. necessary when passing pointers to the color and depth buffer from a host program to a CUDA kernel, or when the render target manages distributed memory. The class template render_target_ref<ColorFormatConstant, DepthFormatConstant> is used for referencing render targets. It is a lightweight object that just stores the width and height of the render target images in pixels, as well as pointers to the color and depth images. Custom render targets must implement a function ref() that returns an initialized render_target_ref.

Frame Rendering

Render targets may require custom state being set up before being able to store color and depth values to their buffers. In order to initialize and uninitialize this state, the functions begin_frame() and end_frame() may be used. Since these functions are called internally by Visionaray's built-in schedulers, implementations must be provided but may be left empty in case that custom state is not required.

Render targets will populate the color and depth buffer based on the pixel sampler type (TODO: link) that is associated with them. Depending on the pixel sampler type, the color and depth buffer may either be overwritten, or incoming color and depth values may be blended on top of the buffers. It is the application programmer's responsibility to clear the buffers appropriately with the functions clear_color_buffer() (taking a clamped RGBA color in PF_RGBA32F format) and clear_depth_buffer() (taking a clamped depth value in 32-bit floating point format).

NOTE: clear_color_buffer() and clear_depth_buffer() may not be called in between calls to begin_frame() and end_frame().

List of Pixel Format Constants

The following pixel format constants for colors are currently supported by Visionaray render targets.

PF_RGB8 [red|green|blue] integer values in the range from [0..255] stored with 8-bit precision.

C++ type: vector<3, unorm< 8>>.
PF_RGBA8 [red|green|blue|alpha] integer values in the range from [0..255] stored with 8-bit precision.

C++ type: vector<4, unorm< 8>>.
PF_RGB32F Clamped [red|green|blue] values stored with 32-bit floating point precision, clamped to the interval [0.0..1.0].

C++ type: vec3.
PF_RGBA32F Clamped [red|green|blue|alpha] values stored with 32-bit floating point precision, clamped to the interval [0.0..1.0].

C++ type: vec4.

The following pixel format constants for depth values are currently supported by Visionaray render targets.

PF_DEPTH24_STENCIL8 Packed depth (24-bit) and stencil buffer (8-bit) value. The stencil buffer bits are ignored by the built-in render targets.

C++ type: unsigned int.
PF_DEPTH32F Clamped depth value stored with 32-bit floating point precision, clamped to the interval [0.0..1.0].

C++ type: float.
PF_UNSPECIFIED Unspecified depth type.

C++ type: [empty].