diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 18edf0e7da2..4e5734787d1 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -945,7 +945,7 @@ zink_set_vertex_buffers(struct pipe_context *pctx, if (buffers) { if (!zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state) - ctx->gfx_pipeline_state.vertex_state_dirty = true; + ctx->vertex_state_changed = true; for (unsigned i = 0; i < num_buffers; ++i) { const struct pipe_vertex_buffer *vb = buffers + i; struct pipe_vertex_buffer *ctx_vb = &ctx->vertex_buffers[start_slot + i]; @@ -971,7 +971,7 @@ zink_set_vertex_buffers(struct pipe_context *pctx, } } else { if (!zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state) - ctx->gfx_pipeline_state.vertex_state_dirty = true; + ctx->vertex_state_changed = true; for (unsigned i = 0; i < num_buffers; ++i) { update_existing_vbo(ctx, start_slot + i); pipe_resource_reference(&ctx->vertex_buffers[start_slot + i].buffer.resource, NULL); diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index 79499c6c03c..f4ebce713e6 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -303,6 +303,7 @@ struct zink_context { bool have_timelines; bool is_device_lost; + bool vertex_state_changed : 1; bool blend_state_changed : 1; bool rast_state_changed : 1; bool dsa_state_changed : 1; diff --git a/src/gallium/drivers/zink/zink_device_info.py b/src/gallium/drivers/zink/zink_device_info.py index 205e2d6d7f6..133dfd94b3e 100644 --- a/src/gallium/drivers/zink/zink_device_info.py +++ b/src/gallium/drivers/zink/zink_device_info.py @@ -176,6 +176,10 @@ EXTENSIONS = [ alias="line_rast", properties=True, features=True), + Extension("VK_EXT_vertex_input_dynamic_state", + alias="vertex_input", + features=True, + conditions=["$feats.vertexInputDynamicState"]), Extension("VK_KHR_dedicated_allocation", alias="dedicated"), ] diff --git a/src/gallium/drivers/zink/zink_draw.cpp b/src/gallium/drivers/zink/zink_draw.cpp index c06e25d92f8..13d948e9e37 100644 --- a/src/gallium/drivers/zink/zink_draw.cpp +++ b/src/gallium/drivers/zink/zink_draw.cpp @@ -130,7 +130,7 @@ zink_bind_vertex_buffers(struct zink_batch *batch, struct zink_context *ctx) VkBuffer buffers[PIPE_MAX_ATTRIBS]; VkDeviceSize buffer_offsets[PIPE_MAX_ATTRIBS]; VkDeviceSize buffer_strides[PIPE_MAX_ATTRIBS]; - const struct zink_vertex_elements_state *elems = ctx->element_state; + struct zink_vertex_elements_state *elems = ctx->element_state; struct zink_screen *screen = zink_screen(ctx->base.screen); if (!elems->hw_state.num_bindings) @@ -143,12 +143,16 @@ zink_bind_vertex_buffers(struct zink_batch *batch, struct zink_context *ctx) if (vb->buffer.resource) { buffers[i] = ctx->vbufs[buffer_id]; assert(buffers[i]); + if (screen->info.have_EXT_vertex_input_dynamic_state) + elems->hw_state.dynbindings[i].stride = vb->stride; buffer_offsets[i] = ctx->vbuf_offsets[buffer_id]; buffer_strides[i] = vb->stride; } else { buffers[i] = zink_resource(ctx->dummy_vertex_buffer)->obj->buffer; buffer_offsets[i] = 0; buffer_strides[i] = 0; + if (screen->info.have_EXT_vertex_input_dynamic_state) + elems->hw_state.dynbindings[i].stride = 0; } } @@ -160,6 +164,13 @@ zink_bind_vertex_buffers(struct zink_batch *batch, struct zink_context *ctx) vkCmdBindVertexBuffers(batch->state->cmdbuf, 0, elems->hw_state.num_bindings, buffers, buffer_offsets); + + if (screen->info.have_EXT_vertex_input_dynamic_state) + screen->vk.CmdSetVertexInputEXT(batch->state->cmdbuf, + elems->hw_state.num_bindings, elems->hw_state.dynbindings, + elems->hw_state.num_attribs, elems->hw_state.dynattribs); + + ctx->vertex_state_changed = false; ctx->vertex_buffers_dirty = false; } diff --git a/src/gallium/drivers/zink/zink_pipeline.c b/src/gallium/drivers/zink/zink_pipeline.c index 7f5763d28a5..26167b0f06d 100644 --- a/src/gallium/drivers/zink/zink_pipeline.c +++ b/src/gallium/drivers/zink/zink_pipeline.c @@ -51,19 +51,23 @@ zink_create_gfx_pipeline(struct zink_screen *screen, struct zink_gfx_pipeline_state *state, VkPrimitiveTopology primitive_topology) { - VkPipelineVertexInputStateCreateInfo vertex_input_state = {0}; - vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input_state.pVertexBindingDescriptions = state->element_state->bindings; - vertex_input_state.vertexBindingDescriptionCount = state->element_state->num_bindings; - vertex_input_state.pVertexAttributeDescriptions = state->element_state->attribs; - vertex_input_state.vertexAttributeDescriptionCount = state->element_state->num_attribs; + VkPipelineVertexInputStateCreateInfo vertex_input_state; + if (!screen->info.have_EXT_vertex_input_dynamic_state) { + memset(&vertex_input_state, 0, sizeof(vertex_input_state)); + vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_input_state.pVertexBindingDescriptions = state->element_state->b.bindings; + vertex_input_state.vertexBindingDescriptionCount = state->element_state->num_bindings; + vertex_input_state.pVertexAttributeDescriptions = state->element_state->attribs; + vertex_input_state.vertexAttributeDescriptionCount = state->element_state->num_attribs; + } - VkPipelineVertexInputDivisorStateCreateInfoEXT vdiv_state = {0}; - if (state->element_state->divisors_present) { + VkPipelineVertexInputDivisorStateCreateInfoEXT vdiv_state; + if (!screen->info.have_EXT_vertex_input_dynamic_state && state->element_state->b.divisors_present) { + memset(&vdiv_state, 0, sizeof(vdiv_state)); vertex_input_state.pNext = &vdiv_state; vdiv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; - vdiv_state.vertexBindingDivisorCount = state->element_state->divisors_present; - vdiv_state.pVertexBindingDivisors = state->element_state->divisors; + vdiv_state.vertexBindingDivisorCount = state->element_state->b.divisors_present; + vdiv_state.pVertexBindingDivisors = state->element_state->b.divisors; } VkPipelineInputAssemblyStateCreateInfo primitive_state = {0}; @@ -202,6 +206,9 @@ zink_create_gfx_pipeline(struct zink_screen *screen, dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VIEWPORT; dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SCISSOR; } + if (screen->info.have_EXT_vertex_input_dynamic_state) { + dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_EXT; + } VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {0}; pipelineDynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; @@ -212,7 +219,8 @@ zink_create_gfx_pipeline(struct zink_screen *screen, pci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pci.layout = prog->base.layout; pci.renderPass = state->render_pass->render_pass; - pci.pVertexInputState = &vertex_input_state; + if (!screen->info.have_EXT_vertex_input_dynamic_state) + pci.pVertexInputState = &vertex_input_state; pci.pInputAssemblyState = &primitive_state; pci.pRasterizationState = &rast_state; pci.pColorBlendState = &blend_state; diff --git a/src/gallium/drivers/zink/zink_pipeline.h b/src/gallium/drivers/zink/zink_pipeline.h index 2a171a2163e..69464808027 100644 --- a/src/gallium/drivers/zink/zink_pipeline.h +++ b/src/gallium/drivers/zink/zink_pipeline.h @@ -69,7 +69,6 @@ struct zink_gfx_pipeline_state { bool combined_dirty; struct zink_vertex_elements_hw_state *element_state; - bool vertex_state_dirty; uint32_t final_hash; diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index eee98b493ca..de3f1eaacc9 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -764,41 +764,49 @@ zink_get_gfx_pipeline(struct zink_context *ctx, struct zink_gfx_pipeline_state *state, enum pipe_prim_type mode) { - if (!state->dirty && !state->combined_dirty && !state->vertex_state_dirty && mode == state->mode) + struct zink_screen *screen = zink_screen(ctx->base.screen); + const bool have_EXT_vertex_input_dynamic_state = screen->info.have_EXT_vertex_input_dynamic_state; + if (!state->dirty && !state->combined_dirty && mode == state->mode && + (have_EXT_vertex_input_dynamic_state || !ctx->vertex_state_changed)) return state->pipeline; - struct zink_screen *screen = zink_screen(ctx->base.screen); VkPrimitiveTopology vkmode = primitive_topology(mode); assert(vkmode <= ARRAY_SIZE(prog->pipelines)); struct hash_entry *entry = NULL; if (state->dirty) { - state->vertex_state_dirty = state->combined_dirty = true; + if (!have_EXT_vertex_input_dynamic_state) + ctx->vertex_state_changed = true; + state->combined_dirty = true; state->hash = hash_gfx_pipeline_state(state); state->dirty = false; } if (state->combined_dirty) { - state->vertex_state_dirty = true; + if (!have_EXT_vertex_input_dynamic_state) + ctx->vertex_state_changed = true; state->combined_hash = XXH32(&state->module_hash, sizeof(uint32_t), state->hash); state->combined_dirty = false; } - if (state->vertex_state_dirty) { - uint32_t hash = state->combined_hash; - if (!state->have_EXT_extended_dynamic_state) { - /* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */ - uint32_t vertex_buffers_enabled_mask = state->vertex_buffers_enabled_mask; - hash = XXH32(&vertex_buffers_enabled_mask, sizeof(uint32_t), hash); + if (have_EXT_vertex_input_dynamic_state) + state->final_hash = state->combined_hash; + else + if (ctx->vertex_state_changed) { + uint32_t hash = state->combined_hash; + if (!state->have_EXT_extended_dynamic_state) { + /* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */ + uint32_t vertex_buffers_enabled_mask = state->vertex_buffers_enabled_mask; + hash = XXH32(&vertex_buffers_enabled_mask, sizeof(uint32_t), hash); - for (unsigned i = 0; i < state->element_state->num_bindings; i++) { - struct pipe_vertex_buffer *vb = ctx->vertex_buffers + ctx->element_state->binding_map[i]; - state->vertex_strides[i] = vb->buffer.resource ? vb->stride : 0; - hash = XXH32(&state->vertex_strides[i], sizeof(uint32_t), hash); + for (unsigned i = 0; i < state->element_state->num_bindings; i++) { + struct pipe_vertex_buffer *vb = ctx->vertex_buffers + ctx->element_state->binding_map[i]; + state->vertex_strides[i] = vb->buffer.resource ? vb->stride : 0; + hash = XXH32(&state->vertex_strides[i], sizeof(uint32_t), hash); + } } + state->final_hash = XXH32(&state->element_state, sizeof(void*), hash); + ctx->vertex_state_changed = false; } - state->final_hash = XXH32(&state->element_state, sizeof(void*), hash); - state->vertex_state_dirty = false; - } entry = _mesa_hash_table_search_pre_hashed(prog->pipelines[vkmode], state->final_hash, state); if (!entry) { diff --git a/src/gallium/drivers/zink/zink_state.c b/src/gallium/drivers/zink/zink_state.c index 95453cb3c8a..cf8a1ce7643 100644 --- a/src/gallium/drivers/zink/zink_state.c +++ b/src/gallium/drivers/zink/zink_state.c @@ -66,23 +66,45 @@ zink_create_vertex_elements_state(struct pipe_context *pctx, ves->divisor[binding] = elem->instance_divisor; assert(elem->instance_divisor <= screen->info.vdiv_props.maxVertexAttribDivisor); - ves->hw_state.attribs[i].binding = binding; - ves->hw_state.attribs[i].location = i; - ves->hw_state.attribs[i].format = zink_get_format(screen, - elem->src_format); - assert(ves->hw_state.attribs[i].format != VK_FORMAT_UNDEFINED); - ves->hw_state.attribs[i].offset = elem->src_offset; + if (screen->info.have_EXT_vertex_input_dynamic_state) { + ves->hw_state.dynattribs[i].sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT; + ves->hw_state.dynattribs[i].binding = binding; + ves->hw_state.dynattribs[i].location = i; + ves->hw_state.dynattribs[i].format = zink_get_format(screen, + elem->src_format); + assert(ves->hw_state.dynattribs[i].format != VK_FORMAT_UNDEFINED); + ves->hw_state.dynattribs[i].offset = elem->src_offset; + } else { + ves->hw_state.attribs[i].binding = binding; + ves->hw_state.attribs[i].location = i; + ves->hw_state.attribs[i].format = zink_get_format(screen, + elem->src_format); + assert(ves->hw_state.attribs[i].format != VK_FORMAT_UNDEFINED); + ves->hw_state.attribs[i].offset = elem->src_offset; + } } ves->hw_state.num_bindings = num_bindings; ves->hw_state.num_attribs = num_elements; - for (int i = 0; i < num_bindings; ++i) { - ves->hw_state.bindings[i].binding = ves->bindings[i].binding; - ves->hw_state.bindings[i].inputRate = ves->bindings[i].inputRate; - if (ves->divisor[i]) { - ves->hw_state.divisors[ves->hw_state.divisors_present].divisor = ves->divisor[i]; - ves->hw_state.divisors[ves->hw_state.divisors_present].binding = ves->bindings[i].binding; - ves->hw_state.divisors_present++; + if (screen->info.have_EXT_vertex_input_dynamic_state) { + for (int i = 0; i < num_bindings; ++i) { + ves->hw_state.dynbindings[i].sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT; + ves->hw_state.dynbindings[i].binding = ves->bindings[i].binding; + ves->hw_state.dynbindings[i].inputRate = ves->bindings[i].inputRate; + if (ves->divisor[i]) + ves->hw_state.dynbindings[i].divisor = ves->divisor[i]; + else + ves->hw_state.dynbindings[i].divisor = 1; + } + } else { + for (int i = 0; i < num_bindings; ++i) { + ves->hw_state.b.bindings[i].binding = ves->bindings[i].binding; + ves->hw_state.b.bindings[i].inputRate = ves->bindings[i].inputRate; + if (ves->divisor[i]) { + ves->hw_state.b.divisors[ves->hw_state.b.divisors_present].divisor = ves->divisor[i]; + ves->hw_state.b.divisors[ves->hw_state.b.divisors_present].binding = ves->bindings[i].binding; + ves->hw_state.b.divisors_present++; + } } } return ves; @@ -97,7 +119,7 @@ zink_bind_vertex_elements_state(struct pipe_context *pctx, ctx->element_state = cso; if (cso) { if (state->element_state != &ctx->element_state->hw_state) { - state->vertex_state_dirty = true; + ctx->vertex_state_changed = true; ctx->vertex_buffers_dirty = ctx->element_state->hw_state.num_bindings > 0; } state->element_state = &ctx->element_state->hw_state; diff --git a/src/gallium/drivers/zink/zink_state.h b/src/gallium/drivers/zink/zink_state.h index c333afcd9ad..e314a9bed23 100644 --- a/src/gallium/drivers/zink/zink_state.h +++ b/src/gallium/drivers/zink/zink_state.h @@ -29,11 +29,19 @@ #include "pipe/p_state.h" struct zink_vertex_elements_hw_state { - VkVertexInputAttributeDescription attribs[PIPE_MAX_ATTRIBS]; - VkVertexInputBindingDivisorDescriptionEXT divisors[PIPE_MAX_ATTRIBS]; - VkVertexInputBindingDescription bindings[PIPE_MAX_ATTRIBS]; // combination of element_state and stride + union { + VkVertexInputAttributeDescription attribs[PIPE_MAX_ATTRIBS]; + VkVertexInputAttributeDescription2EXT dynattribs[PIPE_MAX_ATTRIBS]; + }; + union { + struct { + VkVertexInputBindingDivisorDescriptionEXT divisors[PIPE_MAX_ATTRIBS]; + VkVertexInputBindingDescription bindings[PIPE_MAX_ATTRIBS]; // combination of element_state and stride + uint8_t divisors_present; + } b; + VkVertexInputBindingDescription2EXT dynbindings[PIPE_MAX_ATTRIBS]; + }; uint32_t num_bindings, num_attribs; - uint8_t divisors_present; }; struct zink_vertex_elements_state {