zink: implement pipe_context::draw_vertex_state

rough implementation, but it should be a decent start

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13692>
This commit is contained in:
Mike Blumenkrantz 2021-11-05 12:00:25 -04:00 committed by Marge Bot
parent 02e5f4fb10
commit 86eb1549ef
7 changed files with 258 additions and 25 deletions

View File

@ -160,7 +160,12 @@ typedef void (*pipe_draw_vbo_func)(struct pipe_context *pipe,
const struct pipe_draw_indirect_info *indirect,
const struct pipe_draw_start_count_bias *draws,
unsigned num_draws);
typedef void (*pipe_draw_vertex_state_func)(struct pipe_context *ctx,
struct pipe_vertex_state *vstate,
uint32_t partial_velem_mask,
struct pipe_draw_vertex_state_info info,
const struct pipe_draw_start_count_bias *draws,
unsigned num_draws);
typedef void (*pipe_launch_grid_func)(struct pipe_context *pipe, const struct pipe_grid_info *info);
typedef enum {
@ -183,6 +188,7 @@ struct zink_context {
struct blitter_context *blitter;
pipe_draw_vbo_func draw_vbo[2]; //batch changed
pipe_draw_vertex_state_func draw_state[2]; //batch changed
pipe_launch_grid_func launch_grid[2]; //batch changed
struct pipe_device_reset_callback reset;

View File

@ -171,6 +171,28 @@ zink_bind_vertex_buffers(struct zink_batch *batch, struct zink_context *ctx)
ctx->vertex_buffers_dirty = false;
}
static void
zink_bind_vertex_state(struct zink_batch *batch, struct zink_context *ctx,
struct pipe_vertex_state *vstate, uint32_t partial_velem_mask)
{
if (!vstate->input.vbuffer.buffer.resource)
return;
const struct zink_vertex_elements_hw_state *hw_state = zink_vertex_state_mask(vstate, partial_velem_mask, true);
assert(hw_state);
struct zink_resource *res = zink_resource(vstate->input.vbuffer.buffer.resource);
zink_batch_resource_usage_set(&ctx->batch, res, false);
VkDeviceSize offset = vstate->input.vbuffer.buffer_offset;
VKCTX(CmdBindVertexBuffers)(batch->state->cmdbuf, 0,
hw_state->num_bindings,
&res->obj->buffer, &offset);
VKCTX(CmdSetVertexInputEXT)(batch->state->cmdbuf,
hw_state->num_bindings, hw_state->dynbindings,
hw_state->num_attribs, hw_state->dynattribs);
}
static void
update_gfx_program(struct zink_context *ctx)
{
@ -452,14 +474,16 @@ hack_conditional_render(struct pipe_context *pctx,
return true;
}
template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED>
template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED, bool DRAW_STATE>
void
zink_draw_vbo(struct pipe_context *pctx,
const struct pipe_draw_info *dinfo,
unsigned drawid_offset,
const struct pipe_draw_indirect_info *dindirect,
const struct pipe_draw_start_count_bias *draws,
unsigned num_draws)
zink_draw(struct pipe_context *pctx,
const struct pipe_draw_info *dinfo,
unsigned drawid_offset,
const struct pipe_draw_indirect_info *dindirect,
const struct pipe_draw_start_count_bias *draws,
unsigned num_draws,
struct pipe_vertex_state *vstate,
uint32_t partial_velem_mask)
{
struct zink_context *ctx = zink_context(pctx);
struct zink_screen *screen = zink_screen(pctx->screen);
@ -734,7 +758,9 @@ zink_draw_vbo(struct pipe_context *pctx,
}
ctx->blend_state_changed = false;
if (BATCH_CHANGED || ctx->vertex_buffers_dirty)
if (DRAW_STATE)
zink_bind_vertex_state(batch, ctx, vstate, partial_velem_mask);
else if (BATCH_CHANGED || ctx->vertex_buffers_dirty)
zink_bind_vertex_buffers<DYNAMIC_STATE>(batch, ctx);
zink_query_update_gs_states(ctx);
@ -859,6 +885,47 @@ zink_draw_vbo(struct pipe_context *pctx,
pctx->flush(pctx, NULL, 0);
}
template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED>
static void
zink_draw_vbo(struct pipe_context *pctx,
const struct pipe_draw_info *info,
unsigned drawid_offset,
const struct pipe_draw_indirect_info *indirect,
const struct pipe_draw_start_count_bias *draws,
unsigned num_draws)
{
zink_draw<HAS_MULTIDRAW, DYNAMIC_STATE, BATCH_CHANGED, false>(pctx, info, drawid_offset, indirect, draws, num_draws, NULL, 0);
}
template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED>
static void
zink_draw_vertex_state(struct pipe_context *pctx,
struct pipe_vertex_state *vstate,
uint32_t partial_velem_mask,
struct pipe_draw_vertex_state_info info,
const struct pipe_draw_start_count_bias *draws,
unsigned num_draws)
{
struct pipe_draw_info dinfo = {};
dinfo.mode = info.mode;
dinfo.index_size = 4;
dinfo.instance_count = 1;
dinfo.index.resource = vstate->input.indexbuf;
struct zink_context *ctx = zink_context(pctx);
struct zink_resource *res = zink_resource(vstate->input.vbuffer.buffer.resource);
zink_resource_buffer_barrier(ctx, res, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
struct zink_vertex_elements_hw_state *hw_state = ctx->gfx_pipeline_state.element_state;
ctx->gfx_pipeline_state.element_state = &((struct zink_vertex_state*)vstate)->velems.hw_state;
zink_draw<HAS_MULTIDRAW, DYNAMIC_STATE, BATCH_CHANGED, true>(pctx, &dinfo, 0, NULL, draws, num_draws, vstate, partial_velem_mask);
ctx->gfx_pipeline_state.element_state = hw_state;
if (info.take_vertex_state_ownership)
pipe_vertex_state_reference(&vstate, NULL);
}
template <bool BATCH_CHANGED>
static void
zink_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
@ -928,35 +995,35 @@ zink_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED>
static void
init_batch_changed_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2])
init_batch_changed_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2], pipe_draw_vertex_state_func draw_state_array[2][4][2])
{
draw_vbo_array[HAS_MULTIDRAW][DYNAMIC_STATE][BATCH_CHANGED] =
zink_draw_vbo<HAS_MULTIDRAW, DYNAMIC_STATE, BATCH_CHANGED>;
draw_vbo_array[HAS_MULTIDRAW][DYNAMIC_STATE][BATCH_CHANGED] = zink_draw_vbo<HAS_MULTIDRAW, DYNAMIC_STATE, BATCH_CHANGED>;
draw_state_array[HAS_MULTIDRAW][DYNAMIC_STATE][BATCH_CHANGED] = zink_draw_vertex_state<HAS_MULTIDRAW, DYNAMIC_STATE, BATCH_CHANGED>;
}
template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE>
static void
init_dynamic_state_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2])
init_dynamic_state_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2], pipe_draw_vertex_state_func draw_state_array[2][4][2])
{
init_batch_changed_functions<HAS_MULTIDRAW, DYNAMIC_STATE, false>(ctx, draw_vbo_array);
init_batch_changed_functions<HAS_MULTIDRAW, DYNAMIC_STATE, true>(ctx, draw_vbo_array);
init_batch_changed_functions<HAS_MULTIDRAW, DYNAMIC_STATE, false>(ctx, draw_vbo_array, draw_state_array);
init_batch_changed_functions<HAS_MULTIDRAW, DYNAMIC_STATE, true>(ctx, draw_vbo_array, draw_state_array);
}
template <zink_multidraw HAS_MULTIDRAW>
static void
init_multidraw_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2])
init_multidraw_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2], pipe_draw_vertex_state_func draw_state_array[2][4][2])
{
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_NO_DYNAMIC_STATE>(ctx, draw_vbo_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_STATE>(ctx, draw_vbo_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_STATE2>(ctx, draw_vbo_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_VERTEX_INPUT>(ctx, draw_vbo_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_NO_DYNAMIC_STATE>(ctx, draw_vbo_array, draw_state_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_STATE>(ctx, draw_vbo_array, draw_state_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_STATE2>(ctx, draw_vbo_array, draw_state_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_VERTEX_INPUT>(ctx, draw_vbo_array, draw_state_array);
}
static void
init_all_draw_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2])
init_all_draw_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2], pipe_draw_vertex_state_func draw_state_array[2][4][2])
{
init_multidraw_functions<ZINK_NO_MULTIDRAW>(ctx, draw_vbo_array);
init_multidraw_functions<ZINK_MULTIDRAW>(ctx, draw_vbo_array);
init_multidraw_functions<ZINK_NO_MULTIDRAW>(ctx, draw_vbo_array, draw_state_array);
init_multidraw_functions<ZINK_MULTIDRAW>(ctx, draw_vbo_array, draw_state_array);
}
template <bool BATCH_CHANGED>
@ -984,6 +1051,17 @@ zink_invalid_draw_vbo(struct pipe_context *pipe,
unreachable("vertex shader not bound");
}
static void
zink_invalid_draw_vertex_state(struct pipe_context *pipe,
struct pipe_vertex_state *vstate,
uint32_t partial_velem_mask,
struct pipe_draw_vertex_state_info info,
const struct pipe_draw_start_count_bias *draws,
unsigned num_draws)
{
unreachable("vertex shader not bound");
}
static void
zink_invalid_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
{
@ -1043,6 +1121,8 @@ zink_init_draw_functions(struct zink_context *ctx, struct zink_screen *screen)
{
pipe_draw_vbo_func draw_vbo_array[2][4] //multidraw, zink_dynamic_state
[2]; //batch changed
pipe_draw_vertex_state_func draw_state_array[2][4] //multidraw, zink_dynamic_state
[2]; //batch changed
zink_dynamic_state dynamic;
if (screen->info.have_EXT_extended_dynamic_state) {
if (screen->info.have_EXT_extended_dynamic_state2) {
@ -1056,15 +1136,19 @@ zink_init_draw_functions(struct zink_context *ctx, struct zink_screen *screen)
} else {
dynamic = ZINK_NO_DYNAMIC_STATE;
}
init_all_draw_functions(ctx, draw_vbo_array);
init_all_draw_functions(ctx, draw_vbo_array, draw_state_array);
memcpy(ctx->draw_vbo, &draw_vbo_array[screen->info.have_EXT_multi_draw]
[dynamic],
sizeof(ctx->draw_vbo));
memcpy(ctx->draw_state, &draw_state_array[screen->info.have_EXT_multi_draw]
[dynamic],
sizeof(ctx->draw_state));
/* Bind a fake draw_vbo, so that draw_vbo isn't NULL, which would skip
* initialization of callbacks in upper layers (such as u_threaded_context).
*/
ctx->base.draw_vbo = zink_invalid_draw_vbo;
ctx->base.draw_vertex_state = zink_invalid_draw_vertex_state;
_mesa_hash_table_init(&ctx->program_cache[0], ctx, hash_gfx_program<0>, equals_gfx_program<0>);
_mesa_hash_table_init(&ctx->program_cache[1], ctx, hash_gfx_program<1>, equals_gfx_program<1>);

View File

@ -6,7 +6,9 @@ static inline void
zink_select_draw_vbo(struct zink_context *ctx)
{
ctx->base.draw_vbo = ctx->draw_vbo[ctx->pipeline_changed[0]];
ctx->base.draw_vertex_state = ctx->draw_state[ctx->pipeline_changed[0]];
assert(ctx->base.draw_vbo);
assert(ctx->base.draw_vertex_state);
}
static inline void

View File

@ -363,6 +363,9 @@ zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_PACK_HALF_FLOAT:
return 1;
case PIPE_CAP_DRAW_VERTEX_STATE:
return screen->info.have_EXT_vertex_input_dynamic_state;
case PIPE_CAP_SURFACE_SAMPLE_COUNT:
return screen->vk_version >= VK_MAKE_VERSION(1,2,0);
@ -2068,6 +2071,11 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
zink_screen_init_descriptor_funcs(screen, false);
util_idalloc_mt_init_tc(&screen->buffer_ids);
util_vertex_state_cache_init(&screen->vertex_state_cache,
zink_create_vertex_state, zink_vertex_state_destroy);
screen->base.create_vertex_state = zink_cache_create_vertex_state;
screen->base.vertex_state_destroy = zink_cache_vertex_state_destroy;
return screen;
fail:

View File

@ -37,6 +37,7 @@
#include "util/simple_mtx.h"
#include "util/u_queue.h"
#include "util/u_live_shader_cache.h"
#include "util/u_vertex_state_cache.h"
#include "pipebuffer/pb_cache.h"
#include "pipebuffer/pb_slab.h"
#include <vulkan/vulkan.h>
@ -120,6 +121,7 @@ struct zink_screen {
VkPhysicalDevice pdev;
uint32_t vk_version, spirv_version;
struct util_idalloc_mt buffer_ids;
struct util_vertex_state_cache vertex_state_cache;
struct zink_device_info info;
struct nir_shader_compiler_options nir_options;

View File

@ -31,6 +31,7 @@
#include "compiler/shader_enums.h"
#include "util/u_dual_blend.h"
#include "util/u_memory.h"
#include "util/u_helpers.h"
#include <math.h>
@ -714,6 +715,98 @@ zink_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state)
FREE(rs_state);
}
struct pipe_vertex_state *
zink_create_vertex_state(struct pipe_screen *pscreen,
struct pipe_vertex_buffer *buffer,
const struct pipe_vertex_element *elements,
unsigned num_elements,
struct pipe_resource *indexbuf,
uint32_t full_velem_mask)
{
struct zink_vertex_state *zstate = CALLOC_STRUCT(zink_vertex_state);
_mesa_set_init(&zstate->masks, NULL, NULL, _mesa_key_pointer_equal);
util_init_pipe_vertex_state(pscreen, buffer, elements, num_elements, indexbuf, full_velem_mask,
&zstate->b);
/* Initialize the vertex element state in state->element.
* Do it by creating a vertex element state object and copying it there.
*/
struct zink_context ctx;
ctx.base.screen = pscreen;
struct zink_vertex_elements_state *elems = zink_create_vertex_elements_state(&ctx.base, num_elements, elements);
for (unsigned i = 0; i < elems->hw_state.num_bindings; i++) {
if (zink_screen(pscreen)->info.have_EXT_vertex_input_dynamic_state)
elems->hw_state.dynbindings[i].stride = buffer->stride;
}
zstate->velems = *elems;
zink_delete_vertex_elements_state(&ctx.base, elems);
return &zstate->b;
}
void
zink_vertex_state_destroy(struct pipe_screen *pscreen, struct pipe_vertex_state *vstate)
{
struct zink_vertex_state *zstate = (struct zink_vertex_state *)vstate;
ralloc_free(zstate->masks.table);
pipe_vertex_buffer_unreference(&vstate->input.vbuffer);
pipe_resource_reference(&vstate->input.indexbuf, NULL);
FREE(vstate);
}
const struct zink_vertex_elements_hw_state *
zink_vertex_state_mask(struct pipe_vertex_state *vstate, uint32_t partial_velem_mask, bool have_EXT_vertex_input_dynamic_state)
{
struct zink_vertex_state *zstate = (struct zink_vertex_state *)vstate;
if (partial_velem_mask == vstate->input.full_velem_mask)
return &zstate->velems.hw_state;
struct set_entry *he = _mesa_set_search_pre_hashed(&zstate->masks, partial_velem_mask, (void*)(uintptr_t)partial_velem_mask);
if (he)
return he->key;
struct zink_vertex_elements_hw_state *hw_state = rzalloc(zstate->masks.table, struct zink_vertex_elements_hw_state);
unsigned i = 0;
if (have_EXT_vertex_input_dynamic_state) {
u_foreach_bit(elem, vstate->input.full_velem_mask & partial_velem_mask) {
unsigned idx = util_bitcount(vstate->input.full_velem_mask & BITFIELD_MASK(elem));
hw_state->dynattribs[i] = zstate->velems.hw_state.dynattribs[idx];
hw_state->dynattribs[i].location = i;
i++;
}
memcpy(hw_state->dynbindings, zstate->velems.hw_state.dynbindings,
zstate->velems.hw_state.num_bindings * sizeof(VkVertexInputBindingDescription2EXT));
} else {
}
hw_state->num_attribs = i;
hw_state->num_bindings = zstate->velems.hw_state.num_bindings;
_mesa_set_add_pre_hashed(&zstate->masks, partial_velem_mask, hw_state);
return hw_state;
}
struct pipe_vertex_state *
zink_cache_create_vertex_state(struct pipe_screen *pscreen,
struct pipe_vertex_buffer *buffer,
const struct pipe_vertex_element *elements,
unsigned num_elements,
struct pipe_resource *indexbuf,
uint32_t full_velem_mask)
{
struct zink_screen *screen = zink_screen(pscreen);
return util_vertex_state_cache_get(pscreen, buffer, elements, num_elements, indexbuf,
full_velem_mask, &screen->vertex_state_cache);
}
void
zink_cache_vertex_state_destroy(struct pipe_screen *pscreen, struct pipe_vertex_state *vstate)
{
struct zink_screen *screen = zink_screen(pscreen);
util_vertex_state_destroy(pscreen, &screen->vertex_state_cache, vstate);
}
void
zink_context_state_init(struct pipe_context *pctx)
{

View File

@ -27,9 +27,11 @@
#include <vulkan/vulkan.h>
#include "pipe/p_state.h"
#include "util/set.h"
struct zink_vertex_elements_hw_state {
uint32_t hash;
uint32_t num_bindings, num_attribs;
union {
VkVertexInputAttributeDescription attribs[PIPE_MAX_ATTRIBS];
VkVertexInputAttributeDescription2EXT dynattribs[PIPE_MAX_ATTRIBS];
@ -42,7 +44,6 @@ struct zink_vertex_elements_hw_state {
} b;
VkVertexInputBindingDescription2EXT dynbindings[PIPE_MAX_ATTRIBS];
};
uint32_t num_bindings, num_attribs;
};
struct zink_vertex_elements_state {
@ -59,6 +60,12 @@ struct zink_vertex_elements_state {
struct zink_vertex_elements_hw_state hw_state;
};
struct zink_vertex_state {
struct pipe_vertex_state b;
struct zink_vertex_elements_state velems;
struct set masks;
};
struct zink_rasterizer_hw_state {
unsigned polygon_mode : 2; //VkPolygonMode
unsigned cull_mode : 2; //VkCullModeFlags
@ -115,7 +122,38 @@ struct zink_depth_stencil_alpha_state {
struct zink_depth_stencil_alpha_hw_state hw_state;
};
#ifdef __cplusplus
extern "C" {
#endif
void
zink_context_state_init(struct pipe_context *pctx);
struct pipe_vertex_state *
zink_create_vertex_state(struct pipe_screen *pscreen,
struct pipe_vertex_buffer *buffer,
const struct pipe_vertex_element *elements,
unsigned num_elements,
struct pipe_resource *indexbuf,
uint32_t full_velem_mask);
void
zink_vertex_state_destroy(struct pipe_screen *pscreen, struct pipe_vertex_state *vstate);
struct pipe_vertex_state *
zink_cache_create_vertex_state(struct pipe_screen *pscreen,
struct pipe_vertex_buffer *buffer,
const struct pipe_vertex_element *elements,
unsigned num_elements,
struct pipe_resource *indexbuf,
uint32_t full_velem_mask);
void
zink_cache_vertex_state_destroy(struct pipe_screen *pscreen, struct pipe_vertex_state *vstate);
const struct zink_vertex_elements_hw_state *
zink_vertex_state_mask(struct pipe_vertex_state *vstate, uint32_t partial_velem_mask, bool have_EXT_vertex_input_dynamic_state);
#ifdef __cplusplus
}
#endif
#endif