diff --git a/docs/features.txt b/docs/features.txt index 9433b2cbd45..95d1c589f93 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -578,7 +578,7 @@ Khronos extensions that are not part of any Vulkan version: VK_EXT_shader_module_identifier DONE (anv, radv, tu) VK_EXT_transform_feedback DONE (anv, lvp, radv, tu, vn) VK_EXT_vertex_attribute_divisor DONE (anv, radv, lvp, tu, v3dv) - VK_EXT_vertex_input_dynamic_state DONE (lvp, radv) + VK_EXT_vertex_input_dynamic_state DONE (lvp, radv, tu) VK_EXT_ycbcr_image_arrays DONE (anv, radv) VK_ANDROID_external_memory_android_hardware_buffer DONE (anv, radv, vn) VK_ANDROID_native_buffer DONE (anv, radv, tu, v3dv, vn) diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index 52d15a4984d..f4c8ed40fd7 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -1867,6 +1867,105 @@ tu_BeginCommandBuffer(VkCommandBuffer commandBuffer, return VK_SUCCESS; } +static void +tu6_emit_vertex_strides(struct tu_cmd_buffer *cmd, unsigned num_vbs) +{ + struct tu_cs cs; + cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].iova = + tu_cs_draw_state(&cmd->sub_cs, &cs, 2 * num_vbs).iova; + + for (uint32_t i = 0; i < num_vbs; i++) + tu_cs_emit_regs(&cs, A6XX_VFD_FETCH_STRIDE(i, cmd->state.vb[i].stride)); + + cmd->state.dirty |= TU_CMD_DIRTY_VB_STRIDE; +} + +static struct tu_cs +tu_cmd_dynamic_state(struct tu_cmd_buffer *cmd, uint32_t id, uint32_t size) +{ + struct tu_cs cs; + + assert(id < ARRAY_SIZE(cmd->state.dynamic_state)); + cmd->state.dynamic_state[id] = tu_cs_draw_state(&cmd->sub_cs, &cs, size); + + /* note: this also avoids emitting draw states before renderpass clears, + * which may use the 3D clear path (for MSAA cases) + */ + if (cmd->state.dirty & TU_CMD_DIRTY_DRAW_STATE) + return cs; + + tu_cs_emit_pkt7(&cmd->draw_cs, CP_SET_DRAW_STATE, 3); + tu_cs_emit_draw_state(&cmd->draw_cs, TU_DRAW_STATE_DYNAMIC + id, cmd->state.dynamic_state[id]); + + return cs; +} + +static void +tu_cmd_end_dynamic_state(struct tu_cmd_buffer *cmd, struct tu_cs *cs, + uint32_t id) +{ + assert(id < ARRAY_SIZE(cmd->state.dynamic_state)); + cmd->state.dynamic_state[id] = tu_cs_end_draw_state(&cmd->sub_cs, cs); + + /* note: this also avoids emitting draw states before renderpass clears, + * which may use the 3D clear path (for MSAA cases) + */ + if (cmd->state.dirty & TU_CMD_DIRTY_DRAW_STATE) + return; + + tu_cs_emit_pkt7(&cmd->draw_cs, CP_SET_DRAW_STATE, 3); + tu_cs_emit_draw_state(&cmd->draw_cs, TU_DRAW_STATE_DYNAMIC + id, cmd->state.dynamic_state[id]); +} + +static void +tu_update_num_vbs(struct tu_cmd_buffer *cmd, unsigned num_vbs) +{ + /* the vertex_buffers draw state always contains all the currently + * bound vertex buffers. update its size to only emit the vbs which + * are actually used by the pipeline + * note there is a HW optimization which makes it so the draw state + * is not re-executed completely when only the size changes + */ + if (cmd->state.vertex_buffers.size != num_vbs * 4) { + cmd->state.vertex_buffers.size = num_vbs * 4; + cmd->state.dirty |= TU_CMD_DIRTY_VERTEX_BUFFERS; + } + + if (cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].size != num_vbs * 2) { + cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].size = num_vbs * 2; + cmd->state.dirty |= TU_CMD_DIRTY_VB_STRIDE; + } +} + +VKAPI_ATTR void VKAPI_CALL +tu_CmdSetVertexInputEXT(VkCommandBuffer commandBuffer, + uint32_t vertexBindingDescriptionCount, + const VkVertexInputBindingDescription2EXT *pVertexBindingDescriptions, + uint32_t vertexAttributeDescriptionCount, + const VkVertexInputAttributeDescription2EXT *pVertexAttributeDescriptions) +{ + TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer); + struct tu_cs cs; + + unsigned num_vbs = 0; + for (unsigned i = 0; i < vertexBindingDescriptionCount; i++) { + const VkVertexInputBindingDescription2EXT *binding = + &pVertexBindingDescriptions[i]; + num_vbs = MAX2(num_vbs, binding->binding + 1); + cmd->state.vb[binding->binding].stride = binding->stride; + } + + tu6_emit_vertex_strides(cmd, num_vbs); + tu_update_num_vbs(cmd, num_vbs); + + tu_cs_begin_sub_stream(&cmd->sub_cs, TU6_EMIT_VERTEX_INPUT_MAX_DWORDS, &cs); + tu6_emit_vertex_input(&cs, vertexBindingDescriptionCount, + pVertexBindingDescriptions, + vertexAttributeDescriptionCount, + pVertexAttributeDescriptions); + tu_cmd_end_dynamic_state(cmd, &cs, TU_DYNAMIC_STATE_VERTEX_INPUT); +} + VKAPI_ATTR void VKAPI_CALL tu_CmdBindVertexBuffers2EXT(VkCommandBuffer commandBuffer, uint32_t firstBinding, @@ -1903,15 +2002,8 @@ tu_CmdBindVertexBuffers2EXT(VkCommandBuffer commandBuffer, cmd->state.dirty |= TU_CMD_DIRTY_VERTEX_BUFFERS; - if (pStrides) { - cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].iova = - tu_cs_draw_state(&cmd->sub_cs, &cs, 2 * MAX_VBS).iova; - - for (uint32_t i = 0; i < MAX_VBS; i++) - tu_cs_emit_regs(&cs, A6XX_VFD_FETCH_STRIDE(i, cmd->state.vb[i].stride)); - - cmd->state.dirty |= TU_CMD_DIRTY_VB_STRIDE; - } + if (pStrides) + tu6_emit_vertex_strides(cmd, MAX_VBS); } VKAPI_ATTR void VKAPI_CALL @@ -2390,26 +2482,6 @@ tu_EndCommandBuffer(VkCommandBuffer commandBuffer) return cmd_buffer->record_result; } -static struct tu_cs -tu_cmd_dynamic_state(struct tu_cmd_buffer *cmd, uint32_t id, uint32_t size) -{ - struct tu_cs cs; - - assert(id < ARRAY_SIZE(cmd->state.dynamic_state)); - cmd->state.dynamic_state[id] = tu_cs_draw_state(&cmd->sub_cs, &cs, size); - - /* note: this also avoids emitting draw states before renderpass clears, - * which may use the 3D clear path (for MSAA cases) - */ - if (cmd->state.dirty & TU_CMD_DIRTY_DRAW_STATE) - return cs; - - tu_cs_emit_pkt7(&cmd->draw_cs, CP_SET_DRAW_STATE, 3); - tu_cs_emit_draw_state(&cmd->draw_cs, TU_DRAW_STATE_DYNAMIC + id, cmd->state.dynamic_state[id]); - - return cs; -} - VKAPI_ATTR void VKAPI_CALL tu_CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, @@ -2438,11 +2510,10 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer, if (!(cmd->state.dirty & TU_CMD_DIRTY_DRAW_STATE)) { uint32_t mask = ~pipeline->dynamic_state_mask & BITFIELD_MASK(TU_DYNAMIC_STATE_COUNT); - tu_cs_emit_pkt7(cs, CP_SET_DRAW_STATE, 3 * (7 + util_bitcount(mask))); + tu_cs_emit_pkt7(cs, CP_SET_DRAW_STATE, 3 * (6 + util_bitcount(mask))); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM_CONFIG, pipeline->program.config_state); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM, pipeline->program.state); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM_BINNING, pipeline->program.binning_state); - tu_cs_emit_draw_state(cs, TU_DRAW_STATE_VI, pipeline->vi.state); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_RAST, pipeline->rast_state); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PRIM_MODE_SYSMEM, pipeline->prim_order_state_sysmem); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PRIM_MODE_GMEM, pipeline->prim_order_state_gmem); @@ -2486,22 +2557,8 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer, cmd->state.dirty |= TU_CMD_DIRTY_VIEWPORTS; } - /* the vertex_buffers draw state always contains all the currently - * bound vertex buffers. update its size to only emit the vbs which - * are actually used by the pipeline - * note there is a HW optimization which makes it so the draw state - * is not re-executed completely when only the size changes - */ - if (cmd->state.vertex_buffers.size != pipeline->num_vbs * 4) { - cmd->state.vertex_buffers.size = pipeline->num_vbs * 4; - cmd->state.dirty |= TU_CMD_DIRTY_VERTEX_BUFFERS; - } - - if ((pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_VB_STRIDE)) && - cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].size != pipeline->num_vbs * 2) { - cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].size = pipeline->num_vbs * 2; - cmd->state.dirty |= TU_CMD_DIRTY_VB_STRIDE; - } + if (!(pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_VERTEX_INPUT))) + tu_update_num_vbs(cmd, pipeline->num_vbs); #define UPDATE_REG(X, Y) { \ /* note: would be better to have pipeline bits already masked */ \ @@ -4478,7 +4535,6 @@ tu6_draw_common(struct tu_cmd_buffer *cmd, tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM_CONFIG, pipeline->program.config_state); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM, pipeline->program.state); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM_BINNING, pipeline->program.binning_state); - tu_cs_emit_draw_state(cs, TU_DRAW_STATE_VI, pipeline->vi.state); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_RAST, pipeline->rast_state); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PRIM_MODE_SYSMEM, pipeline->prim_order_state_sysmem); tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PRIM_MODE_GMEM, pipeline->prim_order_state_gmem); diff --git a/src/freedreno/vulkan/tu_cmd_buffer.h b/src/freedreno/vulkan/tu_cmd_buffer.h index 19e842729b0..e49e5e4d6af 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.h +++ b/src/freedreno/vulkan/tu_cmd_buffer.h @@ -25,7 +25,6 @@ enum tu_draw_state_group_id TU_DRAW_STATE_PROGRAM, TU_DRAW_STATE_PROGRAM_BINNING, TU_DRAW_STATE_VB, - TU_DRAW_STATE_VI, TU_DRAW_STATE_RAST, TU_DRAW_STATE_CONST, TU_DRAW_STATE_DESC_SETS, diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index ebaebf52bef..4114a047460 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -212,6 +212,7 @@ get_device_extensions(const struct tu_physical_device *device, .EXT_image_view_min_lod = true, .EXT_pipeline_creation_feedback = true, .EXT_pipeline_creation_cache_control = true, + .EXT_vertex_input_dynamic_state = true, #ifndef TU_USE_KGSL .EXT_physical_device_drm = true, #endif @@ -900,6 +901,12 @@ tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, features->shaderModuleIdentifier = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: { + VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *features = + (VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *)ext; + features->vertexInputDynamicState = true; + break; + } default: break; diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index d3f77060b56..412152d3858 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -1851,63 +1851,42 @@ tu6_emit_program(struct tu_cs *cs, } } -#define TU6_EMIT_VERTEX_INPUT_MAX_DWORDS (MAX_VERTEX_ATTRIBS * 2 + 1) - -static void -tu6_emit_vertex_input(struct tu_pipeline *pipeline, - struct tu_draw_state *vi_state, - const VkPipelineVertexInputStateCreateInfo *info) +void +tu6_emit_vertex_input(struct tu_cs *cs, + uint32_t binding_count, + const VkVertexInputBindingDescription2EXT *bindings, + uint32_t unsorted_attr_count, + const VkVertexInputAttributeDescription2EXT *unsorted_attrs) { uint32_t binding_instanced = 0; /* bitmask of instanced bindings */ uint32_t step_rate[MAX_VBS]; - struct tu_cs cs; - tu_cs_begin_sub_stream(&pipeline->cs, - TU6_EMIT_VERTEX_INPUT_MAX_DWORDS, &cs); - - for (uint32_t i = 0; i < info->vertexBindingDescriptionCount; i++) { - const VkVertexInputBindingDescription *binding = - &info->pVertexBindingDescriptions[i]; - - if (!(pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_VB_STRIDE))) { - tu_cs_emit_regs(&cs, - A6XX_VFD_FETCH_STRIDE(binding->binding, binding->stride)); - } + for (uint32_t i = 0; i < binding_count; i++) { + const VkVertexInputBindingDescription2EXT *binding = &bindings[i]; if (binding->inputRate == VK_VERTEX_INPUT_RATE_INSTANCE) - binding_instanced |= 1 << binding->binding; + binding_instanced |= 1u << binding->binding; - step_rate[binding->binding] = 1; + step_rate[binding->binding] = binding->divisor; } - const VkPipelineVertexInputDivisorStateCreateInfoEXT *div_state = - vk_find_struct_const(info->pNext, PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT); - if (div_state) { - for (uint32_t i = 0; i < div_state->vertexBindingDivisorCount; i++) { - const VkVertexInputBindingDivisorDescriptionEXT *desc = - &div_state->pVertexBindingDivisors[i]; - step_rate[desc->binding] = desc->divisor; - } - } - - const VkVertexInputAttributeDescription *attrs[MAX_VERTEX_ATTRIBS] = { }; + const VkVertexInputAttributeDescription2EXT *attrs[MAX_VERTEX_ATTRIBS] = { }; unsigned attr_count = 0; - for (uint32_t i = 0; i < info->vertexAttributeDescriptionCount; i++) { - const VkVertexInputAttributeDescription *attr = - &info->pVertexAttributeDescriptions[i]; + for (uint32_t i = 0; i < unsorted_attr_count; i++) { + const VkVertexInputAttributeDescription2EXT *attr = &unsorted_attrs[i]; attrs[attr->location] = attr; attr_count = MAX2(attr_count, attr->location + 1); } if (attr_count != 0) - tu_cs_emit_pkt4(&cs, REG_A6XX_VFD_DECODE_INSTR(0), attr_count * 2); + tu_cs_emit_pkt4(cs, REG_A6XX_VFD_DECODE_INSTR(0), attr_count * 2); for (uint32_t loc = 0; loc < attr_count; loc++) { - const VkVertexInputAttributeDescription *attr = attrs[loc]; + const VkVertexInputAttributeDescription2EXT *attr = attrs[loc]; if (attr) { const struct tu_native_format format = tu6_format_vtx(attr->format); - tu_cs_emit(&cs, A6XX_VFD_DECODE_INSTR(0, + tu_cs_emit(cs, A6XX_VFD_DECODE_INSTR(0, .idx = attr->binding, .offset = attr->offset, .instanced = binding_instanced & (1 << attr->binding), @@ -1915,14 +1894,12 @@ tu6_emit_vertex_input(struct tu_pipeline *pipeline, .swap = format.swap, .unk30 = 1, ._float = !vk_format_is_int(attr->format)).value); - tu_cs_emit(&cs, A6XX_VFD_DECODE_STEP_RATE(0, step_rate[attr->binding]).value); + tu_cs_emit(cs, A6XX_VFD_DECODE_STEP_RATE(0, step_rate[attr->binding]).value); } else { - tu_cs_emit(&cs, 0); - tu_cs_emit(&cs, 0); + tu_cs_emit(cs, 0); + tu_cs_emit(cs, 0); } } - - *vi_state = tu_cs_end_draw_state(&pipeline->cs, &cs); } void @@ -3212,6 +3189,10 @@ tu_pipeline_builder_parse_dynamic(struct tu_pipeline_builder *builder, */ pipeline->dynamic_state_mask |= BIT(TU_DYNAMIC_STATE_COLOR_WRITE_ENABLE); break; + case VK_DYNAMIC_STATE_VERTEX_INPUT_EXT: + pipeline->dynamic_state_mask |= BIT(TU_DYNAMIC_STATE_VERTEX_INPUT) | + BIT(TU_DYNAMIC_STATE_VB_STRIDE); + break; default: assert(!"unsupported dynamic state"); break; @@ -3274,33 +3255,6 @@ tu_pipeline_builder_parse_shader_stages(struct tu_pipeline_builder *builder, } } -static void -tu_pipeline_builder_parse_vertex_input(struct tu_pipeline_builder *builder, - struct tu_pipeline *pipeline) -{ - const VkPipelineVertexInputStateCreateInfo *vi_info = - builder->create_info->pVertexInputState; - - /* Bindings may contain holes */ - for (unsigned i = 0; i < vi_info->vertexBindingDescriptionCount; i++) { - pipeline->num_vbs = - MAX2(pipeline->num_vbs, vi_info->pVertexBindingDescriptions[i].binding + 1); - } - - tu6_emit_vertex_input(pipeline, &pipeline->vi.state, vi_info); -} - -static void -tu_pipeline_builder_parse_input_assembly(struct tu_pipeline_builder *builder, - struct tu_pipeline *pipeline) -{ - const VkPipelineInputAssemblyStateCreateInfo *ia_info = - builder->create_info->pInputAssemblyState; - - pipeline->ia.primtype = tu6_primtype(ia_info->topology); - pipeline->ia.primitive_restart = ia_info->primitiveRestartEnable; -} - static bool tu_pipeline_static_state(struct tu_pipeline *pipeline, struct tu_cs *cs, uint32_t id, uint32_t size) @@ -3314,6 +3268,90 @@ tu_pipeline_static_state(struct tu_pipeline *pipeline, struct tu_cs *cs, return true; } +static void +tu_pipeline_builder_parse_vertex_input(struct tu_pipeline_builder *builder, + struct tu_pipeline *pipeline) +{ + if (pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_VERTEX_INPUT)) + return; + + const VkPipelineVertexInputStateCreateInfo *vi_info = + builder->create_info->pVertexInputState; + + struct tu_cs cs; + if (tu_pipeline_static_state(pipeline, &cs, TU_DYNAMIC_STATE_VB_STRIDE, + 2 * vi_info->vertexBindingDescriptionCount)) { + for (uint32_t i = 0; i < vi_info->vertexBindingDescriptionCount; i++) { + const VkVertexInputBindingDescription *binding = + &vi_info->pVertexBindingDescriptions[i]; + + tu_cs_emit_regs(&cs, + A6XX_VFD_FETCH_STRIDE(binding->binding, binding->stride)); + } + } + + VkVertexInputBindingDescription2EXT bindings[MAX_VBS]; + VkVertexInputAttributeDescription2EXT attrs[MAX_VERTEX_ATTRIBS]; + + for (unsigned i = 0; i < vi_info->vertexBindingDescriptionCount; i++) { + const VkVertexInputBindingDescription *binding = + &vi_info->pVertexBindingDescriptions[i]; + bindings[i] = (VkVertexInputBindingDescription2EXT) { + .sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, + .pNext = NULL, + .binding = binding->binding, + .inputRate = binding->inputRate, + .stride = binding->stride, + .divisor = 1, + }; + + /* Bindings may contain holes */ + pipeline->num_vbs = MAX2(pipeline->num_vbs, binding->binding + 1); + } + + const VkPipelineVertexInputDivisorStateCreateInfoEXT *div_state = + vk_find_struct_const(vi_info->pNext, PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT); + if (div_state) { + for (uint32_t i = 0; i < div_state->vertexBindingDivisorCount; i++) { + const VkVertexInputBindingDivisorDescriptionEXT *desc = + &div_state->pVertexBindingDivisors[i]; + bindings[desc->binding].divisor = desc->divisor; + } + } + + for (unsigned i = 0; i < vi_info->vertexAttributeDescriptionCount; i++) { + const VkVertexInputAttributeDescription *attr = + &vi_info->pVertexAttributeDescriptions[i]; + attrs[i] = (VkVertexInputAttributeDescription2EXT) { + .sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, + .pNext = NULL, + .binding = attr->binding, + .location = attr->location, + .offset = attr->offset, + .format = attr->format, + }; + } + + tu_cs_begin_sub_stream(&pipeline->cs, + TU6_EMIT_VERTEX_INPUT_MAX_DWORDS, &cs); + tu6_emit_vertex_input(&cs, + vi_info->vertexBindingDescriptionCount, bindings, + vi_info->vertexAttributeDescriptionCount, attrs); + pipeline->dynamic_state[TU_DYNAMIC_STATE_VERTEX_INPUT] = + tu_cs_end_draw_state(&pipeline->cs, &cs); +} + +static void +tu_pipeline_builder_parse_input_assembly(struct tu_pipeline_builder *builder, + struct tu_pipeline *pipeline) +{ + const VkPipelineInputAssemblyStateCreateInfo *ia_info = + builder->create_info->pInputAssemblyState; + + pipeline->ia.primtype = tu6_primtype(ia_info->topology); + pipeline->ia.primitive_restart = ia_info->primitiveRestartEnable; +} + static void tu_pipeline_builder_parse_tessellation(struct tu_pipeline_builder *builder, struct tu_pipeline *pipeline) diff --git a/src/freedreno/vulkan/tu_pipeline.h b/src/freedreno/vulkan/tu_pipeline.h index 6b074b4b71b..b6e5247beeb 100644 --- a/src/freedreno/vulkan/tu_pipeline.h +++ b/src/freedreno/vulkan/tu_pipeline.h @@ -26,6 +26,7 @@ enum tu_dynamic_state TU_DYNAMIC_STATE_VB_STRIDE, TU_DYNAMIC_STATE_RASTERIZER_DISCARD, TU_DYNAMIC_STATE_BLEND, + TU_DYNAMIC_STATE_VERTEX_INPUT, TU_DYNAMIC_STATE_COUNT, /* no associated draw state: */ TU_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY = TU_DYNAMIC_STATE_COUNT, @@ -164,11 +165,6 @@ struct tu_pipeline struct tu_program_descriptor_linkage link[MESA_SHADER_STAGES]; } program; - struct - { - struct tu_draw_state state; - } vi; - struct { enum pc_di_primtype primtype; @@ -227,6 +223,14 @@ tu6_emit_depth_bias(struct tu_cs *cs, float clamp, float slope_factor); +#define TU6_EMIT_VERTEX_INPUT_MAX_DWORDS (MAX_VERTEX_ATTRIBS * 2 + 1) + +void tu6_emit_vertex_input(struct tu_cs *cs, + uint32_t binding_count, + const VkVertexInputBindingDescription2EXT *bindings, + uint32_t attr_count, + const VkVertexInputAttributeDescription2EXT *attrs); + uint32_t tu6_rb_mrt_control_rop(VkLogicOp op, bool *rop_reads_dst); struct tu_pvtmem_config {