This is a new implementation of the draw manager using modern rendering practices and GPU driven culling. This only ports features that are not considered deprecated or to be removed. The old DRW API is kept working along side this new one, and does not interfeer with it. However this needed some more hacking inside the draw_view_lib.glsl. At least the create info are well separated. The reviewer might start by looking at `draw_pass_test.cc` to see the API in usage. Important files are `draw_pass.hh`, `draw_command.hh`, `draw_command_shared.hh`. In a nutshell (for a developper used to old DRW API): - `DRWShadingGroups` are replaced by `Pass<T>::Sub`. - Contrary to DRWShadingGroups, all commands recorded inside a pass or sub-pass (even binds / push_constant / uniforms) will be executed in order. - All memory is managed per object (except for Sub-Pass which are managed by their parent pass) and not from draw manager pools. So passes "can" potentially be recorded once and submitted multiple time (but this is not really encouraged for now). The only implicit link is between resource lifetime and `ResourceHandles` - Sub passes can be any level deep. - IMPORTANT: All state propagate from sub pass to subpass. There is no state stack concept anymore. Ensure the correct render state is set before drawing anything using `Pass::state_set()`. - The drawcalls now needs a `ResourceHandle` instead of an `Object *`. This is to remove any implicit dependency between `Pass` and `Manager`. This was a huge problem in old implementation since the manager did not know what to pull from the object. Now it is explicitly requested by the engine. - The pases need to be submitted to a `draw::Manager` instance which can be retrieved using `DRW_manager_get()` (for now). Internally: - All object data are stored in contiguous storage buffers. Removing a lot of complexity in the pass submission. - Draw calls are sorted and visibility tested on GPU. Making more modern culling and better instancing usage possible in the future. - Unit Tests have been added for regression testing and avoid most API breakage. - `draw::View` now contains culling data for all objects in the scene allowing caching for multiple views. - Bounding box and sphere final setup is moved to GPU. - Some global resources locations have been hardcoded to reduce complexity. What is missing: - ~~Workaround for lack of gl_BaseInstanceARB.~~ Done - ~~Object Uniform Attributes.~~ Done (Not in this patch) - Workaround for hardware supporting a maximum of 8 SSBO. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D15817
226 lines
7.1 KiB
C++
226 lines
7.1 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright 2022 Blender Foundation. */
|
|
|
|
#pragma once
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** \file
|
|
* \ingroup draw
|
|
*
|
|
* Internal Pipeline State tracking. It is higher level than GPU state as everything fits a single
|
|
* enum.
|
|
*/
|
|
|
|
/**
|
|
* DRWState is a bit-mask that stores the current render state and the desired render state. Based
|
|
* on the differences the minimum state changes can be invoked to setup the desired render state.
|
|
*
|
|
* The Write Stencil, Stencil test, Depth test and Blend state options are mutual exclusive
|
|
* therefore they aren't ordered as a bit mask.
|
|
*/
|
|
typedef enum {
|
|
/** To be used for compute passes. */
|
|
DRW_STATE_NO_DRAW = 0,
|
|
/** Write mask */
|
|
DRW_STATE_WRITE_DEPTH = (1 << 0),
|
|
DRW_STATE_WRITE_COLOR = (1 << 1),
|
|
/* Write Stencil. These options are mutual exclusive and packed into 2 bits */
|
|
DRW_STATE_WRITE_STENCIL = (1 << 2),
|
|
DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (2 << 2),
|
|
DRW_STATE_WRITE_STENCIL_SHADOW_FAIL = (3 << 2),
|
|
/** Depth test. These options are mutual exclusive and packed into 3 bits */
|
|
DRW_STATE_DEPTH_ALWAYS = (1 << 4),
|
|
DRW_STATE_DEPTH_LESS = (2 << 4),
|
|
DRW_STATE_DEPTH_LESS_EQUAL = (3 << 4),
|
|
DRW_STATE_DEPTH_EQUAL = (4 << 4),
|
|
DRW_STATE_DEPTH_GREATER = (5 << 4),
|
|
DRW_STATE_DEPTH_GREATER_EQUAL = (6 << 4),
|
|
/** Culling test */
|
|
DRW_STATE_CULL_BACK = (1 << 7),
|
|
DRW_STATE_CULL_FRONT = (1 << 8),
|
|
/** Stencil test. These options are mutually exclusive and packed into 2 bits. */
|
|
DRW_STATE_STENCIL_ALWAYS = (1 << 9),
|
|
DRW_STATE_STENCIL_EQUAL = (2 << 9),
|
|
DRW_STATE_STENCIL_NEQUAL = (3 << 9),
|
|
|
|
/** Blend state. These options are mutual exclusive and packed into 4 bits */
|
|
DRW_STATE_BLEND_ADD = (1 << 11),
|
|
/** Same as additive but let alpha accumulate without pre-multiply. */
|
|
DRW_STATE_BLEND_ADD_FULL = (2 << 11),
|
|
/** Standard alpha blending. */
|
|
DRW_STATE_BLEND_ALPHA = (3 << 11),
|
|
/** Use that if color is already pre-multiply by alpha. */
|
|
DRW_STATE_BLEND_ALPHA_PREMUL = (4 << 11),
|
|
DRW_STATE_BLEND_BACKGROUND = (5 << 11),
|
|
DRW_STATE_BLEND_OIT = (6 << 11),
|
|
DRW_STATE_BLEND_MUL = (7 << 11),
|
|
DRW_STATE_BLEND_SUB = (8 << 11),
|
|
/** Use dual source blending. WARNING: Only one color buffer allowed. */
|
|
DRW_STATE_BLEND_CUSTOM = (9 << 11),
|
|
DRW_STATE_LOGIC_INVERT = (10 << 11),
|
|
DRW_STATE_BLEND_ALPHA_UNDER_PREMUL = (11 << 11),
|
|
|
|
DRW_STATE_IN_FRONT_SELECT = (1 << 27),
|
|
DRW_STATE_SHADOW_OFFSET = (1 << 28),
|
|
DRW_STATE_CLIP_PLANES = (1 << 29),
|
|
DRW_STATE_FIRST_VERTEX_CONVENTION = (1 << 30),
|
|
/** DO NOT USE. Assumed always enabled. Only used internally. */
|
|
DRW_STATE_PROGRAM_POINT_SIZE = (1u << 31),
|
|
} DRWState;
|
|
|
|
ENUM_OPERATORS(DRWState, DRW_STATE_PROGRAM_POINT_SIZE);
|
|
|
|
#define DRW_STATE_DEFAULT \
|
|
(DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL)
|
|
#define DRW_STATE_BLEND_ENABLED \
|
|
(DRW_STATE_BLEND_ADD | DRW_STATE_BLEND_ADD_FULL | DRW_STATE_BLEND_ALPHA | \
|
|
DRW_STATE_BLEND_ALPHA_PREMUL | DRW_STATE_BLEND_BACKGROUND | DRW_STATE_BLEND_OIT | \
|
|
DRW_STATE_BLEND_MUL | DRW_STATE_BLEND_SUB | DRW_STATE_BLEND_CUSTOM | DRW_STATE_LOGIC_INVERT)
|
|
#define DRW_STATE_RASTERIZER_ENABLED \
|
|
(DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_STENCIL | \
|
|
DRW_STATE_WRITE_STENCIL_SHADOW_PASS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL)
|
|
#define DRW_STATE_DEPTH_TEST_ENABLED \
|
|
(DRW_STATE_DEPTH_ALWAYS | DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_LESS_EQUAL | \
|
|
DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER | DRW_STATE_DEPTH_GREATER_EQUAL)
|
|
#define DRW_STATE_STENCIL_TEST_ENABLED \
|
|
(DRW_STATE_STENCIL_ALWAYS | DRW_STATE_STENCIL_EQUAL | DRW_STATE_STENCIL_NEQUAL)
|
|
#define DRW_STATE_WRITE_STENCIL_ENABLED \
|
|
(DRW_STATE_WRITE_STENCIL | DRW_STATE_WRITE_STENCIL_SHADOW_PASS | \
|
|
DRW_STATE_WRITE_STENCIL_SHADOW_FAIL)
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
|
|
namespace blender::draw {
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name DRWState to GPU state conversion
|
|
* \{ */
|
|
|
|
static inline eGPUWriteMask to_write_mask(DRWState state)
|
|
{
|
|
eGPUWriteMask write_mask = GPU_WRITE_NONE;
|
|
if (state & DRW_STATE_WRITE_DEPTH) {
|
|
write_mask |= GPU_WRITE_DEPTH;
|
|
}
|
|
if (state & DRW_STATE_WRITE_COLOR) {
|
|
write_mask |= GPU_WRITE_COLOR;
|
|
}
|
|
if (state & DRW_STATE_WRITE_STENCIL_ENABLED) {
|
|
write_mask |= GPU_WRITE_STENCIL;
|
|
}
|
|
return write_mask;
|
|
}
|
|
|
|
static inline eGPUFaceCullTest to_face_cull_test(DRWState state)
|
|
{
|
|
switch (state & (DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT)) {
|
|
case DRW_STATE_CULL_BACK:
|
|
return GPU_CULL_BACK;
|
|
case DRW_STATE_CULL_FRONT:
|
|
return GPU_CULL_FRONT;
|
|
default:
|
|
return GPU_CULL_NONE;
|
|
}
|
|
}
|
|
|
|
static inline eGPUDepthTest to_depth_test(DRWState state)
|
|
{
|
|
switch (state & DRW_STATE_DEPTH_TEST_ENABLED) {
|
|
case DRW_STATE_DEPTH_LESS:
|
|
return GPU_DEPTH_LESS;
|
|
case DRW_STATE_DEPTH_LESS_EQUAL:
|
|
return GPU_DEPTH_LESS_EQUAL;
|
|
case DRW_STATE_DEPTH_EQUAL:
|
|
return GPU_DEPTH_EQUAL;
|
|
case DRW_STATE_DEPTH_GREATER:
|
|
return GPU_DEPTH_GREATER;
|
|
case DRW_STATE_DEPTH_GREATER_EQUAL:
|
|
return GPU_DEPTH_GREATER_EQUAL;
|
|
case DRW_STATE_DEPTH_ALWAYS:
|
|
return GPU_DEPTH_ALWAYS;
|
|
default:
|
|
return GPU_DEPTH_NONE;
|
|
}
|
|
}
|
|
|
|
static inline eGPUStencilOp to_stencil_op(DRWState state)
|
|
{
|
|
switch (state & DRW_STATE_WRITE_STENCIL_ENABLED) {
|
|
case DRW_STATE_WRITE_STENCIL:
|
|
return GPU_STENCIL_OP_REPLACE;
|
|
case DRW_STATE_WRITE_STENCIL_SHADOW_PASS:
|
|
return GPU_STENCIL_OP_COUNT_DEPTH_PASS;
|
|
case DRW_STATE_WRITE_STENCIL_SHADOW_FAIL:
|
|
return GPU_STENCIL_OP_COUNT_DEPTH_FAIL;
|
|
default:
|
|
return GPU_STENCIL_OP_NONE;
|
|
}
|
|
}
|
|
|
|
static inline eGPUStencilTest to_stencil_test(DRWState state)
|
|
{
|
|
switch (state & DRW_STATE_STENCIL_TEST_ENABLED) {
|
|
case DRW_STATE_STENCIL_ALWAYS:
|
|
return GPU_STENCIL_ALWAYS;
|
|
case DRW_STATE_STENCIL_EQUAL:
|
|
return GPU_STENCIL_EQUAL;
|
|
case DRW_STATE_STENCIL_NEQUAL:
|
|
return GPU_STENCIL_NEQUAL;
|
|
default:
|
|
return GPU_STENCIL_NONE;
|
|
}
|
|
}
|
|
|
|
static inline eGPUBlend to_blend(DRWState state)
|
|
{
|
|
switch (state & DRW_STATE_BLEND_ENABLED) {
|
|
case DRW_STATE_BLEND_ADD:
|
|
return GPU_BLEND_ADDITIVE;
|
|
case DRW_STATE_BLEND_ADD_FULL:
|
|
return GPU_BLEND_ADDITIVE_PREMULT;
|
|
case DRW_STATE_BLEND_ALPHA:
|
|
return GPU_BLEND_ALPHA;
|
|
case DRW_STATE_BLEND_ALPHA_PREMUL:
|
|
return GPU_BLEND_ALPHA_PREMULT;
|
|
case DRW_STATE_BLEND_BACKGROUND:
|
|
return GPU_BLEND_BACKGROUND;
|
|
case DRW_STATE_BLEND_OIT:
|
|
return GPU_BLEND_OIT;
|
|
case DRW_STATE_BLEND_MUL:
|
|
return GPU_BLEND_MULTIPLY;
|
|
case DRW_STATE_BLEND_SUB:
|
|
return GPU_BLEND_SUBTRACT;
|
|
case DRW_STATE_BLEND_CUSTOM:
|
|
return GPU_BLEND_CUSTOM;
|
|
case DRW_STATE_LOGIC_INVERT:
|
|
return GPU_BLEND_INVERT;
|
|
case DRW_STATE_BLEND_ALPHA_UNDER_PREMUL:
|
|
return GPU_BLEND_ALPHA_UNDER_PREMUL;
|
|
default:
|
|
return GPU_BLEND_NONE;
|
|
}
|
|
}
|
|
|
|
static inline eGPUProvokingVertex to_provoking_vertex(DRWState state)
|
|
{
|
|
switch (state & DRW_STATE_FIRST_VERTEX_CONVENTION) {
|
|
case DRW_STATE_FIRST_VERTEX_CONVENTION:
|
|
return GPU_VERTEX_FIRST;
|
|
default:
|
|
return GPU_VERTEX_LAST;
|
|
}
|
|
}
|
|
|
|
/** \} */
|
|
|
|
}; // namespace blender::draw
|
|
|
|
#endif
|