vulkan: Add a common data structure for dynamic states

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17328>
This commit is contained in:
Jason Ekstrand 2022-06-29 18:26:05 -05:00 committed by Marge Bot
parent 09188c9659
commit fcedb1250b
3 changed files with 667 additions and 0 deletions

View File

@ -82,6 +82,32 @@ together but store the final state on the stack for immediate consumption:
.. doxygenfunction:: vk_graphics_pipeline_state_merge
Dynamic state
-------------
All dynamic states in Vulkan, regardless of which API version or extension
introduced them, are represented by the
:cpp:enum:`mesa_vk_dynamic_graphics_state` enum. This corresponds to the
:cpp:type:`VkDynamicState` enum in the Vulkan API only it's compact (has no
holes due to extension namespacing) and a bit better organized. Each
enumerant is named with the name of the state group to which the dynamic
state belongs as well as the name of the dynamic state itself. The fact
that it's compact allows us to use to index bitsets.
.. doxygenfunction:: vk_get_dynamic_graphics_states
We also provide a :cpp:struct:`vk_dynamic_graphics_state` structure which
contains all the dynamic graphics states, regardless of which API version
or extension introduced them. This structure can be populated from a
:cpp:struct:`vk_graphics_pipeline_state` via
:cpp:func:`vk_dynamic_graphics_state_init`.
.. doxygenfunction:: vk_dynamic_graphics_state_init
.. doxygenfunction:: vk_dynamic_graphics_state_copy
Reference
---------
@ -133,3 +159,7 @@ Reference
.. doxygenstruct:: vk_render_pass_state
:members:
.. doxygenenum:: mesa_vk_dynamic_graphics_state
.. doxygenstruct:: vk_dynamic_graphics_state
:members:

View File

