Skip to content

Graphics Library FAQ

harrand edited this page Sep 22, 2023 · 1 revision

Frequently Asked Questions

Why do I get a white-screen/vulkan validation error in a trivial topaz program?

If you are beginning and ending frames while the render graph is empty, you will run into these problems.

If you're sure you don't want to do any rendering, then you can disable graphics entirely when initialising the engine:

tz::initialise({.flags = {tz::application_flag::no_graphics}});
{
    // program...
}
tz::terminate();

My program looks/works different with the OpenGL backend compared to the Vulkan backend, why is that?

Every effort has been made to ensure that tz::gl acts consistently between different backends as much as possible. However, here are some reasons which could cause discrepancies:

  • Your machine might not support the OpenGL extension ARB_bindless_texture. This means that Image Resources may not work correctly, leading to untextured draws. Warnings should be printed if this is the case (on debug builds).
  • You may be relying on something that is prohibited in one graphics API but not the other. For example, in OpenGL, a Buffer Resource with dynamic access can have size zero. For static access resources that is not the case, nor is it the case with any buffers at all in Vulkan. An exhaustive list of these discrepancies is unfortunately not yet available. If you think a discrepancy might be down to a bug in the engine, please consider submitting a bug report - its easy!

How do I render into a texture?

To render into a texture, you will need:

  • Two renderers. One that will render into the texture (which we call the producer), and one that will actually use the texture in some way (which we will call the consumer).
  • Basic information about the texture (e.g its format, dimensions etc...) before the renderers are created. The process is as follows:
  1. Add an image resource to the tz::gl::renderer_info that will go on to spawn the consumer renderer. Keep ahold of the resource handle.
  2. Create the consumer renderer, and retrieve the image component using the handle.
  3. Create a tz::gl::image_output with a single colour component - the aforementioned image component.
  4. Set the output of the producer's tz::gl::renderer_info to be the newly-created image_output.
  5. Create the producer renderer.
  6. Ensure that both renderers are in the render-graph, and also ensure that the consumer renderer depends on the producer renderer.

Example

tz::gl::renderer_info consumer_info;
// populate consumer_info with lots of cool features...
// 1
tz::gl::resource_handle render_to_textureh = consumer_info.add_resource(
    tz::gl::image_resource::from_uninitialised({/*...image dimensions/flags/format goes here*/})
);

// 2
tz::gl::renderer_handle consumerh = tz::gl::get_device().create_renderer(consumer_info);

tz::gl::icomponent* render_to_texture_component = tz::gl::get_device().get_renderer(consumerh).get_component(render_to_textureh);
// 3
tz::gl::image_output out
{{
    .colours = {render_to_texture_component}
}};

tz::gl::renderer_info producer_info;
// populate producer info with lots of cool features...
// 4
producer_info.set_output(out);

// 5
tz::gl::renderer_handle producerh = tz::gl::get_device().create_renderer(producer_info);

// 6
tz::gl::get_device().render_graph().timeline = {producer, consumer};
tz::gl::get_device().render_graph().add_dependencies(consumer, producer);

How do I enable/disable culling?

Unfortunately, this feature does not yet exist, even though its pretty basic functionality. It is planned, but feel free to create a feature request if you're blocked by it.

How do I change the clear-colour of a graphics renderer?

You will need to perform a renderer edit:

  1. Express the new clear colour as a tz::vec4, representing normalised RGBA floats.
  2. Retrieve the underlying renderer object.
  3. Perform a render_state renderer edit, passing in the new clear colour.

Example

#include "tz/gl/device.hpp"
#include "tz/gl/renderer.hpp"

tz::vec4 new_colour{0.0f, 1.0f, 0.5f, 1.0f};
tz::gl::renderer& r = tz::gl::get_device().get_renderer(my_renderer_handle);
r.edit
(
    tz::gl::RendererEditBuilder{}
    .render_state
    ({
        .clear_colour = new_colour
    })
);

How do I change the launched workgroup sizes for a compute renderer (i.e compute kernel)?

You will need to perform a renderer edit:

  1. Express the new kernel dimensions as a tz::vec3ui - comprised of 32-bit unsigned integers XYZ.
  2. Retrieve the underlying renderer object.
  3. Perform a compute renderer edit, passing in the new kernel.

Example

#include "tz/gl/device.hpp"
#include "tz/gl/renderer.hpp"

tz::vec3ui new_kernel{32u, 64u, 32u};
tz::gl::renderer& r = tz::gl::get_device().get_renderer(my_renderer_handle);
r.edit
(
    tz::gl::RendererEditBuilder{}
    .compute
    ({
        .kernel = new_kernel
    })
);