--- src/intel/vulkan/genX_pipeline.c | 178 +++++++++++++++++-------------- 1 file changed, 99 insertions(+), 79 deletions(-)
diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c index 297e9455b51..d3c77ecb89b 100644 --- a/src/intel/vulkan/genX_pipeline.c +++ b/src/intel/vulkan/genX_pipeline.c @@ -83,6 +83,8 @@ vertex_element_comp_control(enum isl_format format, unsigned comp) } } +#define DUMMY_64BIT_ATTRIB ((const VkVertexInputAttributeDescription *)1) + static void emit_vertex_input(struct anv_pipeline *pipeline, const VkPipelineVertexInputStateCreateInfo *info) @@ -91,18 +93,40 @@ emit_vertex_input(struct anv_pipeline *pipeline, /* Pull inputs_read out of the VS prog data */ const uint64_t inputs_read = vs_prog_data->inputs_read; - const uint64_t double_inputs_read = - vs_prog_data->double_inputs_read & inputs_read; assert((inputs_read & ((1 << VERT_ATTRIB_GENERIC0) - 1)) == 0); const uint32_t elements = inputs_read >> VERT_ATTRIB_GENERIC0; - const uint32_t elements_double = double_inputs_read >> VERT_ATTRIB_GENERIC0; + const VkVertexInputAttributeDescription *attribs[MAX_VBS] = { }; + + uint32_t elem_count = __builtin_popcount(elements); + for (uint32_t i = 0; i < info->vertexAttributeDescriptionCount; i++) { + const VkVertexInputAttributeDescription *desc = + &info->pVertexAttributeDescriptions[i]; + if ((elements & (1 << desc->location)) == 0) + continue; /* Binding unused */ + + /* Record the description for the second pass. */ + attribs[desc->location] = desc; + + enum isl_format format = anv_get_isl_format(&pipeline->device->info, + desc->format, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_TILING_LINEAR); + + /* 64-bit 3 and 4-channel formats consume two slots in the shader but + * are only one VERTEX_ELEMENT_STATE. + */ + if (isl_format_layouts[format].channels.b.bits == 64) { + assert(elements & (1 << (desc->location + 1))); + attribs[desc->location + 1] = DUMMY_64BIT_ATTRIB; + elem_count--; + } + } + const bool needs_svgs_elem = vs_prog_data->uses_vertexid || vs_prog_data->uses_instanceid || vs_prog_data->uses_firstvertex || vs_prog_data->uses_baseinstance; - uint32_t elem_count = __builtin_popcount(elements) - - __builtin_popcount(elements_double) / 2; const uint32_t total_elems = elem_count + needs_svgs_elem + vs_prog_data->uses_drawid; @@ -117,80 +141,75 @@ emit_vertex_input(struct anv_pipeline *pipeline, if (!p) return; - for (uint32_t i = 0; i < total_elems; i++) { - /* The SKL docs for VERTEX_ELEMENT_STATE say: - * - * "All elements must be valid from Element[0] to the last valid - * element. (I.e. if Element[2] is valid then Element[1] and - * Element[0] must also be valid)." - * - * The SKL docs for 3D_Vertex_Component_Control say: - * - * "Don't store this component. (Not valid for Component 0, but can - * be used for Component 1-3)." - * - * So we can't just leave a vertex element blank and hope for the best. - * We have to tell the VF hardware to put something in it; so we just - * store a bunch of zero. - * - * TODO: Compact vertex elements so we never end up with holes. - */ - struct GENX(VERTEX_ELEMENT_STATE) element = { - .Valid = true, - .Component0Control = VFCOMP_STORE_0, - .Component1Control = VFCOMP_STORE_0, - .Component2Control = VFCOMP_STORE_0, - .Component3Control = VFCOMP_STORE_0, - }; - GENX(VERTEX_ELEMENT_STATE_pack)(NULL, &p[1 + i * 2], &element); - } - - for (uint32_t i = 0; i < info->vertexAttributeDescriptionCount; i++) { - const VkVertexInputAttributeDescription *desc = - &info->pVertexAttributeDescriptions[i]; - enum isl_format format = anv_get_isl_format(&pipeline->device->info, - desc->format, - VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_TILING_LINEAR); - - assert(desc->binding < MAX_VBS); - - if ((elements & (1 << desc->location)) == 0) - continue; /* Binding unused */ - - uint32_t slot = - __builtin_popcount(elements & ((1 << desc->location) - 1)) - - DIV_ROUND_UP(__builtin_popcount(elements_double & - ((1 << desc->location) -1)), 2); + uint32_t loc, slot = 0; + for_each_bit(loc, elements) { + /* The previous VERTEX_ELEMENT_STATE takes two slots */ + if (attribs[loc] == DUMMY_64BIT_ATTRIB) + continue; - struct GENX(VERTEX_ELEMENT_STATE) element = { - .VertexBufferIndex = desc->binding, - .Valid = true, - .SourceElementFormat = format, - .EdgeFlagEnable = false, - .SourceElementOffset = desc->offset, - .Component0Control = vertex_element_comp_control(format, 0), - .Component1Control = vertex_element_comp_control(format, 1), - .Component2Control = vertex_element_comp_control(format, 2), - .Component3Control = vertex_element_comp_control(format, 3), - }; - GENX(VERTEX_ELEMENT_STATE_pack)(NULL, &p[1 + slot * 2], &element); + struct GENX(VERTEX_ELEMENT_STATE) element; + if (attribs[loc]) { + const VkVertexInputAttributeDescription *desc = attribs[loc]; + enum isl_format format = anv_get_isl_format(&pipeline->device->info, + desc->format, + VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_TILING_LINEAR); + element = (struct GENX(VERTEX_ELEMENT_STATE)) { + .VertexBufferIndex = desc->binding, + .Valid = true, + .SourceElementFormat = format, + .EdgeFlagEnable = false, + .SourceElementOffset = desc->offset, + .Component0Control = vertex_element_comp_control(format, 0), + .Component1Control = vertex_element_comp_control(format, 1), + .Component2Control = vertex_element_comp_control(format, 2), + .Component3Control = vertex_element_comp_control(format, 3), + }; #if GEN_GEN >= 8 - /* On Broadwell and later, we have a separate VF_INSTANCING packet - * that controls instancing. On Haswell and prior, that's part of - * VERTEX_BUFFER_STATE which we emit later. - */ - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_INSTANCING), vfi) { - vfi.InstancingEnable = pipeline->vb[desc->binding].instanced; - vfi.VertexElementIndex = slot; - vfi.InstanceDataStepRate = - pipeline->vb[desc->binding].instance_divisor; - } + /* On Broadwell and later, we have a separate VF_INSTANCING packet + * that controls instancing. On Haswell and prior, that's part of + * VERTEX_BUFFER_STATE which we emit later. + */ + anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_INSTANCING), vfi) { + vfi.InstancingEnable = pipeline->vb[desc->binding].instanced; + vfi.VertexElementIndex = slot; + vfi.InstanceDataStepRate = + pipeline->vb[desc->binding].instance_divisor; + } #endif + } else { + /* The SKL docs for VERTEX_ELEMENT_STATE say: + * + * "All elements must be valid from Element[0] to the last valid + * element. (I.e. if Element[2] is valid then Element[1] and + * Element[0] must also be valid)." + * + * The SKL docs for 3D_Vertex_Component_Control say: + * + * "Don't store this component. (Not valid for Component 0, but can + * be used for Component 1-3)." + * + * So we can't just leave a vertex element blank and hope for the best. + * We have to tell the VF hardware to put something in it; so we just + * store a bunch of zero. + * + * TODO: Compact vertex elements so we never end up with holes. + */ + element = (struct GENX(VERTEX_ELEMENT_STATE)) { + .Valid = true, + .Component0Control = VFCOMP_STORE_0, + .Component1Control = VFCOMP_STORE_0, + .Component2Control = VFCOMP_STORE_0, + .Component3Control = VFCOMP_STORE_0, + }; + } + GENX(VERTEX_ELEMENT_STATE_pack)(NULL, &p[1 + slot * 2], &element); + slot++; } + assert(slot == elem_count); - const uint32_t id_slot = elem_count; + const uint32_t id_slot = slot; if (needs_svgs_elem) { /* From the Broadwell PRM for the 3D_Vertex_Component_Control enum: * "Within a VERTEX_ELEMENT_STATE structure, if a Component @@ -219,7 +238,8 @@ emit_vertex_input(struct anv_pipeline *pipeline, .Component3Control = VFCOMP_STORE_IID, #endif }; - GENX(VERTEX_ELEMENT_STATE_pack)(NULL, &p[1 + id_slot * 2], &element); + GENX(VERTEX_ELEMENT_STATE_pack)(NULL, &p[1 + slot * 2], &element); + slot++; } #if GEN_GEN >= 8 @@ -233,7 +253,6 @@ emit_vertex_input(struct anv_pipeline *pipeline, } #endif - const uint32_t drawid_slot = elem_count + needs_svgs_elem; if (vs_prog_data->uses_drawid) { struct GENX(VERTEX_ELEMENT_STATE) element = { .VertexBufferIndex = ANV_DRAWID_VB_INDEX, @@ -244,16 +263,17 @@ emit_vertex_input(struct anv_pipeline *pipeline, .Component2Control = VFCOMP_STORE_0, .Component3Control = VFCOMP_STORE_0, }; - GENX(VERTEX_ELEMENT_STATE_pack)(NULL, - &p[1 + drawid_slot * 2], - &element); + GENX(VERTEX_ELEMENT_STATE_pack)(NULL, &p[1 + slot * 2], &element); #if GEN_GEN >= 8 anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_INSTANCING), vfi) { - vfi.VertexElementIndex = drawid_slot; + vfi.VertexElementIndex = slot; } #endif + + slot++; } + assert(slot == total_elems); } void -- 2.17.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev