diff --git a/docs/features.txt b/docs/features.txt index 7028870c62f..610241d8b96 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -107,7 +107,7 @@ GL 3.3, GLSL 3.30 --- all DONE: i965, nv50, nvc0, r600, radeonsi, llvmpipe, soft GL_ARB_texture_rgb10_a2ui DONE (freedreno, swr, zink, panfrost) GL_ARB_texture_swizzle DONE (freedreno, swr, v3d, zink, panfrost) GL_ARB_timer_query DONE (freedreno, swr) - GL_ARB_instanced_arrays DONE (freedreno, swr, v3d, panfrost) + GL_ARB_instanced_arrays DONE (freedreno, swr, v3d, panfrost, zink) GL_ARB_vertex_type_2_10_10_10_rev DONE (freedreno, swr, v3d, panfrost) diff --git a/src/gallium/drivers/zink/zink_pipeline.c b/src/gallium/drivers/zink/zink_pipeline.c index 976c3afc857..f36943a3347 100644 --- a/src/gallium/drivers/zink/zink_pipeline.c +++ b/src/gallium/drivers/zink/zink_pipeline.c @@ -46,6 +46,14 @@ zink_create_gfx_pipeline(struct zink_screen *screen, vertex_input_state.pVertexAttributeDescriptions = state->element_state->attribs; vertex_input_state.vertexAttributeDescriptionCount = state->element_state->num_attribs; + VkPipelineVertexInputDivisorStateCreateInfoEXT vdiv_state = {}; + if (state->divisors_present) { + vertex_input_state.pNext = &vdiv_state; + vdiv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; + vdiv_state.vertexBindingDivisorCount = state->divisors_present; + vdiv_state.pVertexBindingDivisors = state->divisors; + } + VkPipelineInputAssemblyStateCreateInfo primitive_state = {}; primitive_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; primitive_state.topology = primitive_topology; diff --git a/src/gallium/drivers/zink/zink_pipeline.h b/src/gallium/drivers/zink/zink_pipeline.h index 116ce656405..25c9db3ed66 100644 --- a/src/gallium/drivers/zink/zink_pipeline.h +++ b/src/gallium/drivers/zink/zink_pipeline.h @@ -41,6 +41,8 @@ struct zink_gfx_pipeline_state { struct zink_vertex_elements_hw_state *element_state; VkVertexInputBindingDescription bindings[PIPE_MAX_ATTRIBS]; // combination of element_state and stride + VkVertexInputBindingDivisorDescriptionEXT divisors[PIPE_MAX_ATTRIBS]; + uint8_t divisors_present; uint32_t num_attachments; struct zink_blend_state *blend_state; diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 6cec34ac7f1..2c0d59f9b2f 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -98,6 +98,9 @@ zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_TEXCOORD: return 1; + case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: + return screen->have_EXT_vertex_attribute_divisor; + case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: if (!screen->feats.dualSrcBlend) return 0; diff --git a/src/gallium/drivers/zink/zink_state.c b/src/gallium/drivers/zink/zink_state.c index 95f23c273ba..fbb3bd1272f 100644 --- a/src/gallium/drivers/zink/zink_state.c +++ b/src/gallium/drivers/zink/zink_state.c @@ -48,7 +48,6 @@ zink_create_vertex_elements_state(struct pipe_context *pctx, int num_bindings = 0; for (i = 0; i < num_elements; ++i) { const struct pipe_vertex_element *elem = elements + i; - assert(!elem->instance_divisor); int binding = elem->vertex_buffer_index; if (buffer_map[binding] < 0) { @@ -59,7 +58,11 @@ zink_create_vertex_elements_state(struct pipe_context *pctx, ves->bindings[binding].binding = binding; - ves->bindings[binding].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + ves->bindings[binding].inputRate = elem->instance_divisor ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; + + assert(!elem->instance_divisor || zink_screen(pctx->screen)->have_EXT_vertex_attribute_divisor); + ves->divisor[binding] = elem->instance_divisor; + assert(elem->instance_divisor <= screen->max_vertex_attrib_divisor); ves->hw_state.attribs[i].binding = binding; ves->hw_state.attribs[i].location = i; // TODO: unsure @@ -82,12 +85,18 @@ zink_bind_vertex_elements_state(struct pipe_context *pctx, struct zink_gfx_pipeline_state *state = &ctx->gfx_pipeline_state; ctx->element_state = cso; state->hash = 0; + state->divisors_present = 0; if (cso) { state->element_state = &ctx->element_state->hw_state; struct zink_vertex_elements_state *ves = cso; for (int i = 0; i < state->element_state->num_bindings; ++i) { state->bindings[i].binding = ves->bindings[i].binding; state->bindings[i].inputRate = ves->bindings[i].inputRate; + if (ves->divisor[i]) { + state->divisors[state->divisors_present].divisor = ves->divisor[i]; + state->divisors[state->divisors_present].binding = state->bindings[i].binding; + state->divisors_present++; + } } } else state->element_state = NULL; diff --git a/src/gallium/drivers/zink/zink_state.h b/src/gallium/drivers/zink/zink_state.h index ef5e18176d4..5f0bc304da9 100644 --- a/src/gallium/drivers/zink/zink_state.h +++ b/src/gallium/drivers/zink/zink_state.h @@ -38,6 +38,7 @@ struct zink_vertex_elements_state { uint32_t binding; VkVertexInputRate inputRate; } bindings[PIPE_MAX_ATTRIBS]; + uint32_t divisor[PIPE_MAX_ATTRIBS]; uint8_t binding_map[PIPE_MAX_ATTRIBS]; struct zink_vertex_elements_hw_state hw_state; };