@ -180,6 +180,9 @@ vk_get_dynamic_graphics_states(BITSET_WORD *dynamic,
#define IS_DYNAMIC(STATE) \
BITSET_TEST(dynamic, MESA_VK_DYNAMIC_##STATE)
#define IS_NEEDED(STATE) \
BITSET_TEST(needed, MESA_VK_DYNAMIC_##STATE)
static void
vk_vertex_input_state_init(struct vk_vertex_input_state *vi,
const BITSET_WORD *dynamic,
@ -236,6 +239,24 @@ vk_vertex_input_state_init(struct vk_vertex_input_state *vi,
}
}
static void
vk_dynamic_graphics_state_init_vi(struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_vertex_input_state *vi)
{
if (IS_NEEDED(VI))
*dst->vi = *vi;
if (IS_NEEDED(VI_BINDING_STRIDES)) {
for (uint32_t b = 0; b < MESA_VK_MAX_VERTEX_BINDINGS; b++) {
if (vi->bindings_valid & BITFIELD_BIT(b))
dst->vi_binding_strides[b] = vi->bindings[b].stride;
else
dst->vi_binding_strides[b] = 0;
}
}
}
static void
vk_input_assembly_state_init(struct vk_input_assembly_state *ia,
const BITSET_WORD *dynamic,
@ -251,6 +272,14 @@ vk_input_assembly_state_init(struct vk_input_assembly_state *ia,
ia->primitive_restart_enable = ia_info->primitiveRestartEnable;
}
static void
vk_dynamic_graphics_state_init_ia(struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_input_assembly_state *ia)
{
dst->ia = *ia;
}
static void
vk_tessellation_state_init(struct vk_tessellation_state *ts,
const BITSET_WORD *dynamic,
@ -274,6 +303,14 @@ vk_tessellation_state_init(struct vk_tessellation_state *ts,
}
}
static void
vk_dynamic_graphics_state_init_ts(struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_tessellation_state *ts)
{
dst->ts.patch_control_points = ts->patch_control_points;
}
static void
vk_viewport_state_init(struct vk_viewport_state *vp,
const BITSET_WORD *dynamic,
@ -310,6 +347,20 @@ vk_viewport_state_init(struct vk_viewport_state *vp,
vp->negative_one_to_one = vp_dcc_info->negativeOneToOne;
}
static void
vk_dynamic_graphics_state_init_vp(struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_viewport_state *vp)
{
dst->vp.viewport_count = vp->viewport_count;
if (IS_NEEDED(VP_VIEWPORTS))
typed_memcpy(dst->vp.viewports, vp->viewports, vp->viewport_count);
dst->vp.scissor_count = vp->scissor_count;
if (IS_NEEDED(VP_SCISSORS))
typed_memcpy(dst->vp.scissors, vp->scissors, vp->scissor_count);
}
static void
vk_discard_rectangles_state_init(struct vk_discard_rectangles_state *dr,
const BITSET_WORD *dynamic,
@ -330,6 +381,15 @@ vk_discard_rectangles_state_init(struct vk_discard_rectangles_state *dr,
}
}
static void
vk_dynamic_graphics_state_init_dr(struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_discard_rectangles_state *dr)
{
dst->dr.rectangle_count = dr->rectangle_count;
typed_memcpy(dst->dr.rectangles, dr->rectangles, dr->rectangle_count);
}
static void
vk_rasterization_state_init(struct vk_rasterization_state *rs,
const BITSET_WORD *dynamic,
@ -427,6 +487,23 @@ vk_rasterization_state_init(struct vk_rasterization_state *rs,
}
}
static void
vk_dynamic_graphics_state_init_rs(struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_rasterization_state *rs)
{
dst->rs.rasterizer_discard_enable = rs->rasterizer_discard_enable;
dst->rs.cull_mode = rs->cull_mode;
dst->rs.front_face = rs->front_face;
dst->rs.depth_bias.enable = rs->depth_bias.enable;
dst->rs.depth_bias.constant = rs->depth_bias.constant;
dst->rs.depth_bias.clamp = rs->depth_bias.clamp;
dst->rs.depth_bias.slope = rs->depth_bias.slope;
dst->rs.line.width = rs->line.width;
dst->rs.line.stipple.factor = rs->line.stipple.factor;
dst->rs.line.stipple.pattern = rs->line.stipple.pattern;
}
static void
vk_fragment_shading_rate_state_init(
struct vk_fragment_shading_rate_state *fsr,
@ -444,6 +521,15 @@ vk_fragment_shading_rate_state_init(
}
}
static void
vk_dynamic_graphics_state_init_fsr(
struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_fragment_shading_rate_state *fsr)
{
dst->fsr = *fsr;
}
static void
vk_sample_locations_state_init(struct vk_sample_locations_state *sl,
const VkSampleLocationsInfoEXT *sl_info)
@ -529,6 +615,15 @@ vk_multisample_sample_locations_state_init(
}
}
static void
vk_dynamic_graphics_state_init_ms(struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_multisample_state *ms)
{
if (IS_NEEDED(MS_SAMPLE_LOCATIONS))
*dst->ms.sample_locations = *ms->sample_locations;
}
static void
vk_stencil_test_face_state_init(struct vk_stencil_test_face_state *face,
const VkStencilOpState *info)
@ -561,6 +656,14 @@ vk_depth_stencil_state_init(struct vk_depth_stencil_state *ds,
vk_stencil_test_face_state_init(&ds->stencil.back, &ds_info->back);
}
static void
vk_dynamic_graphics_state_init_ds(struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_depth_stencil_state *ds)
{
dst->ds = *ds;
}
static void
vk_color_blend_state_init(struct vk_color_blend_state *cb,
const BITSET_WORD *dynamic,
@ -605,6 +708,18 @@ vk_color_blend_state_init(struct vk_color_blend_state *cb,
}
}
static void
vk_dynamic_graphics_state_init_cb(struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_color_blend_state *cb)
{
dst->cb.logic_op = cb->logic_op;
dst->cb.color_write_enables = cb->color_write_enables;
if (IS_NEEDED(CB_BLEND_CONSTANTS))
typed_memcpy(dst->cb.blend_constants, cb->blend_constants, 4);
}
static bool
vk_render_pass_state_is_complete(const struct vk_render_pass_state *rp)
{
@ -696,6 +811,12 @@ vk_render_pass_state_init(struct vk_render_pass_state *rp,
}
}
static void
vk_dynamic_graphics_state_init_rp(struct vk_dynamic_graphics_state *dst,
const BITSET_WORD *needed,
const struct vk_render_pass_state *rp)
{ }
#define FOREACH_STATE_GROUP(f) \
f(MESA_VK_GRAPHICS_STATE_VERTEX_INPUT_BIT, \
vk_vertex_input_state, vi); \
@ -1061,6 +1182,7 @@ vk_graphics_pipeline_state_fill(const struct vk_device *device,
}
#undef IS_DYNAMIC
#undef IS_NEEDED
void
vk_graphics_pipeline_state_merge(struct vk_graphics_pipeline_state *dst,
@ -1086,3 +1208,271 @@ vk_graphics_pipeline_state_merge(struct vk_graphics_pipeline_state *dst,
#undef MERGE
}
const struct vk_dynamic_graphics_state vk_default_dynamic_graphics_state = {
.rs = {
.line = {
.width = 1.0f,
},
},
.fsr = {
.fragment_size = {1u, 1u},
.combiner_ops = {
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
},
},
.ds = {
.depth = {
.bounds_test = {
.min = 0.0f,
.max = 1.0f,
},
},
.stencil = {
.front = {
.compare_mask = -1,
.write_mask = -1,
},
.back = {
.compare_mask = -1,
.write_mask = -1,
},
},
},
.cb = {
.color_write_enables = 0xffffffffu,
},
};
void
vk_dynamic_graphics_state_init(struct vk_dynamic_graphics_state *dyn)
{
*dyn = vk_default_dynamic_graphics_state;
}
void
vk_dynamic_graphics_state_clear(struct vk_dynamic_graphics_state *dyn)
{
struct vk_vertex_input_state *vi = dyn->vi;
struct vk_sample_locations_state *sl = dyn->ms.sample_locations;
*dyn = vk_default_dynamic_graphics_state;
if (vi != NULL) {
memset(vi, 0, sizeof(*vi));
dyn->vi = vi;
}
if (sl != NULL) {
memset(sl, 0, sizeof(*sl));
dyn->ms.sample_locations = sl;
}
}
void
vk_dynamic_graphics_state_fill(struct vk_dynamic_graphics_state *dyn,
const struct vk_graphics_pipeline_state *p)
{
/* This funciton (and the individual vk_dynamic_graphics_state_init_*
* functions it calls) are a bit sloppy. Instead of checking every single
* bit, we just copy everything and set the bits the right way at the end
* based on what groups we actually had.
*/
enum mesa_vk_graphics_state_groups groups = 0;
BITSET_DECLARE(needed, MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX);
BITSET_COPY(needed, p->dynamic);
BITSET_NOT(needed);
/* We only want to copy these if the driver has filled out the relevant
* pointer in the dynamic state struct. If not, they don't support them
* as dynamic state and we should leave them alone.
*/
if (dyn->vi == NULL)
BITSET_CLEAR(needed, MESA_VK_DYNAMIC_VI);
if (dyn->ms.sample_locations == NULL)
BITSET_CLEAR(needed, MESA_VK_DYNAMIC_MS_SAMPLE_LOCATIONS);
#define INIT_DYNAMIC_STATE(STATE, type, s) \
if (p->s != NULL) { \
vk_dynamic_graphics_state_init_##s(dyn, needed, p->s); \
groups |= STATE; \
}
FOREACH_STATE_GROUP(INIT_DYNAMIC_STATE);
#undef INIT_DYNAMIC_STATE
/* Mask off all but the groups we actually found */
get_dynamic_state_groups(dyn->set, groups);
BITSET_AND(dyn->set, dyn->set, needed);
}
#define SET_DYN_VALUE(dst, STATE, state, value) do { \
if (!BITSET_TEST((dst)->set, MESA_VK_DYNAMIC_##STATE) || \
(dst)->state != (value)) { \
(dst)->state = (value); \
assert((dst)->state == (value)); \
BITSET_SET(dst->set, MESA_VK_DYNAMIC_##STATE); \
BITSET_SET(dst->dirty, MESA_VK_DYNAMIC_##STATE); \
} \
} while(0)
#define SET_DYN_BOOL(dst, STATE, state, value) \
SET_DYN_VALUE(dst, STATE, state, (bool)value);
#define SET_DYN_ARRAY(dst, STATE, state, start, count, src) do { \
assert(start + count <= ARRAY_SIZE((dst)->state)); \
STATIC_ASSERT(sizeof(*(dst)->state) == sizeof(*(src))); \
const size_t __state_size = sizeof(*(dst)->state) * (count); \
if (!BITSET_TEST((dst)->set, MESA_VK_DYNAMIC_##STATE) || \
memcmp((dst)->state + start, src, __state_size)) { \
memcpy((dst)->state + start, src, __state_size); \
BITSET_SET(dst->set, MESA_VK_DYNAMIC_##STATE); \
BITSET_SET(dst->dirty, MESA_VK_DYNAMIC_##STATE); \
} \
} while(0)
void
vk_dynamic_graphics_state_copy(struct vk_dynamic_graphics_state *dst,
const struct vk_dynamic_graphics_state *src)
{
#define IS_SET_IN_SRC(STATE) \
BITSET_TEST(src->set, MESA_VK_DYNAMIC_##STATE)
#define COPY_MEMBER(STATE, state) \
SET_DYN_VALUE(dst, STATE, state, src->state)
#define COPY_ARRAY(STATE, state, count) \
SET_DYN_ARRAY(dst, STATE, state, 0, count, src->state)
#define COPY_IF_SET(STATE, state) \
if (IS_SET_IN_SRC(STATE)) SET_DYN_VALUE(dst, STATE, state, src->state)
assert((dst->vi != NULL) == (src->vi != NULL));
if (dst->vi != NULL && IS_SET_IN_SRC(VI)) {
COPY_MEMBER(VI, vi->bindings_valid);
u_foreach_bit(b, src->vi->bindings_valid) {
COPY_MEMBER(VI, vi->bindings[b].stride);
COPY_MEMBER(VI, vi->bindings[b].input_rate);
COPY_MEMBER(VI, vi->bindings[b].divisor);
}
COPY_MEMBER(VI, vi->attributes_valid);
u_foreach_bit(a, src->vi->attributes_valid) {
COPY_MEMBER(VI, vi->attributes[a].binding);
COPY_MEMBER(VI, vi->attributes[a].format);
COPY_MEMBER(VI, vi->attributes[a].offset);
}
}
if (IS_SET_IN_SRC(VI_BINDING_STRIDES)) {
COPY_ARRAY(VI_BINDING_STRIDES, vi_binding_strides,
MESA_VK_MAX_VERTEX_BINDINGS);
}
COPY_IF_SET(IA_PRIMITIVE_TOPOLOGY, ia.primitive_topology);
COPY_IF_SET(IA_PRIMITIVE_RESTART_ENABLE, ia.primitive_restart_enable);
COPY_IF_SET(TS_PATCH_CONTROL_POINTS, ts.patch_control_points);
COPY_IF_SET(VP_VIEWPORT_COUNT, vp.viewport_count);
if (IS_SET_IN_SRC(VP_VIEWPORTS)) {
assert(IS_SET_IN_SRC(VP_VIEWPORT_COUNT));
COPY_ARRAY(VP_VIEWPORT_COUNT, vp.viewports, src->vp.viewport_count);
}
COPY_IF_SET(VP_SCISSOR_COUNT, vp.scissor_count);
if (IS_SET_IN_SRC(VP_SCISSORS)) {
assert(IS_SET_IN_SRC(VP_SCISSOR_COUNT));
COPY_ARRAY(VP_SCISSOR_COUNT, vp.scissors, src->vp.scissor_count);
}
if (IS_SET_IN_SRC(DR_RECTANGLES)) {
COPY_MEMBER(DR_RECTANGLES, dr.rectangle_count);
COPY_ARRAY(DR_RECTANGLES, dr.rectangles, src->dr.rectangle_count);
}
COPY_IF_SET(RS_RASTERIZER_DISCARD_ENABLE, rs.rasterizer_discard_enable);
COPY_IF_SET(RS_CULL_MODE, rs.cull_mode);
COPY_IF_SET(RS_FRONT_FACE, rs.front_face);
COPY_IF_SET(RS_DEPTH_BIAS_ENABLE, rs.depth_bias.enable);
COPY_IF_SET(RS_DEPTH_BIAS_FACTORS, rs.depth_bias.constant);
COPY_IF_SET(RS_DEPTH_BIAS_FACTORS, rs.depth_bias.clamp);
COPY_IF_SET(RS_DEPTH_BIAS_FACTORS, rs.depth_bias.slope);
COPY_IF_SET(RS_LINE_WIDTH, rs.line.width);
COPY_IF_SET(RS_LINE_STIPPLE, rs.line.stipple.factor);
COPY_IF_SET(RS_LINE_STIPPLE, rs.line.stipple.pattern);
COPY_IF_SET(FSR, fsr.fragment_size.width);
COPY_IF_SET(FSR, fsr.fragment_size.height);
COPY_IF_SET(FSR, fsr.combiner_ops[0]);
COPY_IF_SET(FSR, fsr.combiner_ops[1]);
assert((dst->ms.sample_locations == NULL) ==
(src->ms.sample_locations == NULL));
if (dst->ms.sample_locations != NULL &&
IS_SET_IN_SRC(MS_SAMPLE_LOCATIONS)) {
COPY_MEMBER(MS_SAMPLE_LOCATIONS, ms.sample_locations->per_pixel);
COPY_MEMBER(MS_SAMPLE_LOCATIONS, ms.sample_locations->grid_size.width);
COPY_MEMBER(MS_SAMPLE_LOCATIONS, ms.sample_locations->grid_size.height);
const uint32_t sl_count = src->ms.sample_locations->per_pixel *
src->ms.sample_locations->grid_size.width *
src->ms.sample_locations->grid_size.height;
COPY_ARRAY(MS_SAMPLE_LOCATIONS, ms.sample_locations->locations, sl_count);
}
COPY_IF_SET(DS_DEPTH_TEST_ENABLE, ds.depth.test_enable);
COPY_IF_SET(DS_DEPTH_WRITE_ENABLE, ds.depth.write_enable);
COPY_IF_SET(DS_DEPTH_COMPARE_OP, ds.depth.compare_op);
COPY_IF_SET(DS_DEPTH_BOUNDS_TEST_ENABLE, ds.depth.bounds_test.enable);
if (IS_SET_IN_SRC(DS_DEPTH_BOUNDS_TEST_BOUNDS)) {
COPY_MEMBER(DS_DEPTH_BOUNDS_TEST_BOUNDS, ds.depth.bounds_test.min);
COPY_MEMBER(DS_DEPTH_BOUNDS_TEST_BOUNDS, ds.depth.bounds_test.max);
}
COPY_IF_SET(DS_STENCIL_TEST_ENABLE, ds.stencil.test_enable);
if (IS_SET_IN_SRC(DS_STENCIL_OP)) {
COPY_MEMBER(DS_STENCIL_OP, ds.stencil.front.op.fail);
COPY_MEMBER(DS_STENCIL_OP, ds.stencil.front.op.pass);
COPY_MEMBER(DS_STENCIL_OP, ds.stencil.front.op.depth_fail);
COPY_MEMBER(DS_STENCIL_OP, ds.stencil.front.op.compare);
COPY_MEMBER(DS_STENCIL_OP, ds.stencil.back.op.fail);
COPY_MEMBER(DS_STENCIL_OP, ds.stencil.back.op.pass);
COPY_MEMBER(DS_STENCIL_OP, ds.stencil.back.op.depth_fail);
COPY_MEMBER(DS_STENCIL_OP, ds.stencil.back.op.compare);
}
if (IS_SET_IN_SRC(DS_STENCIL_COMPARE_MASK)) {
COPY_MEMBER(DS_STENCIL_COMPARE_MASK, ds.stencil.front.compare_mask);
COPY_MEMBER(DS_STENCIL_COMPARE_MASK, ds.stencil.back.compare_mask);
}
if (IS_SET_IN_SRC(DS_STENCIL_WRITE_MASK)) {
COPY_MEMBER(DS_STENCIL_WRITE_MASK, ds.stencil.front.write_mask);
COPY_MEMBER(DS_STENCIL_WRITE_MASK, ds.stencil.back.write_mask);
}
if (IS_SET_IN_SRC(DS_STENCIL_REFERENCE)) {
COPY_MEMBER(DS_STENCIL_REFERENCE, ds.stencil.front.reference);
COPY_MEMBER(DS_STENCIL_REFERENCE, ds.stencil.back.reference);
}
COPY_IF_SET(CB_LOGIC_OP, cb.logic_op);
COPY_IF_SET(CB_COLOR_WRITE_ENABLES, cb.color_write_enables);
if (IS_SET_IN_SRC(CB_BLEND_CONSTANTS))
COPY_ARRAY(CB_BLEND_CONSTANTS, cb.blend_constants, 4);
#undef IS_SET_IN_SRC
#undef MARK_DIRTY
#undef COPY_MEMBER
#undef COPY_ARRAY
#undef COPY_IF_SET
for (uint32_t w = 0; w < ARRAY_SIZE(dst->dirty); w++) {
/* If it's in the source but isn't set in the destination at all, mark
* it dirty. It's possible that the default values just happen to equal
* the value from src.
*/
dst->dirty[w] |= src->set[w] & ~dst->set[w];
/* Everything that was in the source is now in the destination */
dst->set[w] |= src->set[w];
}
}

View File

@ -474,6 +474,184 @@ struct vk_render_pass_state {
VkFormat stencil_attachment_format;
};
/** Struct representing all dynamic graphics state
*
* Before invoking any core functions, the driver must properly populate
* initialize this struct:
*
* - Initialize using vk_default_dynamic_graphics_state, if desired
* - Set vi to a driver-allocated vk_vertex_input_state struct
* - Set ms.sample_locations to a driver-allocated
* vk_sample_locations_state struct
*/
struct vk_dynamic_graphics_state {
/** Vertex input state
*
* Must be provided by the driver if VK_EXT_vertex_input_dynamic_state is
* supported.
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_VI
*/
struct vk_vertex_input_state *vi;
/** Vertex binding strides
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_VI_BINDING_STRIDES
*/
uint16_t vi_binding_strides[MESA_VK_MAX_VERTEX_BINDINGS];
struct vk_input_assembly_state ia;
struct {
uint32_t patch_control_points;
} ts;
/** Viewport state */
struct {
/** Viewport count
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_VP_VIEWPORT_COUNT
*/
uint32_t viewport_count;
/** Viewports
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_VP_VIEWPORTS
*/
VkViewport viewports[MESA_VK_MAX_VIEWPORTS];
/** Scissor count
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_VP_SCISSOR_COUNT
*/
uint32_t scissor_count;
/** Scissor rects
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_VP_SCISSORS
*/
VkRect2D scissors[MESA_VK_MAX_SCISSORS];
} vp;
/** Discard rectangles
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_DR_RECTANGLES
*/
struct {
uint32_t rectangle_count;
VkRect2D rectangles[MESA_VK_MAX_DISCARD_RECTANGLES];
} dr;
/** Rasterization state */
struct {
/** Rasterizer discard
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_RS_RASTERIZER_DISCARD_ENABLE
*/
bool rasterizer_discard_enable;
/** Cull mode
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_RS_CULL_MODE
*/
VkCullModeFlags cull_mode;
/** Front face
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_RS_FRONT_FACE
*/
VkFrontFace front_face;
struct {
/** Depth bias enable
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_RS_DEPTH_BIAS_ENABLE
*/
bool enable;
/** Depth bias constant factor
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_RS_DEPTH_BIAS_FACTORS
*/
float constant;
/** Depth bias clamp
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_RS_DEPTH_BIAS_FACTORS
*/
float clamp;
/** Depth bias slope
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_RS_DEPTH_BIAS_FACTORS
*/
float slope;
} depth_bias;
struct {
/** Line width
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_RS_LINE_WIDTH
*/
float width;
/** Line stipple
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_RS_LINE_STIPPLE
*/
struct {
uint32_t factor;
uint16_t pattern;
} stipple;
} line;
} rs;
struct vk_fragment_shading_rate_state fsr;
/** Multisample state */
struct {
/** Sample locations
*
* Must be provided by the driver if VK_EXT_sample_locations is
* supported.
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_MS_SAMPLE_LOCATIONS
*/
struct vk_sample_locations_state *sample_locations;
} ms;
struct vk_depth_stencil_state ds;
/** Color blend state */
struct {
/** Integer color logic op
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_CB_LOGIC_OP,
*/
VkLogicOp logic_op;
/** Color write enables
*
* Bitmask of color write enables, indexed by color attachment index.
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_CB_COLOR_WRITE_ENABLES,
*/
uint32_t color_write_enables;
/** Blend constants
*
* MESA_VK_DYNAMIC_GRAPHICS_STATE_CB_BLEND_CONSTANTS,
*/
float blend_constants[4];
} cb;
/** For pipelines, which bits of dynamic state are set */
BITSET_DECLARE(set, MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX);
/** For command buffers, which bits of dynamic state have changed */
BITSET_DECLARE(dirty, MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX);
};
struct vk_graphics_pipeline_all_state {
struct vk_vertex_input_state vi;
struct vk_input_assembly_state ia;
@ -606,6 +784,75 @@ void
vk_graphics_pipeline_state_merge(struct vk_graphics_pipeline_state *dst,
const struct vk_graphics_pipeline_state *src);
extern const struct vk_dynamic_graphics_state vk_default_dynamic_graphics_state;
/** Initialize a vk_dynamic_graphics_state with defaults
*
* @param[out] dyn Dynamic graphics state to initizlie
*/
void
vk_dynamic_graphics_state_init(struct vk_dynamic_graphics_state *dyn);
/** Clear a vk_dynamic_graphics_state to defaults
*
* @param[out] dyn Dynamic graphics state to initizlie
*/
void
vk_dynamic_graphics_state_clear(struct vk_dynamic_graphics_state *dyn);
/** Initialize a vk_dynamic_graphics_state for a pipeline
*
* @param[out] dyn Dynamic graphics state to initizlie
* @param[in] supported Bitset of all dynamic state supported by the driver.
* @param[in] p The pipeline state from which to initialize the
* dynamic state.
*/
void
vk_dynamic_graphics_state_fill(struct vk_dynamic_graphics_state *dyn,
const struct vk_graphics_pipeline_state *p);
/** Mark all states in the given vk_dynamic_graphics_state dirty
*
* @param[out] d Dynamic graphics state struct
*/
static inline void
vk_dynamic_graphics_state_dirty_all(struct vk_dynamic_graphics_state *d)
{
BITSET_SET_RANGE(d->dirty, 0, MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX - 1);
}
/** Mark all states in the given vk_dynamic_graphics_state not dirty
*
* @param[out] d Dynamic graphics state struct
*/
static inline void
vk_dynamic_graphics_state_clear_dirty(struct vk_dynamic_graphics_state *d)
{
memset(d->dirty, 0, sizeof(d->dirty));
}
/** Test if any states in the given vk_dynamic_graphics_state are dirty
*
* @param[in] d Dynamic graphics state struct to test
* @returns true if any state is dirty
*/
static inline bool
vk_dynamic_graphics_state_any_dirty(const struct vk_dynamic_graphics_state *d)
{
return BITSET_TEST_RANGE(d->dirty,
0, MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX - 1);
}
/** Copies all set state from src to dst
*
* Both src and dst are assumed to be properly initialized dynamic state
* structs. Anything not set in src, as indicated by src->set, is ignored and
* those bits of dst are left untouched.
*/
void
vk_dynamic_graphics_state_copy(struct vk_dynamic_graphics_state *dst,
const struct vk_dynamic_graphics_state *src);
#ifdef __cplusplus
}
#endif