turnip: create a less dummy pipeline
[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 VkResult
51 tu_pipeline_builder_create_pipeline(struct tu_pipeline_builder *builder,
52 struct tu_pipeline **out_pipeline)
53 {
54 struct tu_device *dev = builder->device;
55
56 struct tu_pipeline *pipeline =
57 vk_zalloc2(&dev->alloc, builder->alloc, sizeof(*pipeline), 8,
58 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
59 if (!pipeline)
60 return VK_ERROR_OUT_OF_HOST_MEMORY;
61
62 tu_cs_init(&pipeline->cs, TU_CS_MODE_SUB_STREAM, 2048);
63
64 /* reserve the space now such that tu_cs_begin_sub_stream never fails */
65 VkResult result = tu_cs_reserve_space(dev, &pipeline->cs, 2048);
66 if (result != VK_SUCCESS) {
67 vk_free2(&dev->alloc, builder->alloc, pipeline);
68 return result;
69 }
70
71 *out_pipeline = pipeline;
72
73 return VK_SUCCESS;
74 }
75
76 static void
77 tu_pipeline_finish(struct tu_pipeline *pipeline,
78 struct tu_device *dev,
79 const VkAllocationCallbacks *alloc)
80 {
81 tu_cs_finish(dev, &pipeline->cs);
82 }
83
84 static VkResult
85 tu_pipeline_builder_build(struct tu_pipeline_builder *builder,
86 struct tu_pipeline **pipeline)
87 {
88 VkResult result = tu_pipeline_builder_create_pipeline(builder, pipeline);
89 if (result != VK_SUCCESS)
90 return result;
91
92 /* we should have reserved enough space upfront such that the CS never
93 * grows
94 */
95 assert((*pipeline)->cs.bo_count == 1);
96
97 return VK_SUCCESS;
98 }
99
100 static void
101 tu_pipeline_builder_init_graphics(
102 struct tu_pipeline_builder *builder,
103 struct tu_device *dev,
104 struct tu_pipeline_cache *cache,
105 const VkGraphicsPipelineCreateInfo *create_info,
106 const VkAllocationCallbacks *alloc)
107 {
108 *builder = (struct tu_pipeline_builder) {
109 .device = dev,
110 .cache = cache,
111 .create_info = create_info,
112 .alloc = alloc,
113 };
114 }
115
116 VkResult
117 tu_CreateGraphicsPipelines(VkDevice device,
118 VkPipelineCache pipelineCache,
119 uint32_t count,
120 const VkGraphicsPipelineCreateInfo *pCreateInfos,
121 const VkAllocationCallbacks *pAllocator,
122 VkPipeline *pPipelines)
123 {
124 TU_FROM_HANDLE(tu_device, dev, device);
125 TU_FROM_HANDLE(tu_pipeline_cache, cache, pipelineCache);
126
127 for (uint32_t i = 0; i < count; i++) {
128 struct tu_pipeline_builder builder;
129 tu_pipeline_builder_init_graphics(&builder, dev, cache,
130 &pCreateInfos[i], pAllocator);
131
132 struct tu_pipeline *pipeline;
133 VkResult result = tu_pipeline_builder_build(&builder, &pipeline);
134
135 if (result != VK_SUCCESS) {
136 for (uint32_t j = 0; j < i; j++) {
137 tu_DestroyPipeline(device, pPipelines[j], pAllocator);
138 pPipelines[j] = VK_NULL_HANDLE;
139 }
140
141 return result;
142 }
143
144 pPipelines[i] = tu_pipeline_to_handle(pipeline);
145 }
146
147 return VK_SUCCESS;
148 }
149
150 static VkResult
151 tu_compute_pipeline_create(VkDevice _device,
152 VkPipelineCache _cache,
153 const VkComputePipelineCreateInfo *pCreateInfo,
154 const VkAllocationCallbacks *pAllocator,
155 VkPipeline *pPipeline)
156 {
157 return VK_SUCCESS;
158 }
159
160 VkResult
161 tu_CreateComputePipelines(VkDevice _device,
162 VkPipelineCache pipelineCache,
163 uint32_t count,
164 const VkComputePipelineCreateInfo *pCreateInfos,
165 const VkAllocationCallbacks *pAllocator,
166 VkPipeline *pPipelines)
167 {
168 VkResult result = VK_SUCCESS;
169
170 unsigned i = 0;
171 for (; i < count; i++) {
172 VkResult r;
173 r = tu_compute_pipeline_create(_device, pipelineCache, &pCreateInfos[i],
174 pAllocator, &pPipelines[i]);
175 if (r != VK_SUCCESS) {
176 result = r;
177 pPipelines[i] = VK_NULL_HANDLE;
178 }
179 }
180
181 return result;
182 }
183
184 void
185 tu_DestroyPipeline(VkDevice _device,
186 VkPipeline _pipeline,
187 const VkAllocationCallbacks *pAllocator)
188 {
189 TU_FROM_HANDLE(tu_device, dev, _device);
190 TU_FROM_HANDLE(tu_pipeline, pipeline, _pipeline);
191
192 if (!_pipeline)
193 return;
194
195 tu_pipeline_finish(pipeline, dev, pAllocator);
196 vk_free2(&dev->alloc, pAllocator, pipeline);
197 }