Mesa (main): zink: EXT_vertex_input_dynamic_state
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Jul 27 00:49:07 UTC 2021
Module: Mesa
Branch: main
Commit: 6691a48bcc617bd8ec3ba248a4fa79ceb25e86e3
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=6691a48bcc617bd8ec3ba248a4fa79ceb25e86e3
Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date: Thu May 13 15:55:43 2021 -0400
zink: EXT_vertex_input_dynamic_state
this eliminates vertex attributes from the pipeline state, massively
deduplicating the number of pipelines needed
Reviewed-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12009>
---
src/gallium/drivers/zink/zink_context.c | 4 +--
src/gallium/drivers/zink/zink_context.h | 1 +
src/gallium/drivers/zink/zink_device_info.py | 4 +++
src/gallium/drivers/zink/zink_draw.cpp | 13 +++++++-
src/gallium/drivers/zink/zink_pipeline.c | 32 +++++++++++-------
src/gallium/drivers/zink/zink_pipeline.h | 1 -
src/gallium/drivers/zink/zink_program.c | 44 ++++++++++++++----------
src/gallium/drivers/zink/zink_state.c | 50 ++++++++++++++++++++--------
src/gallium/drivers/zink/zink_state.h | 16 ++++++---
9 files changed, 113 insertions(+), 52 deletions(-)
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;
-
- VkPipelineVertexInputDivisorStateCreateInfoEXT vdiv_state = {0};
- if (state->element_state->divisors_present) {
+ 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;
+ 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);
-
- 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);
+ 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);
+ }
}
+ 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 {
More information about the mesa-commit
mailing list