17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2015 Intel Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include <assert.h> 257ec681f3Smrg#include <stdbool.h> 267ec681f3Smrg#include <string.h> 277ec681f3Smrg#include <unistd.h> 287ec681f3Smrg#include <fcntl.h> 297ec681f3Smrg 307ec681f3Smrg#include "anv_private.h" 317ec681f3Smrg#include "vk_format.h" 327ec681f3Smrg 337ec681f3Smrg#include "genxml/gen_macros.h" 347ec681f3Smrg#include "genxml/genX_pack.h" 357ec681f3Smrg 367ec681f3Smrg#if GFX_VERx10 == 70 377ec681f3Smrgstatic int64_t 387ec681f3Smrgclamp_int64(int64_t x, int64_t min, int64_t max) 397ec681f3Smrg{ 407ec681f3Smrg if (x < min) 417ec681f3Smrg return min; 427ec681f3Smrg else if (x < max) 437ec681f3Smrg return x; 447ec681f3Smrg else 457ec681f3Smrg return max; 467ec681f3Smrg} 477ec681f3Smrg 487ec681f3Smrgvoid 497ec681f3Smrggfx7_cmd_buffer_emit_scissor(struct anv_cmd_buffer *cmd_buffer) 507ec681f3Smrg{ 517ec681f3Smrg struct anv_framebuffer *fb = cmd_buffer->state.framebuffer; 527ec681f3Smrg uint32_t count = cmd_buffer->state.gfx.dynamic.scissor.count; 537ec681f3Smrg const VkRect2D *scissors = cmd_buffer->state.gfx.dynamic.scissor.scissors; 547ec681f3Smrg 557ec681f3Smrg /* Wa_1409725701: 567ec681f3Smrg * "The viewport-specific state used by the SF unit (SCISSOR_RECT) is 577ec681f3Smrg * stored as an array of up to 16 elements. The location of first 587ec681f3Smrg * element of the array, as specified by Pointer to SCISSOR_RECT, should 597ec681f3Smrg * be aligned to a 64-byte boundary. 607ec681f3Smrg */ 617ec681f3Smrg uint32_t alignment = 64; 627ec681f3Smrg struct anv_state scissor_state = 637ec681f3Smrg anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, count * 8, alignment); 647ec681f3Smrg 657ec681f3Smrg for (uint32_t i = 0; i < count; i++) { 667ec681f3Smrg const VkRect2D *s = &scissors[i]; 677ec681f3Smrg 687ec681f3Smrg /* Since xmax and ymax are inclusive, we have to have xmax < xmin or 697ec681f3Smrg * ymax < ymin for empty clips. In case clip x, y, width height are all 707ec681f3Smrg * 0, the clamps below produce 0 for xmin, ymin, xmax, ymax, which isn't 717ec681f3Smrg * what we want. Just special case empty clips and produce a canonical 727ec681f3Smrg * empty clip. */ 737ec681f3Smrg static const struct GFX7_SCISSOR_RECT empty_scissor = { 747ec681f3Smrg .ScissorRectangleYMin = 1, 757ec681f3Smrg .ScissorRectangleXMin = 1, 767ec681f3Smrg .ScissorRectangleYMax = 0, 777ec681f3Smrg .ScissorRectangleXMax = 0 787ec681f3Smrg }; 797ec681f3Smrg 807ec681f3Smrg const int max = 0xffff; 817ec681f3Smrg 827ec681f3Smrg uint32_t y_min = s->offset.y; 837ec681f3Smrg uint32_t x_min = s->offset.x; 847ec681f3Smrg uint32_t y_max = s->offset.y + s->extent.height - 1; 857ec681f3Smrg uint32_t x_max = s->offset.x + s->extent.width - 1; 867ec681f3Smrg 877ec681f3Smrg /* Do this math using int64_t so overflow gets clamped correctly. */ 887ec681f3Smrg if (cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 897ec681f3Smrg y_min = clamp_int64((uint64_t) y_min, 907ec681f3Smrg cmd_buffer->state.render_area.offset.y, max); 917ec681f3Smrg x_min = clamp_int64((uint64_t) x_min, 927ec681f3Smrg cmd_buffer->state.render_area.offset.x, max); 937ec681f3Smrg y_max = clamp_int64((uint64_t) y_max, 0, 947ec681f3Smrg cmd_buffer->state.render_area.offset.y + 957ec681f3Smrg cmd_buffer->state.render_area.extent.height - 1); 967ec681f3Smrg x_max = clamp_int64((uint64_t) x_max, 0, 977ec681f3Smrg cmd_buffer->state.render_area.offset.x + 987ec681f3Smrg cmd_buffer->state.render_area.extent.width - 1); 997ec681f3Smrg } else if (fb) { 1007ec681f3Smrg y_min = clamp_int64((uint64_t) y_min, 0, max); 1017ec681f3Smrg x_min = clamp_int64((uint64_t) x_min, 0, max); 1027ec681f3Smrg y_max = clamp_int64((uint64_t) y_max, 0, fb->height - 1); 1037ec681f3Smrg x_max = clamp_int64((uint64_t) x_max, 0, fb->width - 1); 1047ec681f3Smrg } 1057ec681f3Smrg 1067ec681f3Smrg struct GFX7_SCISSOR_RECT scissor = { 1077ec681f3Smrg .ScissorRectangleYMin = y_min, 1087ec681f3Smrg .ScissorRectangleXMin = x_min, 1097ec681f3Smrg .ScissorRectangleYMax = y_max, 1107ec681f3Smrg .ScissorRectangleXMax = x_max 1117ec681f3Smrg }; 1127ec681f3Smrg 1137ec681f3Smrg if (s->extent.width <= 0 || s->extent.height <= 0) { 1147ec681f3Smrg GFX7_SCISSOR_RECT_pack(NULL, scissor_state.map + i * 8, 1157ec681f3Smrg &empty_scissor); 1167ec681f3Smrg } else { 1177ec681f3Smrg GFX7_SCISSOR_RECT_pack(NULL, scissor_state.map + i * 8, &scissor); 1187ec681f3Smrg } 1197ec681f3Smrg } 1207ec681f3Smrg 1217ec681f3Smrg anv_batch_emit(&cmd_buffer->batch, 1227ec681f3Smrg GFX7_3DSTATE_SCISSOR_STATE_POINTERS, ssp) { 1237ec681f3Smrg ssp.ScissorRectPointer = scissor_state.offset; 1247ec681f3Smrg } 1257ec681f3Smrg} 1267ec681f3Smrg#endif 1277ec681f3Smrg 1287ec681f3Smrgstatic uint32_t vk_to_intel_index_type(VkIndexType type) 1297ec681f3Smrg{ 1307ec681f3Smrg switch (type) { 1317ec681f3Smrg case VK_INDEX_TYPE_UINT8_EXT: 1327ec681f3Smrg return INDEX_BYTE; 1337ec681f3Smrg case VK_INDEX_TYPE_UINT16: 1347ec681f3Smrg return INDEX_WORD; 1357ec681f3Smrg case VK_INDEX_TYPE_UINT32: 1367ec681f3Smrg return INDEX_DWORD; 1377ec681f3Smrg default: 1387ec681f3Smrg unreachable("invalid index type"); 1397ec681f3Smrg } 1407ec681f3Smrg} 1417ec681f3Smrg 1427ec681f3Smrgstatic uint32_t restart_index_for_type(VkIndexType type) 1437ec681f3Smrg{ 1447ec681f3Smrg switch (type) { 1457ec681f3Smrg case VK_INDEX_TYPE_UINT8_EXT: 1467ec681f3Smrg return UINT8_MAX; 1477ec681f3Smrg case VK_INDEX_TYPE_UINT16: 1487ec681f3Smrg return UINT16_MAX; 1497ec681f3Smrg case VK_INDEX_TYPE_UINT32: 1507ec681f3Smrg return UINT32_MAX; 1517ec681f3Smrg default: 1527ec681f3Smrg unreachable("invalid index type"); 1537ec681f3Smrg } 1547ec681f3Smrg} 1557ec681f3Smrg 1567ec681f3Smrgvoid genX(CmdBindIndexBuffer)( 1577ec681f3Smrg VkCommandBuffer commandBuffer, 1587ec681f3Smrg VkBuffer _buffer, 1597ec681f3Smrg VkDeviceSize offset, 1607ec681f3Smrg VkIndexType indexType) 1617ec681f3Smrg{ 1627ec681f3Smrg ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 1637ec681f3Smrg ANV_FROM_HANDLE(anv_buffer, buffer, _buffer); 1647ec681f3Smrg 1657ec681f3Smrg cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_INDEX_BUFFER; 1667ec681f3Smrg if (GFX_VERx10 == 75) 1677ec681f3Smrg cmd_buffer->state.restart_index = restart_index_for_type(indexType); 1687ec681f3Smrg cmd_buffer->state.gfx.gfx7.index_buffer = buffer; 1697ec681f3Smrg cmd_buffer->state.gfx.gfx7.index_type = vk_to_intel_index_type(indexType); 1707ec681f3Smrg cmd_buffer->state.gfx.gfx7.index_offset = offset; 1717ec681f3Smrg} 1727ec681f3Smrg 1737ec681f3Smrgstatic uint32_t 1747ec681f3Smrgget_depth_format(struct anv_cmd_buffer *cmd_buffer) 1757ec681f3Smrg{ 1767ec681f3Smrg const struct anv_render_pass *pass = cmd_buffer->state.pass; 1777ec681f3Smrg const struct anv_subpass *subpass = cmd_buffer->state.subpass; 1787ec681f3Smrg 1797ec681f3Smrg if (!subpass->depth_stencil_attachment) 1807ec681f3Smrg return D16_UNORM; 1817ec681f3Smrg 1827ec681f3Smrg struct anv_render_pass_attachment *att = 1837ec681f3Smrg &pass->attachments[subpass->depth_stencil_attachment->attachment]; 1847ec681f3Smrg 1857ec681f3Smrg switch (att->format) { 1867ec681f3Smrg case VK_FORMAT_D16_UNORM: 1877ec681f3Smrg case VK_FORMAT_D16_UNORM_S8_UINT: 1887ec681f3Smrg return D16_UNORM; 1897ec681f3Smrg 1907ec681f3Smrg case VK_FORMAT_X8_D24_UNORM_PACK32: 1917ec681f3Smrg case VK_FORMAT_D24_UNORM_S8_UINT: 1927ec681f3Smrg return D24_UNORM_X8_UINT; 1937ec681f3Smrg 1947ec681f3Smrg case VK_FORMAT_D32_SFLOAT: 1957ec681f3Smrg case VK_FORMAT_D32_SFLOAT_S8_UINT: 1967ec681f3Smrg return D32_FLOAT; 1977ec681f3Smrg 1987ec681f3Smrg default: 1997ec681f3Smrg return D16_UNORM; 2007ec681f3Smrg } 2017ec681f3Smrg} 2027ec681f3Smrg 2037ec681f3Smrgvoid 2047ec681f3SmrggenX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) 2057ec681f3Smrg{ 2067ec681f3Smrg struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline; 2077ec681f3Smrg struct anv_dynamic_state *d = &cmd_buffer->state.gfx.dynamic; 2087ec681f3Smrg 2097ec681f3Smrg if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) { 2107ec681f3Smrg uint32_t topology; 2117ec681f3Smrg if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) 2127ec681f3Smrg topology = pipeline->topology; 2137ec681f3Smrg else 2147ec681f3Smrg topology = genX(vk_to_intel_primitive_type)[d->primitive_topology]; 2157ec681f3Smrg 2167ec681f3Smrg cmd_buffer->state.gfx.primitive_topology = topology; 2177ec681f3Smrg } 2187ec681f3Smrg 2197ec681f3Smrg if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | 2207ec681f3Smrg ANV_CMD_DIRTY_RENDER_TARGETS | 2217ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH | 2227ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS | 2237ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_CULL_MODE | 2247ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE | 2257ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE | 2267ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) { 2277ec681f3Smrg /* Take dynamic primitive topology in to account with 2287ec681f3Smrg * 3DSTATE_SF::MultisampleRasterizationMode 2297ec681f3Smrg */ 2307ec681f3Smrg uint32_t ms_rast_mode = 0; 2317ec681f3Smrg 2327ec681f3Smrg if (cmd_buffer->state.gfx.pipeline->dynamic_states & 2337ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) { 2347ec681f3Smrg VkPrimitiveTopology primitive_topology = 2357ec681f3Smrg cmd_buffer->state.gfx.dynamic.primitive_topology; 2367ec681f3Smrg 2377ec681f3Smrg VkPolygonMode dynamic_raster_mode = 2387ec681f3Smrg genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline, 2397ec681f3Smrg primitive_topology); 2407ec681f3Smrg 2417ec681f3Smrg ms_rast_mode = 2427ec681f3Smrg genX(ms_rasterization_mode)(pipeline, dynamic_raster_mode); 2437ec681f3Smrg } 2447ec681f3Smrg 2457ec681f3Smrg uint32_t sf_dw[GENX(3DSTATE_SF_length)]; 2467ec681f3Smrg struct GENX(3DSTATE_SF) sf = { 2477ec681f3Smrg GENX(3DSTATE_SF_header), 2487ec681f3Smrg .DepthBufferSurfaceFormat = get_depth_format(cmd_buffer), 2497ec681f3Smrg .LineWidth = d->line_width, 2507ec681f3Smrg .GlobalDepthOffsetConstant = d->depth_bias.bias, 2517ec681f3Smrg .GlobalDepthOffsetScale = d->depth_bias.slope, 2527ec681f3Smrg .GlobalDepthOffsetClamp = d->depth_bias.clamp, 2537ec681f3Smrg .FrontWinding = genX(vk_to_intel_front_face)[d->front_face], 2547ec681f3Smrg .CullMode = genX(vk_to_intel_cullmode)[d->cull_mode], 2557ec681f3Smrg .GlobalDepthOffsetEnableSolid = d->depth_bias_enable, 2567ec681f3Smrg .GlobalDepthOffsetEnableWireframe = d->depth_bias_enable, 2577ec681f3Smrg .GlobalDepthOffsetEnablePoint = d->depth_bias_enable, 2587ec681f3Smrg .MultisampleRasterizationMode = ms_rast_mode, 2597ec681f3Smrg }; 2607ec681f3Smrg GENX(3DSTATE_SF_pack)(NULL, sf_dw, &sf); 2617ec681f3Smrg 2627ec681f3Smrg anv_batch_emit_merge(&cmd_buffer->batch, sf_dw, pipeline->gfx7.sf); 2637ec681f3Smrg } 2647ec681f3Smrg 2657ec681f3Smrg if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS | 2667ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE)) { 2677ec681f3Smrg struct anv_state cc_state = 2687ec681f3Smrg anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, 2697ec681f3Smrg GENX(COLOR_CALC_STATE_length) * 4, 2707ec681f3Smrg 64); 2717ec681f3Smrg struct GENX(COLOR_CALC_STATE) cc = { 2727ec681f3Smrg .BlendConstantColorRed = d->blend_constants[0], 2737ec681f3Smrg .BlendConstantColorGreen = d->blend_constants[1], 2747ec681f3Smrg .BlendConstantColorBlue = d->blend_constants[2], 2757ec681f3Smrg .BlendConstantColorAlpha = d->blend_constants[3], 2767ec681f3Smrg .StencilReferenceValue = d->stencil_reference.front & 0xff, 2777ec681f3Smrg .BackfaceStencilReferenceValue = d->stencil_reference.back & 0xff, 2787ec681f3Smrg }; 2797ec681f3Smrg GENX(COLOR_CALC_STATE_pack)(NULL, cc_state.map, &cc); 2807ec681f3Smrg 2817ec681f3Smrg anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_CC_STATE_POINTERS), ccp) { 2827ec681f3Smrg ccp.ColorCalcStatePointer = cc_state.offset; 2837ec681f3Smrg } 2847ec681f3Smrg } 2857ec681f3Smrg 2867ec681f3Smrg if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE) { 2877ec681f3Smrg anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_LINE_STIPPLE), ls) { 2887ec681f3Smrg ls.LineStipplePattern = d->line_stipple.pattern; 2897ec681f3Smrg ls.LineStippleInverseRepeatCount = 2907ec681f3Smrg 1.0f / MAX2(1, d->line_stipple.factor); 2917ec681f3Smrg ls.LineStippleRepeatCount = d->line_stipple.factor; 2927ec681f3Smrg } 2937ec681f3Smrg } 2947ec681f3Smrg 2957ec681f3Smrg if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | 2967ec681f3Smrg ANV_CMD_DIRTY_RENDER_TARGETS | 2977ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK | 2987ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK | 2997ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE | 3007ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE | 3017ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP | 3027ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE | 3037ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP)) { 3047ec681f3Smrg uint32_t depth_stencil_dw[GENX(DEPTH_STENCIL_STATE_length)]; 3057ec681f3Smrg 3067ec681f3Smrg struct GENX(DEPTH_STENCIL_STATE) depth_stencil = { 3077ec681f3Smrg .StencilTestMask = d->stencil_compare_mask.front & 0xff, 3087ec681f3Smrg .StencilWriteMask = d->stencil_write_mask.front & 0xff, 3097ec681f3Smrg 3107ec681f3Smrg .BackfaceStencilTestMask = d->stencil_compare_mask.back & 0xff, 3117ec681f3Smrg .BackfaceStencilWriteMask = d->stencil_write_mask.back & 0xff, 3127ec681f3Smrg 3137ec681f3Smrg .StencilBufferWriteEnable = 3147ec681f3Smrg (d->stencil_write_mask.front || d->stencil_write_mask.back) && 3157ec681f3Smrg d->stencil_test_enable, 3167ec681f3Smrg 3177ec681f3Smrg .DepthTestEnable = d->depth_test_enable, 3187ec681f3Smrg .DepthBufferWriteEnable = d->depth_test_enable && d->depth_write_enable, 3197ec681f3Smrg .DepthTestFunction = genX(vk_to_intel_compare_op)[d->depth_compare_op], 3207ec681f3Smrg .StencilTestEnable = d->stencil_test_enable, 3217ec681f3Smrg .StencilFailOp = genX(vk_to_intel_stencil_op)[d->stencil_op.front.fail_op], 3227ec681f3Smrg .StencilPassDepthPassOp = genX(vk_to_intel_stencil_op)[d->stencil_op.front.pass_op], 3237ec681f3Smrg .StencilPassDepthFailOp = genX(vk_to_intel_stencil_op)[d->stencil_op.front.depth_fail_op], 3247ec681f3Smrg .StencilTestFunction = genX(vk_to_intel_compare_op)[d->stencil_op.front.compare_op], 3257ec681f3Smrg .BackfaceStencilFailOp = genX(vk_to_intel_stencil_op)[d->stencil_op.back.fail_op], 3267ec681f3Smrg .BackfaceStencilPassDepthPassOp = genX(vk_to_intel_stencil_op)[d->stencil_op.back.pass_op], 3277ec681f3Smrg .BackfaceStencilPassDepthFailOp = genX(vk_to_intel_stencil_op)[d->stencil_op.back.depth_fail_op], 3287ec681f3Smrg .BackfaceStencilTestFunction = genX(vk_to_intel_compare_op)[d->stencil_op.back.compare_op], 3297ec681f3Smrg }; 3307ec681f3Smrg GENX(DEPTH_STENCIL_STATE_pack)(NULL, depth_stencil_dw, &depth_stencil); 3317ec681f3Smrg 3327ec681f3Smrg struct anv_state ds_state = 3337ec681f3Smrg anv_cmd_buffer_merge_dynamic(cmd_buffer, depth_stencil_dw, 3347ec681f3Smrg pipeline->gfx7.depth_stencil_state, 3357ec681f3Smrg GENX(DEPTH_STENCIL_STATE_length), 64); 3367ec681f3Smrg 3377ec681f3Smrg anv_batch_emit(&cmd_buffer->batch, 3387ec681f3Smrg GENX(3DSTATE_DEPTH_STENCIL_STATE_POINTERS), dsp) { 3397ec681f3Smrg dsp.PointertoDEPTH_STENCIL_STATE = ds_state.offset; 3407ec681f3Smrg } 3417ec681f3Smrg } 3427ec681f3Smrg 3437ec681f3Smrg if (cmd_buffer->state.gfx.gfx7.index_buffer && 3447ec681f3Smrg cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | 3457ec681f3Smrg ANV_CMD_DIRTY_INDEX_BUFFER | 3467ec681f3Smrg ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE)) { 3477ec681f3Smrg struct anv_buffer *buffer = cmd_buffer->state.gfx.gfx7.index_buffer; 3487ec681f3Smrg uint32_t offset = cmd_buffer->state.gfx.gfx7.index_offset; 3497ec681f3Smrg 3507ec681f3Smrg#if GFX_VERx10 == 75 3517ec681f3Smrg anv_batch_emit(&cmd_buffer->batch, GFX75_3DSTATE_VF, vf) { 3527ec681f3Smrg vf.IndexedDrawCutIndexEnable = d->primitive_restart_enable; 3537ec681f3Smrg vf.CutIndex = cmd_buffer->state.restart_index; 3547ec681f3Smrg } 3557ec681f3Smrg#endif 3567ec681f3Smrg 3577ec681f3Smrg anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_INDEX_BUFFER), ib) { 3587ec681f3Smrg#if GFX_VERx10 != 75 3597ec681f3Smrg ib.CutIndexEnable = d->primitive_restart_enable; 3607ec681f3Smrg#endif 3617ec681f3Smrg ib.IndexFormat = cmd_buffer->state.gfx.gfx7.index_type; 3627ec681f3Smrg ib.MOCS = anv_mocs(cmd_buffer->device, 3637ec681f3Smrg buffer->address.bo, 3647ec681f3Smrg ISL_SURF_USAGE_INDEX_BUFFER_BIT); 3657ec681f3Smrg 3667ec681f3Smrg ib.BufferStartingAddress = anv_address_add(buffer->address, offset); 3677ec681f3Smrg ib.BufferEndingAddress = anv_address_add(buffer->address, 3687ec681f3Smrg buffer->size); 3697ec681f3Smrg } 3707ec681f3Smrg } 3717ec681f3Smrg 3727ec681f3Smrg /* 3DSTATE_WM in the hope we can avoid spawning fragment shaders 3737ec681f3Smrg * threads or if we have dirty dynamic primitive topology state and 3747ec681f3Smrg * need to toggle 3DSTATE_WM::MultisampleRasterizationMode dynamically. 3757ec681f3Smrg */ 3767ec681f3Smrg if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE || 3777ec681f3Smrg cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) { 3787ec681f3Smrg const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes; 3797ec681f3Smrg 3807ec681f3Smrg bool dirty_color_blend = 3817ec681f3Smrg cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE; 3827ec681f3Smrg 3837ec681f3Smrg bool dirty_primitive_topology = 3847ec681f3Smrg cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; 3857ec681f3Smrg 3867ec681f3Smrg VkPolygonMode dynamic_raster_mode; 3877ec681f3Smrg VkPrimitiveTopology primitive_topology = 3887ec681f3Smrg cmd_buffer->state.gfx.dynamic.primitive_topology; 3897ec681f3Smrg dynamic_raster_mode = 3907ec681f3Smrg genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline, 3917ec681f3Smrg primitive_topology); 3927ec681f3Smrg 3937ec681f3Smrg if (dirty_color_blend || dirty_primitive_topology) { 3947ec681f3Smrg uint32_t dwords[GENX(3DSTATE_WM_length)]; 3957ec681f3Smrg struct GENX(3DSTATE_WM) wm = { 3967ec681f3Smrg GENX(3DSTATE_WM_header), 3977ec681f3Smrg 3987ec681f3Smrg .ThreadDispatchEnable = pipeline->force_fragment_thread_dispatch || 3997ec681f3Smrg color_writes, 4007ec681f3Smrg .MultisampleRasterizationMode = 4017ec681f3Smrg genX(ms_rasterization_mode)(pipeline, dynamic_raster_mode), 4027ec681f3Smrg }; 4037ec681f3Smrg GENX(3DSTATE_WM_pack)(NULL, dwords, &wm); 4047ec681f3Smrg 4057ec681f3Smrg anv_batch_emit_merge(&cmd_buffer->batch, dwords, pipeline->gfx7.wm); 4067ec681f3Smrg } 4077ec681f3Smrg 4087ec681f3Smrg } 4097ec681f3Smrg 4107ec681f3Smrg if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) { 4117ec681f3Smrg genX(emit_multisample)(&cmd_buffer->batch, 4127ec681f3Smrg cmd_buffer->state.gfx.dynamic.sample_locations.samples, 4137ec681f3Smrg cmd_buffer->state.gfx.dynamic.sample_locations.locations); 4147ec681f3Smrg } 4157ec681f3Smrg 4167ec681f3Smrg if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE || 4177ec681f3Smrg cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP) { 4187ec681f3Smrg const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes; 4197ec681f3Smrg bool dirty_color_blend = 4207ec681f3Smrg cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE; 4217ec681f3Smrg 4227ec681f3Smrg /* Blend states of each RT */ 4237ec681f3Smrg uint32_t surface_count = 0; 4247ec681f3Smrg struct anv_pipeline_bind_map *map; 4257ec681f3Smrg if (anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT)) { 4267ec681f3Smrg map = &pipeline->shaders[MESA_SHADER_FRAGMENT]->bind_map; 4277ec681f3Smrg surface_count = map->surface_count; 4287ec681f3Smrg } 4297ec681f3Smrg 4307ec681f3Smrg uint32_t blend_dws[GENX(BLEND_STATE_length) + 4317ec681f3Smrg MAX_RTS * GENX(BLEND_STATE_ENTRY_length)]; 4327ec681f3Smrg uint32_t *dws = blend_dws; 4337ec681f3Smrg memset(blend_dws, 0, sizeof(blend_dws)); 4347ec681f3Smrg 4357ec681f3Smrg /* Skip this part */ 4367ec681f3Smrg dws += GENX(BLEND_STATE_length); 4377ec681f3Smrg 4387ec681f3Smrg bool dirty_logic_op = 4397ec681f3Smrg cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP; 4407ec681f3Smrg 4417ec681f3Smrg for (uint32_t i = 0; i < surface_count; i++) { 4427ec681f3Smrg struct anv_pipeline_binding *binding = &map->surface_to_descriptor[i]; 4437ec681f3Smrg bool write_disabled = 4447ec681f3Smrg dirty_color_blend && (color_writes & (1u << binding->index)) == 0; 4457ec681f3Smrg struct GENX(BLEND_STATE_ENTRY) entry = { 4467ec681f3Smrg .WriteDisableAlpha = write_disabled, 4477ec681f3Smrg .WriteDisableRed = write_disabled, 4487ec681f3Smrg .WriteDisableGreen = write_disabled, 4497ec681f3Smrg .WriteDisableBlue = write_disabled, 4507ec681f3Smrg .LogicOpFunction = 4517ec681f3Smrg dirty_logic_op ? genX(vk_to_intel_logic_op)[d->logic_op] : 0, 4527ec681f3Smrg }; 4537ec681f3Smrg GENX(BLEND_STATE_ENTRY_pack)(NULL, dws, &entry); 4547ec681f3Smrg dws += GENX(BLEND_STATE_ENTRY_length); 4557ec681f3Smrg } 4567ec681f3Smrg 4577ec681f3Smrg uint32_t num_dwords = GENX(BLEND_STATE_length) + 4587ec681f3Smrg GENX(BLEND_STATE_ENTRY_length) * surface_count; 4597ec681f3Smrg 4607ec681f3Smrg struct anv_state blend_states = 4617ec681f3Smrg anv_cmd_buffer_merge_dynamic(cmd_buffer, blend_dws, 4627ec681f3Smrg pipeline->gfx7.blend_state, num_dwords, 64); 4637ec681f3Smrg anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_BLEND_STATE_POINTERS), bsp) { 4647ec681f3Smrg bsp.BlendStatePointer = blend_states.offset; 4657ec681f3Smrg } 4667ec681f3Smrg } 4677ec681f3Smrg 4687ec681f3Smrg cmd_buffer->state.gfx.dirty = 0; 4697ec681f3Smrg} 4707ec681f3Smrg 4717ec681f3Smrgvoid 4727ec681f3SmrggenX(cmd_buffer_enable_pma_fix)(struct anv_cmd_buffer *cmd_buffer, 4737ec681f3Smrg bool enable) 4747ec681f3Smrg{ 4757ec681f3Smrg /* The NP PMA fix doesn't exist on gfx7 */ 4767ec681f3Smrg} 477