X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fintel%2Fvulkan%2FgenX_pipeline.c;h=d4b93688da13ccfbf99f40a6619744a688e1e319;hb=03fbff1efcccc0e09fc218c24b29e6d1ad4d4599;hp=2a7044a425e8ee8403acedf5845baa03ea6d898f;hpb=64d3b148fe71453c296ba9525f49ffe728171582;p=mesa.git diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c index 2a7044a425e..d4b93688da1 100644 --- a/src/intel/vulkan/genX_pipeline.c +++ b/src/intel/vulkan/genX_pipeline.c @@ -85,7 +85,7 @@ vertex_element_comp_control(enum isl_format format, unsigned comp) } static void -emit_vertex_input(struct anv_pipeline *pipeline, +emit_vertex_input(struct anv_graphics_pipeline *pipeline, const VkPipelineVertexInputStateCreateInfo *info) { const struct brw_vs_prog_data *vs_prog_data = get_vs_prog_data(pipeline); @@ -111,7 +111,7 @@ emit_vertex_input(struct anv_pipeline *pipeline, uint32_t *p; const uint32_t num_dwords = 1 + total_elems * 2; - p = anv_batch_emitn(&pipeline->batch, num_dwords, + p = anv_batch_emitn(&pipeline->base.batch, num_dwords, GENX(3DSTATE_VERTEX_ELEMENTS)); if (!p) return; @@ -147,7 +147,7 @@ emit_vertex_input(struct anv_pipeline *pipeline, 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, + enum isl_format format = anv_get_isl_format(&pipeline->base.device->info, desc->format, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_TILING_LINEAR); @@ -180,7 +180,7 @@ emit_vertex_input(struct anv_pipeline *pipeline, * 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) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_VF_INSTANCING), vfi) { vfi.InstancingEnable = pipeline->vb[desc->binding].instanced; vfi.VertexElementIndex = slot; vfi.InstanceDataStepRate = @@ -219,10 +219,16 @@ emit_vertex_input(struct anv_pipeline *pipeline, #endif }; GENX(VERTEX_ELEMENT_STATE_pack)(NULL, &p[1 + id_slot * 2], &element); + +#if GEN_GEN >= 8 + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_VF_INSTANCING), vfi) { + vfi.VertexElementIndex = id_slot; + } +#endif } #if GEN_GEN >= 8 - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_SGVS), sgvs) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_VF_SGVS), sgvs) { sgvs.VertexIDEnable = vs_prog_data->uses_vertexid; sgvs.VertexIDComponentNumber = 2; sgvs.VertexIDElementOffset = id_slot; @@ -248,7 +254,7 @@ emit_vertex_input(struct anv_pipeline *pipeline, &element); #if GEN_GEN >= 8 - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_INSTANCING), vfi) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_VF_INSTANCING), vfi) { vfi.VertexElementIndex = drawid_slot; } #endif @@ -259,25 +265,18 @@ void genX(emit_urb_setup)(struct anv_device *device, struct anv_batch *batch, const struct gen_l3_config *l3_config, VkShaderStageFlags active_stages, - const unsigned entry_size[4]) + const unsigned entry_size[4], + enum gen_urb_deref_block_size *deref_block_size) { const struct gen_device_info *devinfo = &device->info; -#if GEN_IS_HASWELL - const unsigned push_constant_kb = devinfo->gt == 3 ? 32 : 16; -#else - const unsigned push_constant_kb = GEN_GEN >= 8 ? 32 : 16; -#endif - - const unsigned urb_size_kb = gen_get_l3_config_urb_size(devinfo, l3_config); unsigned entries[4]; unsigned start[4]; - gen_get_urb_config(devinfo, - 1024 * push_constant_kb, 1024 * urb_size_kb, + gen_get_urb_config(devinfo, l3_config, active_stages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, active_stages & VK_SHADER_STAGE_GEOMETRY_BIT, - entry_size, entries, start); + entry_size, entries, start, deref_block_size); #if GEN_GEN == 7 && !GEN_IS_HASWELL /* From the IVB PRM Vol. 2, Part 1, Section 3.2.1: @@ -291,7 +290,7 @@ genX(emit_urb_setup)(struct anv_device *device, struct anv_batch *batch, anv_batch_emit(batch, GEN7_PIPE_CONTROL, pc) { pc.DepthStallEnable = true; pc.PostSyncOperation = WriteImmediateData; - pc.Address = (struct anv_address) { &device->workaround_bo, 0 }; + pc.Address = device->workaround_address; } #endif @@ -306,7 +305,8 @@ genX(emit_urb_setup)(struct anv_device *device, struct anv_batch *batch, } static void -emit_urb_setup(struct anv_pipeline *pipeline) +emit_urb_setup(struct anv_graphics_pipeline *pipeline, + enum gen_urb_deref_block_size *deref_block_size) { unsigned entry_size[4]; for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) { @@ -317,20 +317,21 @@ emit_urb_setup(struct anv_pipeline *pipeline) entry_size[i] = prog_data ? prog_data->urb_entry_size : 1; } - genX(emit_urb_setup)(pipeline->device, &pipeline->batch, - pipeline->urb.l3_config, - pipeline->active_stages, entry_size); + genX(emit_urb_setup)(pipeline->base.device, &pipeline->base.batch, + pipeline->base.l3_config, + pipeline->active_stages, entry_size, + deref_block_size); } static void -emit_3dstate_sbe(struct anv_pipeline *pipeline) +emit_3dstate_sbe(struct anv_graphics_pipeline *pipeline) { const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline); if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT)) { - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_SBE), sbe); + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_SBE), sbe); #if GEN_GEN >= 8 - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_SBE_SWIZ), sbe); + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_SBE_SWIZ), sbe); #endif return; } @@ -360,18 +361,19 @@ emit_3dstate_sbe(struct anv_pipeline *pipeline) # define swiz sbe #endif - /* Skip the VUE header and position slots by default */ - unsigned urb_entry_read_offset = 1; + int first_slot = brw_compute_first_urb_slot_required(wm_prog_data->inputs, + fs_input_map); + assert(first_slot % 2 == 0); + unsigned urb_entry_read_offset = first_slot / 2; int max_source_attr = 0; - for (int attr = 0; attr < VARYING_SLOT_MAX; attr++) { + for (uint8_t idx = 0; idx < wm_prog_data->urb_setup_attribs_count; idx++) { + uint8_t attr = wm_prog_data->urb_setup_attribs[idx]; int input_index = wm_prog_data->urb_setup[attr]; - if (input_index < 0) - continue; + assert(0 <= input_index); - /* gl_Layer is stored in the VUE header */ - if (attr == VARYING_SLOT_LAYER) { - urb_entry_read_offset = 0; + /* gl_Viewport and gl_Layer are stored in the VUE header */ + if (attr == VARYING_SLOT_VIEWPORT || attr == VARYING_SLOT_LAYER) { continue; } @@ -382,9 +384,6 @@ emit_3dstate_sbe(struct anv_pipeline *pipeline) const int slot = fs_input_map->varying_to_slot[attr]; - if (input_index >= 16) - continue; - if (slot == -1) { /* This attribute does not exist in the VUE--that means that the * vertex shader did not write to it. It could be that it's a @@ -398,15 +397,24 @@ emit_3dstate_sbe(struct anv_pipeline *pipeline) swiz.Attribute[input_index].ComponentOverrideY = true; swiz.Attribute[input_index].ComponentOverrideZ = true; swiz.Attribute[input_index].ComponentOverrideW = true; - } else { - /* We have to subtract two slots to accout for the URB entry output - * read offset in the VS and GS stages. - */ - const int source_attr = slot - 2 * urb_entry_read_offset; - assert(source_attr >= 0 && source_attr < 32); - max_source_attr = MAX2(max_source_attr, source_attr); - swiz.Attribute[input_index].SourceAttribute = source_attr; + continue; } + + /* We have to subtract two slots to accout for the URB entry output + * read offset in the VS and GS stages. + */ + const int source_attr = slot - 2 * urb_entry_read_offset; + assert(source_attr >= 0 && source_attr < 32); + max_source_attr = MAX2(max_source_attr, source_attr); + /* The hardware can only do overrides on 16 overrides at a time, and the + * other up to 16 have to be lined up so that the input index = the + * output index. We'll need to do some tweaking to make sure that's the + * case. + */ + if (input_index < 16) + swiz.Attribute[input_index].SourceAttribute = source_attr; + else + assert(source_attr == input_index); } sbe.VertexURBEntryReadOffset = urb_entry_read_offset; @@ -416,44 +424,166 @@ emit_3dstate_sbe(struct anv_pipeline *pipeline) sbe.ForceVertexURBEntryReadLength = true; #endif - uint32_t *dw = anv_batch_emit_dwords(&pipeline->batch, + uint32_t *dw = anv_batch_emit_dwords(&pipeline->base.batch, GENX(3DSTATE_SBE_length)); if (!dw) return; - GENX(3DSTATE_SBE_pack)(&pipeline->batch, dw, &sbe); + GENX(3DSTATE_SBE_pack)(&pipeline->base.batch, dw, &sbe); #if GEN_GEN >= 8 - dw = anv_batch_emit_dwords(&pipeline->batch, GENX(3DSTATE_SBE_SWIZ_length)); + dw = anv_batch_emit_dwords(&pipeline->base.batch, GENX(3DSTATE_SBE_SWIZ_length)); if (!dw) return; - GENX(3DSTATE_SBE_SWIZ_pack)(&pipeline->batch, dw, &swiz); + GENX(3DSTATE_SBE_SWIZ_pack)(&pipeline->base.batch, dw, &swiz); #endif } -static const uint32_t vk_to_gen_cullmode[] = { +static VkLineRasterizationModeEXT +vk_line_rasterization_mode(const VkPipelineRasterizationLineStateCreateInfoEXT *line_info, + const VkPipelineMultisampleStateCreateInfo *ms_info) +{ + VkLineRasterizationModeEXT line_mode = + line_info ? line_info->lineRasterizationMode : + VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT; + + if (line_mode == VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT) { + if (ms_info && ms_info->rasterizationSamples > 1) { + return VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT; + } else { + return VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT; + } + } + + return line_mode; +} + +/** Returns the final polygon mode for rasterization + * + * This function takes into account polygon mode, primitive topology and the + * different shader stages which might generate their own type of primitives. + */ +static VkPolygonMode +anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline, + const VkPipelineInputAssemblyStateCreateInfo *ia_info, + const VkPipelineRasterizationStateCreateInfo *rs_info) +{ + if (anv_pipeline_has_stage(pipeline, MESA_SHADER_GEOMETRY)) { + switch (get_gs_prog_data(pipeline)->output_topology) { + case _3DPRIM_POINTLIST: + return VK_POLYGON_MODE_POINT; + + case _3DPRIM_LINELIST: + case _3DPRIM_LINESTRIP: + case _3DPRIM_LINELOOP: + return VK_POLYGON_MODE_LINE; + + case _3DPRIM_TRILIST: + case _3DPRIM_TRIFAN: + case _3DPRIM_TRISTRIP: + case _3DPRIM_RECTLIST: + case _3DPRIM_QUADLIST: + case _3DPRIM_QUADSTRIP: + case _3DPRIM_POLYGON: + return rs_info->polygonMode; + } + unreachable("Unsupported GS output topology"); + } else if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) { + switch (get_tes_prog_data(pipeline)->output_topology) { + case BRW_TESS_OUTPUT_TOPOLOGY_POINT: + return VK_POLYGON_MODE_POINT; + + case BRW_TESS_OUTPUT_TOPOLOGY_LINE: + return VK_POLYGON_MODE_LINE; + + case BRW_TESS_OUTPUT_TOPOLOGY_TRI_CW: + case BRW_TESS_OUTPUT_TOPOLOGY_TRI_CCW: + return rs_info->polygonMode; + } + unreachable("Unsupported TCS output topology"); + } else { + switch (ia_info->topology) { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + return VK_POLYGON_MODE_POINT; + + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + return VK_POLYGON_MODE_LINE; + + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + return rs_info->polygonMode; + + default: + unreachable("Unsupported primitive topology"); + } + } +} + +#if GEN_GEN <= 7 +static uint32_t +gen7_ms_rast_mode(struct anv_graphics_pipeline *pipeline, + const VkPipelineInputAssemblyStateCreateInfo *ia_info, + const VkPipelineRasterizationStateCreateInfo *rs_info, + const VkPipelineMultisampleStateCreateInfo *ms_info) +{ + const VkPipelineRasterizationLineStateCreateInfoEXT *line_info = + vk_find_struct_const(rs_info->pNext, + PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT); + + VkPolygonMode raster_mode = + anv_raster_polygon_mode(pipeline, ia_info, rs_info); + if (raster_mode == VK_POLYGON_MODE_LINE) { + switch (vk_line_rasterization_mode(line_info, ms_info)) { + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT: + return MSRASTMODE_ON_PATTERN; + + case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT: + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT: + return MSRASTMODE_OFF_PIXEL; + + default: + unreachable("Unsupported line rasterization mode"); + } + } else { + return (ms_info && ms_info->rasterizationSamples > 1) ? + MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL; + } +} +#endif + +const uint32_t genX(vk_to_gen_cullmode)[] = { [VK_CULL_MODE_NONE] = CULLMODE_NONE, [VK_CULL_MODE_FRONT_BIT] = CULLMODE_FRONT, [VK_CULL_MODE_BACK_BIT] = CULLMODE_BACK, [VK_CULL_MODE_FRONT_AND_BACK] = CULLMODE_BOTH }; -static const uint32_t vk_to_gen_fillmode[] = { +const uint32_t genX(vk_to_gen_fillmode)[] = { [VK_POLYGON_MODE_FILL] = FILL_MODE_SOLID, [VK_POLYGON_MODE_LINE] = FILL_MODE_WIREFRAME, [VK_POLYGON_MODE_POINT] = FILL_MODE_POINT, }; -static const uint32_t vk_to_gen_front_face[] = { +const uint32_t genX(vk_to_gen_front_face)[] = { [VK_FRONT_FACE_COUNTER_CLOCKWISE] = 1, [VK_FRONT_FACE_CLOCKWISE] = 0 }; static void -emit_rs_state(struct anv_pipeline *pipeline, +emit_rs_state(struct anv_graphics_pipeline *pipeline, + const VkPipelineInputAssemblyStateCreateInfo *ia_info, const VkPipelineRasterizationStateCreateInfo *rs_info, const VkPipelineMultisampleStateCreateInfo *ms_info, + const VkPipelineRasterizationLineStateCreateInfoEXT *line_info, + const uint32_t dynamic_states, const struct anv_render_pass *pass, - const struct anv_subpass *subpass) + const struct anv_subpass *subpass, + enum gen_urb_deref_block_size urb_deref_block_size) { struct GENX(3DSTATE_SF) sf = { GENX(3DSTATE_SF_header), @@ -464,6 +594,16 @@ emit_rs_state(struct anv_pipeline *pipeline, sf.TriangleStripListProvokingVertexSelect = 0; sf.LineStripListProvokingVertexSelect = 0; sf.TriangleFanProvokingVertexSelect = 1; + sf.VertexSubPixelPrecisionSelect = _8Bit; + sf.AALineDistanceMode = true; + +#if GEN_IS_HASWELL + sf.LineStippleEnable = line_info && line_info->stippledLineEnable; +#endif + +#if GEN_GEN >= 12 + sf.DerefBlockSize = urb_deref_block_size; +#endif const struct brw_vue_prog_data *last_vue_prog_data = anv_pipeline_get_last_vue_prog_data(pipeline); @@ -483,11 +623,47 @@ emit_rs_state(struct anv_pipeline *pipeline, # define raster sf #endif + VkPolygonMode raster_mode = + anv_raster_polygon_mode(pipeline, ia_info, rs_info); + VkLineRasterizationModeEXT line_mode = + vk_line_rasterization_mode(line_info, ms_info); + /* For details on 3DSTATE_RASTER multisample state, see the BSpec table * "Multisample Modes State". */ #if GEN_GEN >= 8 - raster.DXMultisampleRasterizationEnable = true; + if (raster_mode == VK_POLYGON_MODE_LINE) { + /* Unfortunately, configuring our line rasterization hardware on gen8 + * and later is rather painful. Instead of giving us bits to tell the + * hardware what line mode to use like we had on gen7, we now have an + * arcane combination of API Mode and MSAA enable bits which do things + * in a table which are expected to magically put the hardware into the + * right mode for your API. Sadly, Vulkan isn't any of the APIs the + * hardware people thought of so nothing works the way you want it to. + * + * Look at the table titled "Multisample Rasterization Modes" in Vol 7 + * of the Skylake PRM for more details. + */ + switch (line_mode) { + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT: + raster.APIMode = DX100; + raster.DXMultisampleRasterizationEnable = true; + break; + + case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT: + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT: + raster.APIMode = DX9OGL; + raster.DXMultisampleRasterizationEnable = false; + break; + + default: + unreachable("Unsupported line rasterization mode"); + } + } else { + raster.APIMode = DX100; + raster.DXMultisampleRasterizationEnable = true; + } + /* NOTE: 3DSTATE_RASTER::ForcedSampleCount affects the BDW and SKL PMA fix * computations. If we ever set this bit to a different value, they will * need to be updated accordingly. @@ -496,22 +672,30 @@ emit_rs_state(struct anv_pipeline *pipeline, raster.ForceMultisampling = false; #else raster.MultisampleRasterizationMode = - (ms_info && ms_info->rasterizationSamples > 1) ? - MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL; + gen7_ms_rast_mode(pipeline, ia_info, rs_info, ms_info); #endif - raster.FrontWinding = vk_to_gen_front_face[rs_info->frontFace]; - raster.CullMode = vk_to_gen_cullmode[rs_info->cullMode]; - raster.FrontFaceFillMode = vk_to_gen_fillmode[rs_info->polygonMode]; - raster.BackFaceFillMode = vk_to_gen_fillmode[rs_info->polygonMode]; + if (raster_mode == VK_POLYGON_MODE_LINE && + line_mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT) + raster.AntialiasingEnable = true; + + raster.FrontWinding = + dynamic_states & ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE ? + 0 : genX(vk_to_gen_front_face)[rs_info->frontFace]; + raster.CullMode = + dynamic_states & ANV_CMD_DIRTY_DYNAMIC_CULL_MODE ? + 0 : genX(vk_to_gen_cullmode)[rs_info->cullMode]; + + raster.FrontFaceFillMode = genX(vk_to_gen_fillmode)[rs_info->polygonMode]; + raster.BackFaceFillMode = genX(vk_to_gen_fillmode)[rs_info->polygonMode]; raster.ScissorRectangleEnable = true; #if GEN_GEN >= 9 /* GEN9+ splits ViewportZClipTestEnable into near and far enable bits */ - raster.ViewportZFarClipTestEnable = !pipeline->depth_clamp_enable; - raster.ViewportZNearClipTestEnable = !pipeline->depth_clamp_enable; + raster.ViewportZFarClipTestEnable = pipeline->depth_clip_enable; + raster.ViewportZNearClipTestEnable = pipeline->depth_clip_enable; #elif GEN_GEN >= 8 - raster.ViewportZClipTestEnable = !pipeline->depth_clamp_enable; + raster.ViewportZClipTestEnable = pipeline->depth_clip_enable; #endif raster.GlobalDepthOffsetEnableSolid = rs_info->depthBiasEnable; @@ -528,7 +712,7 @@ emit_rs_state(struct anv_pipeline *pipeline, assert(vk_format_is_depth_or_stencil(vk_format)); if (vk_format_aspects(vk_format) & VK_IMAGE_ASPECT_DEPTH_BIT) { enum isl_format isl_format = - anv_get_isl_format(&pipeline->device->info, vk_format, + anv_get_isl_format(&pipeline->base.device->info, vk_format, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_TILING_OPTIMAL); sf.DepthBufferSurfaceFormat = @@ -547,7 +731,7 @@ emit_rs_state(struct anv_pipeline *pipeline, } static void -emit_ms_state(struct anv_pipeline *pipeline, +emit_ms_state(struct anv_graphics_pipeline *pipeline, const VkPipelineMultisampleStateCreateInfo *info) { uint32_t samples = 1; @@ -573,7 +757,7 @@ emit_ms_state(struct anv_pipeline *pipeline, if (info && info->pSampleMask) sample_mask &= info->pSampleMask[0]; - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_MULTISAMPLE), ms) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_MULTISAMPLE), ms) { ms.NumberofMultisamples = log2_samples; ms.PixelLocation = CENTER; @@ -605,7 +789,7 @@ emit_ms_state(struct anv_pipeline *pipeline, #endif } - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_SAMPLE_MASK), sm) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_SAMPLE_MASK), sm) { sm.SampleMask = sample_mask; } } @@ -659,7 +843,7 @@ static const uint32_t vk_to_gen_blend_op[] = { [VK_BLEND_OP_MAX] = BLENDFUNCTION_MAX, }; -static const uint32_t vk_to_gen_compare_op[] = { +const uint32_t genX(vk_to_gen_compare_op)[] = { [VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER, [VK_COMPARE_OP_LESS] = PREFILTEROPLESS, [VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL, @@ -670,7 +854,7 @@ static const uint32_t vk_to_gen_compare_op[] = { [VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS, }; -static const uint32_t vk_to_gen_stencil_op[] = { +const uint32_t genX(vk_to_gen_stencil_op)[] = { [VK_STENCIL_OP_KEEP] = STENCILOP_KEEP, [VK_STENCIL_OP_ZERO] = STENCILOP_ZERO, [VK_STENCIL_OP_REPLACE] = STENCILOP_REPLACE, @@ -681,6 +865,19 @@ static const uint32_t vk_to_gen_stencil_op[] = { [VK_STENCIL_OP_DECREMENT_AND_WRAP] = STENCILOP_DECR, }; +const uint32_t genX(vk_to_gen_primitive_type)[] = { + [VK_PRIMITIVE_TOPOLOGY_POINT_LIST] = _3DPRIM_POINTLIST, + [VK_PRIMITIVE_TOPOLOGY_LINE_LIST] = _3DPRIM_LINELIST, + [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP] = _3DPRIM_LINESTRIP, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = _3DPRIM_TRILIST, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = _3DPRIM_TRISTRIP, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN] = _3DPRIM_TRIFAN, + [VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY] = _3DPRIM_LINELIST_ADJ, + [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY] = _3DPRIM_LINESTRIP_ADJ, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY] = _3DPRIM_TRILIST_ADJ, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY] = _3DPRIM_TRISTRIP_ADJ, +}; + /* This function sanitizes the VkStencilOpState by looking at the compare ops * and trying to determine whether or not a given stencil op can ever actually * occur. Stencil ops which can never occur are set to VK_STENCIL_OP_KEEP. @@ -813,8 +1010,9 @@ sanitize_ds_state(VkPipelineDepthStencilStateCreateInfo *state, } static void -emit_ds_state(struct anv_pipeline *pipeline, +emit_ds_state(struct anv_graphics_pipeline *pipeline, const VkPipelineDepthStencilStateCreateInfo *pCreateInfo, + const uint32_t dynamic_states, const struct anv_render_pass *pass, const struct anv_subpass *subpass) { @@ -834,6 +1032,7 @@ emit_ds_state(struct anv_pipeline *pipeline, pipeline->stencil_test_enable = false; pipeline->writes_depth = false; pipeline->depth_test_enable = false; + pipeline->depth_bounds_test_enable = false; memset(depth_stencil_dw, 0, sizeof(depth_stencil_dw)); return; } @@ -850,30 +1049,55 @@ emit_ds_state(struct anv_pipeline *pipeline, pipeline->stencil_test_enable = info.stencilTestEnable; pipeline->writes_depth = info.depthWriteEnable; pipeline->depth_test_enable = info.depthTestEnable; + pipeline->depth_bounds_test_enable = info.depthBoundsTestEnable; - /* VkBool32 depthBoundsTestEnable; // optional (depth_bounds_test) */ + bool dynamic_stencil_op = + dynamic_states & ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP; #if GEN_GEN <= 7 struct GENX(DEPTH_STENCIL_STATE) depth_stencil = { #else struct GENX(3DSTATE_WM_DEPTH_STENCIL) depth_stencil = { #endif - .DepthTestEnable = info.depthTestEnable, - .DepthBufferWriteEnable = info.depthWriteEnable, - .DepthTestFunction = vk_to_gen_compare_op[info.depthCompareOp], + .DepthTestEnable = + dynamic_states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE ? + 0 : info.depthTestEnable, + + .DepthBufferWriteEnable = + dynamic_states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE ? + 0 : info.depthWriteEnable, + + .DepthTestFunction = + dynamic_states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP ? + 0 : genX(vk_to_gen_compare_op)[info.depthCompareOp], + .DoubleSidedStencilEnable = true, - .StencilTestEnable = info.stencilTestEnable, - .StencilFailOp = vk_to_gen_stencil_op[info.front.failOp], - .StencilPassDepthPassOp = vk_to_gen_stencil_op[info.front.passOp], - .StencilPassDepthFailOp = vk_to_gen_stencil_op[info.front.depthFailOp], - .StencilTestFunction = vk_to_gen_compare_op[info.front.compareOp], - .BackfaceStencilFailOp = vk_to_gen_stencil_op[info.back.failOp], - .BackfaceStencilPassDepthPassOp = vk_to_gen_stencil_op[info.back.passOp], - .BackfaceStencilPassDepthFailOp =vk_to_gen_stencil_op[info.back.depthFailOp], - .BackfaceStencilTestFunction = vk_to_gen_compare_op[info.back.compareOp], + .StencilTestEnable = + dynamic_states & ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE ? + 0 : info.stencilTestEnable, + + .StencilFailOp = genX(vk_to_gen_stencil_op)[info.front.failOp], + .StencilPassDepthPassOp = genX(vk_to_gen_stencil_op)[info.front.passOp], + .StencilPassDepthFailOp = genX(vk_to_gen_stencil_op)[info.front.depthFailOp], + .StencilTestFunction = genX(vk_to_gen_compare_op)[info.front.compareOp], + .BackfaceStencilFailOp = genX(vk_to_gen_stencil_op)[info.back.failOp], + .BackfaceStencilPassDepthPassOp = genX(vk_to_gen_stencil_op)[info.back.passOp], + .BackfaceStencilPassDepthFailOp = genX(vk_to_gen_stencil_op)[info.back.depthFailOp], + .BackfaceStencilTestFunction = genX(vk_to_gen_compare_op)[info.back.compareOp], }; + if (dynamic_stencil_op) { + depth_stencil.StencilFailOp = 0; + depth_stencil.StencilPassDepthPassOp = 0; + depth_stencil.StencilPassDepthFailOp = 0; + depth_stencil.StencilTestFunction = 0; + depth_stencil.BackfaceStencilFailOp = 0; + depth_stencil.BackfaceStencilPassDepthPassOp = 0; + depth_stencil.BackfaceStencilPassDepthFailOp = 0; + depth_stencil.BackfaceStencilTestFunction = 0; + } + #if GEN_GEN <= 7 GENX(DEPTH_STENCIL_STATE_pack)(NULL, depth_stencil_dw, &depth_stencil); #else @@ -881,7 +1105,7 @@ emit_ds_state(struct anv_pipeline *pipeline, #endif } -MAYBE_UNUSED static bool +static bool is_dual_src_blend_factor(VkBlendFactor factor) { return factor == VK_BLEND_FACTOR_SRC1_COLOR || @@ -891,11 +1115,11 @@ is_dual_src_blend_factor(VkBlendFactor factor) } static void -emit_cb_state(struct anv_pipeline *pipeline, +emit_cb_state(struct anv_graphics_pipeline *pipeline, const VkPipelineColorBlendStateCreateInfo *info, const VkPipelineMultisampleStateCreateInfo *ms_info) { - struct anv_device *device = pipeline->device; + struct anv_device *device = pipeline->base.device; const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline); struct GENX(BLEND_STATE) blend_state = { @@ -946,7 +1170,6 @@ emit_cb_state(struct anv_pipeline *pipeline, continue; } - assert(binding->binding == 0); const VkPipelineColorBlendAttachmentState *a = &info->pAttachments[binding->index]; @@ -999,7 +1222,7 @@ emit_cb_state(struct anv_pipeline *pipeline, is_dual_src_blend_factor(a->dstColorBlendFactor) || is_dual_src_blend_factor(a->srcAlphaBlendFactor) || is_dual_src_blend_factor(a->dstAlphaBlendFactor))) { - vk_debug_report(&device->instance->debug_report_callbacks, + vk_debug_report(&device->physical->instance->debug_report_callbacks, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, (uint64_t)(uintptr_t)device, @@ -1037,7 +1260,7 @@ emit_cb_state(struct anv_pipeline *pipeline, } #if GEN_GEN >= 8 - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_PS_BLEND), blend) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_PS_BLEND), blend) { blend.AlphaToCoverageEnable = blend_state.AlphaToCoverageEnable; blend.HasWriteableRT = has_writeable_rt; blend.ColorBufferBlendEnable = bs0.ColorBufferBlendEnable; @@ -1055,7 +1278,7 @@ emit_cb_state(struct anv_pipeline *pipeline, GENX(BLEND_STATE_pack)(NULL, pipeline->blend_state.map, &blend_state); - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_BLEND_STATE_POINTERS), bsp) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_BLEND_STATE_POINTERS), bsp) { bsp.BlendStatePointer = pipeline->blend_state.offset; #if GEN_GEN >= 8 bsp.BlendStatePointerValid = true; @@ -1064,75 +1287,93 @@ emit_cb_state(struct anv_pipeline *pipeline, } static void -emit_3dstate_clip(struct anv_pipeline *pipeline, +emit_3dstate_clip(struct anv_graphics_pipeline *pipeline, + const VkPipelineInputAssemblyStateCreateInfo *ia_info, const VkPipelineViewportStateCreateInfo *vp_info, - const VkPipelineRasterizationStateCreateInfo *rs_info) + const VkPipelineRasterizationStateCreateInfo *rs_info, + const uint32_t dynamic_states) { const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline); (void) wm_prog_data; - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_CLIP), clip) { - clip.ClipEnable = true; - clip.StatisticsEnable = true; - clip.EarlyCullEnable = true; - clip.APIMode = APIMODE_D3D, - clip.ViewportXYClipTestEnable = true; - clip.ClipMode = CLIPMODE_NORMAL; + struct GENX(3DSTATE_CLIP) clip = { + GENX(3DSTATE_CLIP_header), + }; - clip.TriangleStripListProvokingVertexSelect = 0; - clip.LineStripListProvokingVertexSelect = 0; - clip.TriangleFanProvokingVertexSelect = 1; + clip.ClipEnable = true; + clip.StatisticsEnable = true; + clip.EarlyCullEnable = true; + clip.APIMode = APIMODE_D3D; + clip.GuardbandClipTestEnable = true; - clip.MinimumPointWidth = 0.125; - clip.MaximumPointWidth = 255.875; + /* Only enable the XY clip test when the final polygon rasterization + * mode is VK_POLYGON_MODE_FILL. We want to leave it disabled for + * points and lines so we get "pop-free" clipping. + */ + VkPolygonMode raster_mode = + anv_raster_polygon_mode(pipeline, ia_info, rs_info); + clip.ViewportXYClipTestEnable = (raster_mode == VK_POLYGON_MODE_FILL); - const struct brw_vue_prog_data *last = - anv_pipeline_get_last_vue_prog_data(pipeline); +#if GEN_GEN >= 8 + clip.VertexSubPixelPrecisionSelect = _8Bit; +#endif + clip.ClipMode = CLIPMODE_NORMAL; - /* From the Vulkan 1.0.45 spec: - * - * "If the last active vertex processing stage shader entry point's - * interface does not include a variable decorated with - * ViewportIndex, then the first viewport is used." - */ - if (vp_info && (last->vue_map.slots_valid & VARYING_BIT_VIEWPORT)) { - clip.MaximumVPIndex = vp_info->viewportCount - 1; - } else { - clip.MaximumVPIndex = 0; - } + clip.TriangleStripListProvokingVertexSelect = 0; + clip.LineStripListProvokingVertexSelect = 0; + clip.TriangleFanProvokingVertexSelect = 1; - /* From the Vulkan 1.0.45 spec: - * - * "If the last active vertex processing stage shader entry point's - * interface does not include a variable decorated with Layer, then - * the first layer is used." - */ - clip.ForceZeroRTAIndexEnable = - !(last->vue_map.slots_valid & VARYING_BIT_LAYER); + clip.MinimumPointWidth = 0.125; + clip.MaximumPointWidth = 255.875; + + const struct brw_vue_prog_data *last = + anv_pipeline_get_last_vue_prog_data(pipeline); + + /* From the Vulkan 1.0.45 spec: + * + * "If the last active vertex processing stage shader entry point's + * interface does not include a variable decorated with + * ViewportIndex, then the first viewport is used." + */ + if (vp_info && (last->vue_map.slots_valid & VARYING_BIT_VIEWPORT)) { + clip.MaximumVPIndex = vp_info->viewportCount > 0 ? + vp_info->viewportCount - 1 : 0; + } else { + clip.MaximumVPIndex = 0; + } + + /* From the Vulkan 1.0.45 spec: + * + * "If the last active vertex processing stage shader entry point's + * interface does not include a variable decorated with Layer, then + * the first layer is used." + */ + clip.ForceZeroRTAIndexEnable = + !(last->vue_map.slots_valid & VARYING_BIT_LAYER); #if GEN_GEN == 7 - clip.FrontWinding = vk_to_gen_front_face[rs_info->frontFace]; - clip.CullMode = vk_to_gen_cullmode[rs_info->cullMode]; - clip.ViewportZClipTestEnable = !pipeline->depth_clamp_enable; - clip.UserClipDistanceClipTestEnableBitmask = last->clip_distance_mask; - clip.UserClipDistanceCullTestEnableBitmask = last->cull_distance_mask; + clip.FrontWinding = genX(vk_to_gen_front_face)[rs_info->frontFace]; + clip.CullMode = genX(vk_to_gen_cullmode)[rs_info->cullMode]; + clip.ViewportZClipTestEnable = pipeline->depth_clip_enable; + clip.UserClipDistanceClipTestEnableBitmask = last->clip_distance_mask; + clip.UserClipDistanceCullTestEnableBitmask = last->cull_distance_mask; #else - clip.NonPerspectiveBarycentricEnable = wm_prog_data ? - (wm_prog_data->barycentric_interp_modes & - BRW_BARYCENTRIC_NONPERSPECTIVE_BITS) != 0 : 0; + clip.NonPerspectiveBarycentricEnable = wm_prog_data ? + (wm_prog_data->barycentric_interp_modes & + BRW_BARYCENTRIC_NONPERSPECTIVE_BITS) != 0 : 0; #endif - } + + GENX(3DSTATE_CLIP_pack)(NULL, pipeline->gen7.clip, &clip); } static void -emit_3dstate_streamout(struct anv_pipeline *pipeline, +emit_3dstate_streamout(struct anv_graphics_pipeline *pipeline, const VkPipelineRasterizationStateCreateInfo *rs_info) { #if GEN_GEN >= 8 const struct brw_vue_prog_data *prog_data = anv_pipeline_get_last_vue_prog_data(pipeline); const struct brw_vue_map *vue_map = &prog_data->vue_map; -#endif nir_xfb_info *xfb_info; if (anv_pipeline_has_stage(pipeline, MESA_SHADER_GEOMETRY)) @@ -1141,10 +1382,9 @@ emit_3dstate_streamout(struct anv_pipeline *pipeline, xfb_info = pipeline->shaders[MESA_SHADER_TESS_EVAL]->xfb_info; else xfb_info = pipeline->shaders[MESA_SHADER_VERTEX]->xfb_info; +#endif - pipeline->xfb_used = xfb_info ? xfb_info->buffers_written : 0; - - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_STREAMOUT), so) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_STREAMOUT), so) { so.RenderingDisable = rs_info->rasterizerDiscardEnable; #if GEN_GEN >= 8 @@ -1157,10 +1397,10 @@ emit_3dstate_streamout(struct anv_pipeline *pipeline, so.RenderStreamSelect = stream_info ? stream_info->rasterizationStream : 0; - so.Buffer0SurfacePitch = xfb_info->strides[0]; - so.Buffer1SurfacePitch = xfb_info->strides[1]; - so.Buffer2SurfacePitch = xfb_info->strides[2]; - so.Buffer3SurfacePitch = xfb_info->strides[3]; + so.Buffer0SurfacePitch = xfb_info->buffers[0].stride; + so.Buffer1SurfacePitch = xfb_info->buffers[1].stride; + so.Buffer2SurfacePitch = xfb_info->buffers[2].stride; + so.Buffer3SurfacePitch = xfb_info->buffers[3].stride; int urb_entry_read_offset = 0; int urb_entry_read_length = @@ -1231,11 +1471,23 @@ emit_3dstate_streamout(struct anv_pipeline *pipeline, next_offset[buffer] = output->offset + __builtin_popcount(component_mask) * 4; - so_decl[stream][decls[stream]++] = (struct GENX(SO_DECL)) { - .OutputBufferSlot = buffer, - .RegisterIndex = vue_map->varying_to_slot[varying], - .ComponentMask = component_mask, - }; + const int slot = vue_map->varying_to_slot[varying]; + if (slot < 0) { + /* This can happen if the shader never writes to the varying. + * Insert a hole instead of actual varying data. + */ + so_decl[stream][decls[stream]++] = (struct GENX(SO_DECL)) { + .HoleFlag = true, + .OutputBufferSlot = buffer, + .ComponentMask = component_mask, + }; + } else { + so_decl[stream][decls[stream]++] = (struct GENX(SO_DECL)) { + .OutputBufferSlot = buffer, + .RegisterIndex = slot, + .ComponentMask = component_mask, + }; + } } int max_decls = 0; @@ -1248,7 +1500,7 @@ emit_3dstate_streamout(struct anv_pipeline *pipeline, sbs[xfb_info->buffer_to_stream[b]] |= 1 << b; } - uint32_t *dw = anv_batch_emitn(&pipeline->batch, 3 + 2 * max_decls, + uint32_t *dw = anv_batch_emitn(&pipeline->base.batch, 3 + 2 * max_decls, GENX(3DSTATE_SO_DECL_LIST), .StreamtoBufferSelects0 = sbs[0], .StreamtoBufferSelects1 = sbs[1], @@ -1310,16 +1562,16 @@ get_scratch_space(const struct anv_shader_bin *bin) } static void -emit_3dstate_vs(struct anv_pipeline *pipeline) +emit_3dstate_vs(struct anv_graphics_pipeline *pipeline) { - const struct gen_device_info *devinfo = &pipeline->device->info; + const struct gen_device_info *devinfo = &pipeline->base.device->info; const struct brw_vs_prog_data *vs_prog_data = get_vs_prog_data(pipeline); const struct anv_shader_bin *vs_bin = pipeline->shaders[MESA_SHADER_VERTEX]; assert(anv_pipeline_has_stage(pipeline, MESA_SHADER_VERTEX)); - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VS), vs) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_VS), vs) { vs.Enable = true; vs.StatisticsEnable = true; vs.KernelStartPointer = vs_bin->kernel.offset; @@ -1339,11 +1591,7 @@ emit_3dstate_vs(struct anv_pipeline *pipeline) * programming 0xB000[30] to '1'. */ vs.SamplerCount = GEN_GEN == 11 ? 0 : get_sampler_count(vs_bin); - /* Gen 11 workarounds table #2056 WABTPPrefetchDisable suggests to - * disable prefetching of binding tables on A0 and B0 steppings. - * TODO: Revisit this WA on newer steppings. - */ - vs.BindingTableEntryCount = GEN_GEN == 11 ? 0 : get_binding_table_entry_count(vs_bin); + vs.BindingTableEntryCount = get_binding_table_entry_count(vs_bin); vs.FloatingPointMode = IEEE754; vs.IllegalOpcodeExceptionEnable = false; vs.SoftwareExceptionEnable = false; @@ -1385,22 +1633,22 @@ emit_3dstate_vs(struct anv_pipeline *pipeline) vs.PerThreadScratchSpace = get_scratch_space(vs_bin); vs.ScratchSpaceBasePointer = - get_scratch_address(pipeline, MESA_SHADER_VERTEX, vs_bin); + get_scratch_address(&pipeline->base, MESA_SHADER_VERTEX, vs_bin); } } static void -emit_3dstate_hs_te_ds(struct anv_pipeline *pipeline, +emit_3dstate_hs_te_ds(struct anv_graphics_pipeline *pipeline, const VkPipelineTessellationStateCreateInfo *tess_info) { if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) { - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_HS), hs); - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_TE), te); - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_DS), ds); + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_HS), hs); + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_TE), te); + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_DS), ds); return; } - const struct gen_device_info *devinfo = &pipeline->device->info; + const struct gen_device_info *devinfo = &pipeline->base.device->info; const struct anv_shader_bin *tcs_bin = pipeline->shaders[MESA_SHADER_TESS_CTRL]; const struct anv_shader_bin *tes_bin = @@ -1409,14 +1657,24 @@ emit_3dstate_hs_te_ds(struct anv_pipeline *pipeline, const struct brw_tcs_prog_data *tcs_prog_data = get_tcs_prog_data(pipeline); const struct brw_tes_prog_data *tes_prog_data = get_tes_prog_data(pipeline); - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_HS), hs) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_HS), hs) { hs.Enable = true; hs.StatisticsEnable = true; hs.KernelStartPointer = tcs_bin->kernel.offset; /* WA_1606682166 */ hs.SamplerCount = GEN_GEN == 11 ? 0 : get_sampler_count(tcs_bin); - /* Gen 11 workarounds table #2056 WABTPPrefetchDisable */ - hs.BindingTableEntryCount = GEN_GEN == 11 ? 0 : get_binding_table_entry_count(tcs_bin); + hs.BindingTableEntryCount = get_binding_table_entry_count(tcs_bin); + +#if GEN_GEN >= 12 + /* GEN:BUG:1604578095: + * + * Hang occurs when the number of max threads is less than 2 times + * the number of instance count. The number of max threads must be + * more than 2 times the number of instance count. + */ + assert((devinfo->max_tcs_threads / 2) > tcs_prog_data->instances); +#endif + hs.MaximumNumberofThreads = devinfo->max_tcs_threads - 1; hs.IncludeVertexHandles = true; hs.InstanceCount = tcs_prog_data->instances - 1; @@ -1424,11 +1682,28 @@ emit_3dstate_hs_te_ds(struct anv_pipeline *pipeline, hs.VertexURBEntryReadLength = 0; hs.VertexURBEntryReadOffset = 0; hs.DispatchGRFStartRegisterForURBData = - tcs_prog_data->base.base.dispatch_grf_start_reg; + tcs_prog_data->base.base.dispatch_grf_start_reg & 0x1f; +#if GEN_GEN >= 12 + hs.DispatchGRFStartRegisterForURBData5 = + tcs_prog_data->base.base.dispatch_grf_start_reg >> 5; +#endif + hs.PerThreadScratchSpace = get_scratch_space(tcs_bin); hs.ScratchSpaceBasePointer = - get_scratch_address(pipeline, MESA_SHADER_TESS_CTRL, tcs_bin); + get_scratch_address(&pipeline->base, MESA_SHADER_TESS_CTRL, tcs_bin); + +#if GEN_GEN == 12 + /* Patch Count threshold specifies the maximum number of patches that + * will be accumulated before a thread dispatch is forced. + */ + hs.PatchCountThreshold = tcs_prog_data->patch_count_threshold; +#endif + +#if GEN_GEN >= 9 + hs.DispatchMode = tcs_prog_data->base.dispatch_mode; + hs.IncludePrimitiveID = tcs_prog_data->include_primitive_id; +#endif } const VkPipelineTessellationDomainOriginStateCreateInfo *domain_origin_state = @@ -1438,7 +1713,7 @@ emit_3dstate_hs_te_ds(struct anv_pipeline *pipeline, domain_origin_state ? domain_origin_state->domainOrigin : VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT; - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_TE), te) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_TE), te) { te.Partitioning = tes_prog_data->partitioning; if (uv_origin == VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT) { @@ -1460,14 +1735,13 @@ emit_3dstate_hs_te_ds(struct anv_pipeline *pipeline, te.MaximumTessellationFactorNotOdd = 64.0; } - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_DS), ds) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_DS), ds) { ds.Enable = true; ds.StatisticsEnable = true; ds.KernelStartPointer = tes_bin->kernel.offset; /* WA_1606682166 */ ds.SamplerCount = GEN_GEN == 11 ? 0 : get_sampler_count(tes_bin); - /* Gen 11 workarounds table #2056 WABTPPrefetchDisable */ - ds.BindingTableEntryCount = GEN_GEN == 11 ? 0 : get_binding_table_entry_count(tes_bin); + ds.BindingTableEntryCount = get_binding_table_entry_count(tes_bin); ds.MaximumNumberofThreads = devinfo->max_tes_threads - 1; ds.ComputeWCoordinateEnable = @@ -1497,25 +1771,25 @@ emit_3dstate_hs_te_ds(struct anv_pipeline *pipeline, ds.PerThreadScratchSpace = get_scratch_space(tes_bin); ds.ScratchSpaceBasePointer = - get_scratch_address(pipeline, MESA_SHADER_TESS_EVAL, tes_bin); + get_scratch_address(&pipeline->base, MESA_SHADER_TESS_EVAL, tes_bin); } } static void -emit_3dstate_gs(struct anv_pipeline *pipeline) +emit_3dstate_gs(struct anv_graphics_pipeline *pipeline) { - const struct gen_device_info *devinfo = &pipeline->device->info; + const struct gen_device_info *devinfo = &pipeline->base.device->info; const struct anv_shader_bin *gs_bin = pipeline->shaders[MESA_SHADER_GEOMETRY]; if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_GEOMETRY)) { - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_GS), gs); + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_GS), gs); return; } const struct brw_gs_prog_data *gs_prog_data = get_gs_prog_data(pipeline); - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_GS), gs) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_GS), gs) { gs.Enable = true; gs.StatisticsEnable = true; gs.KernelStartPointer = gs_bin->kernel.offset; @@ -1525,8 +1799,7 @@ emit_3dstate_gs(struct anv_pipeline *pipeline) gs.VectorMaskEnable = false; /* WA_1606682166 */ gs.SamplerCount = GEN_GEN == 11 ? 0 : get_sampler_count(gs_bin); - /* Gen 11 workarounds table #2056 WABTPPrefetchDisable */ - gs.BindingTableEntryCount = GEN_GEN == 11 ? 0 : get_binding_table_entry_count(gs_bin); + gs.BindingTableEntryCount = get_binding_table_entry_count(gs_bin); gs.IncludeVertexHandles = gs_prog_data->base.include_vue_handles; gs.IncludePrimitiveID = gs_prog_data->include_primitive_id; @@ -1566,12 +1839,12 @@ emit_3dstate_gs(struct anv_pipeline *pipeline) gs.PerThreadScratchSpace = get_scratch_space(gs_bin); gs.ScratchSpaceBasePointer = - get_scratch_address(pipeline, MESA_SHADER_GEOMETRY, gs_bin); + get_scratch_address(&pipeline->base, MESA_SHADER_GEOMETRY, gs_bin); } } static bool -has_color_buffer_write_enabled(const struct anv_pipeline *pipeline, +has_color_buffer_write_enabled(const struct anv_graphics_pipeline *pipeline, const VkPipelineColorBlendStateCreateInfo *blend) { const struct anv_shader_bin *shader_bin = @@ -1597,16 +1870,16 @@ has_color_buffer_write_enabled(const struct anv_pipeline *pipeline, } static void -emit_3dstate_wm(struct anv_pipeline *pipeline, struct anv_subpass *subpass, +emit_3dstate_wm(struct anv_graphics_pipeline *pipeline, struct anv_subpass *subpass, + const VkPipelineInputAssemblyStateCreateInfo *ia, + const VkPipelineRasterizationStateCreateInfo *raster, const VkPipelineColorBlendStateCreateInfo *blend, - const VkPipelineMultisampleStateCreateInfo *multisample) + const VkPipelineMultisampleStateCreateInfo *multisample, + const VkPipelineRasterizationLineStateCreateInfoEXT *line) { const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline); - MAYBE_UNUSED uint32_t samples = - multisample ? multisample->rasterizationSamples : 1; - - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_WM), wm) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_WM), wm) { wm.StatisticsEnable = true; wm.LineEndCapAntialiasingRegionWidth = _05pixels; wm.LineAntialiasingRegionWidth = _10pixels; @@ -1668,33 +1941,35 @@ emit_3dstate_wm(struct anv_pipeline *pipeline, struct anv_subpass *subpass, has_color_buffer_write_enabled(pipeline, blend)) wm.ThreadDispatchEnable = true; - if (samples > 1) { - wm.MultisampleRasterizationMode = MSRASTMODE_ON_PATTERN; + if (multisample && multisample->rasterizationSamples > 1) { if (wm_prog_data->persample_dispatch) { wm.MultisampleDispatchMode = MSDISPMODE_PERSAMPLE; } else { wm.MultisampleDispatchMode = MSDISPMODE_PERPIXEL; } } else { - wm.MultisampleRasterizationMode = MSRASTMODE_OFF_PIXEL; wm.MultisampleDispatchMode = MSDISPMODE_PERSAMPLE; } + wm.MultisampleRasterizationMode = + gen7_ms_rast_mode(pipeline, ia, raster, multisample); #endif + + wm.LineStippleEnable = line && line->stippledLineEnable; } } } static void -emit_3dstate_ps(struct anv_pipeline *pipeline, +emit_3dstate_ps(struct anv_graphics_pipeline *pipeline, const VkPipelineColorBlendStateCreateInfo *blend, const VkPipelineMultisampleStateCreateInfo *multisample) { - MAYBE_UNUSED const struct gen_device_info *devinfo = &pipeline->device->info; + UNUSED const struct gen_device_info *devinfo = &pipeline->base.device->info; const struct anv_shader_bin *fs_bin = pipeline->shaders[MESA_SHADER_FRAGMENT]; if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT)) { - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_PS), ps) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_PS), ps) { #if GEN_GEN == 7 /* Even if no fragments are ever dispatched, gen7 hardware hangs if * we don't at least set the maximum number of threads. @@ -1729,7 +2004,7 @@ emit_3dstate_ps(struct anv_pipeline *pipeline, } #endif - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_PS), ps) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_PS), ps) { ps._8PixelDispatchEnable = wm_prog_data->dispatch_8; ps._16PixelDispatchEnable = wm_prog_data->dispatch_16; ps._32PixelDispatchEnable = wm_prog_data->dispatch_32; @@ -1756,11 +2031,10 @@ emit_3dstate_ps(struct anv_pipeline *pipeline, brw_wm_prog_data_prog_offset(wm_prog_data, ps, 2); ps.SingleProgramFlow = false; - ps.VectorMaskEnable = true; + ps.VectorMaskEnable = GEN_GEN >= 8; /* WA_1606682166 */ ps.SamplerCount = GEN_GEN == 11 ? 0 : get_sampler_count(fs_bin); - /* Gen 11 workarounds table #2056 WABTPPrefetchDisable */ - ps.BindingTableEntryCount = GEN_GEN == 11 ? 0 : get_binding_table_entry_count(fs_bin); + ps.BindingTableEntryCount = get_binding_table_entry_count(fs_bin); ps.PushConstantEnable = wm_prog_data->base.nr_params > 0 || wm_prog_data->base.ubo_ranges[0].length; ps.PositionXYOffsetSelect = wm_prog_data->uses_pos_offset ? @@ -1795,24 +2069,23 @@ emit_3dstate_ps(struct anv_pipeline *pipeline, ps.PerThreadScratchSpace = get_scratch_space(fs_bin); ps.ScratchSpaceBasePointer = - get_scratch_address(pipeline, MESA_SHADER_FRAGMENT, fs_bin); + get_scratch_address(&pipeline->base, MESA_SHADER_FRAGMENT, fs_bin); } } #if GEN_GEN >= 8 static void -emit_3dstate_ps_extra(struct anv_pipeline *pipeline, - struct anv_subpass *subpass, - const VkPipelineColorBlendStateCreateInfo *blend) +emit_3dstate_ps_extra(struct anv_graphics_pipeline *pipeline, + struct anv_subpass *subpass) { const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline); if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT)) { - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_PS_EXTRA), ps); + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_PS_EXTRA), ps); return; } - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_PS_EXTRA), ps) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_PS_EXTRA), ps) { ps.PixelShaderValid = true; ps.AttributeEnable = wm_prog_data->num_varying_inputs > 0; ps.oMaskPresenttoRenderTarget = wm_prog_data->uses_omask; @@ -1848,24 +2121,24 @@ emit_3dstate_ps_extra(struct anv_pipeline *pipeline, } static void -emit_3dstate_vf_topology(struct anv_pipeline *pipeline) +emit_3dstate_vf_topology(struct anv_graphics_pipeline *pipeline) { - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_TOPOLOGY), vft) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_VF_TOPOLOGY), vft) { vft.PrimitiveTopologyType = pipeline->topology; } } #endif static void -emit_3dstate_vf_statistics(struct anv_pipeline *pipeline) +emit_3dstate_vf_statistics(struct anv_graphics_pipeline *pipeline) { - anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_STATISTICS), vfs) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_VF_STATISTICS), vfs) { vfs.StatisticsEnable = true; } } static void -compute_kill_pixel(struct anv_pipeline *pipeline, +compute_kill_pixel(struct anv_graphics_pipeline *pipeline, const VkPipelineMultisampleStateCreateInfo *ms_info, const struct anv_subpass *subpass) { @@ -1896,6 +2169,32 @@ compute_kill_pixel(struct anv_pipeline *pipeline, (ms_info && ms_info->alphaToCoverageEnable); } +#if GEN_GEN == 12 +static void +emit_3dstate_primitive_replication(struct anv_graphics_pipeline *pipeline) +{ + if (!pipeline->use_primitive_replication) { + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_PRIMITIVE_REPLICATION), pr); + return; + } + + uint32_t view_mask = pipeline->subpass->view_mask; + int view_count = util_bitcount(view_mask); + assert(view_count > 1 && view_count <= MAX_VIEWS_FOR_PRIMITIVE_REPLICATION); + + anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_PRIMITIVE_REPLICATION), pr) { + pr.ReplicaMask = (1 << view_count) - 1; + pr.ReplicationCount = view_count - 1; + + int i = 0, view_index; + for_each_bit(view_index, view_mask) { + pr.RTAIOffset[i] = view_index; + i++; + } + } +} +#endif + static VkResult genX(graphics_pipeline_create)( VkDevice _device, @@ -1907,44 +2206,87 @@ genX(graphics_pipeline_create)( ANV_FROM_HANDLE(anv_device, device, _device); ANV_FROM_HANDLE(anv_render_pass, pass, pCreateInfo->renderPass); struct anv_subpass *subpass = &pass->subpasses[pCreateInfo->subpass]; - struct anv_pipeline *pipeline; + struct anv_graphics_pipeline *pipeline; VkResult result; assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO); /* Use the default pipeline cache if none is specified */ - if (cache == NULL && device->instance->pipeline_cache_enabled) + if (cache == NULL && device->physical->instance->pipeline_cache_enabled) cache = &device->default_pipeline_cache; - pipeline = vk_alloc2(&device->alloc, pAllocator, sizeof(*pipeline), 8, + pipeline = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (pipeline == NULL) return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - result = anv_pipeline_init(pipeline, device, cache, - pCreateInfo, pAllocator); + result = anv_graphics_pipeline_init(pipeline, device, cache, + pCreateInfo, pAllocator); if (result != VK_SUCCESS) { - vk_free2(&device->alloc, pAllocator, pipeline); + vk_free2(&device->vk.alloc, pAllocator, pipeline); + if (result == VK_PIPELINE_COMPILE_REQUIRED_EXT) + *pPipeline = VK_NULL_HANDLE; return result; } + /* If rasterization is not enabled, various CreateInfo structs must be + * ignored. + */ + const bool raster_enabled = + !pCreateInfo->pRasterizationState->rasterizerDiscardEnable; + + const VkPipelineViewportStateCreateInfo *vp_info = + raster_enabled ? pCreateInfo->pViewportState : NULL; + + const VkPipelineMultisampleStateCreateInfo *ms_info = + raster_enabled ? pCreateInfo->pMultisampleState : NULL; + + const VkPipelineDepthStencilStateCreateInfo *ds_info = + raster_enabled ? pCreateInfo->pDepthStencilState : NULL; + + const VkPipelineColorBlendStateCreateInfo *cb_info = + raster_enabled ? pCreateInfo->pColorBlendState : NULL; + + const VkPipelineRasterizationLineStateCreateInfoEXT *line_info = + vk_find_struct_const(pCreateInfo->pRasterizationState->pNext, + PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT); + + /* Information on which states are considered dynamic. */ + const VkPipelineDynamicStateCreateInfo *dyn_info = + pCreateInfo->pDynamicState; + uint32_t dynamic_states = 0; + if (dyn_info) { + for (unsigned i = 0; i < dyn_info->dynamicStateCount; i++) + dynamic_states |= + anv_cmd_dirty_bit_for_vk_dynamic_state(dyn_info->pDynamicStates[i]); + } + + enum gen_urb_deref_block_size urb_deref_block_size; + emit_urb_setup(pipeline, &urb_deref_block_size); + assert(pCreateInfo->pVertexInputState); emit_vertex_input(pipeline, pCreateInfo->pVertexInputState); assert(pCreateInfo->pRasterizationState); - emit_rs_state(pipeline, pCreateInfo->pRasterizationState, - pCreateInfo->pMultisampleState, pass, subpass); - emit_ms_state(pipeline, pCreateInfo->pMultisampleState); - emit_ds_state(pipeline, pCreateInfo->pDepthStencilState, pass, subpass); - emit_cb_state(pipeline, pCreateInfo->pColorBlendState, - pCreateInfo->pMultisampleState); - compute_kill_pixel(pipeline, pCreateInfo->pMultisampleState, subpass); - - emit_urb_setup(pipeline); - - emit_3dstate_clip(pipeline, pCreateInfo->pViewportState, - pCreateInfo->pRasterizationState); + emit_rs_state(pipeline, pCreateInfo->pInputAssemblyState, + pCreateInfo->pRasterizationState, + ms_info, line_info, dynamic_states, pass, subpass, + urb_deref_block_size); + emit_ms_state(pipeline, ms_info); + emit_ds_state(pipeline, ds_info, dynamic_states, pass, subpass); + emit_cb_state(pipeline, cb_info, ms_info); + compute_kill_pixel(pipeline, ms_info, subpass); + + emit_3dstate_clip(pipeline, + pCreateInfo->pInputAssemblyState, + vp_info, + pCreateInfo->pRasterizationState, + dynamic_states); emit_3dstate_streamout(pipeline, pCreateInfo->pRasterizationState); +#if GEN_GEN == 12 + emit_3dstate_primitive_replication(pipeline); +#endif + #if 0 /* From gen7_vs_state.c */ @@ -1968,103 +2310,46 @@ genX(graphics_pipeline_create)( emit_3dstate_hs_te_ds(pipeline, pCreateInfo->pTessellationState); emit_3dstate_gs(pipeline); emit_3dstate_sbe(pipeline); - emit_3dstate_wm(pipeline, subpass, pCreateInfo->pColorBlendState, - pCreateInfo->pMultisampleState); - emit_3dstate_ps(pipeline, pCreateInfo->pColorBlendState, - pCreateInfo->pMultisampleState); + emit_3dstate_wm(pipeline, subpass, + pCreateInfo->pInputAssemblyState, + pCreateInfo->pRasterizationState, + cb_info, ms_info, line_info); + emit_3dstate_ps(pipeline, cb_info, ms_info); #if GEN_GEN >= 8 - emit_3dstate_ps_extra(pipeline, subpass, pCreateInfo->pColorBlendState); - emit_3dstate_vf_topology(pipeline); + emit_3dstate_ps_extra(pipeline, subpass); + + if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) + emit_3dstate_vf_topology(pipeline); #endif emit_3dstate_vf_statistics(pipeline); - *pPipeline = anv_pipeline_to_handle(pipeline); + *pPipeline = anv_pipeline_to_handle(&pipeline->base); - return pipeline->batch.status; + return pipeline->base.batch.status; } -static VkResult -compute_pipeline_create( - VkDevice _device, - struct anv_pipeline_cache * cache, - const VkComputePipelineCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkPipeline* pPipeline) +static void +emit_media_cs_state(struct anv_compute_pipeline *pipeline, + const struct anv_device *device) { - ANV_FROM_HANDLE(anv_device, device, _device); - const struct anv_physical_device *physical_device = - &device->instance->physicalDevice; - const struct gen_device_info *devinfo = &physical_device->info; - struct anv_pipeline *pipeline; - VkResult result; - - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO); - - /* Use the default pipeline cache if none is specified */ - if (cache == NULL && device->instance->pipeline_cache_enabled) - cache = &device->default_pipeline_cache; - - pipeline = vk_alloc2(&device->alloc, pAllocator, sizeof(*pipeline), 8, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (pipeline == NULL) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - - pipeline->device = device; - - pipeline->blend_state.map = NULL; - - result = anv_reloc_list_init(&pipeline->batch_relocs, - pAllocator ? pAllocator : &device->alloc); - if (result != VK_SUCCESS) { - vk_free2(&device->alloc, pAllocator, pipeline); - return result; - } - pipeline->batch.next = pipeline->batch.start = pipeline->batch_data; - pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data); - pipeline->batch.relocs = &pipeline->batch_relocs; - pipeline->batch.status = VK_SUCCESS; - - /* When we free the pipeline, we detect stages based on the NULL status - * of various prog_data pointers. Make them NULL by default. - */ - memset(pipeline->shaders, 0, sizeof(pipeline->shaders)); - - pipeline->needs_data_cache = false; - - assert(pCreateInfo->stage.stage == VK_SHADER_STAGE_COMPUTE_BIT); - pipeline->active_stages |= VK_SHADER_STAGE_COMPUTE_BIT; - ANV_FROM_HANDLE(anv_shader_module, module, pCreateInfo->stage.module); - result = anv_pipeline_compile_cs(pipeline, cache, pCreateInfo, module, - pCreateInfo->stage.pName, - pCreateInfo->stage.pSpecializationInfo); - if (result != VK_SUCCESS) { - vk_free2(&device->alloc, pAllocator, pipeline); - return result; - } - const struct brw_cs_prog_data *cs_prog_data = get_cs_prog_data(pipeline); - anv_pipeline_setup_l3_config(pipeline, cs_prog_data->base.total_shared > 0); + anv_pipeline_setup_l3_config(&pipeline->base, cs_prog_data->base.total_shared > 0); - uint32_t group_size = cs_prog_data->local_size[0] * - cs_prog_data->local_size[1] * cs_prog_data->local_size[2]; - uint32_t remainder = group_size & (cs_prog_data->simd_size - 1); + const struct anv_cs_parameters cs_params = anv_cs_parameters(pipeline); - if (remainder > 0) - pipeline->cs_right_mask = ~0u >> (32 - remainder); - else - pipeline->cs_right_mask = ~0u >> (32 - cs_prog_data->simd_size); + pipeline->cs_right_mask = brw_cs_right_mask(cs_params.group_size, cs_params.simd_size); const uint32_t vfe_curbe_allocation = - ALIGN(cs_prog_data->push.per_thread.regs * cs_prog_data->threads + + ALIGN(cs_prog_data->push.per_thread.regs * cs_params.threads + cs_prog_data->push.cross_thread.regs, 2); - const uint32_t subslices = MAX2(physical_device->subslice_total, 1); + const uint32_t subslices = MAX2(device->physical->subslice_total, 1); - const struct anv_shader_bin *cs_bin = - pipeline->shaders[MESA_SHADER_COMPUTE]; + const struct anv_shader_bin *cs_bin = pipeline->cs; + const struct gen_device_info *devinfo = &device->info; - anv_batch_emit(&pipeline->batch, GENX(MEDIA_VFE_STATE), vfe) { + anv_batch_emit(&pipeline->base.batch, GENX(MEDIA_VFE_STATE), vfe) { #if GEN_GEN > 7 vfe.StackSize = 0; #else @@ -2082,21 +2367,42 @@ compute_pipeline_create( vfe.URBEntryAllocationSize = GEN_GEN <= 7 ? 0 : 2; vfe.CURBEAllocationSize = vfe_curbe_allocation; - vfe.PerThreadScratchSpace = get_scratch_space(cs_bin); - vfe.ScratchSpaceBasePointer = - get_scratch_address(pipeline, MESA_SHADER_COMPUTE, cs_bin); + if (cs_bin->prog_data->total_scratch) { + if (GEN_GEN >= 8) { + /* Broadwell's Per Thread Scratch Space is in the range [0, 11] + * where 0 = 1k, 1 = 2k, 2 = 4k, ..., 11 = 2M. + */ + vfe.PerThreadScratchSpace = + ffs(cs_bin->prog_data->total_scratch) - 11; + } else if (GEN_IS_HASWELL) { + /* Haswell's Per Thread Scratch Space is in the range [0, 10] + * where 0 = 2k, 1 = 4k, 2 = 8k, ..., 10 = 2M. + */ + vfe.PerThreadScratchSpace = + ffs(cs_bin->prog_data->total_scratch) - 12; + } else { + /* IVB and BYT use the range [0, 11] to mean [1kB, 12kB] + * where 0 = 1kB, 1 = 2kB, 2 = 3kB, ..., 11 = 12kB. + */ + vfe.PerThreadScratchSpace = + cs_bin->prog_data->total_scratch / 1024 - 1; + } + vfe.ScratchSpaceBasePointer = + get_scratch_address(&pipeline->base, MESA_SHADER_COMPUTE, cs_bin); + } } struct GENX(INTERFACE_DESCRIPTOR_DATA) desc = { - .KernelStartPointer = cs_bin->kernel.offset, + .KernelStartPointer = + cs_bin->kernel.offset + + brw_cs_prog_data_prog_offset(cs_prog_data, cs_params.simd_size), + /* WA_1606682166 */ .SamplerCount = GEN_GEN == 11 ? 0 : get_sampler_count(cs_bin), - /* Gen 11 workarounds table #2056 WABTPPrefetchDisable - * - * We add 1 because the CS indirect parameters buffer isn't accounted + /* We add 1 because the CS indirect parameters buffer isn't accounted * for in bind_map.surface_count. */ - .BindingTableEntryCount = GEN_GEN == 11 ? 0 : 1 + MIN2(cs_bin->bind_map.surface_count, 30), + .BindingTableEntryCount = 1 + MIN2(cs_bin->bind_map.surface_count, 30), .BarrierEnable = cs_prog_data->uses_barrier, .SharedLocalMemorySize = encode_slm_size(GEN_GEN, cs_prog_data->base.total_shared), @@ -2109,16 +2415,80 @@ compute_pipeline_create( .CrossThreadConstantDataReadLength = cs_prog_data->push.cross_thread.regs, #endif +#if GEN_GEN >= 12 + /* TODO: Check if we are missing workarounds and enable mid-thread + * preemption. + * + * We still have issues with mid-thread preemption (it was already + * disabled by the kernel on gen11, due to missing workarounds). It's + * possible that we are just missing some workarounds, and could enable + * it later, but for now let's disable it to fix a GPU in compute in Car + * Chase (and possibly more). + */ + .ThreadPreemptionDisable = true, +#endif - .NumberofThreadsinGPGPUThreadGroup = cs_prog_data->threads, + .NumberofThreadsinGPGPUThreadGroup = cs_params.threads, }; GENX(INTERFACE_DESCRIPTOR_DATA_pack)(NULL, pipeline->interface_descriptor_data, &desc); +} + +static VkResult +compute_pipeline_create( + VkDevice _device, + struct anv_pipeline_cache * cache, + const VkComputePipelineCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipeline) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + struct anv_compute_pipeline *pipeline; + VkResult result; + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO); + + /* Use the default pipeline cache if none is specified */ + if (cache == NULL && device->physical->instance->pipeline_cache_enabled) + cache = &device->default_pipeline_cache; + + pipeline = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (pipeline == NULL) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + + result = anv_pipeline_init(&pipeline->base, device, + ANV_PIPELINE_COMPUTE, pCreateInfo->flags, + pAllocator); + if (result != VK_SUCCESS) { + vk_free2(&device->vk.alloc, pAllocator, pipeline); + return result; + } - *pPipeline = anv_pipeline_to_handle(pipeline); + anv_batch_set_storage(&pipeline->base.batch, ANV_NULL_ADDRESS, + pipeline->batch_data, sizeof(pipeline->batch_data)); - return pipeline->batch.status; + pipeline->cs = NULL; + + assert(pCreateInfo->stage.stage == VK_SHADER_STAGE_COMPUTE_BIT); + ANV_FROM_HANDLE(anv_shader_module, module, pCreateInfo->stage.module); + result = anv_pipeline_compile_cs(pipeline, cache, pCreateInfo, module, + pCreateInfo->stage.pName, + pCreateInfo->stage.pSpecializationInfo); + if (result != VK_SUCCESS) { + anv_pipeline_finish(&pipeline->base, device, pAllocator); + vk_free2(&device->vk.alloc, pAllocator, pipeline); + if (result == VK_PIPELINE_COMPILE_REQUIRED_EXT) + *pPipeline = VK_NULL_HANDLE; + return result; + } + + emit_media_cs_state(pipeline, device); + + *pPipeline = anv_pipeline_to_handle(&pipeline->base); + + return pipeline->base.batch.status; } VkResult genX(CreateGraphicsPipelines)( @@ -2135,14 +2505,22 @@ VkResult genX(CreateGraphicsPipelines)( unsigned i; for (i = 0; i < count; i++) { - result = genX(graphics_pipeline_create)(_device, - pipeline_cache, - &pCreateInfos[i], - pAllocator, &pPipelines[i]); - - /* Bail out on the first error as it is not obvious what error should be - * report upon 2 different failures. */ - if (result != VK_SUCCESS) + VkResult res = genX(graphics_pipeline_create)(_device, + pipeline_cache, + &pCreateInfos[i], + pAllocator, &pPipelines[i]); + + if (res == VK_SUCCESS) + continue; + + /* Bail out on the first error != VK_PIPELINE_COMPILE_REQUIRED_EX as it + * is not obvious what error should be report upon 2 different failures. + * */ + result = res; + if (res != VK_PIPELINE_COMPILE_REQUIRED_EXT) + break; + + if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT) break; } @@ -2166,13 +2544,21 @@ VkResult genX(CreateComputePipelines)( unsigned i; for (i = 0; i < count; i++) { - result = compute_pipeline_create(_device, pipeline_cache, - &pCreateInfos[i], - pAllocator, &pPipelines[i]); + VkResult res = compute_pipeline_create(_device, pipeline_cache, + &pCreateInfos[i], + pAllocator, &pPipelines[i]); + + if (res == VK_SUCCESS) + continue; + + /* Bail out on the first error != VK_PIPELINE_COMPILE_REQUIRED_EX as it + * is not obvious what error should be report upon 2 different failures. + * */ + result = res; + if (res != VK_PIPELINE_COMPILE_REQUIRED_EXT) + break; - /* Bail out on the first error as it is not obvious what error should be - * report upon 2 different failures. */ - if (result != VK_SUCCESS) + if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT) break; }