zink: add a graphics pipeline library implementation

this is only for driver debugging/validation and will not
activate unless ZINK_PIPELINE_LIBRARY_FORCE=1 is specified since it
can only ever add overhead and slow things down

...for now

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17225>
This commit is contained in:
Mike Blumenkrantz
2022-06-23 17:07:12 -04:00
committed by Marge Bot
parent e20aa7eb3a
commit 86e4fcd9a9
7 changed files with 625 additions and 9 deletions

View File

@@ -252,6 +252,8 @@ struct zink_context {
struct hash_table program_cache[8];
uint32_t gfx_hash;
struct zink_gfx_program *curr_program;
struct set gfx_inputs;
struct set gfx_outputs;
struct zink_descriptor_data *dd;

View File

@@ -426,3 +426,390 @@ zink_create_compute_pipeline(struct zink_screen *screen, struct zink_compute_pro
return pipeline;
}
VkPipeline
zink_create_gfx_pipeline_output(struct zink_screen *screen, struct zink_gfx_pipeline_state *state)
{
VkGraphicsPipelineLibraryCreateInfoEXT gplci = {
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,
&state->rendering_info,
VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
};
VkPipelineColorBlendAttachmentState blend_att[PIPE_MAX_COLOR_BUFS];
VkPipelineColorBlendStateCreateInfo blend_state = {0};
blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
if (state->blend_state) {
unsigned num_attachments = state->rendering_info.colorAttachmentCount;
if (state->void_alpha_attachments) {
for (unsigned i = 0; i < num_attachments; i++) {
blend_att[i] = state->blend_state->attachments[i];
if (state->void_alpha_attachments & BITFIELD_BIT(i)) {
blend_att[i].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
blend_att[i].srcColorBlendFactor = clamp_void_blend_factor(blend_att[i].srcColorBlendFactor);
blend_att[i].dstColorBlendFactor = clamp_void_blend_factor(blend_att[i].dstColorBlendFactor);
}
}
blend_state.pAttachments = blend_att;
} else
blend_state.pAttachments = state->blend_state->attachments;
blend_state.attachmentCount = num_attachments;
blend_state.logicOpEnable = state->blend_state->logicop_enable;
blend_state.logicOp = state->blend_state->logicop_func;
}
VkPipelineMultisampleStateCreateInfo ms_state = {0};
ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
ms_state.rasterizationSamples = state->rast_samples + 1;
if (state->blend_state) {
ms_state.alphaToCoverageEnable = state->blend_state->alpha_to_coverage;
if (state->blend_state->alpha_to_one && !screen->info.feats.features.alphaToOne) {
static bool warned = false;
warn_missing_feature(warned, "alphaToOne");
}
ms_state.alphaToOneEnable = state->blend_state->alpha_to_one;
}
/* "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
* - Chapter 27. Rasterization
*
* thus it never makes sense to leave this as NULL since gallium will provide correct
* data here as long as sample_mask is initialized on context creation
*/
ms_state.pSampleMask = &state->sample_mask;
if (state->force_persample_interp) {
ms_state.sampleShadingEnable = VK_TRUE;
ms_state.minSampleShading = 1.0;
}
VkDynamicState dynamicStateEnables[30] = {
VK_DYNAMIC_STATE_BLEND_CONSTANTS,
};
unsigned state_count = 1;
if (screen->info.have_EXT_extended_dynamic_state) {
if (state->sample_locations_enabled)
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT;
}
if (!screen->driver_workarounds.color_write_missing)
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
assert(state_count < ARRAY_SIZE(dynamicStateEnables));
VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {0};
pipelineDynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
pipelineDynamicStateCreateInfo.pDynamicStates = dynamicStateEnables;
pipelineDynamicStateCreateInfo.dynamicStateCount = state_count;
VkGraphicsPipelineCreateInfo pci = {0};
pci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pci.pNext = &gplci;
pci.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
pci.pColorBlendState = &blend_state;
pci.pMultisampleState = &ms_state;
pci.pDynamicState = &pipelineDynamicStateCreateInfo;
VkPipeline pipeline;
if (VKSCR(CreateGraphicsPipelines)(screen->dev, VK_NULL_HANDLE, 1, &pci,
NULL, &pipeline) != VK_SUCCESS) {
mesa_loge("ZINK: vkCreateGraphicsPipelines failed");
return VK_NULL_HANDLE;
}
return pipeline;
}
VkPipeline
zink_create_gfx_pipeline_input(struct zink_screen *screen,
struct zink_gfx_pipeline_state *state,
const uint8_t *binding_map,
VkPrimitiveTopology primitive_topology)
{
VkGraphicsPipelineLibraryCreateInfoEXT gplci = {
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,
NULL,
VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT
};
VkPipelineVertexInputStateCreateInfo vertex_input_state;
memset(&vertex_input_state, 0, sizeof(vertex_input_state));
vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
if (!screen->info.have_EXT_vertex_input_dynamic_state || !state->uses_dynamic_stride) {
vertex_input_state.pVertexBindingDescriptions = state->element_state->b.bindings;
vertex_input_state.vertexBindingDescriptionCount = state->element_state->num_bindings;
vertex_input_state.pVertexAttributeDescriptions = state->element_state->attribs;
vertex_input_state.vertexAttributeDescriptionCount = state->element_state->num_attribs;
if (!state->uses_dynamic_stride) {
for (int i = 0; i < state->element_state->num_bindings; ++i) {
const unsigned buffer_id = binding_map[i];
VkVertexInputBindingDescription *binding = &state->element_state->b.bindings[i];
binding->stride = state->vertex_strides[buffer_id];
}
}
}
VkPipelineVertexInputDivisorStateCreateInfoEXT vdiv_state;
if (!screen->info.have_EXT_vertex_input_dynamic_state && state->element_state->b.divisors_present) {
memset(&vdiv_state, 0, sizeof(vdiv_state));
vertex_input_state.pNext = &vdiv_state;
vdiv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
vdiv_state.vertexBindingDivisorCount = state->element_state->b.divisors_present;
vdiv_state.pVertexBindingDivisors = state->element_state->b.divisors;
}
VkPipelineInputAssemblyStateCreateInfo primitive_state = {0};
primitive_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
primitive_state.topology = primitive_topology;
assert(screen->info.have_EXT_extended_dynamic_state2);
VkDynamicState dynamicStateEnables[30];
unsigned state_count = 0;
if (screen->info.have_EXT_vertex_input_dynamic_state)
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_EXT;
else if (state->uses_dynamic_stride)
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE;
assert(state_count < ARRAY_SIZE(dynamicStateEnables));
VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {0};
pipelineDynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
pipelineDynamicStateCreateInfo.pDynamicStates = dynamicStateEnables;
pipelineDynamicStateCreateInfo.dynamicStateCount = state_count;
VkGraphicsPipelineCreateInfo pci = {0};
pci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pci.pNext = &gplci;
pci.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
pci.pVertexInputState = &vertex_input_state;
pci.pInputAssemblyState = &primitive_state;
pci.pDynamicState = &pipelineDynamicStateCreateInfo;
VkPipeline pipeline;
if (VKSCR(CreateGraphicsPipelines)(screen->dev, VK_NULL_HANDLE, 1, &pci,
NULL, &pipeline) != VK_SUCCESS) {
mesa_loge("ZINK: vkCreateGraphicsPipelines failed");
return VK_NULL_HANDLE;
}
return pipeline;
}
VkPipeline
zink_create_gfx_pipeline_library(struct zink_screen *screen, struct zink_gfx_program *prog,
struct zink_rasterizer_hw_state *hw_rast_state, bool line)
{
assert(screen->info.have_EXT_extended_dynamic_state && screen->info.have_EXT_extended_dynamic_state2);
VkPipelineRenderingCreateInfo rendering_info;
rendering_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
rendering_info.pNext = NULL;
rendering_info.viewMask = 0;
VkGraphicsPipelineLibraryCreateInfoEXT gplci = {
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,
&rendering_info,
VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT | VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT
};
VkPipelineViewportStateCreateInfo viewport_state = {0};
VkPipelineViewportDepthClipControlCreateInfoEXT clip = {
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT,
NULL,
VK_TRUE
};
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state.viewportCount = 0;
viewport_state.pViewports = NULL;
viewport_state.scissorCount = 0;
viewport_state.pScissors = NULL;
if (!screen->driver_workarounds.depth_clip_control_missing && !hw_rast_state->clip_halfz)
viewport_state.pNext = &clip;
VkPipelineRasterizationStateCreateInfo rast_state = {0};
rast_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rast_state.depthClampEnable = VK_TRUE;
rast_state.polygonMode = hw_rast_state->polygon_mode;
rast_state.depthBiasEnable = VK_TRUE;
rast_state.depthBiasConstantFactor = 0.0;
rast_state.depthBiasClamp = 0.0;
rast_state.depthBiasSlopeFactor = 0.0;
VkPipelineRasterizationDepthClipStateCreateInfoEXT depth_clip_state = {0};
depth_clip_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT;
depth_clip_state.depthClipEnable = hw_rast_state->depth_clip;
if (screen->info.have_EXT_depth_clip_enable) {
depth_clip_state.pNext = rast_state.pNext;
rast_state.pNext = &depth_clip_state;
} else {
static bool warned = false;
warn_missing_feature(warned, "VK_EXT_depth_clip_enable");
rast_state.depthClampEnable = !hw_rast_state->depth_clip;
}
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT pv_state;
pv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT;
pv_state.provokingVertexMode = hw_rast_state->pv_last ?
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT :
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
if (screen->info.have_EXT_provoking_vertex && hw_rast_state->pv_last) {
pv_state.pNext = rast_state.pNext;
rast_state.pNext = &pv_state;
}
VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {0};
depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
VkDynamicState dynamicStateEnables[30] = {
VK_DYNAMIC_STATE_LINE_WIDTH,
VK_DYNAMIC_STATE_DEPTH_BIAS,
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
};
unsigned state_count = 3;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_BOUNDS;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_COMPARE_OP;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_OP;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_FRONT_FACE;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_CULL_MODE;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE;
if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints)
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
VkPipelineRasterizationLineStateCreateInfoEXT rast_line_state;
if (screen->info.have_EXT_line_rasterization) {
rast_line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
rast_line_state.pNext = rast_state.pNext;
rast_line_state.stippledLineEnable = VK_FALSE;
rast_line_state.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
bool check_warn = line;
if (prog->nir[PIPE_SHADER_TESS_EVAL]) {
check_warn |= !prog->nir[PIPE_SHADER_TESS_EVAL]->info.tess.point_mode &&
prog->nir[PIPE_SHADER_TESS_EVAL]->info.tess._primitive_mode == TESS_PRIMITIVE_ISOLINES;
}
if (prog->nir[PIPE_SHADER_GEOMETRY]) {
switch (prog->nir[PIPE_SHADER_GEOMETRY]->info.gs.output_primitive) {
case SHADER_PRIM_LINES:
case SHADER_PRIM_LINE_LOOP:
case SHADER_PRIM_LINE_STRIP:
case SHADER_PRIM_LINES_ADJACENCY:
case SHADER_PRIM_LINE_STRIP_ADJACENCY:
check_warn = true;
break;
default: break;
}
}
if (check_warn) {
const char *features[4][2] = {
[VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT] = {"",""},
[VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT] = {"rectangularLines", "stippledRectangularLines"},
[VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT] = {"bresenhamLines", "stippledBresenhamLines"},
[VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT] = {"smoothLines", "stippledSmoothLines"},
};
static bool warned[6] = {0};
const VkPhysicalDeviceLineRasterizationFeaturesEXT *line_feats = &screen->info.line_rast_feats;
/* line features can be represented as an array VkBool32[6],
* with the 3 base features preceding the 3 (matching) stippled features
*/
const VkBool32 *feat = &line_feats->rectangularLines;
unsigned mode_idx = hw_rast_state->line_mode - VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
/* add base mode index, add 3 if stippling is enabled */
mode_idx += hw_rast_state->line_stipple_enable * 3;
if (*(feat + mode_idx))
rast_line_state.lineRasterizationMode = hw_rast_state->line_mode;
else
warn_missing_feature(warned[mode_idx], features[hw_rast_state->line_mode][hw_rast_state->line_stipple_enable]);
}
if (hw_rast_state->line_stipple_enable) {
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
rast_line_state.stippledLineEnable = VK_TRUE;
}
rast_state.pNext = &rast_line_state;
}
assert(state_count < ARRAY_SIZE(dynamicStateEnables));
VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {0};
pipelineDynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
pipelineDynamicStateCreateInfo.pDynamicStates = dynamicStateEnables;
pipelineDynamicStateCreateInfo.dynamicStateCount = state_count;
VkGraphicsPipelineCreateInfo pci = {0};
pci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pci.pNext = &gplci;
pci.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
pci.layout = prog->base.layout;
pci.pRasterizationState = &rast_state;
pci.pViewportState = &viewport_state;
pci.pDepthStencilState = &depth_stencil_state;
pci.pDynamicState = &pipelineDynamicStateCreateInfo;
VkPipelineTessellationStateCreateInfo tci = {0};
VkPipelineTessellationDomainOriginStateCreateInfo tdci = {0};
if (prog->shaders[PIPE_SHADER_TESS_CTRL] && prog->shaders[PIPE_SHADER_TESS_EVAL]) {
tci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
tci.patchControlPoints = 3; //this is a wild guess; pray for extendedDynamicState2PatchControlPoints
pci.pTessellationState = &tci;
tci.pNext = &tdci;
tdci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;
tdci.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
}
VkPipelineShaderStageCreateInfo shader_stages[ZINK_SHADER_COUNT];
uint32_t num_stages = 0;
for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
if (!prog->modules[i])
continue;
VkPipelineShaderStageCreateInfo stage = {0};
stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stage.stage = zink_shader_stage(i);
stage.module = prog->modules[i]->shader;
stage.pName = "main";
shader_stages[num_stages++] = stage;
}
assert(num_stages > 0);
pci.pStages = shader_stages;
pci.stageCount = num_stages;
VkPipeline pipeline;
if (VKSCR(CreateGraphicsPipelines)(screen->dev, prog->base.pipeline_cache, 1, &pci,
NULL, &pipeline) != VK_SUCCESS) {
mesa_loge("ZINK: vkCreateGraphicsPipelines failed");
return VK_NULL_HANDLE;
}
return pipeline;
}
VkPipeline
zink_create_gfx_pipeline_combined(struct zink_screen *screen, struct zink_gfx_program *prog, VkPipeline input, VkPipeline library, VkPipeline output)
{
VkPipeline libraries[] = {input, library, output};
VkPipelineLibraryCreateInfoKHR libstate = {0};
libstate.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR;
libstate.libraryCount = 3;
libstate.pLibraries = libraries;
VkGraphicsPipelineCreateInfo pci = {0};
pci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pci.pNext = &libstate;
VkPipeline pipeline;
if (VKSCR(CreateGraphicsPipelines)(screen->dev, prog->base.pipeline_cache, 1, &pci,
NULL, &pipeline) != VK_SUCCESS) {
mesa_loge("ZINK: vkCreateGraphicsPipelines failed");
return VK_NULL_HANDLE;
}
return pipeline;
}

