Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- v4: Use input_register map to find unbound registers. Don't include system values. Bind the null buffer separately from other vertex buffers, so that STREAMSRC does not have to be invalidated when the null binding changes. --- dlls/wined3d/context_vk.c | 62 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 8719d54644b..6dc04f97a8c 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -2005,7 +2005,7 @@ static void wined3d_context_vk_update_blend_state(const struct wined3d_context_v }
static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk *context_vk, - const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout) + const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout, uint32_t *null_buffer_binding) { unsigned int i, attribute_count, binding_count, divisor_count, stage_count; const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info; @@ -2041,6 +2041,9 @@ static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_conte || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC) || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX))) { + struct wined3d_shader *vertex_shader = state->shader[WINED3D_SHADER_TYPE_VERTEX]; + struct wined3d_shader_signature *signature = &vertex_shader->input_signature; + uint32_t unbound_map; wined3d_stream_info_from_declaration(&stream_info, state, d3d_info); divisor_count = 0; for (i = 0, mask = 0, attribute_count = 0, binding_count = 0; i < ARRAY_SIZE(stream_info.elements); ++i) @@ -2080,6 +2083,52 @@ static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_conte } }
+ if ((unbound_map = ~stream_info.use_map & vertex_shader->reg_maps.input_registers)) + { + uint32_t null_binding; + for (i = 0; i < ARRAY_SIZE(state->streams); ++i) + { + if (!state->streams[i].buffer) + { + null_binding = i; + break; + } + } + + if (i == ARRAY_SIZE(state->streams)) + ERR("No streams left for a null buffer binding.\n"); + else + { + VkVertexInputBindingDescription *b; + + for (i = 0; i < signature->element_count; ++i) + { + struct wined3d_shader_signature_element *element = &signature->elements[i]; + uint32_t location = element->register_idx; + VkVertexInputAttributeDescription *a; + + if (!(unbound_map & (1 << location)) || element->sysval_semantic) + continue; + + unbound_map &= ~(1 << location); + + a = &key->attributes[attribute_count++]; + a->location = location; + a->binding = null_binding; + a->format = vk_format_from_component_type(element->component_type); + a->offset = 0; + } + + if (unbound_map != (~stream_info.use_map & vertex_shader->reg_maps.input_registers)) + { + b = &key->bindings[binding_count++]; + *null_buffer_binding = b->binding = null_binding; + b->stride = 0; + b->inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + } + } + } + key->input_desc.pNext = NULL; key->input_desc.vertexBindingDescriptionCount = binding_count; key->input_desc.vertexAttributeDescriptionCount = attribute_count; @@ -2989,6 +3038,7 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c struct wined3d_rendertarget_view *dsv; struct wined3d_buffer_vk *buffer_vk; VkSampleCountFlagBits sample_count; + uint32_t null_buffer_binding = ~0; VkCommandBuffer vk_command_buffer; struct wined3d_buffer *buffer; unsigned int i; @@ -3120,8 +3170,8 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c return VK_NULL_HANDLE; }
- if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout) - || !context_vk->graphics.vk_pipeline) + if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout, + &null_buffer_binding) || !context_vk->graphics.vk_pipeline) { if (!(context_vk->graphics.vk_pipeline = wined3d_context_vk_get_graphics_pipeline(context_vk))) { @@ -3131,6 +3181,12 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
VK_CALL(vkCmdBindPipeline(vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context_vk->graphics.vk_pipeline)); + if (null_buffer_binding != ~0) + { + VkDeviceSize offset = 0; + VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, null_buffer_binding, 1, + &device_vk->null_resources_vk.buffer_info.buffer, &offset)); + } }
if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STENCIL_REF) && dsv)