Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_state.c
4570 views
/*1* Copyright 2018 Collabora Ltd.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE.21*/2223#include "zink_state.h"2425#include "zink_context.h"26#include "zink_screen.h"2728#include "compiler/shader_enums.h"29#include "util/u_dual_blend.h"30#include "util/u_memory.h"3132#include <math.h>3334static void *35zink_create_vertex_elements_state(struct pipe_context *pctx,36unsigned num_elements,37const struct pipe_vertex_element *elements)38{39struct zink_screen *screen = zink_screen(pctx->screen);40unsigned int i;41struct zink_vertex_elements_state *ves = CALLOC_STRUCT(zink_vertex_elements_state);42if (!ves)43return NULL;4445int buffer_map[PIPE_MAX_ATTRIBS];46for (int i = 0; i < ARRAY_SIZE(buffer_map); ++i)47buffer_map[i] = -1;4849int num_bindings = 0;50for (i = 0; i < num_elements; ++i) {51const struct pipe_vertex_element *elem = elements + i;5253int binding = elem->vertex_buffer_index;54if (buffer_map[binding] < 0) {55ves->binding_map[num_bindings] = binding;56buffer_map[binding] = num_bindings++;57}58binding = buffer_map[binding];596061ves->bindings[binding].binding = binding;62ves->bindings[binding].inputRate = elem->instance_divisor ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;6364assert(!elem->instance_divisor || zink_screen(pctx->screen)->info.have_EXT_vertex_attribute_divisor);65ves->divisor[binding] = elem->instance_divisor;66assert(elem->instance_divisor <= screen->info.vdiv_props.maxVertexAttribDivisor);6768ves->hw_state.attribs[i].binding = binding;69ves->hw_state.attribs[i].location = i;70ves->hw_state.attribs[i].format = zink_get_format(screen,71elem->src_format);72assert(ves->hw_state.attribs[i].format != VK_FORMAT_UNDEFINED);73ves->hw_state.attribs[i].offset = elem->src_offset;74}7576ves->hw_state.num_bindings = num_bindings;77ves->hw_state.num_attribs = num_elements;78for (int i = 0; i < num_bindings; ++i) {79ves->hw_state.bindings[i].binding = ves->bindings[i].binding;80ves->hw_state.bindings[i].inputRate = ves->bindings[i].inputRate;81if (ves->divisor[i]) {82ves->hw_state.divisors[ves->hw_state.divisors_present].divisor = ves->divisor[i];83ves->hw_state.divisors[ves->hw_state.divisors_present].binding = ves->bindings[i].binding;84ves->hw_state.divisors_present++;85}86}87return ves;88}8990static void91zink_bind_vertex_elements_state(struct pipe_context *pctx,92void *cso)93{94struct zink_context *ctx = zink_context(pctx);95struct zink_gfx_pipeline_state *state = &ctx->gfx_pipeline_state;96ctx->element_state = cso;97if (cso) {98if (state->element_state != &ctx->element_state->hw_state) {99state->vertex_state_dirty = true;100ctx->vertex_buffers_dirty = ctx->element_state->hw_state.num_bindings > 0;101}102state->element_state = &ctx->element_state->hw_state;103} else {104state->element_state = NULL;105ctx->vertex_buffers_dirty = false;106}107}108109static void110zink_delete_vertex_elements_state(struct pipe_context *pctx,111void *ves)112{113FREE(ves);114}115116static VkBlendFactor117blend_factor(enum pipe_blendfactor factor)118{119switch (factor) {120case PIPE_BLENDFACTOR_ONE: return VK_BLEND_FACTOR_ONE;121case PIPE_BLENDFACTOR_SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR;122case PIPE_BLENDFACTOR_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA;123case PIPE_BLENDFACTOR_DST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA;124case PIPE_BLENDFACTOR_DST_COLOR: return VK_BLEND_FACTOR_DST_COLOR;125case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:126return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;127case PIPE_BLENDFACTOR_CONST_COLOR: return VK_BLEND_FACTOR_CONSTANT_COLOR;128case PIPE_BLENDFACTOR_CONST_ALPHA: return VK_BLEND_FACTOR_CONSTANT_ALPHA;129case PIPE_BLENDFACTOR_SRC1_COLOR: return VK_BLEND_FACTOR_SRC1_COLOR;130case PIPE_BLENDFACTOR_SRC1_ALPHA: return VK_BLEND_FACTOR_SRC1_ALPHA;131132case PIPE_BLENDFACTOR_ZERO: return VK_BLEND_FACTOR_ZERO;133134case PIPE_BLENDFACTOR_INV_SRC_COLOR:135return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;136case PIPE_BLENDFACTOR_INV_SRC_ALPHA:137return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;138case PIPE_BLENDFACTOR_INV_DST_ALPHA:139return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;140case PIPE_BLENDFACTOR_INV_DST_COLOR:141return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;142143case PIPE_BLENDFACTOR_INV_CONST_COLOR:144return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;145case PIPE_BLENDFACTOR_INV_CONST_ALPHA:146return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;147case PIPE_BLENDFACTOR_INV_SRC1_COLOR:148return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;149case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:150return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;151}152unreachable("unexpected blend factor");153}154155156static bool157need_blend_constants(enum pipe_blendfactor factor)158{159switch (factor) {160case PIPE_BLENDFACTOR_CONST_COLOR:161case PIPE_BLENDFACTOR_CONST_ALPHA:162case PIPE_BLENDFACTOR_INV_CONST_COLOR:163case PIPE_BLENDFACTOR_INV_CONST_ALPHA:164return true;165166default:167return false;168}169}170171static VkBlendOp172blend_op(enum pipe_blend_func func)173{174switch (func) {175case PIPE_BLEND_ADD: return VK_BLEND_OP_ADD;176case PIPE_BLEND_SUBTRACT: return VK_BLEND_OP_SUBTRACT;177case PIPE_BLEND_REVERSE_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT;178case PIPE_BLEND_MIN: return VK_BLEND_OP_MIN;179case PIPE_BLEND_MAX: return VK_BLEND_OP_MAX;180}181unreachable("unexpected blend function");182}183184static VkLogicOp185logic_op(enum pipe_logicop func)186{187switch (func) {188case PIPE_LOGICOP_CLEAR: return VK_LOGIC_OP_CLEAR;189case PIPE_LOGICOP_NOR: return VK_LOGIC_OP_NOR;190case PIPE_LOGICOP_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED;191case PIPE_LOGICOP_COPY_INVERTED: return VK_LOGIC_OP_COPY_INVERTED;192case PIPE_LOGICOP_AND_REVERSE: return VK_LOGIC_OP_AND_REVERSE;193case PIPE_LOGICOP_INVERT: return VK_LOGIC_OP_INVERT;194case PIPE_LOGICOP_XOR: return VK_LOGIC_OP_XOR;195case PIPE_LOGICOP_NAND: return VK_LOGIC_OP_NAND;196case PIPE_LOGICOP_AND: return VK_LOGIC_OP_AND;197case PIPE_LOGICOP_EQUIV: return VK_LOGIC_OP_EQUIVALENT;198case PIPE_LOGICOP_NOOP: return VK_LOGIC_OP_NO_OP;199case PIPE_LOGICOP_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED;200case PIPE_LOGICOP_COPY: return VK_LOGIC_OP_COPY;201case PIPE_LOGICOP_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE;202case PIPE_LOGICOP_OR: return VK_LOGIC_OP_OR;203case PIPE_LOGICOP_SET: return VK_LOGIC_OP_SET;204}205unreachable("unexpected logicop function");206}207208/* from iris */209static enum pipe_blendfactor210fix_blendfactor(enum pipe_blendfactor f, bool alpha_to_one)211{212if (alpha_to_one) {213if (f == PIPE_BLENDFACTOR_SRC1_ALPHA)214return PIPE_BLENDFACTOR_ONE;215216if (f == PIPE_BLENDFACTOR_INV_SRC1_ALPHA)217return PIPE_BLENDFACTOR_ZERO;218}219220return f;221}222223static void *224zink_create_blend_state(struct pipe_context *pctx,225const struct pipe_blend_state *blend_state)226{227struct zink_blend_state *cso = CALLOC_STRUCT(zink_blend_state);228if (!cso)229return NULL;230231if (blend_state->logicop_enable) {232cso->logicop_enable = VK_TRUE;233cso->logicop_func = logic_op(blend_state->logicop_func);234}235236/* TODO: figure out what to do with dither (nothing is probably "OK" for now,237* as dithering is undefined in GL238*/239240/* TODO: these are multisampling-state, and should be set there instead of241* here, as that's closer tied to the update-frequency242*/243cso->alpha_to_coverage = blend_state->alpha_to_coverage;244cso->alpha_to_one = blend_state->alpha_to_one;245246cso->need_blend_constants = false;247248for (int i = 0; i < blend_state->max_rt + 1; ++i) {249const struct pipe_rt_blend_state *rt = blend_state->rt;250if (blend_state->independent_blend_enable)251rt = blend_state->rt + i;252253VkPipelineColorBlendAttachmentState att = {0};254255if (rt->blend_enable) {256att.blendEnable = VK_TRUE;257att.srcColorBlendFactor = blend_factor(fix_blendfactor(rt->rgb_src_factor, cso->alpha_to_one));258att.dstColorBlendFactor = blend_factor(fix_blendfactor(rt->rgb_dst_factor, cso->alpha_to_one));259att.colorBlendOp = blend_op(rt->rgb_func);260att.srcAlphaBlendFactor = blend_factor(fix_blendfactor(rt->alpha_src_factor, cso->alpha_to_one));261att.dstAlphaBlendFactor = blend_factor(fix_blendfactor(rt->alpha_dst_factor, cso->alpha_to_one));262att.alphaBlendOp = blend_op(rt->alpha_func);263264if (need_blend_constants(rt->rgb_src_factor) ||265need_blend_constants(rt->rgb_dst_factor) ||266need_blend_constants(rt->alpha_src_factor) ||267need_blend_constants(rt->alpha_dst_factor))268cso->need_blend_constants = true;269}270271if (rt->colormask & PIPE_MASK_R)272att.colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;273if (rt->colormask & PIPE_MASK_G)274att.colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;275if (rt->colormask & PIPE_MASK_B)276att.colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;277if (rt->colormask & PIPE_MASK_A)278att.colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;279280cso->attachments[i] = att;281}282cso->dual_src_blend = util_blend_state_is_dual(blend_state, 0);283284return cso;285}286287static void288zink_bind_blend_state(struct pipe_context *pctx, void *cso)289{290struct zink_gfx_pipeline_state* state = &zink_context(pctx)->gfx_pipeline_state;291292if (state->blend_state != cso) {293state->blend_state = cso;294state->dirty = true;295}296}297298static void299zink_delete_blend_state(struct pipe_context *pctx, void *blend_state)300{301FREE(blend_state);302}303304static VkCompareOp305compare_op(enum pipe_compare_func func)306{307switch (func) {308case PIPE_FUNC_NEVER: return VK_COMPARE_OP_NEVER;309case PIPE_FUNC_LESS: return VK_COMPARE_OP_LESS;310case PIPE_FUNC_EQUAL: return VK_COMPARE_OP_EQUAL;311case PIPE_FUNC_LEQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL;312case PIPE_FUNC_GREATER: return VK_COMPARE_OP_GREATER;313case PIPE_FUNC_NOTEQUAL: return VK_COMPARE_OP_NOT_EQUAL;314case PIPE_FUNC_GEQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL;315case PIPE_FUNC_ALWAYS: return VK_COMPARE_OP_ALWAYS;316}317unreachable("unexpected func");318}319320static VkStencilOp321stencil_op(enum pipe_stencil_op op)322{323switch (op) {324case PIPE_STENCIL_OP_KEEP: return VK_STENCIL_OP_KEEP;325case PIPE_STENCIL_OP_ZERO: return VK_STENCIL_OP_ZERO;326case PIPE_STENCIL_OP_REPLACE: return VK_STENCIL_OP_REPLACE;327case PIPE_STENCIL_OP_INCR: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;328case PIPE_STENCIL_OP_DECR: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;329case PIPE_STENCIL_OP_INCR_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP;330case PIPE_STENCIL_OP_DECR_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP;331case PIPE_STENCIL_OP_INVERT: return VK_STENCIL_OP_INVERT;332}333unreachable("unexpected op");334}335336static VkStencilOpState337stencil_op_state(const struct pipe_stencil_state *src)338{339VkStencilOpState ret;340ret.failOp = stencil_op(src->fail_op);341ret.passOp = stencil_op(src->zpass_op);342ret.depthFailOp = stencil_op(src->zfail_op);343ret.compareOp = compare_op(src->func);344ret.compareMask = src->valuemask;345ret.writeMask = src->writemask;346ret.reference = 0; // not used: we'll use a dynamic state for this347return ret;348}349350static void *351zink_create_depth_stencil_alpha_state(struct pipe_context *pctx,352const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha)353{354struct zink_depth_stencil_alpha_state *cso = CALLOC_STRUCT(zink_depth_stencil_alpha_state);355if (!cso)356return NULL;357358cso->base = *depth_stencil_alpha;359360if (depth_stencil_alpha->depth_enabled) {361cso->hw_state.depth_test = VK_TRUE;362cso->hw_state.depth_compare_op = compare_op(depth_stencil_alpha->depth_func);363}364365if (depth_stencil_alpha->depth_bounds_test) {366cso->hw_state.depth_bounds_test = VK_TRUE;367cso->hw_state.min_depth_bounds = depth_stencil_alpha->depth_bounds_min;368cso->hw_state.max_depth_bounds = depth_stencil_alpha->depth_bounds_max;369}370371if (depth_stencil_alpha->stencil[0].enabled) {372cso->hw_state.stencil_test = VK_TRUE;373cso->hw_state.stencil_front = stencil_op_state(depth_stencil_alpha->stencil);374}375376if (depth_stencil_alpha->stencil[1].enabled)377cso->hw_state.stencil_back = stencil_op_state(depth_stencil_alpha->stencil + 1);378else379cso->hw_state.stencil_back = cso->hw_state.stencil_front;380381cso->hw_state.depth_write = depth_stencil_alpha->depth_writemask;382383return cso;384}385386static void387zink_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *cso)388{389struct zink_context *ctx = zink_context(pctx);390391bool prev_zwrite = ctx->dsa_state ? ctx->dsa_state->hw_state.depth_write : false;392ctx->dsa_state = cso;393394if (cso) {395struct zink_gfx_pipeline_state *state = &ctx->gfx_pipeline_state;396if (state->depth_stencil_alpha_state != &ctx->dsa_state->hw_state) {397state->depth_stencil_alpha_state = &ctx->dsa_state->hw_state;398state->dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state;399ctx->dsa_state_changed = true;400}401}402if (prev_zwrite != (ctx->dsa_state ? ctx->dsa_state->hw_state.depth_write : false)) {403ctx->rp_changed = true;404zink_batch_no_rp(ctx);405}406}407408static void409zink_delete_depth_stencil_alpha_state(struct pipe_context *pctx,410void *depth_stencil_alpha)411{412FREE(depth_stencil_alpha);413}414415static float416round_to_granularity(float value, float granularity)417{418return roundf(value / granularity) * granularity;419}420421static float422line_width(float width, float granularity, const float range[2])423{424assert(granularity >= 0);425assert(range[0] <= range[1]);426427if (granularity > 0)428width = round_to_granularity(width, granularity);429430return CLAMP(width, range[0], range[1]);431}432433static void *434zink_create_rasterizer_state(struct pipe_context *pctx,435const struct pipe_rasterizer_state *rs_state)436{437struct zink_screen *screen = zink_screen(pctx->screen);438439struct zink_rasterizer_state *state = CALLOC_STRUCT(zink_rasterizer_state);440if (!state)441return NULL;442443state->base = *rs_state;444445assert(rs_state->depth_clip_far == rs_state->depth_clip_near);446state->hw_state.depth_clamp = rs_state->depth_clip_near == 0;447state->hw_state.rasterizer_discard = rs_state->rasterizer_discard;448state->hw_state.force_persample_interp = rs_state->force_persample_interp;449state->hw_state.pv_mode = rs_state->flatshade_first ? VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT : VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT;450451assert(rs_state->fill_front <= PIPE_POLYGON_MODE_POINT);452if (rs_state->fill_back != rs_state->fill_front)453debug_printf("BUG: vulkan doesn't support different front and back fill modes\n");454state->hw_state.polygon_mode = (VkPolygonMode)rs_state->fill_front; // same values455state->hw_state.cull_mode = (VkCullModeFlags)rs_state->cull_face; // same bits456457state->front_face = rs_state->front_ccw ?458VK_FRONT_FACE_COUNTER_CLOCKWISE :459VK_FRONT_FACE_CLOCKWISE;460461VkPhysicalDeviceLineRasterizationFeaturesEXT *line_feats =462&screen->info.line_rast_feats;463state->hw_state.line_mode =464VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;465466if (rs_state->line_stipple_enable) {467state->hw_state.line_stipple_factor = rs_state->line_stipple_factor;468state->hw_state.line_stipple_pattern = rs_state->line_stipple_pattern;469470if (screen->info.have_EXT_line_rasterization) {471if (rs_state->line_rectangular) {472if (rs_state->line_smooth) {473if (line_feats->stippledSmoothLines)474state->hw_state.line_mode =475VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;476} else if (line_feats->stippledRectangularLines)477state->hw_state.line_mode =478VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;479} else if (line_feats->stippledBresenhamLines)480state->hw_state.line_mode =481VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;482else {483/* no suitable mode that supports line stippling */484state->hw_state.line_stipple_factor = 0;485state->hw_state.line_stipple_pattern = UINT16_MAX;486}487}488} else {489if (screen->info.have_EXT_line_rasterization) {490if (rs_state->line_rectangular) {491if (rs_state->line_smooth) {492if (line_feats->smoothLines)493state->hw_state.line_mode =494VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;495} else if (line_feats->rectangularLines)496state->hw_state.line_mode =497VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;498} else if (line_feats->bresenhamLines)499state->hw_state.line_mode =500VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;501}502state->hw_state.line_stipple_factor = 0;503state->hw_state.line_stipple_pattern = UINT16_MAX;504}505506state->offset_point = rs_state->offset_point;507state->offset_line = rs_state->offset_line;508state->offset_tri = rs_state->offset_tri;509state->offset_units = rs_state->offset_units;510state->offset_clamp = rs_state->offset_clamp;511state->offset_scale = rs_state->offset_scale;512513state->line_width = line_width(rs_state->line_width,514screen->info.props.limits.lineWidthGranularity,515screen->info.props.limits.lineWidthRange);516517return state;518}519520static void521zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)522{523struct zink_context *ctx = zink_context(pctx);524struct zink_screen *screen = zink_screen(pctx->screen);525bool clip_halfz = ctx->rast_state ? ctx->rast_state->base.clip_halfz : false;526bool point_quad_rasterization = ctx->rast_state ? ctx->rast_state->base.point_quad_rasterization : false;527bool scissor = ctx->rast_state ? ctx->rast_state->base.scissor : false;528ctx->rast_state = cso;529530if (ctx->rast_state) {531if (ctx->gfx_pipeline_state.rast_state != &ctx->rast_state->hw_state) {532if (screen->info.have_EXT_provoking_vertex &&533(!ctx->gfx_pipeline_state.rast_state ||534ctx->gfx_pipeline_state.rast_state->pv_mode != ctx->rast_state->hw_state.pv_mode) &&535/* without this prop, change in pv mode requires new rp */536!screen->info.pv_props.provokingVertexModePerPipeline)537zink_batch_no_rp(ctx);538ctx->gfx_pipeline_state.rast_state = &ctx->rast_state->hw_state;539ctx->gfx_pipeline_state.dirty = true;540ctx->rast_state_changed = true;541}542543if (clip_halfz != ctx->rast_state->base.clip_halfz) {544ctx->last_vertex_stage_dirty = true;545ctx->vp_state_changed = true;546}547548if (ctx->gfx_pipeline_state.front_face != ctx->rast_state->front_face) {549ctx->gfx_pipeline_state.front_face = ctx->rast_state->front_face;550ctx->gfx_pipeline_state.dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state;551}552if (ctx->line_width != ctx->rast_state->line_width) {553ctx->line_width = ctx->rast_state->line_width;554ctx->gfx_pipeline_state.dirty = true;555}556if (ctx->rast_state->base.point_quad_rasterization != point_quad_rasterization)557ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_FRAGMENT);558if (ctx->rast_state->base.scissor != scissor)559ctx->scissor_changed = true;560}561}562563static void564zink_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state)565{566FREE(rs_state);567}568569void570zink_context_state_init(struct pipe_context *pctx)571{572pctx->create_vertex_elements_state = zink_create_vertex_elements_state;573pctx->bind_vertex_elements_state = zink_bind_vertex_elements_state;574pctx->delete_vertex_elements_state = zink_delete_vertex_elements_state;575576pctx->create_blend_state = zink_create_blend_state;577pctx->bind_blend_state = zink_bind_blend_state;578pctx->delete_blend_state = zink_delete_blend_state;579580pctx->create_depth_stencil_alpha_state = zink_create_depth_stencil_alpha_state;581pctx->bind_depth_stencil_alpha_state = zink_bind_depth_stencil_alpha_state;582pctx->delete_depth_stencil_alpha_state = zink_delete_depth_stencil_alpha_state;583584pctx->create_rasterizer_state = zink_create_rasterizer_state;585pctx->bind_rasterizer_state = zink_bind_rasterizer_state;586pctx->delete_rasterizer_state = zink_delete_rasterizer_state;587}588589590