View File

@@ -72,9 +72,7 @@ struct zink_gfx_pipeline_state {
struct zink_pipeline_dynamic_state2 dyn_state2;
#if VK_USE_64_BIT_PTR_DEFINES
uint32_t _pad;
#endif
uint32_t gkey; //for pipeline library lookups
VkShaderModule modules[PIPE_SHADER_TYPES - 1];
bool modules_changed;
@@ -83,9 +81,7 @@ struct zink_gfx_pipeline_state {
uint32_t final_hash;
#if VK_USE_64_BIT_PTR_DEFINES
uint32_t _pad2;
#endif
/* order matches zink_gfx_input_key */
union {
struct {
@@ -142,4 +138,17 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
VkPipeline
zink_create_compute_pipeline(struct zink_screen *screen, struct zink_compute_program *comp, struct zink_compute_pipeline_state *state);
VkPipeline
zink_create_gfx_pipeline_input(struct zink_screen *screen,
struct zink_gfx_pipeline_state *state,
const uint8_t *binding_map,
VkPrimitiveTopology primitive_topology);
VkPipeline
zink_create_gfx_pipeline_library(struct zink_screen *screen, struct zink_gfx_program *prog,
struct zink_rasterizer_hw_state *hw_rast_state, bool line);
VkPipeline
zink_create_gfx_pipeline_output(struct zink_screen *screen, struct zink_gfx_pipeline_state *state);
VkPipeline
zink_create_gfx_pipeline_combined(struct zink_screen *screen, struct zink_gfx_program *prog, VkPipeline input, VkPipeline library, VkPipeline output);
#endif

View File

@@ -224,6 +224,18 @@ update_gfx_shader_modules(struct zink_context *ctx,
}
}
static uint32_t
hash_pipeline_lib(const void *key)
{
return _mesa_hash_data(key, sizeof(struct zink_rasterizer_hw_state));
}
static bool
equals_pipeline_lib(const void *a, const void *b)
{
return !memcmp(a, b, offsetof(struct zink_gfx_library_key, pipeline));
}
static uint32_t
hash_gfx_pipeline_state(const void *key)
{
@@ -279,6 +291,60 @@ equals_gfx_pipeline_state(const void *a, const void *b)
!memcmp(a, b, offsetof(struct zink_gfx_pipeline_state, hash));
}
static uint32_t
hash_gfx_input_dynamic(const void *key)
{
const struct zink_gfx_input_key *ikey = key;
return ikey->idx;
}
static bool
equals_gfx_input_dynamic(const void *a, const void *b)
{
const struct zink_gfx_input_key *ikey_a = a;
const struct zink_gfx_input_key *ikey_b = b;
return ikey_a->idx == ikey_b->idx;
}
static uint32_t
hash_gfx_input(const void *key)
{
const struct zink_gfx_input_key *ikey = key;
if (ikey->uses_dynamic_stride)
return ikey->input;
return _mesa_hash_data(key, offsetof(struct zink_gfx_input_key, pipeline));
}
static bool
equals_gfx_input(const void *a, const void *b)
{
const struct zink_gfx_input_key *ikey_a = a;
const struct zink_gfx_input_key *ikey_b = b;
if (ikey_a->uses_dynamic_stride)
return ikey_a->element_state == ikey_b->element_state &&
!memcmp(a, b, offsetof(struct zink_gfx_input_key, vertex_buffers_enabled_mask));
return !memcmp(a, b, offsetof(struct zink_gfx_input_key, pipeline));
}
static uint32_t
hash_gfx_output(const void *key)
{
const uint8_t *data = key;
const struct zink_gfx_output_key *okey = key;
/* manually add in force_persample_interp */
return okey->force_persample_interp ^
_mesa_hash_data(data + sizeof(uint16_t), offsetof(struct zink_gfx_output_key, pipeline) - sizeof(uint16_t));
}
static bool
equals_gfx_output(const void *a, const void *b)
{
const uint8_t *da = a;
const uint8_t *db = b;
return !memcmp(da + sizeof(uint16_t), db + sizeof(uint16_t), offsetof(struct zink_gfx_output_key, pipeline) - sizeof(uint16_t));
}
void
zink_update_gfx_program(struct zink_context *ctx, struct zink_gfx_program *prog)
{
@@ -473,6 +539,9 @@ zink_create_gfx_program(struct zink_context *ctx,
break;
}
for (unsigned i = 0; i < ARRAY_SIZE(prog->libs); i++)
_mesa_set_init(&prog->libs[i], prog, hash_pipeline_lib, equals_pipeline_lib);
struct mesa_sha1 sctx;
_mesa_sha1_init(&sctx);
for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
@@ -700,6 +769,13 @@ zink_destroy_gfx_program(struct zink_context *ctx,
ralloc_free(prog->nir[i]);
}
for (unsigned i = 0; i < ARRAY_SIZE(prog->libs); i++) {
set_foreach_remove(&prog->libs[i], he) {
struct zink_gfx_library_key *gkey = (void*)he->key;
VKSCR(DestroyPipeline)(screen->dev, gkey->pipeline, NULL);
}
}
unsigned max_idx = ARRAY_SIZE(prog->pipelines);
if (screen->info.have_EXT_extended_dynamic_state) {
/* only need first 3/4 for point/line/tri/patch */
@@ -772,6 +848,17 @@ get_primtype_idx(enum pipe_prim_type mode)
}
}
static void
create_pipeline_lib(struct zink_screen *screen, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state, enum pipe_prim_type mode)
{
struct zink_gfx_library_key *gkey = rzalloc(prog, struct zink_gfx_library_key);
gkey->hw_rast_state = state->rast_state;
memcpy(gkey->modules, state->modules, sizeof(gkey->modules));
bool line = u_reduced_prim(mode) == PIPE_PRIM_LINES;
gkey->pipeline = zink_create_gfx_pipeline_library(screen, prog, (struct zink_rasterizer_hw_state*)state, line);
_mesa_set_add(&prog->libs[get_primtype_idx(mode)], gkey);
}
static unsigned
get_pipeline_idx(bool have_EXT_extended_dynamic_state, enum pipe_prim_type mode, VkPrimitiveTopology vkmode)
{
@@ -786,6 +873,54 @@ get_pipeline_idx(bool have_EXT_extended_dynamic_state, enum pipe_prim_type mode,
return vkmode;
}
static struct zink_gfx_input_key *
find_or_create_input_dynamic(struct zink_context *ctx, VkPrimitiveTopology vkmode)
{
uint32_t hash = hash_gfx_input_dynamic(&ctx->gfx_pipeline_state.input);
struct set_entry *he = _mesa_set_search_pre_hashed(&ctx->gfx_inputs, hash, &ctx->gfx_pipeline_state.input);
if (!he) {
struct zink_gfx_input_key *ikey = rzalloc(ctx, struct zink_gfx_input_key);
ikey->idx = ctx->gfx_pipeline_state.idx;
ikey->pipeline = zink_create_gfx_pipeline_input(zink_screen(ctx->base.screen), &ctx->gfx_pipeline_state, ctx->element_state->binding_map, vkmode);
he = _mesa_set_add_pre_hashed(&ctx->gfx_inputs, hash, ikey);
}
return (void*)he->key;
}
static struct zink_gfx_input_key *
find_or_create_input(struct zink_context *ctx, VkPrimitiveTopology vkmode)
{
uint32_t hash = hash_gfx_input(&ctx->gfx_pipeline_state.input);
struct set_entry *he = _mesa_set_search_pre_hashed(&ctx->gfx_inputs, hash, &ctx->gfx_pipeline_state.input);
if (!he) {
struct zink_gfx_input_key *ikey = rzalloc(ctx, struct zink_gfx_input_key);
if (ctx->gfx_pipeline_state.uses_dynamic_stride) {
memcpy(ikey, &ctx->gfx_pipeline_state.input, offsetof(struct zink_gfx_input_key, vertex_buffers_enabled_mask));
ikey->element_state = ctx->gfx_pipeline_state.element_state;
} else {
memcpy(ikey, &ctx->gfx_pipeline_state.input, offsetof(struct zink_gfx_input_key, pipeline));
}
ikey->pipeline = zink_create_gfx_pipeline_input(zink_screen(ctx->base.screen), &ctx->gfx_pipeline_state, ctx->element_state->binding_map, vkmode);
he = _mesa_set_add_pre_hashed(&ctx->gfx_inputs, hash, ikey);
}
return (void*)he->key;
}
static struct zink_gfx_output_key *
find_or_create_output(struct zink_context *ctx)
{
uint32_t hash = hash_gfx_output(&ctx->gfx_pipeline_state);
struct set_entry *he = _mesa_set_search_pre_hashed(&ctx->gfx_outputs, hash, &ctx->gfx_pipeline_state);
if (!he) {
struct zink_gfx_output_key *okey = rzalloc(ctx, struct zink_gfx_output_key);
memcpy(okey, &ctx->gfx_pipeline_state, offsetof(struct zink_gfx_output_key, pipeline));
okey->_pad = 0;
okey->pipeline = zink_create_gfx_pipeline_output(zink_screen(ctx->base.screen), &ctx->gfx_pipeline_state);
he = _mesa_set_add_pre_hashed(&ctx->gfx_outputs, hash, okey);
}
return (void*)he->key;
}
/*
VUID-vkCmdBindVertexBuffers2-pStrides-06209
If pStrides is not NULL each element of pStrides must be either 0 or greater than or equal
@@ -868,9 +1003,33 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
if (!entry) {
util_queue_fence_wait(&prog->base.cache_fence);
VkPipeline pipeline = zink_create_gfx_pipeline(screen, prog, state,
ctx->element_state->binding_map,
vkmode);
VkPipeline pipeline = VK_NULL_HANDLE;
if (screen->info.have_EXT_graphics_pipeline_library &&
/* TODO: if there's ever a dynamic render extension with input attachments */
!ctx->gfx_pipeline_state.render_pass) {
ctx->gfx_pipeline_state.gkey = ctx->gfx_pipeline_state.rast_state;
struct set_entry *he = NULL;
/* TODO: this will eventually be pre-populated by async shader compile */
//struct set_entry *he = _mesa_set_search(&prog->libs[idx], &ctx->gfx_pipeline_state.gkey);
if (!he && screen->driver_workarounds.force_pipeline_library) {
create_pipeline_lib(screen, prog, &ctx->gfx_pipeline_state, mode);
he = _mesa_set_search(&prog->libs[idx], &ctx->gfx_pipeline_state.gkey);
assert(he);
}
if (he) {
struct zink_gfx_library_key *gkey = (void*)he->key;
struct zink_gfx_input_key *ikey = have_EXT_vertex_input_dynamic_state ?
find_or_create_input_dynamic(ctx, vkmode) :
find_or_create_input(ctx, vkmode);
struct zink_gfx_output_key *okey = find_or_create_output(ctx);
pipeline = zink_create_gfx_pipeline_combined(screen, prog, ikey->pipeline, gkey->pipeline, okey->pipeline);
}
}
if (!pipeline) {
pipeline = zink_create_gfx_pipeline(screen, prog, state,
ctx->element_state->binding_map,
vkmode);
}
if (pipeline == VK_NULL_HANDLE)
return VK_NULL_HANDLE;
@@ -1209,6 +1368,22 @@ zink_program_init(struct zink_context *ctx)
ctx->base.create_compute_state = zink_create_cs_state;
ctx->base.bind_compute_state = zink_bind_cs_state;
ctx->base.delete_compute_state = zink_delete_shader_state;
if (zink_screen(ctx->base.screen)->info.have_EXT_vertex_input_dynamic_state)
_mesa_set_init(&ctx->gfx_inputs, ctx, hash_gfx_input_dynamic, equals_gfx_input_dynamic);
else
_mesa_set_init(&ctx->gfx_inputs, ctx, hash_gfx_input, equals_gfx_input);
_mesa_set_init(&ctx->gfx_outputs, ctx, hash_gfx_output, equals_gfx_output);
/* validate struct packing */
STATIC_ASSERT(offsetof(struct zink_gfx_pipeline_state, vertex_buffers_enabled_mask) - offsetof(struct zink_gfx_pipeline_state, input) ==
offsetof(struct zink_gfx_input_key, vertex_buffers_enabled_mask) - offsetof(struct zink_gfx_input_key, input));
STATIC_ASSERT(offsetof(struct zink_gfx_pipeline_state, vertex_strides) - offsetof(struct zink_gfx_pipeline_state, input) ==
offsetof(struct zink_gfx_input_key, vertex_strides) - offsetof(struct zink_gfx_input_key, input));
STATIC_ASSERT(offsetof(struct zink_gfx_pipeline_state, element_state) - offsetof(struct zink_gfx_pipeline_state, input) ==
offsetof(struct zink_gfx_input_key, element_state) - offsetof(struct zink_gfx_input_key, input));
STATIC_ASSERT(offsetof(struct zink_gfx_pipeline_state, modules) - offsetof(struct zink_gfx_pipeline_state, gkey) ==
offsetof(struct zink_gfx_library_key, modules) - offsetof(struct zink_gfx_library_key, hw_rast_state));
}
bool

View File

@@ -95,6 +95,38 @@ struct zink_program {
#define ZINK_MAX_INLINED_VARIANTS 5
struct zink_gfx_library_key {
uint32_t hw_rast_state;
VkShaderModule modules[ZINK_SHADER_COUNT];
VkPipeline pipeline;
};
struct zink_gfx_input_key {
union {
struct {
unsigned idx:8;
bool uses_dynamic_stride;
};
uint32_t input;
};
uint32_t vertex_buffers_enabled_mask;
uint32_t vertex_strides[PIPE_MAX_ATTRIBS];
struct zink_vertex_elements_hw_state *element_state;
VkPipeline pipeline;
};
struct zink_gfx_output_key {
uint32_t _pad:15;
uint32_t force_persample_interp:1;
uint32_t rast_samples:8;
uint32_t void_alpha_attachments:PIPE_MAX_COLOR_BUFS;
VkSampleMask sample_mask;
unsigned rp_state;
uint32_t blend_id;
VkPipeline pipeline;
};
struct zink_gfx_program {
struct zink_program base;
@@ -112,6 +144,8 @@ struct zink_gfx_program {
struct hash_table pipelines[11]; // number of draw modes we support
uint32_t default_variant_hash;
uint32_t last_variant_hash;
struct set libs[4]; //zink_gfx_library_key[primtype] -> VkPipeline
};
struct zink_compute_program {

View File

@@ -2083,6 +2083,7 @@ static void
init_driver_workarounds(struct zink_screen *screen)
{
/* enable implicit sync for all non-mesa drivers */
screen->driver_workarounds.force_pipeline_library = debug_get_bool_option("ZINK_PIPELINE_LIBRARY_FORCE", false);
screen->driver_workarounds.implicit_sync = true;
switch (screen->info.driver_props.driverID) {
case VK_DRIVER_ID_MESA_RADV:
@@ -2097,11 +2098,18 @@ init_driver_workarounds(struct zink_screen *screen)
default:
break;
}
if (screen->info.have_EXT_graphics_pipeline_library)
screen->info.have_EXT_graphics_pipeline_library = screen->info.have_EXT_extended_dynamic_state &&
screen->info.have_EXT_extended_dynamic_state2 &&
screen->info.have_KHR_dynamic_rendering &&
(screen->info.gpl_props.graphicsPipelineLibraryFastLinking ||
screen->is_cpu ||
screen->driver_workarounds.force_pipeline_library);
if (!screen->driver_workarounds.force_pipeline_library)
screen->info.have_EXT_graphics_pipeline_library = false;
screen->driver_workarounds.color_write_missing =
!screen->info.have_EXT_color_write_enable ||
!screen->info.cwrite_feats.colorWriteEnable;
screen->driver_workarounds.depth_clip_control_missing = !screen->info.have_EXT_depth_clip_control;
if (screen->info.driver_props.driverID == VK_DRIVER_ID_AMD_PROPRIETARY)
/* this completely breaks xfb somehow */

View File

@@ -210,6 +210,7 @@ struct zink_screen {
bool color_write_missing;
bool depth_clip_control_missing;
bool implicit_sync;
bool force_pipeline_library;
} driver_workarounds;
};