VPP  0.8
A high-level modern C++ API for Vulkan
vpp::inUniformBuffer Class Reference

Binding point class for uniform (read-only) data input to shaders. Place in your pipeline configuration class to declare a uniform data source. More...

#include <vppLangIntUniform.hpp>

Public Member Functions

 inUniformBuffer (std::uint32_t set=0, int binding=-1)
 Creates the binding point. More...
 
auto operator= (const UniformBufferView &value)
 Binds a buffer to the binding point. More...
 

Detailed Description

Binding point class for uniform (read-only) data input to shaders. Place in your pipeline configuration class to declare a uniform data source.

This class should be used only to define a binding point inside your custom pipeline configuration (a PipelineConfig or ComputePipelineConfig subclass).

There are the following steps to consider when using uniform buffers within pipeline config:

  • Definition of data structure to be stored within the buffer. Either use UniformStruct template for that, or assume the buffer is an array of simple objects: scalars, vectors or matrices. In second case, separate definition is not needed.
  • Declaration of binding point inside PipelineConfig (or ComputePipelineConfig) derived class. It can be private member.
  • Supplying actual data buffer on CPU side. For that end, write a helper method in your derved class to bind supplied buffers to declared binding points. the method should accept a UniformBufferView reference for each buffer. It should also get a pointer to ShaderDataBlock, because at this stage the bindings are only remembered inside ShaderDataBlock. The block is later selected as a whole into rendering pipeline and subsequent draw commands will act on supplied data buffers.
  • Reading the data in a shader on the GPU side. All shader types can read uniform buffers. This is being done by means of accessor object declared within the shader. Declare UniformVar object for a buffer (or multiple buffers in arrayOf) containing single structure. Use UniformArray instead for buffers containing multiple structures. Finally, use UniformSimpleArray for buffers containing multiple simple objects. To read particular data field or value, use indexing operators provided by the accessor object.

Example:

// define data structure for the buffer
template< ETag TAG >
struct TMyBufferStructure : public UniformStruct< TAG, TMyBufferStructure >
{
UniformFld< TAG, glm::mat4 > m_matrixField;
UniformFld< TAG, glm::vec4 > m_vectorField;
// ...
};
// it is convenient to make these typedefs
typedef TMyBufferStructure< vpp::CPU > CMyBufferStructure;
typedef TMyBufferStructure< vpp::GPU > GMyBufferStructure;
class MyPipelineConfig : public vpp::PipelineConfig
{
// defines the binding point - assume it contains TMyBufferStructure entries
vpp::inUniformBuffer m_inUniformBuffer;
// another binding point - assume it contains simple array of floats
vpp::inUniformBuffer m_inUniformBuffer2;
// This binds actual buffers to binding points.
// The binding is stored within ShaderDataBlock object.
// Later, the ShaderDataBlock must be selected into the rendering pipeline
// by calling its bind() function from your rendering (Process) sequence.
// As arguments to the function, you can directly provide \ref gvector
// references, as UniformBufferView has a constructor accepting \ref gvector
// objects.
void bindDataBuffers (
vpp::ShaderDataBlock* pDataBlock )
{
pDataBlock->update ((
m_inUniformBuffer = buf1,
m_inUniformBuffer2 = buf2
));
}
void fVertexShader ( vpp::VertexShader* pShader )
{
using namespace vpp;
// Accessing a buffer containing single structure.
varUniformBuffer ( m_inUniformBuffer );
Mat4 m1 = varUniformBuffer [ & GMyBufferStructure::m_matrixField ];
// Accessing a buffer containing array of structures.
varUniformBufferArr ( m_inUniformBuffer );
Int arrayIdx = ...; // compute array index
Mat4 m2 = varUniformBufferArr [ arrayIdx ][ & GMyBufferStructure::m_matrixField ];
// Accessing a buffer containing array of scalars.
varUniformBufferSimpleArr ( m_inUniformBuffer2 );
Int arrayIdx = ...; // compute array index
Float fv = varUniformBufferSimpleArr [ arrayIdx ];
}
};

Constructor & Destructor Documentation

◆ inUniformBuffer()

vpp::inUniformBuffer::inUniformBuffer ( std::uint32_t  set = 0,
int  binding = -1 
)

Creates the binding point.

Typically you do not need to specify any arguments for the constructor.

Optionally you can force the set and binding index. This feature may be useful if you need to interface VPP binding point with externally supplied shader (written in GLSL and compiled externally to SPIR-V blob).

Member Function Documentation

◆ operator=()

auto vpp::inUniformBuffer::operator= ( const UniformBufferView value)

Binds a buffer to the binding point.

Accepts single argument which is generic buffer abstraction represented by UniformBufferView object. Usually just use gvector object in that place (it will be automatically cast to UniformBufferView). Alternatively, any Vulkan uniform buffer bound to memory may be used.

Calling this operator does not bind the buffer immediately. It only generates an entry inside ShaderDataBlock. The operator returns an opaque value that must be supplied to ShaderDataBlock::update method. Several buffers can be bound at once. The binding will actually occur when the ShaderDataBlock is selected in the rendering pipeline.

Example:

class MyPipelineConfig : public vpp::PipelineConfig
{
vpp::inUniformBuffer m_inUniformBuffer;
vpp::inUniformBuffer m_inUniformBuffer2;
void bindDataBuffers (
vpp::ShaderDataBlock* pDataBlock )
{
// Note that multiple bindings may occur simultaneously.
// Also note that we use double parentheses, because this is
// a list constructed with overloaded comma operator, not multiple
// arguments.
pDataBlock->update ((
m_inUniformBuffer = buf1,
m_inUniformBuffer2 = buf2
));
}
};
// later, when defining a render graph (irrelevant details not shown):
void initializeRenderGraph ( ... )
{
// Here fill the data block.
m_myPipelineConfig.bindDataBuffers ( myBuffer0, myBuffer1, & m_dataBlock );
// m_render is a Process node
m_renderGraph.m_render << [ this ]()
{
// this lambda routine defines a rendering sequence (render pass)
// select current pipeline
m_renderPass.pipeline ( 0, 0 ).cmdBind();
// bind the data block
m_dataBlock.cmdBind();
m_renderGraph.cmdDraw ( ... );
// You can select a different block (or pipeline) now and draw again.
};
}

The documentation for this class was generated from the following file: