turnip: Move stream functions to tu_cs.c
[mesa.git] / src / freedreno / vulkan / tu_cs.c
1 /*
2 * Copyright © 2019 Google LLC
3 *
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
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
13 * Software.
14 *
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 NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "tu_cs.h"
25
26 void
27 tu_cmd_stream_init(struct tu_cmd_stream *stream)
28 {
29 stream->start = stream->cur = stream->end = NULL;
30
31 stream->entry_count = stream->entry_capacity = 0;
32 stream->entries = NULL;
33
34 stream->bo_count = stream->bo_capacity = 0;
35 stream->bos = NULL;
36 }
37
38 void
39 tu_cmd_stream_finish(struct tu_device *dev, struct tu_cmd_stream *stream)
40 {
41 for (uint32_t i = 0; i < stream->bo_count; ++i) {
42 tu_bo_finish(dev, stream->bos[i]);
43 free(stream->bos[i]);
44 }
45
46 free(stream->entries);
47 free(stream->bos);
48 }
49
50 VkResult
51 tu_cmd_stream_begin(struct tu_device *dev,
52 struct tu_cmd_stream *stream,
53 uint32_t reserve_size)
54 {
55 assert(reserve_size);
56
57 if (stream->end - stream->cur < reserve_size) {
58 if (stream->bo_count == stream->bo_capacity) {
59 uint32_t new_capacity = MAX2(4, 2 * stream->bo_capacity);
60 struct tu_bo **new_bos =
61 realloc(stream->bos, new_capacity * sizeof(struct tu_bo *));
62 if (!new_bos)
63 abort();
64
65 stream->bo_capacity = new_capacity;
66 stream->bos = new_bos;
67 }
68
69 uint32_t new_size = MAX2(16384, reserve_size * sizeof(uint32_t));
70 if (stream->bo_count)
71 new_size =
72 MAX2(new_size, stream->bos[stream->bo_count - 1]->size * 2);
73
74 struct tu_bo *new_bo = malloc(sizeof(struct tu_bo));
75 if (!new_bo)
76 abort();
77
78 VkResult result = tu_bo_init_new(dev, new_bo, new_size);
79 if (result != VK_SUCCESS) {
80 free(new_bo);
81 return result;
82 }
83
84 result = tu_bo_map(dev, new_bo);
85 if (result != VK_SUCCESS) {
86 tu_bo_finish(dev, new_bo);
87 free(new_bo);
88 return result;
89 }
90
91 stream->bos[stream->bo_count] = new_bo;
92 ++stream->bo_count;
93
94 stream->start = stream->cur = (uint32_t *) new_bo->map;
95 stream->end = stream->start + new_bo->size / sizeof(uint32_t);
96 }
97 stream->start = stream->cur;
98
99 return VK_SUCCESS;
100 }
101
102 VkResult
103 tu_cmd_stream_end(struct tu_cmd_stream *stream)
104 {
105 if (stream->start == stream->cur)
106 return VK_SUCCESS;
107
108 if (stream->entry_capacity == stream->entry_count) {
109 uint32_t new_capacity = MAX2(stream->entry_capacity * 2, 4);
110 struct tu_cmd_stream_entry *new_entries = realloc(
111 stream->entries, new_capacity * sizeof(struct tu_cmd_stream_entry));
112 if (!new_entries)
113 abort(); /* TODO */
114
115 stream->entries = new_entries;
116 stream->entry_capacity = new_capacity;
117 }
118
119 assert(stream->bo_count);
120
121 struct tu_cmd_stream_entry entry;
122 entry.bo = stream->bos[stream->bo_count - 1];
123 entry.size = (stream->cur - stream->start) * sizeof(uint32_t);
124 entry.offset =
125 (stream->start - (uint32_t *) entry.bo->map) * sizeof(uint32_t);
126
127 stream->entries[stream->entry_count] = entry;
128 ++stream->entry_count;
129
130 return VK_SUCCESS;
131 }
132
133 void
134 tu_cmd_stream_reset(struct tu_device *dev, struct tu_cmd_stream *stream)
135 {
136 for (uint32_t i = 0; i + 1 < stream->bo_count; ++i) {
137 tu_bo_finish(dev, stream->bos[i]);
138 free(stream->bos[i]);
139 }
140
141 if (stream->bo_count) {
142 stream->bos[0] = stream->bos[stream->bo_count - 1];
143 stream->bo_count = 1;
144
145 stream->start = stream->cur = (uint32_t *) stream->bos[0]->map;
146 stream->end = stream->start + stream->bos[0]->size / sizeof(uint32_t);
147 }
148
149 stream->entry_count = 0;
150 }
151
152 VkResult
153 tu_cs_check_space(struct tu_device *dev,
154 struct tu_cmd_stream *stream,
155 size_t size)
156 {
157 if (stream->end - stream->cur >= size)
158 return VK_SUCCESS;
159
160 VkResult result = tu_cmd_stream_end(stream);
161 if (result != VK_SUCCESS)
162 return result;
163
164 return tu_cmd_stream_begin(dev, stream, size);
165 }