Home

Awesome

GLSL Generator for DescriptorSet Indexed Types

About

This project serves as proof of concept how to simplify the usage of VK_EXT_descriptor_indexing and GL_EXT_nonuniform_qualifier within GLSL (typically used in combination with VK_NV_ray_tracing). A script generates structures and function overloads to hide the code for indexing descriptor sets of samplers and textures.

Regular GLSL

// BEFORE

// we use a big resource table for descriptorset indexing
layout(set = 0, binding=0) uniform sampler2D  res_tex2Ds[];

// let's make use of GL_EXT_buffer_reference2
layout(buffer_reference, scalar) buffer Material {
  // we want to be cache efficient 
  uint16_t albedoTex;
  uint16_t normalTex;
  ...
};

layout(push_constant, scalar) uniform inputData {
  Material materials;
};

  // example usage
  Material  mat = materials[idx];
  
  // if idx varies non-uniformly (e.g. raytracing)
  // our texture fetches can start to look pretty ugly
  
  vec4 albedo = texture(res_tex2Ds[nonuniformEXT(uint(mat.albedoTex))], uv);

After including the file generated by the script, new types are available which wrap the index. Furthermore there are many texture functions that make use of operator overloading (thanks to Jeff Bolz for the idea). This makes the code easier to write and read.

// AFTER

// where descriptorsets start that are used for indexing
#define DIT_DSET_IDX 0

// this file is generated by the lua script
#include "sampler_indexed_types.glsl"

layout(buffer_reference, scalar) buffer Material {
  // new types are available
  // for example: struct sampler2D_u16 { uint16_t idx; }
  
  sampler2D_u16 albedoTex;
  sampler2D_u16 normalTex;
  ...
};

layout(push_constant, scalar) uniform inputData {
  Material materials;
};

  // example usage
  Material  mat = materials[idx];
  
  // much nicer looking access
  vec4 albedo = texture(mat.albedoTex, uv);

How To

The project serves as proof of concept, and is expected to be customized or embedded in other languages for your own needs.

Generator

The generator operates based on the provided configuration file which can be passed from the commandline (if no argument is given it defaults to config.lua):

lua glsl_indexed_types_generator.lua myconfig.lua

In the example/ directory there is a test with generated output.

The script requires a symbol file of all builtin functions. This can be generated with:

glslangValidator --dump-builtin-symbols --target-env vulkan1.1 dummy.frag > vk_fragment.txt

Note: This commandline option requires a specific glslang feature

Limitations

The script can generate wrappers for all samplers and textures. It can cover most functions, but not all, for example textureOffsets need to be used with compile-time constants which the function overloading cannot achieve. To help this you can make use of the generated constructor functions:

... = textureOffset(c_sampler2D(myTex),...);

Currently "image" resources are not generated yet, due to the need of additional qualifiers ("writeonly" etc.).

Extensions have to be enabled explicitly prior the include using defines:

#define DIT_GL_NV_shader_texture_footprint 1'

The extension handling, however, is not fully robust at the moment, as glslang doesn't store all the necessary information in the symbol files, but does some additional parsing validation that is not covered here.