diff --git a/src/panfrost/vulkan/panvk_cmd_buffer.h b/src/panfrost/vulkan/panvk_cmd_buffer.h index d98eacb941b..77e8c452843 100644 --- a/src/panfrost/vulkan/panvk_cmd_buffer.h +++ b/src/panfrost/vulkan/panvk_cmd_buffer.h @@ -72,14 +72,6 @@ struct panvk_cmd_event_op { struct panvk_event *event; }; -enum panvk_dynamic_state_bits { - PANVK_DYNAMIC_DEPTH_BOUNDS = 1 << 5, - PANVK_DYNAMIC_STENCIL_COMPARE_MASK = 1 << 6, - PANVK_DYNAMIC_STENCIL_WRITE_MASK = 1 << 7, - PANVK_DYNAMIC_STENCIL_REFERENCE = 1 << 8, - PANVK_DYNAMIC_ALL = (1 << 9) - 1, -}; - struct panvk_descriptor_state { const struct panvk_descriptor_set *sets[MAX_SETS]; struct panvk_push_descriptor_set *push_sets[MAX_SETS]; @@ -133,14 +125,6 @@ struct panvk_cmd_graphics_state { uint32_t first_vertex, base_vertex, base_instance; } ib; - struct { - struct { - uint8_t compare_mask; - uint8_t write_mask; - uint8_t ref; - } s_front, s_back; - } zs; - struct { struct pan_fb_info info; bool crc_valid[MAX_RTS]; diff --git a/src/panfrost/vulkan/panvk_pipeline.h b/src/panfrost/vulkan/panvk_pipeline.h index e5f56b2ffb9..8741277a5f5 100644 --- a/src/panfrost/vulkan/panvk_pipeline.h +++ b/src/panfrost/vulkan/panvk_pipeline.h @@ -77,8 +77,6 @@ struct panvk_graphics_pipeline { struct panvk_varyings_info varyings; struct { - uint32_t dynamic_mask; - struct { struct panvk_attribs_info attribs; bool writes_point_size; @@ -93,22 +91,6 @@ struct panvk_graphics_pipeline { struct mali_renderer_state_packed rsd_template; } fs; - struct { - bool z_test; - bool z_write; - unsigned z_compare_func; - bool s_test; - struct { - unsigned fail_op; - unsigned pass_op; - unsigned z_fail_op; - unsigned compare_func; - uint8_t compare_mask; - uint8_t write_mask; - uint8_t ref; - } s_front, s_back; - } zs; - struct { uint8_t rast_samples; uint8_t min_samples; diff --git a/src/panfrost/vulkan/panvk_vX_cmd_buffer.c b/src/panfrost/vulkan/panvk_vX_cmd_buffer.c index 2111a6e3104..af3af45e65f 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_buffer.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_buffer.c @@ -541,14 +541,18 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf, bool dirty = is_dirty(cmdbuf, RS_DEPTH_BIAS_FACTORS) || is_dirty(cmdbuf, CB_BLEND_CONSTANTS) || + is_dirty(cmdbuf, DS_STENCIL_COMPARE_MASK) || + is_dirty(cmdbuf, DS_STENCIL_WRITE_MASK) || + is_dirty(cmdbuf, DS_STENCIL_REFERENCE) || !cmdbuf->state.gfx.fs_rsd; if (dirty) { - const struct panvk_cmd_graphics_state *state = &cmdbuf->state.gfx; const struct vk_rasterization_state *rs = &cmdbuf->vk.dynamic_graphics_state.rs; const struct vk_color_blend_state *cb = &cmdbuf->vk.dynamic_graphics_state.cb; + const struct vk_depth_stencil_state *ds = + &cmdbuf->vk.dynamic_graphics_state.ds; struct panfrost_ptr rsd = pan_pool_alloc_desc_aggregate( &cmdbuf->desc_pool.base, PAN_DESC(RENDERER_STATE), PAN_DESC_ARRAY(pipeline->state.blend.pstate.rt_count, BLEND)); @@ -562,25 +566,13 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf, cfg.depth_factor = rs->depth_bias.slope; cfg.depth_bias_clamp = rs->depth_bias.clamp; - if (pipeline->state.dynamic_mask & - (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK)) { - cfg.stencil_front.mask = state->zs.s_front.compare_mask; - cfg.stencil_back.mask = state->zs.s_back.compare_mask; - } - - if (pipeline->state.dynamic_mask & - (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK)) { - cfg.stencil_mask_misc.stencil_mask_front = - state->zs.s_front.write_mask; - cfg.stencil_mask_misc.stencil_mask_back = - state->zs.s_back.write_mask; - } - - if (pipeline->state.dynamic_mask & - (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE)) { - cfg.stencil_front.reference_value = state->zs.s_front.ref; - cfg.stencil_back.reference_value = state->zs.s_back.ref; - } + cfg.stencil_front.mask = ds->stencil.front.compare_mask; + cfg.stencil_back.mask = ds->stencil.back.compare_mask; + cfg.stencil_mask_misc.stencil_mask_front = + ds->stencil.front.write_mask; + cfg.stencil_mask_misc.stencil_mask_back = ds->stencil.back.write_mask; + cfg.stencil_front.reference_value = ds->stencil.front.reference; + cfg.stencil_back.reference_value = ds->stencil.back.reference; } pan_merge(rsd_dyn, (*rsd_templ), RENDERER_STATE); @@ -2199,64 +2191,6 @@ panvk_per_arch(CmdBindPipeline)(VkCommandBuffer commandBuffer, } } -VKAPI_ATTR void VKAPI_CALL -panvk_per_arch(CmdSetDepthBounds)(VkCommandBuffer commandBuffer, - float minDepthBounds, float maxDepthBounds) -{ - panvk_stub(); -} - -VKAPI_ATTR void VKAPI_CALL -panvk_per_arch(CmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, - VkStencilFaceFlags faceMask, - uint32_t compareMask) -{ - VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); - - if (faceMask & VK_STENCIL_FACE_FRONT_BIT) - cmdbuf->state.gfx.zs.s_front.compare_mask = compareMask; - - if (faceMask & VK_STENCIL_FACE_BACK_BIT) - cmdbuf->state.gfx.zs.s_back.compare_mask = compareMask; - - cmdbuf->state.gfx.dirty |= PANVK_DYNAMIC_STENCIL_COMPARE_MASK; - cmdbuf->state.gfx.fs_rsd = 0; -} - -VKAPI_ATTR void VKAPI_CALL -panvk_per_arch(CmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, - VkStencilFaceFlags faceMask, - uint32_t writeMask) -{ - VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); - - if (faceMask & VK_STENCIL_FACE_FRONT_BIT) - cmdbuf->state.gfx.zs.s_front.write_mask = writeMask; - - if (faceMask & VK_STENCIL_FACE_BACK_BIT) - cmdbuf->state.gfx.zs.s_back.write_mask = writeMask; - - cmdbuf->state.gfx.dirty |= PANVK_DYNAMIC_STENCIL_WRITE_MASK; - cmdbuf->state.gfx.fs_rsd = 0; -} - -VKAPI_ATTR void VKAPI_CALL -panvk_per_arch(CmdSetStencilReference)(VkCommandBuffer commandBuffer, - VkStencilFaceFlags faceMask, - uint32_t reference) -{ - VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); - - if (faceMask & VK_STENCIL_FACE_FRONT_BIT) - cmdbuf->state.gfx.zs.s_front.ref = reference; - - if (faceMask & VK_STENCIL_FACE_BACK_BIT) - cmdbuf->state.gfx.zs.s_back.ref = reference; - - cmdbuf->state.gfx.dirty |= PANVK_DYNAMIC_STENCIL_REFERENCE; - cmdbuf->state.gfx.fs_rsd = 0; -} - VKAPI_ATTR void VKAPI_CALL panvk_per_arch(CmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer _buffer, VkDeviceSize offset, uint32_t drawCount, diff --git a/src/panfrost/vulkan/panvk_vX_pipeline.c b/src/panfrost/vulkan/panvk_vX_pipeline.c index b759cb3776c..d68c9b589f1 100644 --- a/src/panfrost/vulkan/panvk_vX_pipeline.c +++ b/src/panfrost/vulkan/panvk_vX_pipeline.c @@ -141,12 +141,97 @@ emit_non_fs_rsd(const struct pan_shader_info *shader_info, mali_ptr shader_ptr, } } +static bool +writes_depth(const struct vk_depth_stencil_state *ds) +{ + + return ds && ds->depth.test_enable && ds->depth.write_enable && + ds->depth.compare_op != VK_COMPARE_OP_NEVER; +} + +static bool +writes_stencil(const struct vk_depth_stencil_state *ds) +{ + return ds && ds->stencil.test_enable && + ((ds->stencil.front.write_mask && + (ds->stencil.front.op.fail != VK_STENCIL_OP_KEEP || + ds->stencil.front.op.pass != VK_STENCIL_OP_KEEP || + ds->stencil.front.op.depth_fail != VK_STENCIL_OP_KEEP)) || + (ds->stencil.back.write_mask && + (ds->stencil.back.op.fail != VK_STENCIL_OP_KEEP || + ds->stencil.back.op.pass != VK_STENCIL_OP_KEEP || + ds->stencil.back.op.depth_fail != VK_STENCIL_OP_KEEP))); +} + +static bool +ds_test_always_passes(const struct vk_depth_stencil_state *ds) +{ + if (!ds) + return true; + + if (ds->depth.test_enable && ds->depth.compare_op != VK_COMPARE_OP_ALWAYS) + return false; + + if (ds->stencil.test_enable && + (ds->stencil.front.op.compare != VK_COMPARE_OP_ALWAYS || + ds->stencil.back.op.compare != VK_COMPARE_OP_ALWAYS)) + return false; + + return true; +} + +static inline enum mali_func +translate_compare_func(VkCompareOp comp) +{ + STATIC_ASSERT(VK_COMPARE_OP_NEVER == (VkCompareOp)MALI_FUNC_NEVER); + STATIC_ASSERT(VK_COMPARE_OP_LESS == (VkCompareOp)MALI_FUNC_LESS); + STATIC_ASSERT(VK_COMPARE_OP_EQUAL == (VkCompareOp)MALI_FUNC_EQUAL); + STATIC_ASSERT(VK_COMPARE_OP_LESS_OR_EQUAL == (VkCompareOp)MALI_FUNC_LEQUAL); + STATIC_ASSERT(VK_COMPARE_OP_GREATER == (VkCompareOp)MALI_FUNC_GREATER); + STATIC_ASSERT(VK_COMPARE_OP_NOT_EQUAL == (VkCompareOp)MALI_FUNC_NOT_EQUAL); + STATIC_ASSERT(VK_COMPARE_OP_GREATER_OR_EQUAL == + (VkCompareOp)MALI_FUNC_GEQUAL); + STATIC_ASSERT(VK_COMPARE_OP_ALWAYS == (VkCompareOp)MALI_FUNC_ALWAYS); + + return (enum mali_func)comp; +} + +static enum mali_stencil_op +translate_stencil_op(VkStencilOp in) +{ + switch (in) { + case VK_STENCIL_OP_KEEP: + return MALI_STENCIL_OP_KEEP; + case VK_STENCIL_OP_ZERO: + return MALI_STENCIL_OP_ZERO; + case VK_STENCIL_OP_REPLACE: + return MALI_STENCIL_OP_REPLACE; + case VK_STENCIL_OP_INCREMENT_AND_CLAMP: + return MALI_STENCIL_OP_INCR_SAT; + case VK_STENCIL_OP_DECREMENT_AND_CLAMP: + return MALI_STENCIL_OP_DECR_SAT; + case VK_STENCIL_OP_INCREMENT_AND_WRAP: + return MALI_STENCIL_OP_INCR_WRAP; + case VK_STENCIL_OP_DECREMENT_AND_WRAP: + return MALI_STENCIL_OP_DECR_WRAP; + case VK_STENCIL_OP_INVERT: + return MALI_STENCIL_OP_INVERT; + default: + unreachable("Invalid stencil op"); + } +} + static void emit_base_fs_rsd(const struct panvk_graphics_pipeline *pipeline, const struct vk_graphics_pipeline_state *state, void *rsd) { const struct pan_shader_info *info = &pipeline->state.fs.info; const struct vk_rasterization_state *rs = state->rs; + const struct vk_depth_stencil_state *ds = state->ds; + bool test_s = ds && ds->stencil.test_enable; + bool test_z = ds && ds->depth.test_enable; + bool writes_z = writes_depth(ds); + bool writes_s = writes_stencil(ds); pan_pack(rsd, RENDERER_STATE, cfg) { if (pipeline->state.fs.required) { @@ -160,10 +245,8 @@ emit_base_fs_rsd(const struct panvk_graphics_pipeline *pipeline, !pipeline->state.ms.alpha_to_coverage && !pipeline->state.blend.reads_dest; - bool writes_zs = - pipeline->state.zs.z_write || pipeline->state.zs.s_test; - bool zs_always_passes = - !pipeline->state.zs.z_test && !pipeline->state.zs.s_test; + bool writes_zs = writes_z || writes_s; + bool zs_always_passes = ds_test_always_passes(ds); bool oq = false; /* TODO: Occlusion queries */ struct pan_earlyzs_state earlyzs = pan_earlyzs_get( @@ -185,16 +268,16 @@ emit_base_fs_rsd(const struct panvk_graphics_pipeline *pipeline, msaa ? pipeline->state.ms.sample_mask : UINT16_MAX; cfg.multisample_misc.depth_function = - pipeline->state.zs.z_test ? pipeline->state.zs.z_compare_func - : MALI_FUNC_ALWAYS; + test_z ? translate_compare_func(ds->depth.compare_op) + : MALI_FUNC_ALWAYS; - cfg.multisample_misc.depth_write_mask = pipeline->state.zs.z_write; + cfg.multisample_misc.depth_write_mask = writes_z; cfg.multisample_misc.fixed_function_near_discard = !rs->depth_clamp_enable; cfg.multisample_misc.fixed_function_far_discard = !rs->depth_clamp_enable; cfg.multisample_misc.shader_depth_range_fixed = true; - cfg.stencil_mask_misc.stencil_enable = pipeline->state.zs.s_test; + cfg.stencil_mask_misc.stencil_enable = test_s; cfg.stencil_mask_misc.alpha_to_coverage = pipeline->state.ms.alpha_to_coverage; cfg.stencil_mask_misc.alpha_test_compare_function = MALI_FUNC_ALWAYS; @@ -210,32 +293,39 @@ emit_base_fs_rsd(const struct panvk_graphics_pipeline *pipeline, } if (dyn_state_is_set(pipeline, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK)) { - cfg.stencil_front.mask = pipeline->state.zs.s_front.compare_mask; - cfg.stencil_back.mask = pipeline->state.zs.s_back.compare_mask; + cfg.stencil_front.mask = ds->stencil.front.compare_mask; + cfg.stencil_back.mask = ds->stencil.back.compare_mask; } if (dyn_state_is_set(pipeline, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK)) { cfg.stencil_mask_misc.stencil_mask_front = - pipeline->state.zs.s_front.write_mask; - cfg.stencil_mask_misc.stencil_mask_back = - pipeline->state.zs.s_back.write_mask; + ds->stencil.front.write_mask; + cfg.stencil_mask_misc.stencil_mask_back = ds->stencil.back.write_mask; } if (dyn_state_is_set(pipeline, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE)) { - cfg.stencil_front.reference_value = pipeline->state.zs.s_front.ref; - cfg.stencil_back.reference_value = pipeline->state.zs.s_back.ref; + cfg.stencil_front.reference_value = ds->stencil.front.reference; + cfg.stencil_back.reference_value = ds->stencil.back.reference; } - cfg.stencil_front.compare_function = - pipeline->state.zs.s_front.compare_func; - cfg.stencil_front.stencil_fail = pipeline->state.zs.s_front.fail_op; - cfg.stencil_front.depth_fail = pipeline->state.zs.s_front.z_fail_op; - cfg.stencil_front.depth_pass = pipeline->state.zs.s_front.pass_op; - cfg.stencil_back.compare_function = - pipeline->state.zs.s_back.compare_func; - cfg.stencil_back.stencil_fail = pipeline->state.zs.s_back.fail_op; - cfg.stencil_back.depth_fail = pipeline->state.zs.s_back.z_fail_op; - cfg.stencil_back.depth_pass = pipeline->state.zs.s_back.pass_op; + if (test_s) { + cfg.stencil_front.compare_function = + translate_compare_func(ds->stencil.front.op.compare); + cfg.stencil_front.stencil_fail = + translate_stencil_op(ds->stencil.front.op.fail); + cfg.stencil_front.depth_fail = + translate_stencil_op(ds->stencil.front.op.depth_fail); + cfg.stencil_front.depth_pass = + translate_stencil_op(ds->stencil.front.op.pass); + cfg.stencil_back.compare_function = + translate_compare_func(ds->stencil.back.op.compare); + cfg.stencil_back.stencil_fail = + translate_stencil_op(ds->stencil.back.op.fail); + cfg.stencil_back.depth_fail = + translate_stencil_op(ds->stencil.back.op.depth_fail); + cfg.stencil_back.depth_pass = + translate_stencil_op(ds->stencil.back.op.pass); + } } } @@ -392,20 +482,6 @@ init_shaders(struct panvk_pipeline *pipeline, #define is_dyn(__state, __name) \ BITSET_TEST((__state)->dynamic, MESA_VK_DYNAMIC_##__name) -static void -parse_dynamic_state(struct panvk_graphics_pipeline *pipeline, - const struct vk_graphics_pipeline_state *state) -{ - if (is_dyn(state, DS_DEPTH_BOUNDS_TEST_BOUNDS)) - pipeline->state.dynamic_mask |= PANVK_DYNAMIC_DEPTH_BOUNDS; - if (is_dyn(state, DS_STENCIL_COMPARE_MASK)) - pipeline->state.dynamic_mask |= PANVK_DYNAMIC_STENCIL_COMPARE_MASK; - if (is_dyn(state, DS_STENCIL_WRITE_MASK)) - pipeline->state.dynamic_mask |= PANVK_DYNAMIC_STENCIL_WRITE_MASK; - if (is_dyn(state, DS_STENCIL_REFERENCE)) - pipeline->state.dynamic_mask |= PANVK_DYNAMIC_STENCIL_REFERENCE; -} - static uint32_t get_active_color_attachments(const struct vk_graphics_pipeline_state *state) { @@ -516,97 +592,6 @@ parse_multisample(struct panvk_graphics_pipeline *pipeline, MAX2(ms->min_sample_shading * nr_samples, 1); } -static enum mali_stencil_op -translate_stencil_op(VkStencilOp in) -{ - switch (in) { - case VK_STENCIL_OP_KEEP: - return MALI_STENCIL_OP_KEEP; - case VK_STENCIL_OP_ZERO: - return MALI_STENCIL_OP_ZERO; - case VK_STENCIL_OP_REPLACE: - return MALI_STENCIL_OP_REPLACE; - case VK_STENCIL_OP_INCREMENT_AND_CLAMP: - return MALI_STENCIL_OP_INCR_SAT; - case VK_STENCIL_OP_DECREMENT_AND_CLAMP: - return MALI_STENCIL_OP_DECR_SAT; - case VK_STENCIL_OP_INCREMENT_AND_WRAP: - return MALI_STENCIL_OP_INCR_WRAP; - case VK_STENCIL_OP_DECREMENT_AND_WRAP: - return MALI_STENCIL_OP_DECR_WRAP; - case VK_STENCIL_OP_INVERT: - return MALI_STENCIL_OP_INVERT; - default: - unreachable("Invalid stencil op"); - } -} - -static inline enum mali_func -translate_compare_func(VkCompareOp comp) -{ - STATIC_ASSERT(VK_COMPARE_OP_NEVER == (VkCompareOp)MALI_FUNC_NEVER); - STATIC_ASSERT(VK_COMPARE_OP_LESS == (VkCompareOp)MALI_FUNC_LESS); - STATIC_ASSERT(VK_COMPARE_OP_EQUAL == (VkCompareOp)MALI_FUNC_EQUAL); - STATIC_ASSERT(VK_COMPARE_OP_LESS_OR_EQUAL == (VkCompareOp)MALI_FUNC_LEQUAL); - STATIC_ASSERT(VK_COMPARE_OP_GREATER == (VkCompareOp)MALI_FUNC_GREATER); - STATIC_ASSERT(VK_COMPARE_OP_NOT_EQUAL == (VkCompareOp)MALI_FUNC_NOT_EQUAL); - STATIC_ASSERT(VK_COMPARE_OP_GREATER_OR_EQUAL == - (VkCompareOp)MALI_FUNC_GEQUAL); - STATIC_ASSERT(VK_COMPARE_OP_ALWAYS == (VkCompareOp)MALI_FUNC_ALWAYS); - - return (enum mali_func)comp; -} - -static void -parse_zs(struct panvk_graphics_pipeline *pipeline, - const struct vk_graphics_pipeline_state *state) -{ - const struct vk_depth_stencil_state *ds = state->ds; - - if (!ds) - return; - - pipeline->state.zs.z_test = ds->depth.test_enable; - - /* The Vulkan spec says: - * - * depthWriteEnable controls whether depth writes are enabled when - * depthTestEnable is VK_TRUE. Depth writes are always disabled when - * depthTestEnable is VK_FALSE. - * - * The hardware does not make this distinction, though, so we AND in the - * condition ourselves. - */ - pipeline->state.zs.z_write = - pipeline->state.zs.z_test && ds->depth.write_enable; - - pipeline->state.zs.z_compare_func = - translate_compare_func(ds->depth.compare_op); - pipeline->state.zs.s_test = ds->stencil.test_enable; - pipeline->state.zs.s_front.fail_op = - translate_stencil_op(ds->stencil.front.op.fail); - pipeline->state.zs.s_front.pass_op = - translate_stencil_op(ds->stencil.front.op.pass); - pipeline->state.zs.s_front.z_fail_op = - translate_stencil_op(ds->stencil.front.op.depth_fail); - pipeline->state.zs.s_front.compare_func = - translate_compare_func(ds->stencil.front.op.compare); - pipeline->state.zs.s_front.compare_mask = ds->stencil.front.compare_mask; - pipeline->state.zs.s_front.write_mask = ds->stencil.front.write_mask; - pipeline->state.zs.s_front.ref = ds->stencil.front.reference; - pipeline->state.zs.s_back.fail_op = - translate_stencil_op(ds->stencil.back.op.fail); - pipeline->state.zs.s_back.pass_op = - translate_stencil_op(ds->stencil.back.op.pass); - pipeline->state.zs.s_back.z_fail_op = - translate_stencil_op(ds->stencil.back.op.depth_fail); - pipeline->state.zs.s_back.compare_func = - translate_compare_func(ds->stencil.back.op.compare); - pipeline->state.zs.s_back.compare_mask = ds->stencil.back.compare_mask; - pipeline->state.zs.s_back.write_mask = ds->stencil.back.write_mask; - pipeline->state.zs.s_back.ref = ds->stencil.back.reference; -} - static bool fs_required(struct panvk_graphics_pipeline *pipeline) { @@ -802,13 +787,11 @@ panvk_graphics_pipeline_create(struct panvk_device *dev, struct panvk_shader *shaders[MESA_SHADER_STAGES] = {NULL}; - parse_dynamic_state(gfx_pipeline, &state); parse_color_blend(gfx_pipeline, &state); compile_shaders(&gfx_pipeline->base, create_info->pStages, create_info->stageCount, alloc, shaders); collect_varyings(gfx_pipeline, shaders); parse_multisample(gfx_pipeline, &state); - parse_zs(gfx_pipeline, &state); parse_vertex_input(gfx_pipeline, &state, shaders); init_fs_state(gfx_pipeline, &state, shaders[MESA_SHADER_FRAGMENT]); init_shaders(&gfx_pipeline->base, create_info, &state, shaders);