/* * Copyright © 2016 Red Hat. * Copyright © 2016 Bas Nieuwenhuizen * * based in part on anv driver which is: * Copyright © 2015 Intel Corporation * * SPDX-License-Identifier: MIT */ #ifndef RADV_PIPELINE_GRAPHICS_H #define RADV_PIPELINE_GRAPHICS_H #include "sid.h" #include "radv_descriptor_set.h" #include "radv_pipeline.h" #include "radv_shader.h" #include "vk_graphics_state.h" struct radv_sample_locations_state { VkSampleCountFlagBits per_pixel; VkExtent2D grid_size; uint32_t count; VkSampleLocationEXT locations[MAX_SAMPLE_LOCATIONS]; }; struct radv_dynamic_state { struct vk_dynamic_graphics_state vk; /** * Bitmask of (1ull << VK_DYNAMIC_STATE_*). * Defines the set of saved dynamic state. */ uint64_t mask; struct { struct { float scale[3]; float translate[3]; } xform[MAX_VIEWPORTS]; } hw_vp; struct radv_sample_locations_state sample_location; VkImageAspectFlags feedback_loop_aspects; }; struct radv_multisample_state { bool sample_shading_enable; float min_sample_shading; }; struct radv_ia_multi_vgt_param_helpers { uint32_t base; bool partial_es_wave; bool ia_switch_on_eoi; bool partial_vs_wave; }; struct radv_sqtt_shaders_reloc { struct radeon_winsys_bo *bo; union radv_shader_arena_block *alloc; uint64_t va[MESA_VULKAN_SHADER_STAGES]; }; struct radv_graphics_pipeline { struct radv_pipeline base; bool uses_drawid; bool uses_baseinstance; /* Whether the pipeline forces per-vertex VRS (GFX10.3+). */ bool force_vrs_per_vertex; /* Whether the pipeline uses NGG (GFX10+). */ bool is_ngg; bool has_ngg_culling; uint8_t vtx_emit_num; uint32_t vtx_base_sgpr; uint64_t dynamic_states; uint64_t needed_dynamic_state; VkShaderStageFlags active_stages; uint32_t spi_shader_col_format; uint32_t cb_shader_mask; struct radv_dynamic_state dynamic_state; struct radv_vertex_input_state vertex_input; struct radv_multisample_state ms; struct radv_ia_multi_vgt_param_helpers ia_multi_vgt_param; uint32_t binding_stride[MAX_VBS]; uint32_t db_render_control; /* Last pre-PS API stage */ gl_shader_stage last_vgt_api_stage; unsigned rast_prim; /* Custom blend mode for internal operations. */ unsigned custom_blend_mode; /* Whether the pipeline uses out-of-order rasterization. */ bool uses_out_of_order_rast; /* Whether the pipeline uses VRS. */ bool uses_vrs; /* Whether the pipeline uses a VRS attachment. */ bool uses_vrs_attachment; /* Whether the pipeline uses VRS coarse shading internally. */ bool uses_vrs_coarse_shading; /* For relocation of shaders with RGP. */ struct radv_sqtt_shaders_reloc *sqtt_shaders_reloc; /* Whether the pipeline imported binaries. */ bool has_pipeline_binaries; }; RADV_DECL_PIPELINE_DOWNCAST(graphics, RADV_PIPELINE_GRAPHICS) struct radv_retained_shaders { struct { void *serialized_nir; size_t serialized_nir_size; unsigned char shader_sha1[SHA1_DIGEST_LENGTH]; struct radv_shader_stage_key key; } stages[MESA_VULKAN_SHADER_STAGES]; }; struct radv_graphics_lib_pipeline { struct radv_graphics_pipeline base; struct vk_graphics_pipeline_state graphics_state; /* For vk_graphics_pipeline_state */ void *state_data; struct radv_pipeline_layout layout; VkGraphicsPipelineLibraryFlagsEXT lib_flags; struct radv_retained_shaders retained_shaders; void *mem_ctx; unsigned stage_count; VkPipelineShaderStageCreateInfo *stages; struct radv_shader_stage_key stage_keys[MESA_VULKAN_SHADER_STAGES]; }; RADV_DECL_PIPELINE_DOWNCAST(graphics_lib, RADV_PIPELINE_GRAPHICS_LIB) static inline bool radv_pipeline_has_stage(const struct radv_graphics_pipeline *pipeline, gl_shader_stage stage) { return pipeline->base.shaders[stage]; } static inline uint32_t radv_conv_prim_to_gs_out(uint32_t topology, bool is_ngg) { switch (topology) { case V_008958_DI_PT_POINTLIST: case V_008958_DI_PT_PATCH: return V_028A6C_POINTLIST; case V_008958_DI_PT_LINELIST: case V_008958_DI_PT_LINESTRIP: case V_008958_DI_PT_LINELIST_ADJ: case V_008958_DI_PT_LINESTRIP_ADJ: return V_028A6C_LINESTRIP; case V_008958_DI_PT_TRILIST: case V_008958_DI_PT_TRISTRIP: case V_008958_DI_PT_TRIFAN: case V_008958_DI_PT_TRILIST_ADJ: case V_008958_DI_PT_TRISTRIP_ADJ: return V_028A6C_TRISTRIP; case V_008958_DI_PT_RECTLIST: return is_ngg ? V_028A6C_RECTLIST : V_028A6C_TRISTRIP; default: assert(0); return 0; } } static inline uint32_t radv_conv_gl_prim_to_gs_out(unsigned gl_prim) { switch (gl_prim) { case MESA_PRIM_POINTS: return V_028A6C_POINTLIST; case MESA_PRIM_LINES: case MESA_PRIM_LINE_STRIP: case MESA_PRIM_LINES_ADJACENCY: return V_028A6C_LINESTRIP; case MESA_PRIM_TRIANGLES: case MESA_PRIM_TRIANGLE_STRIP_ADJACENCY: case MESA_PRIM_TRIANGLE_STRIP: case MESA_PRIM_QUADS: return V_028A6C_TRISTRIP; default: assert(0); return 0; } } static inline uint32_t radv_translate_prim(unsigned topology) { switch (topology) { case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return V_008958_DI_PT_POINTLIST; case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return V_008958_DI_PT_LINELIST; case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return V_008958_DI_PT_LINESTRIP; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return V_008958_DI_PT_TRILIST; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return V_008958_DI_PT_TRISTRIP; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return V_008958_DI_PT_TRIFAN; case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return V_008958_DI_PT_LINELIST_ADJ; case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return V_008958_DI_PT_LINESTRIP_ADJ; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return V_008958_DI_PT_TRILIST_ADJ; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return V_008958_DI_PT_TRISTRIP_ADJ; case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: return V_008958_DI_PT_PATCH; default: unreachable("unhandled primitive type"); } } static inline bool radv_prim_is_points_or_lines(unsigned topology) { switch (topology) { case V_008958_DI_PT_POINTLIST: case V_008958_DI_PT_LINELIST: case V_008958_DI_PT_LINESTRIP: case V_008958_DI_PT_LINELIST_ADJ: case V_008958_DI_PT_LINESTRIP_ADJ: return true; default: return false; } } static inline bool radv_rast_prim_is_point(unsigned rast_prim) { return rast_prim == V_028A6C_POINTLIST; } static inline bool radv_rast_prim_is_line(unsigned rast_prim) { return rast_prim == V_028A6C_LINESTRIP; } static inline bool radv_rast_prim_is_points_or_lines(unsigned rast_prim) { return radv_rast_prim_is_point(rast_prim) || radv_rast_prim_is_line(rast_prim); } static inline bool radv_polygon_mode_is_point(unsigned polygon_mode) { return polygon_mode == V_028814_X_DRAW_POINTS; } static inline bool radv_polygon_mode_is_line(unsigned polygon_mode) { return polygon_mode == V_028814_X_DRAW_LINES; } static inline bool radv_polygon_mode_is_points_or_lines(unsigned polygon_mode) { return radv_polygon_mode_is_point(polygon_mode) || radv_polygon_mode_is_line(polygon_mode); } static inline bool radv_primitive_topology_is_line_list(unsigned primitive_topology) { return primitive_topology == V_008958_DI_PT_LINELIST || primitive_topology == V_008958_DI_PT_LINELIST_ADJ; } static inline unsigned radv_get_num_vertices_per_prim(const struct radv_graphics_state_key *gfx_state) { if (gfx_state->ia.topology == V_008958_DI_PT_NONE) { /* When the topology is unknown (with graphics pipeline library), return the maximum number of * vertices per primitives for VS. This is used to lower NGG (the HW will ignore the extra * bits for points/lines) and also to enable NGG culling unconditionally (it will be disabled * dynamically for points/lines). */ return 3; } else { /* Need to add 1, because: V_028A6C_POINTLIST=0, V_028A6C_LINESTRIP=1, V_028A6C_TRISTRIP=2, etc. */ return radv_conv_prim_to_gs_out(gfx_state->ia.topology, false) + 1; } } static inline uint32_t radv_translate_fill(VkPolygonMode func) { switch (func) { case VK_POLYGON_MODE_FILL: return V_028814_X_DRAW_TRIANGLES; case VK_POLYGON_MODE_LINE: return V_028814_X_DRAW_LINES; case VK_POLYGON_MODE_POINT: return V_028814_X_DRAW_POINTS; default: assert(0); return V_028814_X_DRAW_POINTS; } } static inline uint32_t radv_translate_stencil_op(enum VkStencilOp op) { switch (op) { case VK_STENCIL_OP_KEEP: return V_02842C_STENCIL_KEEP; case VK_STENCIL_OP_ZERO: return V_02842C_STENCIL_ZERO; case VK_STENCIL_OP_REPLACE: return V_02842C_STENCIL_REPLACE_TEST; case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return V_02842C_STENCIL_ADD_CLAMP; case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return V_02842C_STENCIL_SUB_CLAMP; case VK_STENCIL_OP_INVERT: return V_02842C_STENCIL_INVERT; case VK_STENCIL_OP_INCREMENT_AND_WRAP: return V_02842C_STENCIL_ADD_WRAP; case VK_STENCIL_OP_DECREMENT_AND_WRAP: return V_02842C_STENCIL_SUB_WRAP; default: return 0; } } static inline uint32_t radv_translate_blend_logic_op(VkLogicOp op) { switch (op) { case VK_LOGIC_OP_CLEAR: return V_028808_ROP3_CLEAR; case VK_LOGIC_OP_AND: return V_028808_ROP3_AND; case VK_LOGIC_OP_AND_REVERSE: return V_028808_ROP3_AND_REVERSE; case VK_LOGIC_OP_COPY: return V_028808_ROP3_COPY; case VK_LOGIC_OP_AND_INVERTED: return V_028808_ROP3_AND_INVERTED; case VK_LOGIC_OP_NO_OP: return V_028808_ROP3_NO_OP; case VK_LOGIC_OP_XOR: return V_028808_ROP3_XOR; case VK_LOGIC_OP_OR: return V_028808_ROP3_OR; case VK_LOGIC_OP_NOR: return V_028808_ROP3_NOR; case VK_LOGIC_OP_EQUIVALENT: return V_028808_ROP3_EQUIVALENT; case VK_LOGIC_OP_INVERT: return V_028808_ROP3_INVERT; case VK_LOGIC_OP_OR_REVERSE: return V_028808_ROP3_OR_REVERSE; case VK_LOGIC_OP_COPY_INVERTED: return V_028808_ROP3_COPY_INVERTED; case VK_LOGIC_OP_OR_INVERTED: return V_028808_ROP3_OR_INVERTED; case VK_LOGIC_OP_NAND: return V_028808_ROP3_NAND; case VK_LOGIC_OP_SET: return V_028808_ROP3_SET; default: unreachable("Unhandled logic op"); } } static inline uint32_t radv_translate_blend_function(VkBlendOp op) { switch (op) { case VK_BLEND_OP_ADD: return V_028780_COMB_DST_PLUS_SRC; case VK_BLEND_OP_SUBTRACT: return V_028780_COMB_SRC_MINUS_DST; case VK_BLEND_OP_REVERSE_SUBTRACT: return V_028780_COMB_DST_MINUS_SRC; case VK_BLEND_OP_MIN: return V_028780_COMB_MIN_DST_SRC; case VK_BLEND_OP_MAX: return V_028780_COMB_MAX_DST_SRC; default: return 0; } } static inline uint32_t radv_translate_blend_factor(enum amd_gfx_level gfx_level, VkBlendFactor factor) { switch (factor) { case VK_BLEND_FACTOR_ZERO: return V_028780_BLEND_ZERO; case VK_BLEND_FACTOR_ONE: return V_028780_BLEND_ONE; case VK_BLEND_FACTOR_SRC_COLOR: return V_028780_BLEND_SRC_COLOR; case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: return V_028780_BLEND_ONE_MINUS_SRC_COLOR; case VK_BLEND_FACTOR_DST_COLOR: return V_028780_BLEND_DST_COLOR; case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: return V_028780_BLEND_ONE_MINUS_DST_COLOR; case VK_BLEND_FACTOR_SRC_ALPHA: return V_028780_BLEND_SRC_ALPHA; case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return V_028780_BLEND_ONE_MINUS_SRC_ALPHA; case VK_BLEND_FACTOR_DST_ALPHA: return V_028780_BLEND_DST_ALPHA; case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: return V_028780_BLEND_ONE_MINUS_DST_ALPHA; case VK_BLEND_FACTOR_CONSTANT_COLOR: return gfx_level >= GFX11 ? V_028780_BLEND_CONSTANT_COLOR_GFX11 : V_028780_BLEND_CONSTANT_COLOR_GFX6; case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: return gfx_level >= GFX11 ? V_028780_BLEND_ONE_MINUS_CONSTANT_COLOR_GFX11 : V_028780_BLEND_ONE_MINUS_CONSTANT_COLOR_GFX6; case VK_BLEND_FACTOR_CONSTANT_ALPHA: return gfx_level >= GFX11 ? V_028780_BLEND_CONSTANT_ALPHA_GFX11 : V_028780_BLEND_CONSTANT_ALPHA_GFX6; case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: return gfx_level >= GFX11 ? V_028780_BLEND_ONE_MINUS_CONSTANT_ALPHA_GFX11 : V_028780_BLEND_ONE_MINUS_CONSTANT_ALPHA_GFX6; case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: return V_028780_BLEND_SRC_ALPHA_SATURATE; case VK_BLEND_FACTOR_SRC1_COLOR: return gfx_level >= GFX11 ? V_028780_BLEND_SRC1_COLOR_GFX11 : V_028780_BLEND_SRC1_COLOR_GFX6; case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: return gfx_level >= GFX11 ? V_028780_BLEND_INV_SRC1_COLOR_GFX11 : V_028780_BLEND_INV_SRC1_COLOR_GFX6; case VK_BLEND_FACTOR_SRC1_ALPHA: return gfx_level >= GFX11 ? V_028780_BLEND_SRC1_ALPHA_GFX11 : V_028780_BLEND_SRC1_ALPHA_GFX6; case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: return gfx_level >= GFX11 ? V_028780_BLEND_INV_SRC1_ALPHA_GFX11 : V_028780_BLEND_INV_SRC1_ALPHA_GFX6; default: return 0; } } static inline uint32_t radv_translate_blend_opt_factor(VkBlendFactor factor, bool is_alpha) { switch (factor) { case VK_BLEND_FACTOR_ZERO: return V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_ALL; case VK_BLEND_FACTOR_ONE: return V_028760_BLEND_OPT_PRESERVE_ALL_IGNORE_NONE; case VK_BLEND_FACTOR_SRC_COLOR: return is_alpha ? V_028760_BLEND_OPT_PRESERVE_A1_IGNORE_A0 : V_028760_BLEND_OPT_PRESERVE_C1_IGNORE_C0; case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: return is_alpha ? V_028760_BLEND_OPT_PRESERVE_A0_IGNORE_A1 : V_028760_BLEND_OPT_PRESERVE_C0_IGNORE_C1; case VK_BLEND_FACTOR_SRC_ALPHA: return V_028760_BLEND_OPT_PRESERVE_A1_IGNORE_A0; case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return V_028760_BLEND_OPT_PRESERVE_A0_IGNORE_A1; case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: return is_alpha ? V_028760_BLEND_OPT_PRESERVE_ALL_IGNORE_NONE : V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_A0; default: return V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_NONE; } } static inline uint32_t radv_translate_blend_opt_function(VkBlendOp op) { switch (op) { case VK_BLEND_OP_ADD: return V_028760_OPT_COMB_ADD; case VK_BLEND_OP_SUBTRACT: return V_028760_OPT_COMB_SUBTRACT; case VK_BLEND_OP_REVERSE_SUBTRACT: return V_028760_OPT_COMB_REVSUBTRACT; case VK_BLEND_OP_MIN: return V_028760_OPT_COMB_MIN; case VK_BLEND_OP_MAX: return V_028760_OPT_COMB_MAX; default: return V_028760_OPT_COMB_BLEND_DISABLED; } } static inline bool radv_blend_factor_uses_dst(VkBlendFactor factor) { return factor == VK_BLEND_FACTOR_DST_COLOR || factor == VK_BLEND_FACTOR_DST_ALPHA || factor == VK_BLEND_FACTOR_SRC_ALPHA_SATURATE || factor == VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA || factor == VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; } static inline bool radv_is_dual_src(VkBlendFactor factor) { switch (factor) { case VK_BLEND_FACTOR_SRC1_COLOR: case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: case VK_BLEND_FACTOR_SRC1_ALPHA: case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: return true; default: return false; } } static ALWAYS_INLINE bool radv_can_enable_dual_src(const struct vk_color_blend_attachment_state *att) { VkBlendOp eqRGB = att->color_blend_op; VkBlendFactor srcRGB = att->src_color_blend_factor; VkBlendFactor dstRGB = att->dst_color_blend_factor; VkBlendOp eqA = att->alpha_blend_op; VkBlendFactor srcA = att->src_alpha_blend_factor; VkBlendFactor dstA = att->dst_alpha_blend_factor; bool eqRGB_minmax = eqRGB == VK_BLEND_OP_MIN || eqRGB == VK_BLEND_OP_MAX; bool eqA_minmax = eqA == VK_BLEND_OP_MIN || eqA == VK_BLEND_OP_MAX; if (!eqRGB_minmax && (radv_is_dual_src(srcRGB) || radv_is_dual_src(dstRGB))) return true; if (!eqA_minmax && (radv_is_dual_src(srcA) || radv_is_dual_src(dstA))) return true; return false; } static inline void radv_normalize_blend_factor(VkBlendOp op, VkBlendFactor *src_factor, VkBlendFactor *dst_factor) { if (op == VK_BLEND_OP_MIN || op == VK_BLEND_OP_MAX) { *src_factor = VK_BLEND_FACTOR_ONE; *dst_factor = VK_BLEND_FACTOR_ONE; } } void radv_blend_remove_dst(VkBlendOp *func, VkBlendFactor *src_factor, VkBlendFactor *dst_factor, VkBlendFactor expected_dst, VkBlendFactor replacement_src); unsigned radv_compact_spi_shader_col_format(uint32_t spi_shader_col_format); unsigned radv_format_meta_fs_key(struct radv_device *device, VkFormat format); struct radv_ia_multi_vgt_param_helpers radv_compute_ia_multi_vgt_param(const struct radv_device *device, struct radv_shader *const *shaders); void radv_get_viewport_xform(const VkViewport *viewport, float scale[3], float translate[3]); struct radv_shader *radv_get_shader(struct radv_shader *const *shaders, gl_shader_stage stage); struct radv_ps_epilog_state { uint8_t color_attachment_count; VkFormat color_attachment_formats[MAX_RTS]; uint8_t color_attachment_mappings[MAX_RTS]; uint32_t color_write_mask; uint32_t color_blend_enable; uint32_t colors_written; bool mrt0_is_dual_src; bool export_depth; bool export_stencil; bool export_sample_mask; bool alpha_to_coverage_via_mrtz; bool alpha_to_one; uint8_t need_src_alpha; }; struct radv_ps_epilog_key radv_generate_ps_epilog_key(const struct radv_device *device, const struct radv_ps_epilog_state *state); void radv_graphics_shaders_compile(struct radv_device *device, struct vk_pipeline_cache *cache, struct radv_shader_stage *stages, const struct radv_graphics_state_key *gfx_state, bool keep_executable_info, bool keep_statistic_info, bool is_internal, struct radv_retained_shaders *retained_shaders, bool noop_fs, struct radv_shader **shaders, struct radv_shader_binary **binaries, struct radv_shader **gs_copy_shader, struct radv_shader_binary **gs_copy_binary); struct radv_vgt_shader_key { uint8_t tess : 1; uint8_t gs : 1; uint8_t mesh_scratch_ring : 1; uint8_t mesh : 1; uint8_t ngg_passthrough : 1; uint8_t ngg : 1; /* gfx10+ */ uint8_t ngg_streamout : 1; uint8_t hs_wave32 : 1; uint8_t gs_wave32 : 1; uint8_t vs_wave32 : 1; }; struct radv_vgt_shader_key radv_get_vgt_shader_key(const struct radv_device *device, struct radv_shader **shaders, const struct radv_shader *gs_copy_shader); uint32_t radv_get_vgt_gs_out(struct radv_shader **shaders, uint32_t primitive_topology); bool radv_needs_null_export_workaround(const struct radv_device *device, const struct radv_shader *ps, unsigned custom_blend_mode); struct radv_graphics_pipeline_create_info { bool use_rectlist; bool db_depth_clear; bool db_stencil_clear; bool depth_compress_disable; bool stencil_compress_disable; uint32_t custom_blend_mode; }; VkResult radv_graphics_pipeline_create(VkDevice device, VkPipelineCache cache, const VkGraphicsPipelineCreateInfo *pCreateInfo, const struct radv_graphics_pipeline_create_info *extra, const VkAllocationCallbacks *alloc, VkPipeline *pPipeline); void radv_destroy_graphics_pipeline(struct radv_device *device, struct radv_graphics_pipeline *pipeline); void radv_destroy_graphics_lib_pipeline(struct radv_device *device, struct radv_graphics_lib_pipeline *pipeline); struct radv_graphics_pipeline_state { struct vk_graphics_pipeline_state vk; void *vk_data; bool compilation_required; struct radv_shader_stage *stages; struct radv_graphics_pipeline_key key; struct radv_pipeline_layout layout; }; void radv_graphics_pipeline_hash(const struct radv_device *device, const struct radv_graphics_pipeline_state *gfx_state, unsigned char *hash); VkResult radv_generate_graphics_pipeline_state(struct radv_device *device, const VkGraphicsPipelineCreateInfo *pCreateInfo, struct radv_graphics_pipeline_state *gfx_state); void radv_graphics_pipeline_state_finish(struct radv_device *device, struct radv_graphics_pipeline_state *gfx_state); #endif /* RADV_PIPELINE_GRAPHICS_H */