turnip: parse VkPipelineInputAssemblyStateCreateInfo
[mesa.git] / src / freedreno / vulkan / tu_pipeline.c
1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 */
27
28 #include "tu_private.h"
29
30 #include "main/menums.h"
31 #include "nir/nir.h"
32 #include "nir/nir_builder.h"
33 #include "spirv/nir_spirv.h"
34 #include "util/debug.h"
35 #include "util/mesa-sha1.h"
36 #include "util/u_atomic.h"
37 #include "vk_format.h"
38 #include "vk_util.h"
39
40 #include "tu_cs.h"
41
42 struct tu_pipeline_builder
43 {
44 struct tu_device *device;
45 struct tu_pipeline_cache *cache;
46 const VkAllocationCallbacks *alloc;
47 const VkGraphicsPipelineCreateInfo *create_info;
48 };
49
50 static enum tu_dynamic_state_bits
51 tu_dynamic_state_bit(VkDynamicState state)
52 {
53 switch (state) {
54 case VK_DYNAMIC_STATE_VIEWPORT:
55 return TU_DYNAMIC_VIEWPORT;
56 case VK_DYNAMIC_STATE_SCISSOR:
57 return TU_DYNAMIC_SCISSOR;
58 case VK_DYNAMIC_STATE_LINE_WIDTH:
59 return TU_DYNAMIC_LINE_WIDTH;
60 case VK_DYNAMIC_STATE_DEPTH_BIAS:
61 return TU_DYNAMIC_DEPTH_BIAS;
62 case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
63 return TU_DYNAMIC_BLEND_CONSTANTS;
64 case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
65 return TU_DYNAMIC_DEPTH_BOUNDS;
66 case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
67 return TU_DYNAMIC_STENCIL_COMPARE_MASK;
68 case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
69 return TU_DYNAMIC_STENCIL_WRITE_MASK;
70 case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
71 return TU_DYNAMIC_STENCIL_REFERENCE;
72 default:
73 unreachable("invalid dynamic state");
74 return 0;
75 }
76 }
77
78 static enum pc_di_primtype
79 tu6_primtype(VkPrimitiveTopology topology)
80 {
81 switch (topology) {
82 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
83 return DI_PT_POINTLIST;
84 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
85 return DI_PT_LINELIST;
86 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
87 return DI_PT_LINESTRIP;
88 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
89 return DI_PT_TRILIST;
90 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
91 return DI_PT_TRILIST;
92 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
93 return DI_PT_TRIFAN;
94 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
95 return DI_PT_LINE_ADJ;
96 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
97 return DI_PT_LINESTRIP_ADJ;
98 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
99 return DI_PT_TRI_ADJ;
100 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
101 return DI_PT_TRISTRIP_ADJ;
102 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
103 default:
104 unreachable("invalid primitive topology");
105 return DI_PT_NONE;
106 }
107 }
108
109 static VkResult
110 tu_pipeline_builder_create_pipeline(struct tu_pipeline_builder *builder,
111 struct tu_pipeline **out_pipeline)
112 {
113 struct tu_device *dev = builder->device;
114
115 struct tu_pipeline *pipeline =
116 vk_zalloc2(&dev->alloc, builder->alloc, sizeof(*pipeline), 8,
117 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
118 if (!pipeline)
119 return VK_ERROR_OUT_OF_HOST_MEMORY;
120
121 tu_cs_init(&pipeline->cs, TU_CS_MODE_SUB_STREAM, 2048);
122
123 /* reserve the space now such that tu_cs_begin_sub_stream never fails */
124 VkResult result = tu_cs_reserve_space(dev, &pipeline->cs, 2048);
125 if (result != VK_SUCCESS) {
126 vk_free2(&dev->alloc, builder->alloc, pipeline);
127 return result;
128 }
129
130 *out_pipeline = pipeline;
131
132 return VK_SUCCESS;
133 }
134
135 static void
136 tu_pipeline_builder_parse_dynamic(struct tu_pipeline_builder *builder,
137 struct tu_pipeline *pipeline)
138 {
139 const VkPipelineDynamicStateCreateInfo *dynamic_info =
140 builder->create_info->pDynamicState;
141
142 if (!dynamic_info)
143 return;
144
145 for (uint32_t i = 0; i < dynamic_info->dynamicStateCount; i++) {
146 pipeline->dynamic_state.mask |=
147 tu_dynamic_state_bit(dynamic_info->pDynamicStates[i]);
148 }
149 }
150
151 static void
152 tu_pipeline_builder_parse_input_assembly(struct tu_pipeline_builder *builder,
153 struct tu_pipeline *pipeline)
154 {
155 const VkPipelineInputAssemblyStateCreateInfo *ia_info =
156 builder->create_info->pInputAssemblyState;
157
158 pipeline->ia.primtype = tu6_primtype(ia_info->topology);
159 pipeline->ia.primitive_restart = ia_info->primitiveRestartEnable;
160 }
161
162 static void
163 tu_pipeline_finish(struct tu_pipeline *pipeline,
164 struct tu_device *dev,
165 const VkAllocationCallbacks *alloc)
166 {
167 tu_cs_finish(dev, &pipeline->cs);
168 }
169
170 static VkResult
171 tu_pipeline_builder_build(struct tu_pipeline_builder *builder,
172 struct tu_pipeline **pipeline)
173 {
174 VkResult result = tu_pipeline_builder_create_pipeline(builder, pipeline);
175 if (result != VK_SUCCESS)
176 return result;
177
178 tu_pipeline_builder_parse_dynamic(builder, *pipeline);
179 tu_pipeline_builder_parse_input_assembly(builder, *pipeline);
180
181 /* we should have reserved enough space upfront such that the CS never
182 * grows
183 */
184 assert((*pipeline)->cs.bo_count == 1);
185
186 return VK_SUCCESS;
187 }
188
189 static void
190 tu_pipeline_builder_init_graphics(
191 struct tu_pipeline_builder *builder,
192 struct tu_device *dev,
193 struct tu_pipeline_cache *cache,
194 const VkGraphicsPipelineCreateInfo *create_info,
195 const VkAllocationCallbacks *alloc)
196 {
197 *builder = (struct tu_pipeline_builder) {
198 .device = dev,
199 .cache = cache,
200 .create_info = create_info,
201 .alloc = alloc,
202 };
203 }
204
205 VkResult
206 tu_CreateGraphicsPipelines(VkDevice device,
207 VkPipelineCache pipelineCache,
208 uint32_t count,
209 const VkGraphicsPipelineCreateInfo *pCreateInfos,
210 const VkAllocationCallbacks *pAllocator,
211 VkPipeline *pPipelines)
212 {
213 TU_FROM_HANDLE(tu_device, dev, device);
214 TU_FROM_HANDLE(tu_pipeline_cache, cache, pipelineCache);
215
216 for (uint32_t i = 0; i < count; i++) {
217 struct tu_pipeline_builder builder;
218 tu_pipeline_builder_init_graphics(&builder, dev, cache,
219 &pCreateInfos[i], pAllocator);
220
221 struct tu_pipeline *pipeline;
222 VkResult result = tu_pipeline_builder_build(&builder, &pipeline);
223
224 if (result != VK_SUCCESS) {
225 for (uint32_t j = 0; j < i; j++) {
226 tu_DestroyPipeline(device, pPipelines[j], pAllocator);
227 pPipelines[j] = VK_NULL_HANDLE;
228 }
229
230 return result;
231 }
232
233 pPipelines[i] = tu_pipeline_to_handle(pipeline);
234 }
235
236 return VK_SUCCESS;
237 }
238
239 static VkResult
240 tu_compute_pipeline_create(VkDevice _device,
241 VkPipelineCache _cache,
242 const VkComputePipelineCreateInfo *pCreateInfo,
243 const VkAllocationCallbacks *pAllocator,
244 VkPipeline *pPipeline)
245 {
246 return VK_SUCCESS;
247 }
248
249 VkResult
250 tu_CreateComputePipelines(VkDevice _device,
251 VkPipelineCache pipelineCache,
252 uint32_t count,
253 const VkComputePipelineCreateInfo *pCreateInfos,
254 const VkAllocationCallbacks *pAllocator,
255 VkPipeline *pPipelines)
256 {
257 VkResult result = VK_SUCCESS;
258
259 unsigned i = 0;
260 for (; i < count; i++) {
261 VkResult r;
262 r = tu_compute_pipeline_create(_device, pipelineCache, &pCreateInfos[i],
263 pAllocator, &pPipelines[i]);
264 if (r != VK_SUCCESS) {
265 result = r;
266 pPipelines[i] = VK_NULL_HANDLE;
267 }
268 }
269
270 return result;
271 }
272
273 void
274 tu_DestroyPipeline(VkDevice _device,
275 VkPipeline _pipeline,
276 const VkAllocationCallbacks *pAllocator)
277 {
278 TU_FROM_HANDLE(tu_device, dev, _device);
279 TU_FROM_HANDLE(tu_pipeline, pipeline, _pipeline);
280
281 if (!_pipeline)
282 return;
283
284 tu_pipeline_finish(pipeline, dev, pAllocator);
285 vk_free2(&dev->alloc, pAllocator, pipeline);
286 }