Files
libsst/Include/ZRenderer/ZRenderer.hpp
2026-04-03 00:22:39 -05:00

560 lines
17 KiB
C++

/*
ZRenderer.hpp
Authors: Patrick Baggett <ptbaggett@762studios.com>,
Chris Ertel <crertel@762studios.com>,
James Russell <jcrussell@762studios.com>
Created: 3/20/2011
Purpose:
Defines an interface for rendering to screen in graphics-library agnostic fashion.
License:
TODO
*/
#pragma once
#ifndef _ZRENDERER_HPP
#define _ZRENDERER_HPP
#include <ZRenderer/ZRendererBuild.hpp>
#include <SST/SST_WM.h>
#include <ZUtil/ZUtil.hpp>
#include <ZRenderer/ZDataBuffer.hpp>
#include <ZRenderer/ZRenderTarget.hpp>
#include <ZRenderer/ZFramebufferRenderTarget.hpp>
#include <ZRenderer/ZWindowRenderTarget.hpp>
#include <ZRenderer/ZTexture.hpp>
#include <ZRenderer/ZSampler.hpp>
#include <ZRenderer/ZShader.hpp>
#include <ZRenderer/ZShaderProgram.hpp>
#include <ZRenderer/ZShaderParams.hpp>
#include <ZRenderer/ZVertexParams.hpp>
#include <ZRenderer/ZIndexParams.hpp>
//Forward Declarations
class ZRenderer;
//Typedef for a frame context (opaque handle)
typedef void* ZFrameContext;
//Rendering phases the ZRenderer can exist in
enum ZRenderPhase
{
ZRP_UNINITIALIZED, //Renderer has yet to be initialized
ZRP_IDLE, //Renderer is idle (no frame contexts currently created)
ZRP_FRAME_ACCEPTING, //Renderer is accepting SubmitDrawData calls (frame contexts have been created)
ZRP_FRAME_RENDERING, //Renderer is rendering Geometry (a frame context is rendering)
ZRP_SIZE
};
//Render State Structure, used to set up a render state for SubmitDrawData calls
struct ZRenderState
{
public:
//The default constructor for render state initializes to a sane configuration
ZRenderState()
: EnableStencilTest(false),
EnableBlend(true),
SourceBlendFunc(SBFV_SRC_ALPHA),
DestBlendFunc(DBFV_ONE_MINUS_SRC_ALPHA),
blendR(0), blendG(0), blendB(0), blendA(0),
EnableCullTest(false),
EnableDepthTest(true),
DepthFunc(DFV_LESS_THAN),
EnableDepthWrite(true) { }
/////////////////////////////////
/* Draw Sort Relevant Settings */
/////////////////////////////////
// BLENDING
uint32_t EnableBlend:1; //Enables Blending
uint32_t SourceBlendFunc:4; //Specifies Source Blending Function
uint32_t DestBlendFunc:3; //Specifies Destination Blending Function
enum SourceBlendFuncValue //Values for the Source Blend Function
{
SBFV_ZERO,
SBFV_ONE,
SBFV_SRC_COLOR,
SBFV_ONE_MINUS_SRC_COLOR,
SBFV_DST_COLOR,
SBFV_ONE_MINUS_DST_COLOR,
SBFV_SRC_ALPHA,
SBFV_ONE_MINUS_SRC_ALPHA,
SBFV_DST_ALPHA,
SBFV_ONE_MINUS_DST_ALPHA,
SBFV_CONSTANT_COLOR,
SBFV_ONE_MINUS_CONSTANT_COLOR,
SBFV_CONSTANT_ALPHA,
SBFV_ONE_MINUS_CONSTANT_ALPHA,
SBFV_SRC_ALPHA_SATURATE,
SBFV_SIZE
};
enum DestBlendFuncValue //Values for the Destination Blend Function
{
DBFV_ZERO,
DBFV_ONE,
DBFV_SRC_COLOR,
DBFV_ONE_MINUS_SRC_COLOR,
DBFV_DST_COLOR,
DBFV_ONE_MINUS_DST_COLOR,
DBFV_SRC_ALPHA,
DBFV_ONE_MINUS_SRC_ALPHA,
DBFV_DST_ALPHA,
DBFV_ONE_MINUS_DST_ALPHA,
DBFV_CONSTANT_COLOR,
DBFV_ONE_MINUS_CONSTANT_COLOR,
DBFV_CONSTANT_ALPHA,
DBFV_ONE_MINUS_CONSTANT_ALPHA,
DBFV_SIZE
};
float blendR; //Red value used when blending needs a constant color
float blendG; //Green value used when blending needs a constant color
float blendB; //Blue value used when blending needs a constant color
float blendA; //Alpha value used when blending needs a constant color
// DEPTH
uint32_t EnableDepthTest:1; //Bit Enables Depth Testing
uint32_t EnableDepthWrite:1; //Sets Depth Buffer to Read Only (Depth Values are not written)
uint32_t DepthFunc:3; //Specifies Depth Function
enum DepthFuncValue //Values for the Depth Function
{
DFV_NEVER,
DFV_LESS_THAN,
DFV_EQUAL,
DFV_LESS_THAN_EQUAL,
DFV_GREATER_THAN,
DFV_NOT_EQUAL,
DFV_GREATER_THAN_EQUAL,
DFV_ALWAYS,
DFV_SIZE
};
// CULLING
uint32_t EnableCullTest:1; //Enable or disable face culling.
uint32_t CullMode:2; //Sets up front/back/both culling
enum CullModeValue
{
CMV_FRONT,
CMV_BACK,
CMV_FRONT_AND_BACK,
CMV_SIZE
};
uint32_t CullWinding:1; //Sets winding for culling
enum CullWindingValue
{
CWV_CW,
CWV_CCW,
CWV_SIZE
};
// STENCIL
uint32_t EnableStencilTest:1; //Bit Enables Stencil Testing
uint32_t StencilTestFuncFront:4; //Specifies the stencil comparisons
uint32_t StencilTestMaskFront:8; //Mask for front facing stencil post-op
uint32_t StencilTestReferenceFront:8; //Reference value for front facing stencil post-op
uint32_t StencilTestFuncBack:4; //Specifies the stencil comparisons
uint32_t StencilTestMaskBack:8; //Mask for back facing stencil post-op
uint32_t StencilTestReferenceBack:8; //Reference value for back facing stencil post-op
enum StencilComparisonsValue //Values for the stencil comparisons
{
SCV_NEVER,
SCV_ALWAYS,
SCV_LESS,
SCV_LEQUAL,
SCV_EQUAL,
SCV_GEQUAL,
SCV_GREATER,
SCV_NOTEQUAL,
SCV_SIZE
};
uint32_t StencilOpStencilFailFront:3; //Specifies the stencil operation when stencil test fails for front-facing polys
uint32_t StencilOpStencilPassDepthFailFront:3; //Specifies the stencil operation when stencil test succeeds and depth test fails fails for front-facing polys
uint32_t StencilOpStencilPassDepthPassFront:3; //Specifies the stencil operation when stencil and depth tests pass fails for front-facing polys
uint32_t StencilOpStencilFailBack:3; //Specifies the stencil operation when stencil test fails for back-facing polys
uint32_t StencilOpStencilPassDepthFailBack:3; //Specifies the stencil operation when stencil test succeeds and depth test fails for back-facing polys
uint32_t StencilOpStencilPassDepthPassBack:3; //Specifies the stencil operation when stencil and depth tests pass for back-facing polys
enum StencilOperationValue //Values for the stencil operations
{
SOV_KEEP,
SOV_ZERO,
SOV_REPLACE,
SOV_INCR,
SOV_INCR_WRAP,
SOV_DECR,
SOV_DECR_WRAP,
SOV_INVERT,
SOV_SIZE
};
};
class ZRenderer : public ZThread
{
protected:
//Default Constructor
ZRenderer() : ZThread("ZRenderer Thread") { }
public:
//Virtual Destructor
virtual ~ZRenderer() { }
//////////////////////////
/* Lifecycle Operations */
//////////////////////////
/*
virtual public ZRenderer::Init
Initializes the Renderer for use as a long running subsystem. After this call, the
render thread will be running.
@return (bool)
@context (all)
*/
virtual bool Init() = 0;
/*
virtual public ZRenderer::Shutdown
Shuts down the system and stops the render thread.
@return (void)
@context (all)
*/
virtual void Shutdown() = 0;
///////////////////////////
/* Renderer Data Getters */
///////////////////////////
/*
virtual public ZRenderer::GetCapabilities
Returns a map describing the capabilities and configuration of this renderer. All
renderer implementations must map the following keys:
gl { directx, opengl }
gl.version { 9.0c, 10.0, 10.1, 11.0, 11.1, 2.1, 3.1, 3.2, 3.3 ... }
: version number should always have major.minor format and should be the highest version required
gl.shaderlang { hlsl_40, hlsl_30, hlsl, glsl_14, glsl_13, glsl_12, glsl_11, glsl, ... }
: shading languages accepted should be listed in a comma separated list in order of preference
data_buffer.block_alignment { integer }
: alignment requirement for buffer blocks
frame_buffer_render_target.max_color_attachments { integer }
: maximum number of color buffer attachments
Other keys may be supported depending upon the implementation.
@return (const ZHashMap<ZString, ZString>&) - map of capabilities
@context (all)
*/
virtual const ZHashMap<ZString, ZString>& GetCapabilities() = 0;
/*
virtual public ZRenderer::GetRenderPhase
Gets the current rendering phase.
@return (ZRenderPhase) - current rendering phase
@context (all)
*/
virtual ZRenderPhase GetRenderPhase() = 0;
//////////////////////////
/* Logistics Operations */
//////////////////////////
/*
virtual public ZRenderer::CreateDataBuffer
Creates a data buffer which contains data stored in graphics memory. The data
buffer is created but not initialized with values (use FillBuffer or MapBuffer).
Keep in mind when allocating a buffer that defines block data that determining the
required size to fit all blocks includes taking into account alignment requirements.
The alignment requirement for block data for this renderer can be determined through
the capabilities map with key 'buffer.block_alignment'.
@param _type - the type of buffer to allocate
@param _usage - the usage pattern the buffer will follow
@param _size - the size (in bytes) to allocate
@return (ZDataBuffer) - new data buffer object, NULL if not successful
@context (all)
*/
virtual ZPtr<ZDataBuffer> CreateDataBuffer(ZDataBufferType _type,
ZDataBufferUsage _usage,
size_t _size
) = 0;
/*
virtual public ZRenderer::CreateDrawParams
Creates a draw parameters binding class, which is provided to the draw calls and
is used to bind data to shader variables.
@param _type - the type of draw parameters binding
@return (ZPtr<ZDrawParams>) - new draw parameters object, NULL if not successful
@context (all)
*/
virtual ZPtr<ZDrawParams> CreateDrawParams(ZDrawParamsType _type) = 0;
/*
virtual public ZRenderer::CreateFrameBufferRenderTarget
Function to create a framebuffer-backed render target.
@param _width - number of pixels wide to make the frame buffer
@param _height - number of pixels tall to make the frame buffer
@return (ZPtr<ZFramebufferRenderTarget>) - new frame buffer render target, NULL if not successful
@context (all)
*/
virtual ZPtr<ZFramebufferRenderTarget> CreateFrameBufferRenderTarget(size_t _width, size_t _height) = 0;
/*
virtual public ZRenderer::CreateRenderBuffer
Function to create a render buffer for use in a frame buffer render target.
@param _type - the type of render buffer this will be
@param _width - number of pixels wide to make the render buffer
@param _height - number of pixels tall to make the render buffer
@return (ZPtr<ZRenderBuffer>) - new render buffer, NULL if not successful
@context (all)
*/
virtual ZPtr<ZRenderBuffer> CreateRenderBuffer(ZRenderBufferType _type, size_t _width, size_t _height) = 0;
/*
virtual public ZRenderer::CreateSampler
Creates a sampler object to use as a view onto a texture.
@return (ZPtr<ZSampler>) - new sampler object, NULL if unsuccessful
@context (all)
*/
virtual ZPtr<ZSampler> CreateSampler() = 0;
/*
virtual public ZRenderer::CreateShader
Function to create a shader object for the renderer.
@param _type - type of shader to create:
ZST_SOFT : Soft shaders
ZST_VERTEX : Vertex shaders
ZST_HULL : Hull shaders
ZST_DOMAIN : Domain shaders
ZST_GEOMETRY: Geometry shaders
ZST_FRAGMENT: Fragment (pixel) shaders
@return (ZPtr<ZShader>) - the created shader, NULL if not successful
@context (all)
*/
virtual ZPtr<ZShader> CreateShader(ZShaderType _type) = 0;
/*
virtual public ZRenderer::CreateShaderProgram
Function to create a shader program.
@return (ZPtr<ZShaderProgram>) - new shader program, NULL if not successful
@context (all)
*/
virtual ZPtr<ZShaderProgram> CreateShaderProgram() = 0;
/*
virtual public ZRenderer::CreateTexture
Creates a texture object.
In the case of cube map textures, the bitmap format describes a single 'side'
of the cube map texture.
If the bitmap provided has NULL for data, then the texture storage is initialized
but no data is copied.
@param _type - the type of texture
@param _format - the texture internal storage format
@param _usage - the usage type of the texture
@param _bitmap - bitmap structure containing image format and size, as well as data (can be NULL)
@param _generateMipmaps - indicating whether or not we should generate mipmaps
@return (ZPtr<ZTexture>) - new texture object, NULL if not successful
@context (all)
*/
virtual ZPtr<ZTexture> CreateTexture(ZTextureType _type,
ZTextureFormat _format,
ZTextureUsage _usage,
const ZBitmap& _bitmap,
bool _generateMipmaps) = 0;
/*
virtual public ZRenderer::CreateWindowRenderTarget
Creates a window render target.
@param _window - the window handle (created using libsst-wm)
@param _screenIndex - the screen index bound to the window
@return (ZPtr<ZRenderTarget>) - new window render target, NULL if not successful
@context (all)
*/
virtual ZPtr<ZRenderTarget> CreateWindowRenderTarget(SST_Window _window,
size_t _screenIndex
) = 0;
////////////////////////
/* Frame Data Getters */
////////////////////////
/*
virtual public ZRenderer::GetFrameRenderTarget
Gets the render target set for the given frame context.
@param _frameContext - frame context
@return (ZRenderTarget*) - the render target for the given context
@context (all)
*/
virtual ZRenderTarget* GetFrameRenderTarget(ZFrameContext _frameContext) = 0;
//////////////////////////
/* Rendering Operations */
//////////////////////////
/*
The renderer can maintain a few different states, each of which is described by an enumeration. The various
rendering operations affect this state, and thread synchronization calls such as WaitFrameStart and WaitFrameEnd
will wait until events are triggered after state changes, as follows.
BeginFrame()
| SubmitDrawData()
| | RenderFrame()
| +-------+-------+ |
| | | | |
---------------+---+-------+-------+---+-----------------------+---------------
===============|///////////////////////|///////////////////////|===============
ZRP_IDLE ... =|/ ZRP_FRAME_ACCEPTING /|/ ZRP_FRAME_RENDERING /|= ZRP_IDLE ...
===============|///////////////////////|///////////////////////|===============
| |
+-> WaitFrameStart() +-> WaitFrameEnd()
^ |
| Frame to Render? |
+<----------------------+
Because of the multi threaded nature of ZRenderer, multiple threads can call SubmitDrawData to populate
the render lists full of buffered data to draw. A single call should be placed to BeginFrame for each
frame context that is desired, and a single call to RenderFrame should occur for each frame context that has
been created.
It is guaranteed that order will be maintained between calls to RenderFrame, meaning if RenderFrame is called
for frame context 0, and then afterwards RenderFrame is called for frame context 1, frame context 0 is guaranteed
to render in its entirety before frame context 0 is rendered.
*/
/*
virtual public ZRenderer::BeginFrame
Tells the renderer that threads will begin providing draw data for a frame of rendering. The value returned
is later used as a frame context for render calls.
BeginFrame can be called multiple times, each time returning a new frame context that can be provided
for draw calls.
BeginFrame should be called once for as many frame contexts there will be before beginning render calls
for any of them. Calling BeginFrame after other frames have begun rendering results in undefined
behavior. Frame contexts should never be re-used across multiple render cycles - always ask for a new one.
@param _canvas - the canvas to render to
@return (ZFrameContext) - the frame context that has been created
@context (all)
*/
virtual ZFrameContext BeginFrame(ZPtr<ZRenderTarget> _canvas) = 0;
/*
virtual public ZRenderer::EndFrame
TODO
@param _frameContext - the frame context we are done submitting draw data to
@return (void)
@context (all)
*/
virtual void EndFrame(ZFrameContext _frameContext) = 0;
/*
virtual public ZRenderer::SubmitDrawData
Draws geometry defined in a DataBuffer (Queues them up for rendering).
@param _frameContext - the frame context to provide data for
@param _shaderProgram - the shader program to draw with
@param _shaderParams - the shader parameters binding
@param _vertexParams - the vertex parameters binding
@param _indexParams - the index parameters binding
@param _renderState - the render state to render the geometry with
@param _drawGroup - the draw group to render this call with; objects with lower draw group
are rendered before objects with higher draw group
@return (void)
@context (all)
*/
virtual void SubmitDrawData(ZFrameContext _frameContext,
ZPtr<ZShaderProgram> _shaderProgram,
ZPtr<ZShaderParams> _shaderParams,
ZPtr<ZVertexParams> _vertexParams,
ZPtr<ZIndexParams> _indexParams,
const ZRenderState& _renderState,
int _drawGroup = 0
) = 0;
/*
virtual public ZRenderer::RenderFrame
Renders the frame context.
@param _frameContext - the frame context to render
@return (void)
@context (all)
*/
virtual void RenderFrame(ZFrameContext _frameContext) = 0;
/*
virtual public ZRenderer::WaitFrameStart
Calling thread waits until RenderFrame is called for the given frame context.
@param _frameContext - the frame context to wait for
@return (void)
@context (all)
*/
virtual void WaitFrameStart(ZFrameContext _frameContext) = 0;
/*
virtual public ZRenderer::WaitFrameEnd
Calling thread waits until after the render thread has finished rendering a frame.
@param _frameContext - the frame context to wait for
@return (void)
@context (all)
*/
virtual void WaitFrameEnd(ZFrameContext _frameContext) = 0;
};
#endif