2 * Copyright 2018 Collabora Ltd.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include "zink_program.h"
26 #include "zink_compiler.h"
27 #include "zink_context.h"
28 #include "zink_screen.h"
30 #include "util/hash_table.h"
31 #include "util/u_debug.h"
32 #include "util/u_memory.h"
34 static VkDescriptorSetLayout
35 create_desc_set_layout(VkDevice dev
,
36 struct zink_shader
*stages
[PIPE_SHADER_TYPES
- 1])
38 VkDescriptorSetLayoutBinding bindings
[PIPE_SHADER_TYPES
* PIPE_MAX_CONSTANT_BUFFERS
];
41 for (int i
= 0; i
< PIPE_SHADER_TYPES
- 1; i
++) {
42 struct zink_shader
*shader
= stages
[i
];
46 VkShaderStageFlagBits stage_flags
= zink_shader_stage(i
);
47 for (int j
= 0; j
< shader
->num_bindings
; j
++) {
48 assert(num_bindings
< ARRAY_SIZE(bindings
));
49 bindings
[num_bindings
].binding
= shader
->bindings
[j
].binding
;
50 bindings
[num_bindings
].descriptorType
= shader
->bindings
[j
].type
;
51 bindings
[num_bindings
].descriptorCount
= 1;
52 bindings
[num_bindings
].stageFlags
= stage_flags
;
53 bindings
[num_bindings
].pImmutableSamplers
= NULL
;
58 VkDescriptorSetLayoutCreateInfo dcslci
= {};
59 dcslci
.sType
= VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO
;
62 dcslci
.bindingCount
= num_bindings
;
63 dcslci
.pBindings
= bindings
;
65 VkDescriptorSetLayout dsl
;
66 if (vkCreateDescriptorSetLayout(dev
, &dcslci
, 0, &dsl
) != VK_SUCCESS
) {
67 debug_printf("vkCreateDescriptorSetLayout failed\n");
68 return VK_NULL_HANDLE
;
74 static VkPipelineLayout
75 create_pipeline_layout(VkDevice dev
, VkDescriptorSetLayout dsl
)
77 assert(dsl
!= VK_NULL_HANDLE
);
79 VkPipelineLayoutCreateInfo plci
= {};
80 plci
.sType
= VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
;
82 plci
.pSetLayouts
= &dsl
;
83 plci
.setLayoutCount
= 1;
85 VkPipelineLayout layout
;
86 if (vkCreatePipelineLayout(dev
, &plci
, NULL
, &layout
) != VK_SUCCESS
) {
87 debug_printf("vkCreatePipelineLayout failed!\n");
88 return VK_NULL_HANDLE
;
95 hash_gfx_pipeline_state(const void *key
)
97 return _mesa_hash_data(key
, sizeof(struct zink_gfx_pipeline_state
));
101 equals_gfx_pipeline_state(const void *a
, const void *b
)
103 return memcmp(a
, b
, sizeof(struct zink_gfx_pipeline_state
)) == 0;
106 struct zink_gfx_program
*
107 zink_create_gfx_program(VkDevice dev
,
108 struct zink_shader
*stages
[PIPE_SHADER_TYPES
- 1])
110 struct zink_gfx_program
*prog
= CALLOC_STRUCT(zink_gfx_program
);
114 prog
->pipelines
= _mesa_hash_table_create(NULL
, hash_gfx_pipeline_state
,
115 equals_gfx_pipeline_state
);
116 if (!prog
->pipelines
)
119 for (int i
= 0; i
< PIPE_SHADER_TYPES
- 1; ++i
)
120 prog
->stages
[i
] = stages
[i
];
122 prog
->dsl
= create_desc_set_layout(dev
, stages
);
126 prog
->layout
= create_pipeline_layout(dev
, prog
->dsl
);
134 zink_destroy_gfx_program(dev
, prog
);
139 zink_destroy_gfx_program(VkDevice dev
, struct zink_gfx_program
*prog
)
142 vkDestroyPipelineLayout(dev
, prog
->layout
, NULL
);
145 vkDestroyDescriptorSetLayout(dev
, prog
->dsl
, NULL
);
150 struct pipeline_cache_entry
{
151 struct zink_gfx_pipeline_state state
;
156 zink_get_gfx_pipeline(VkDevice dev
, struct zink_gfx_program
*prog
,
157 struct zink_gfx_pipeline_state
*state
)
159 /* TODO: use pre-hashed versions to save some time (can re-hash only when
161 struct hash_entry
*entry
= _mesa_hash_table_search(prog
->pipelines
, state
);
163 VkPipeline pipeline
= zink_create_gfx_pipeline(dev
, prog
, state
);
164 if (pipeline
== VK_NULL_HANDLE
)
165 return VK_NULL_HANDLE
;
167 struct pipeline_cache_entry
*pc_entry
= CALLOC_STRUCT(pipeline_cache_entry
);
171 memcpy(&pc_entry
->state
, state
, sizeof(*state
));
172 pc_entry
->pipeline
= pipeline
;
174 entry
= _mesa_hash_table_insert(prog
->pipelines
, &pc_entry
->state
, pc_entry
);
178 return ((struct pipeline_cache_entry
*)(entry
->data
))->pipeline
;