lavapipe: use stream uploader for push constant upload

now instead of having static per-stage buffer regions and letting llvmpipe
do the upload, lavapipe creates a new pipe_resource and chucks it away
with take_ownership=true to allow it to be destroyed once it's no longer
in use

this also alters ubo0 mechanics such that the buffer is now sized exactly to
the size of the push constants in the pipeline and push constants are only
updated when the appropriate shader stage is flagged

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15457>
This commit is contained in:
Mike Blumenkrantz 2022-03-18 09:50:36 -04:00 committed by Marge Bot
parent c264b1b6ab
commit 5bbb39a652
1 changed files with 67 additions and 34 deletions

View File

@ -32,6 +32,7 @@
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_text.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_from_mesa.h"
#include "util/format/u_format.h"
#include "util/u_surface.h"
@ -72,6 +73,7 @@ struct rendering_state {
bool vb_dirty;
bool constbuf_dirty[PIPE_SHADER_TYPES];
bool pcbuf_dirty[PIPE_SHADER_TYPES];
bool has_pcbuf[PIPE_SHADER_TYPES];
bool vp_dirty;
bool scissor_dirty;
bool ib_dirty;
@ -110,7 +112,6 @@ struct rendering_state {
ubyte index_size;
unsigned index_offset;
struct pipe_resource *index_buffer;
struct pipe_constant_buffer pc_buffer[PIPE_SHADER_TYPES];
struct pipe_constant_buffer const_buffer[PIPE_SHADER_TYPES][16];
int num_const_bufs[PIPE_SHADER_TYPES];
int num_vb;
@ -144,6 +145,7 @@ struct rendering_state {
void *velems_cso;
uint8_t push_constants[128 * 4];
uint16_t push_size[2]; //gfx, compute
const struct lvp_render_pass *pass;
struct lvp_subpass *subpass;
@ -195,6 +197,43 @@ static void finish_fence(struct rendering_state *state)
&handle, NULL);
}
static unsigned
get_pcbuf_size(struct rendering_state *state, enum pipe_shader_type pstage)
{
bool is_compute = pstage == PIPE_SHADER_COMPUTE;
return state->has_pcbuf[pstage] ? state->push_size[is_compute] : 0;
}
static unsigned
calc_ubo0_size(struct rendering_state *state, enum pipe_shader_type pstage)
{
unsigned size = get_pcbuf_size(state, pstage);
return size;
}
static void
fill_ubo0(struct rendering_state *state, uint8_t *mem, enum pipe_shader_type pstage)
{
unsigned push_size = get_pcbuf_size(state, pstage);
if (push_size)
memcpy(mem, state->push_constants, push_size);
}
static void
update_pcbuf(struct rendering_state *state, enum pipe_shader_type pstage)
{
uint8_t *mem;
struct pipe_constant_buffer cbuf;
unsigned size = calc_ubo0_size(state, pstage);
cbuf.buffer_size = size;
cbuf.buffer = NULL;
cbuf.user_buffer = NULL;
u_upload_alloc(state->uploader, 0, size, 64, &cbuf.buffer_offset, &cbuf.buffer, (void**)&mem);
fill_ubo0(state, mem, pstage);
state->pctx->set_constant_buffer(state->pctx, pstage, 0, true, &cbuf);
state->pcbuf_dirty[pstage] = false;
}
static void emit_compute_state(struct rendering_state *state)
{
if (state->iv_dirty[PIPE_SHADER_COMPUTE]) {
@ -204,11 +243,8 @@ static void emit_compute_state(struct rendering_state *state)
state->iv_dirty[PIPE_SHADER_COMPUTE] = false;
}
if (state->pcbuf_dirty[PIPE_SHADER_COMPUTE]) {
state->pctx->set_constant_buffer(state->pctx, PIPE_SHADER_COMPUTE,
0, false, &state->pc_buffer[PIPE_SHADER_COMPUTE]);
state->pcbuf_dirty[PIPE_SHADER_COMPUTE] = false;
}
if (state->pcbuf_dirty[PIPE_SHADER_COMPUTE])
update_pcbuf(state, PIPE_SHADER_COMPUTE);
if (state->constbuf_dirty[PIPE_SHADER_COMPUTE]) {
for (unsigned i = 0; i < state->num_const_bufs[PIPE_SHADER_COMPUTE]; i++)
@ -327,10 +363,8 @@ static void emit_state(struct rendering_state *state)
}
for (sh = 0; sh < PIPE_SHADER_COMPUTE; sh++) {
if (state->pcbuf_dirty[sh]) {
state->pctx->set_constant_buffer(state->pctx, sh,
0, false, &state->pc_buffer[sh]);
}
if (state->pcbuf_dirty[sh])
update_pcbuf(state, sh);
}
for (sh = 0; sh < PIPE_SHADER_COMPUTE; sh++) {
@ -382,6 +416,11 @@ static void handle_compute_pipeline(struct vk_cmd_queue_entry *cmd,
{
LVP_FROM_HANDLE(lvp_pipeline, pipeline, cmd->u.bind_pipeline.pipeline);
if ((pipeline->layout->push_constant_stages & VK_SHADER_STAGE_COMPUTE_BIT) > 0)
state->has_pcbuf[PIPE_SHADER_COMPUTE] = pipeline->layout->push_constant_size > 0;
if (!state->has_pcbuf[PIPE_SHADER_COMPUTE])
state->pcbuf_dirty[PIPE_SHADER_COMPUTE] = false;
state->dispatch_info.block[0] = pipeline->pipeline_nir[MESA_SHADER_COMPUTE]->info.workgroup_size[0];
state->dispatch_info.block[1] = pipeline->pipeline_nir[MESA_SHADER_COMPUTE]->info.workgroup_size[1];
state->dispatch_info.block[2] = pipeline->pipeline_nir[MESA_SHADER_COMPUTE]->info.workgroup_size[2];
@ -505,6 +544,16 @@ static void handle_graphics_pipeline(struct vk_cmd_queue_entry *cmd,
}
state->has_color_write_disables = dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT)];
for (enum pipe_shader_type sh = PIPE_SHADER_VERTEX; sh < PIPE_SHADER_COMPUTE; sh++)
state->has_pcbuf[sh] = false;
u_foreach_bit(stage, pipeline->layout->push_constant_stages) {
enum pipe_shader_type sh = pipe_shader_type_from_mesa(stage);
state->has_pcbuf[sh] = pipeline->layout->push_constant_size > 0;
if (!state->has_pcbuf[sh])
state->pcbuf_dirty[sh] = false;
}
bool has_stage[PIPE_SHADER_TYPES] = { false };
state->pctx->bind_gs_state(state->pctx, NULL);
@ -883,6 +932,7 @@ static void handle_pipeline(struct vk_cmd_queue_entry *cmd,
handle_compute_pipeline(cmd, state);
else
handle_graphics_pipeline(cmd, state);
state->push_size[pipeline->is_compute_pipeline] = pipeline->layout->push_constant_size;
}
static void vertex_buffers(uint32_t first_binding,
@ -2865,30 +2915,13 @@ static void handle_push_constants(struct vk_cmd_queue_entry *cmd,
{
memcpy(state->push_constants + cmd->u.push_constants.offset, cmd->u.push_constants.values, cmd->u.push_constants.size);
state->pc_buffer[PIPE_SHADER_VERTEX].buffer_size = 128 * 4;
state->pc_buffer[PIPE_SHADER_VERTEX].buffer_offset = 0;
state->pc_buffer[PIPE_SHADER_VERTEX].user_buffer = state->push_constants;
state->pcbuf_dirty[PIPE_SHADER_VERTEX] = true;
state->pc_buffer[PIPE_SHADER_FRAGMENT].buffer_size = 128 * 4;
state->pc_buffer[PIPE_SHADER_FRAGMENT].buffer_offset = 0;
state->pc_buffer[PIPE_SHADER_FRAGMENT].user_buffer = state->push_constants;
state->pcbuf_dirty[PIPE_SHADER_FRAGMENT] = true;
state->pc_buffer[PIPE_SHADER_GEOMETRY].buffer_size = 128 * 4;
state->pc_buffer[PIPE_SHADER_GEOMETRY].buffer_offset = 0;
state->pc_buffer[PIPE_SHADER_GEOMETRY].user_buffer = state->push_constants;
state->pcbuf_dirty[PIPE_SHADER_GEOMETRY] = true;
state->pc_buffer[PIPE_SHADER_TESS_CTRL].buffer_size = 128 * 4;
state->pc_buffer[PIPE_SHADER_TESS_CTRL].buffer_offset = 0;
state->pc_buffer[PIPE_SHADER_TESS_CTRL].user_buffer = state->push_constants;
state->pcbuf_dirty[PIPE_SHADER_TESS_CTRL] = true;
state->pc_buffer[PIPE_SHADER_TESS_EVAL].buffer_size = 128 * 4;
state->pc_buffer[PIPE_SHADER_TESS_EVAL].buffer_offset = 0;
state->pc_buffer[PIPE_SHADER_TESS_EVAL].user_buffer = state->push_constants;
state->pcbuf_dirty[PIPE_SHADER_TESS_EVAL] = true;
state->pc_buffer[PIPE_SHADER_COMPUTE].buffer_size = 128 * 4;
state->pc_buffer[PIPE_SHADER_COMPUTE].buffer_offset = 0;
state->pc_buffer[PIPE_SHADER_COMPUTE].user_buffer = state->push_constants;
state->pcbuf_dirty[PIPE_SHADER_COMPUTE] = true;
VkShaderStageFlags stage_flags = cmd->u.push_constants.stage_flags;
state->pcbuf_dirty[PIPE_SHADER_VERTEX] |= (stage_flags & VK_SHADER_STAGE_VERTEX_BIT) > 0;
state->pcbuf_dirty[PIPE_SHADER_FRAGMENT] |= (stage_flags & VK_SHADER_STAGE_FRAGMENT_BIT) > 0;
state->pcbuf_dirty[PIPE_SHADER_GEOMETRY] |= (stage_flags & VK_SHADER_STAGE_GEOMETRY_BIT) > 0;
state->pcbuf_dirty[PIPE_SHADER_TESS_CTRL] |= (stage_flags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) > 0;
state->pcbuf_dirty[PIPE_SHADER_TESS_EVAL] |= (stage_flags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) > 0;
state->pcbuf_dirty[PIPE_SHADER_COMPUTE] |= (stage_flags & VK_SHADER_STAGE_COMPUTE_BIT) > 0;
}
static void lvp_execute_cmd_buffer(struct lvp_cmd_buffer *cmd_buffer,