vk/0.170.2: Switch to the new dynamic state model
[mesa.git] / src / vulkan / gen7_state.c
1 /*
2 * Copyright © 2015 Intel Corporation
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 DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include "anv_private.h"
31
32 void
33 gen7_fill_buffer_surface_state(void *state, const struct anv_format *format,
34 uint32_t offset, uint32_t range)
35 {
36 /* This assumes RGBA float format. */
37
38 uint32_t stride = 16; /* Depends on whether accessing shader is simd8 or
39 * vec4. Will need one of each for buffers that are
40 * used in both vec4 and simd8. */
41
42 uint32_t num_elements = range / stride;
43
44 struct GEN7_RENDER_SURFACE_STATE surface_state = {
45 .SurfaceType = SURFTYPE_BUFFER,
46 .SurfaceFormat = format->surface_format,
47 .SurfaceVerticalAlignment = VALIGN_4,
48 .SurfaceHorizontalAlignment = HALIGN_4,
49 .TiledSurface = false,
50 .RenderCacheReadWriteMode = false,
51 .SurfaceObjectControlState = GEN7_MOCS,
52 .Height = (num_elements >> 7) & 0x3fff,
53 .Width = num_elements & 0x7f,
54 .Depth = (num_elements >> 21) & 0x3f,
55 .SurfacePitch = stride - 1,
56 .SurfaceBaseAddress = { NULL, offset },
57 };
58
59 GEN7_RENDER_SURFACE_STATE_pack(NULL, state, &surface_state);
60 }
61
62 VkResult gen7_CreateBufferView(
63 VkDevice _device,
64 const VkBufferViewCreateInfo* pCreateInfo,
65 VkBufferView* pView)
66 {
67 ANV_FROM_HANDLE(anv_device, device, _device);
68 struct anv_buffer_view *bview;
69 VkResult result;
70
71 result = anv_buffer_view_create(device, pCreateInfo, &bview);
72 if (result != VK_SUCCESS)
73 return result;
74
75 const struct anv_format *format =
76 anv_format_for_vk_format(pCreateInfo->format);
77
78 gen7_fill_buffer_surface_state(bview->surface_state.map, format,
79 bview->offset, pCreateInfo->range);
80
81 *pView = anv_buffer_view_to_handle(bview);
82
83 return VK_SUCCESS;
84 }
85
86 static const uint32_t vk_to_gen_tex_filter[] = {
87 [VK_TEX_FILTER_NEAREST] = MAPFILTER_NEAREST,
88 [VK_TEX_FILTER_LINEAR] = MAPFILTER_LINEAR
89 };
90
91 static const uint32_t vk_to_gen_mipmap_mode[] = {
92 [VK_TEX_MIPMAP_MODE_BASE] = MIPFILTER_NONE,
93 [VK_TEX_MIPMAP_MODE_NEAREST] = MIPFILTER_NEAREST,
94 [VK_TEX_MIPMAP_MODE_LINEAR] = MIPFILTER_LINEAR
95 };
96
97 static const uint32_t vk_to_gen_tex_address[] = {
98 [VK_TEX_ADDRESS_MODE_WRAP] = TCM_WRAP,
99 [VK_TEX_ADDRESS_MODE_MIRROR] = TCM_MIRROR,
100 [VK_TEX_ADDRESS_MODE_CLAMP] = TCM_CLAMP,
101 [VK_TEX_ADDRESS_MODE_MIRROR_ONCE] = TCM_MIRROR_ONCE,
102 [VK_TEX_ADDRESS_MODE_CLAMP_BORDER] = TCM_CLAMP_BORDER,
103 };
104
105 static const uint32_t vk_to_gen_compare_op[] = {
106 [VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
107 [VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
108 [VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
109 [VK_COMPARE_OP_LESS_EQUAL] = PREFILTEROPLEQUAL,
110 [VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
111 [VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
112 [VK_COMPARE_OP_GREATER_EQUAL] = PREFILTEROPGEQUAL,
113 [VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
114 };
115
116 static struct anv_state
117 gen7_alloc_surface_state(struct anv_device *device,
118 struct anv_cmd_buffer *cmd_buffer)
119 {
120 if (cmd_buffer) {
121 return anv_state_stream_alloc(&cmd_buffer->surface_state_stream,
122 64, 64);
123 } else {
124 return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
125 }
126 }
127
128 VkResult gen7_CreateSampler(
129 VkDevice _device,
130 const VkSamplerCreateInfo* pCreateInfo,
131 VkSampler* pSampler)
132 {
133 ANV_FROM_HANDLE(anv_device, device, _device);
134 struct anv_sampler *sampler;
135 uint32_t mag_filter, min_filter, max_anisotropy;
136
137 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
138
139 sampler = anv_device_alloc(device, sizeof(*sampler), 8,
140 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
141 if (!sampler)
142 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
143
144 if (pCreateInfo->maxAnisotropy > 1) {
145 mag_filter = MAPFILTER_ANISOTROPIC;
146 min_filter = MAPFILTER_ANISOTROPIC;
147 max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
148 } else {
149 mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
150 min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
151 max_anisotropy = RATIO21;
152 }
153
154 struct GEN7_SAMPLER_STATE sampler_state = {
155 .SamplerDisable = false,
156 .TextureBorderColorMode = DX10OGL,
157 .BaseMipLevel = 0.0,
158 .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipMode],
159 .MagModeFilter = mag_filter,
160 .MinModeFilter = min_filter,
161 .TextureLODBias = pCreateInfo->mipLodBias * 256,
162 .AnisotropicAlgorithm = EWAApproximation,
163 .MinLOD = pCreateInfo->minLod,
164 .MaxLOD = pCreateInfo->maxLod,
165 .ChromaKeyEnable = 0,
166 .ChromaKeyIndex = 0,
167 .ChromaKeyMode = 0,
168 .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
169 .CubeSurfaceControlMode = 0,
170
171 .BorderColorPointer =
172 device->border_colors.offset +
173 pCreateInfo->borderColor * sizeof(float) * 4,
174
175 .MaximumAnisotropy = max_anisotropy,
176 .RAddressMinFilterRoundingEnable = 0,
177 .RAddressMagFilterRoundingEnable = 0,
178 .VAddressMinFilterRoundingEnable = 0,
179 .VAddressMagFilterRoundingEnable = 0,
180 .UAddressMinFilterRoundingEnable = 0,
181 .UAddressMagFilterRoundingEnable = 0,
182 .TrilinearFilterQuality = 0,
183 .NonnormalizedCoordinateEnable = pCreateInfo->unnormalizedCoordinates,
184 .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeU],
185 .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeV],
186 .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeW],
187 };
188
189 GEN7_SAMPLER_STATE_pack(NULL, sampler->state, &sampler_state);
190
191 *pSampler = anv_sampler_to_handle(sampler);
192
193 return VK_SUCCESS;
194 }
195
196 static const uint8_t anv_halign[] = {
197 [4] = HALIGN_4,
198 [8] = HALIGN_8,
199 };
200
201 static const uint8_t anv_valign[] = {
202 [2] = VALIGN_2,
203 [4] = VALIGN_4,
204 };
205
206 void
207 gen7_image_view_init(struct anv_image_view *iview,
208 struct anv_device *device,
209 const VkImageViewCreateInfo* pCreateInfo,
210 struct anv_cmd_buffer *cmd_buffer)
211 {
212 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
213
214 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
215
216 struct anv_surface *surface =
217 anv_image_get_surface_for_aspect_mask(image, range->aspectMask);
218
219 const struct anv_format *format =
220 anv_format_for_vk_format(pCreateInfo->format);
221
222 if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_2D)
223 anv_finishme("non-2D image views");
224
225 iview->image = image;
226 iview->bo = image->bo;
227 iview->offset = image->offset + surface->offset;
228 iview->format = anv_format_for_vk_format(pCreateInfo->format);
229
230 iview->extent = (VkExtent3D) {
231 .width = anv_minify(image->extent.width, range->baseMipLevel),
232 .height = anv_minify(image->extent.height, range->baseMipLevel),
233 .depth = anv_minify(image->extent.depth, range->baseMipLevel),
234 };
235
236 uint32_t depth = 1;
237 if (range->arraySize > 1) {
238 depth = range->arraySize;
239 } else if (image->extent.depth > 1) {
240 depth = image->extent.depth;
241 }
242
243 struct GEN7_RENDER_SURFACE_STATE surface_state = {
244 .SurfaceType = image->surface_type,
245 .SurfaceArray = image->array_size > 1,
246 .SurfaceFormat = format->surface_format,
247 .SurfaceVerticalAlignment = anv_valign[surface->v_align],
248 .SurfaceHorizontalAlignment = anv_halign[surface->h_align],
249
250 /* From bspec (DevSNB, DevIVB): "Set Tile Walk to TILEWALK_XMAJOR if
251 * Tiled Surface is False."
252 */
253 .TiledSurface = surface->tile_mode > LINEAR,
254 .TileWalk = surface->tile_mode == YMAJOR ? TILEWALK_YMAJOR : TILEWALK_XMAJOR,
255
256 .VerticalLineStride = 0,
257 .VerticalLineStrideOffset = 0,
258
259 .RenderCacheReadWriteMode = 0, /* TEMPLATE */
260
261 .Height = image->extent.height - 1,
262 .Width = image->extent.width - 1,
263 .Depth = depth - 1,
264 .SurfacePitch = surface->stride - 1,
265 .MinimumArrayElement = range->baseArrayLayer,
266 .NumberofMultisamples = MULTISAMPLECOUNT_1,
267 .XOffset = 0,
268 .YOffset = 0,
269
270 .SurfaceObjectControlState = GEN7_MOCS,
271
272 .MIPCountLOD = 0, /* TEMPLATE */
273 .SurfaceMinLOD = 0, /* TEMPLATE */
274
275 .MCSEnable = false,
276 .RedClearColor = 0,
277 .GreenClearColor = 0,
278 .BlueClearColor = 0,
279 .AlphaClearColor = 0,
280 .ResourceMinLOD = 0.0,
281 .SurfaceBaseAddress = { NULL, iview->offset },
282 };
283
284 if (image->needs_nonrt_surface_state) {
285 iview->nonrt_surface_state =
286 gen7_alloc_surface_state(device, cmd_buffer);
287
288 surface_state.RenderCacheReadWriteMode = false;
289
290 /* For non render target surfaces, the hardware interprets field
291 * MIPCount/LOD as MIPCount. The range of levels accessible by the
292 * sampler engine is [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
293 */
294 surface_state.SurfaceMinLOD = range->baseMipLevel;
295 surface_state.MIPCountLOD = range->mipLevels - 1;
296
297 GEN7_RENDER_SURFACE_STATE_pack(NULL, iview->nonrt_surface_state.map,
298 &surface_state);
299 }
300
301 if (image->needs_color_rt_surface_state) {
302 iview->color_rt_surface_state =
303 gen7_alloc_surface_state(device, cmd_buffer);
304
305 surface_state.RenderCacheReadWriteMode = WriteOnlyCache;
306
307 /* For render target surfaces, the hardware interprets field MIPCount/LOD as
308 * LOD. The Broadwell PRM says:
309 *
310 * MIPCountLOD defines the LOD that will be rendered into.
311 * SurfaceMinLOD is ignored.
312 */
313 surface_state.MIPCountLOD = range->baseMipLevel;
314 surface_state.SurfaceMinLOD = 0;
315
316 GEN7_RENDER_SURFACE_STATE_pack(NULL, iview->color_rt_surface_state.map,
317 &surface_state);
318 }
319 }