v3dv/cmd_buffer: update shader variants at CmdBindDescriptorSets/CmdBindPipeline
Specially after CmdBindDescriptorSets, it is likely that we would need a new shader variant, like for example if sampler descriptor sets are bound. At that moment a new v3d key is populated, using as base the one used at pipeline creation, so only cmd_buffer depending values are changed. Then a new variant is requested. Note that internally it is handled with a cache, so no new compilation will be done if not needed. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This commit is contained in:
parent
f76dad8f89
commit
07addb4183
|
@ -1736,6 +1736,120 @@ cmd_buffer_update_ez_state(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
}
|
||||
}
|
||||
|
||||
/* Note that the following poopulate methods doesn't do a detailed fill-up of
|
||||
* the v3d_fs_key. Here we just fill-up cmd_buffer specific info. All info
|
||||
* coming from the pipeline create info was alredy filled up when the pipeline
|
||||
* was created
|
||||
*/
|
||||
static void
|
||||
cmd_buffer_populate_v3d_key(struct v3d_key *key,
|
||||
struct v3dv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
struct v3dv_descriptor_map *map = &cmd_buffer->state.pipeline->texture_map;
|
||||
struct v3dv_descriptor_state *descriptor_state =
|
||||
&cmd_buffer->state.descriptor_state;
|
||||
|
||||
for (uint32_t i = 0; i < map->num_desc; i++) {
|
||||
struct v3dv_descriptor *descriptor =
|
||||
v3dv_descriptor_map_get_descriptor(descriptor_state,
|
||||
map,
|
||||
cmd_buffer->state.pipeline->layout,
|
||||
i, NULL);
|
||||
|
||||
assert(descriptor->type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
|
||||
descriptor->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||
assert(descriptor);
|
||||
assert(descriptor->image_view);
|
||||
assert(descriptor->image_view->image);
|
||||
|
||||
key->tex[i].return_size =
|
||||
v3dv_get_tex_return_size(descriptor->image_view->format,
|
||||
0); /* FIXME: how to get the sampler compare mode? */
|
||||
|
||||
if (key->tex[i].return_size == 16) {
|
||||
key->tex[i].return_channels = 2;
|
||||
} else {
|
||||
key->tex[i].return_channels = 4;
|
||||
}
|
||||
|
||||
/* Note: we don't need to do anything for the swizzle, as that is
|
||||
* handled with the swizzle info at the Texture State, and the
|
||||
* default values for key->tex[].swizzle were already filled up on
|
||||
* the pipeline populate.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_fs_variant(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
struct v3dv_shader_variant *variant;
|
||||
struct v3dv_pipeline_stage *p_stage = cmd_buffer->state.pipeline->fs;
|
||||
struct v3d_fs_key local_key;
|
||||
|
||||
/* We start with a copy of the original pipeline key */
|
||||
memcpy(&local_key, &p_stage->key.fs, sizeof(struct v3d_fs_key));
|
||||
|
||||
cmd_buffer_populate_v3d_key(&local_key.base, cmd_buffer);
|
||||
|
||||
variant = v3dv_get_shader_variant(p_stage, &local_key.base,
|
||||
sizeof(struct v3d_fs_key));
|
||||
|
||||
if (p_stage->current_variant != variant) {
|
||||
p_stage->current_variant = variant;
|
||||
/* FIXME: we need to set any dirty flag here? */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_vs_variant(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
struct v3dv_shader_variant *variant;
|
||||
struct v3dv_pipeline_stage *p_stage = cmd_buffer->state.pipeline->vs;
|
||||
struct v3d_vs_key local_key;
|
||||
|
||||
/* We start with a copy of the original pipeline key */
|
||||
memcpy(&local_key, &p_stage->key.vs, sizeof(struct v3d_vs_key));
|
||||
|
||||
cmd_buffer_populate_v3d_key(&local_key.base, cmd_buffer);
|
||||
|
||||
variant = v3dv_get_shader_variant(p_stage, &local_key.base,
|
||||
sizeof(struct v3d_vs_key));
|
||||
|
||||
if (p_stage->current_variant != variant) {
|
||||
p_stage->current_variant = variant;
|
||||
/* FIXME: we need to set any dirty flag here? */
|
||||
}
|
||||
|
||||
p_stage = cmd_buffer->state.pipeline->vs_bin;
|
||||
memcpy(&local_key, &p_stage->key.vs, sizeof(struct v3d_vs_key));
|
||||
|
||||
cmd_buffer_populate_v3d_key(&local_key.base, cmd_buffer);
|
||||
variant = v3dv_get_shader_variant(p_stage, &local_key.base,
|
||||
sizeof(struct v3d_vs_key));
|
||||
|
||||
if (p_stage->current_variant != variant) {
|
||||
p_stage->current_variant = variant;
|
||||
/* FIXME: we need to set any dirty flag here? */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some updates on the cmd buffer requires also updates on the shader being
|
||||
* compiled at the pipeline. The poster boy here are textures, as the compiler
|
||||
* needs to do certain things depending on the texture format. So here we
|
||||
* re-create the v3d_keys and update the variant. Note that internally the
|
||||
* pipeline has a variant cache (hash table) to avoid unneeded compilations
|
||||
*/
|
||||
static void
|
||||
update_pipeline_variants(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
assert(cmd_buffer->state.pipeline);
|
||||
|
||||
update_fs_variant(cmd_buffer);
|
||||
update_vs_variant(cmd_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_graphics_pipeline(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
struct v3dv_pipeline *pipeline)
|
||||
|
@ -1768,6 +1882,12 @@ bind_graphics_pipeline(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
cmd_buffer_bind_pipeline_static_state(cmd_buffer, &pipeline->dynamic_state);
|
||||
cmd_buffer_update_ez_state(cmd_buffer, pipeline);
|
||||
|
||||
if (cmd_buffer->state.dirty & V3DV_CMD_DIRTY_SHADER_VARIANTS) {
|
||||
update_pipeline_variants(cmd_buffer);
|
||||
|
||||
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_SHADER_VARIANTS;
|
||||
}
|
||||
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_PIPELINE;
|
||||
}
|
||||
|
||||
|
@ -2787,6 +2907,12 @@ v3dv_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
|
|||
}
|
||||
}
|
||||
|
||||
if (cmd_buffer->state.pipeline) {
|
||||
update_pipeline_variants(cmd_buffer);
|
||||
} else {
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_SHADER_VARIANTS;
|
||||
}
|
||||
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DESCRIPTOR_SETS;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,55 @@
|
|||
|
||||
#include "v3dv_private.h"
|
||||
|
||||
static bool
|
||||
descriptor_type_is_dynamic(VkDescriptorType type)
|
||||
{
|
||||
switch (type) {
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct v3dv_descriptor *
|
||||
v3dv_descriptor_map_get_descriptor(struct v3dv_descriptor_state *descriptor_state,
|
||||
struct v3dv_descriptor_map *map,
|
||||
struct v3dv_pipeline_layout *pipeline_layout,
|
||||
uint32_t index,
|
||||
uint32_t *dynamic_offset)
|
||||
{
|
||||
assert(index >= 0 && index < map->num_desc);
|
||||
|
||||
uint32_t set_number = map->set[index];
|
||||
assert(descriptor_state->valid & 1 << set_number);
|
||||
|
||||
struct v3dv_descriptor_set *set =
|
||||
descriptor_state->descriptor_sets[set_number];
|
||||
assert(set);
|
||||
|
||||
uint32_t binding_number = map->binding[index];
|
||||
assert(binding_number < set->layout->binding_count);
|
||||
|
||||
const struct v3dv_descriptor_set_binding_layout *binding_layout =
|
||||
&set->layout->binding[binding_number];
|
||||
|
||||
uint32_t array_index = map->array_index[index];
|
||||
assert(array_index < binding_layout->array_size);
|
||||
|
||||
if (descriptor_type_is_dynamic(binding_layout->type)) {
|
||||
uint32_t dynamic_offset_index =
|
||||
pipeline_layout->set[set_number].dynamic_offset_start +
|
||||
binding_layout->dynamic_offset_index + array_index;
|
||||
|
||||
*dynamic_offset = descriptor_state->dynamic_offsets[dynamic_offset_index];
|
||||
}
|
||||
|
||||
return &set->descriptors[binding_layout->descriptor_index + array_index];
|
||||
}
|
||||
|
||||
/*
|
||||
* As anv and tu already points:
|
||||
*
|
||||
|
|
|
@ -308,6 +308,16 @@ v3dv_get_format_swizzle(VkFormat f)
|
|||
return vf->swizzle;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
v3dv_get_tex_return_size(const struct v3dv_format *vf,
|
||||
enum pipe_tex_compare compare)
|
||||
{
|
||||
if (compare == PIPE_TEX_COMPARE_R_TO_TEXTURE)
|
||||
return 16;
|
||||
|
||||
return vf->return_size;
|
||||
}
|
||||
|
||||
static bool
|
||||
format_supports_blending(const struct v3dv_format *format)
|
||||
{
|
||||
|
|
|
@ -1056,10 +1056,10 @@ upload_assembly(struct v3dv_pipeline_stage *p_stage,
|
|||
* already compiled, it gets it from the p_stage cache, if not it compiles is
|
||||
* through the v3d compiler
|
||||
*/
|
||||
static struct v3dv_shader_variant*
|
||||
get_shader_variant(struct v3dv_pipeline_stage *p_stage,
|
||||
struct v3d_key *key,
|
||||
size_t key_size)
|
||||
struct v3dv_shader_variant*
|
||||
v3dv_get_shader_variant(struct v3dv_pipeline_stage *p_stage,
|
||||
struct v3d_key *key,
|
||||
size_t key_size)
|
||||
{
|
||||
struct hash_table *ht = p_stage->cache;
|
||||
struct hash_entry *entry = _mesa_hash_table_search(ht, key);
|
||||
|
@ -1359,12 +1359,12 @@ pipeline_compile_graphics(struct v3dv_pipeline *pipeline,
|
|||
struct v3d_vs_key *key = &pipeline->vs->key.vs;
|
||||
pipeline_populate_v3d_vs_key(key, pCreateInfo, pipeline->vs);
|
||||
pipeline->vs->current_variant =
|
||||
get_shader_variant(pipeline->vs, &key->base, sizeof(*key));
|
||||
v3dv_get_shader_variant(pipeline->vs, &key->base, sizeof(*key));
|
||||
|
||||
key = &pipeline->vs_bin->key.vs;
|
||||
pipeline_populate_v3d_vs_key(key, pCreateInfo, pipeline->vs_bin);
|
||||
pipeline->vs_bin->current_variant =
|
||||
get_shader_variant(pipeline->vs_bin, &key->base, sizeof(*key));
|
||||
v3dv_get_shader_variant(pipeline->vs_bin, &key->base, sizeof(*key));
|
||||
break;
|
||||
}
|
||||
case MESA_SHADER_FRAGMENT: {
|
||||
|
@ -1377,7 +1377,7 @@ pipeline_compile_graphics(struct v3dv_pipeline *pipeline,
|
|||
lower_fs_io(p_stage->nir);
|
||||
|
||||
p_stage->current_variant =
|
||||
get_shader_variant(p_stage, &key->base, sizeof(*key));
|
||||
v3dv_get_shader_variant(p_stage, &key->base, sizeof(*key));
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -526,6 +526,7 @@ enum v3dv_cmd_dirty_bits {
|
|||
V3DV_CMD_DIRTY_DESCRIPTOR_SETS = 1 << 7,
|
||||
V3DV_CMD_DIRTY_PUSH_CONSTANTS = 1 << 8,
|
||||
V3DV_CMD_DIRTY_BLEND_CONSTANTS = 1 << 9,
|
||||
V3DV_CMD_DIRTY_SHADER_VARIANTS = 1 << 10,
|
||||
};
|
||||
|
||||
|
||||
|
@ -1126,6 +1127,8 @@ void v3dv_loge_v(const char *format, va_list va);
|
|||
const struct v3dv_format *v3dv_get_format(VkFormat);
|
||||
const uint8_t *v3dv_get_format_swizzle(VkFormat f);
|
||||
void v3dv_get_internal_type_bpp_for_output_format(uint32_t format, uint32_t *type, uint32_t *bpp);
|
||||
uint8_t v3dv_get_tex_return_size(const struct v3dv_format *vf, enum pipe_tex_compare compare);
|
||||
|
||||
|
||||
uint32_t v3d_utile_width(int cpp);
|
||||
uint32_t v3d_utile_height(int cpp);
|
||||
|
@ -1145,6 +1148,18 @@ void v3d_store_tiled_image(void *dst, uint32_t dst_stride,
|
|||
struct v3dv_cl_reloc v3dv_write_uniforms(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
struct v3dv_pipeline_stage *p_stage);
|
||||
|
||||
struct v3dv_shader_variant *
|
||||
v3dv_get_shader_variant(struct v3dv_pipeline_stage *p_stage,
|
||||
struct v3d_key *key,
|
||||
size_t key_size);
|
||||
|
||||
struct v3dv_descriptor *
|
||||
v3dv_descriptor_map_get_descriptor(struct v3dv_descriptor_state *descriptor_state,
|
||||
struct v3dv_descriptor_map *map,
|
||||
struct v3dv_pipeline_layout *pipeline_layout,
|
||||
uint32_t index,
|
||||
uint32_t *dynamic_offset);
|
||||
|
||||
#define V3DV_DEFINE_HANDLE_CASTS(__v3dv_type, __VkType) \
|
||||
\
|
||||
static inline struct __v3dv_type * \
|
||||
|
|
|
@ -28,56 +28,6 @@
|
|||
#include "v3dv_private.h"
|
||||
#include "vk_format_info.h"
|
||||
|
||||
static bool
|
||||
descriptor_type_is_dynamic(VkDescriptorType type)
|
||||
{
|
||||
switch (type) {
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct v3dv_descriptor *
|
||||
get_descriptor(struct v3dv_descriptor_state *descriptor_state,
|
||||
struct v3dv_descriptor_map *map,
|
||||
struct v3dv_pipeline_layout *pipeline_layout,
|
||||
uint32_t index,
|
||||
uint32_t *dynamic_offset)
|
||||
{
|
||||
assert(index >= 0 && index < map->num_desc);
|
||||
|
||||
uint32_t set_number = map->set[index];
|
||||
assert(descriptor_state->valid & 1 << set_number);
|
||||
|
||||
struct v3dv_descriptor_set *set =
|
||||
descriptor_state->descriptor_sets[set_number];
|
||||
assert(set);
|
||||
|
||||
uint32_t binding_number = map->binding[index];
|
||||
assert(binding_number < set->layout->binding_count);
|
||||
|
||||
const struct v3dv_descriptor_set_binding_layout *binding_layout =
|
||||
&set->layout->binding[binding_number];
|
||||
|
||||
uint32_t array_index = map->array_index[index];
|
||||
assert(array_index < binding_layout->array_size);
|
||||
|
||||
if (descriptor_type_is_dynamic(binding_layout->type)) {
|
||||
uint32_t dynamic_offset_index =
|
||||
pipeline_layout->set[set_number].dynamic_offset_start +
|
||||
binding_layout->dynamic_offset_index + array_index;
|
||||
|
||||
*dynamic_offset = descriptor_state->dynamic_offsets[dynamic_offset_index];
|
||||
}
|
||||
|
||||
return &set->descriptors[binding_layout->descriptor_index + array_index];
|
||||
}
|
||||
|
||||
/*
|
||||
* This method checks if the ubo used for push constants is needed to be
|
||||
* updated or not.
|
||||
|
@ -145,8 +95,8 @@ write_tmu_p0(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
&cmd_buffer->state.descriptor_state;
|
||||
|
||||
struct v3dv_descriptor *descriptor =
|
||||
get_descriptor(descriptor_state, &pipeline->texture_map,
|
||||
pipeline->layout, unit, NULL);
|
||||
v3dv_descriptor_map_get_descriptor(descriptor_state, &pipeline->texture_map,
|
||||
pipeline->layout, unit, NULL);
|
||||
|
||||
assert(descriptor);
|
||||
assert(descriptor->image_view);
|
||||
|
@ -172,8 +122,8 @@ write_tmu_p1(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
&cmd_buffer->state.descriptor_state;
|
||||
|
||||
struct v3dv_descriptor *descriptor =
|
||||
get_descriptor(descriptor_state, &pipeline->sampler_map,
|
||||
pipeline->layout, unit, NULL);
|
||||
v3dv_descriptor_map_get_descriptor(descriptor_state, &pipeline->sampler_map,
|
||||
pipeline->layout, unit, NULL);
|
||||
|
||||
assert(descriptor);
|
||||
assert(descriptor->sampler);
|
||||
|
@ -230,9 +180,9 @@ write_ubo_ssbo_uniforms(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
data;
|
||||
|
||||
struct v3dv_descriptor *descriptor =
|
||||
get_descriptor(descriptor_state, map,
|
||||
pipeline->layout,
|
||||
index, &dynamic_offset);
|
||||
v3dv_descriptor_map_get_descriptor(descriptor_state, map,
|
||||
pipeline->layout,
|
||||
index, &dynamic_offset);
|
||||
assert(descriptor);
|
||||
assert(descriptor->buffer);
|
||||
|
||||
|
|
Loading…
Reference in New Issue