genX/state: Pull some generic helpers into a shared header
[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 #include "gen7_pack.h"
33 #include "gen75_pack.h"
34
35 #include "genX_state_util.h"
36
37 GENX_FUNC(GEN7, GEN75) void
38 genX(fill_buffer_surface_state)(void *state, enum isl_format format,
39 uint32_t offset, uint32_t range,
40 uint32_t stride)
41 {
42 uint32_t num_elements = range / stride;
43
44 struct GENX(RENDER_SURFACE_STATE) surface_state = {
45 .SurfaceType = SURFTYPE_BUFFER,
46 .SurfaceFormat = format,
47 .SurfaceVerticalAlignment = VALIGN_4,
48 .SurfaceHorizontalAlignment = HALIGN_4,
49 .TiledSurface = false,
50 .RenderCacheReadWriteMode = false,
51 .SurfaceObjectControlState = GENX(MOCS),
52 .Height = (num_elements >> 7) & 0x3fff,
53 .Width = num_elements & 0x7f,
54 .Depth = (num_elements >> 21) & 0x3f,
55 .SurfacePitch = stride - 1,
56 # if (ANV_IS_HASWELL)
57 .ShaderChannelSelectR = SCS_RED,
58 .ShaderChannelSelectG = SCS_GREEN,
59 .ShaderChannelSelectB = SCS_BLUE,
60 .ShaderChannelSelectA = SCS_ALPHA,
61 # endif
62 .SurfaceBaseAddress = { NULL, offset },
63 };
64
65 GENX(RENDER_SURFACE_STATE_pack)(NULL, state, &surface_state);
66 }
67
68 static const uint32_t vk_to_gen_tex_filter[] = {
69 [VK_FILTER_NEAREST] = MAPFILTER_NEAREST,
70 [VK_FILTER_LINEAR] = MAPFILTER_LINEAR
71 };
72
73 static const uint32_t vk_to_gen_mipmap_mode[] = {
74 [VK_SAMPLER_MIPMAP_MODE_BASE] = MIPFILTER_NONE,
75 [VK_SAMPLER_MIPMAP_MODE_NEAREST] = MIPFILTER_NEAREST,
76 [VK_SAMPLER_MIPMAP_MODE_LINEAR] = MIPFILTER_LINEAR
77 };
78
79 static const uint32_t vk_to_gen_tex_address[] = {
80 [VK_SAMPLER_ADDRESS_MODE_REPEAT] = TCM_WRAP,
81 [VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT] = TCM_MIRROR,
82 [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE] = TCM_CLAMP,
83 [VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE] = TCM_MIRROR_ONCE,
84 [VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER] = TCM_CLAMP_BORDER,
85 };
86
87 static const uint32_t vk_to_gen_compare_op[] = {
88 [VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
89 [VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
90 [VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
91 [VK_COMPARE_OP_LESS_OR_EQUAL] = PREFILTEROPLEQUAL,
92 [VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
93 [VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
94 [VK_COMPARE_OP_GREATER_OR_EQUAL] = PREFILTEROPGEQUAL,
95 [VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
96 };
97
98 static struct anv_state
99 alloc_surface_state(struct anv_device *device,
100 struct anv_cmd_buffer *cmd_buffer)
101 {
102 if (cmd_buffer) {
103 return anv_cmd_buffer_alloc_surface_state(cmd_buffer);
104 } else {
105 return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
106 }
107 }
108
109 VkResult genX(CreateSampler)(
110 VkDevice _device,
111 const VkSamplerCreateInfo* pCreateInfo,
112 const VkAllocationCallbacks* pAllocator,
113 VkSampler* pSampler)
114 {
115 ANV_FROM_HANDLE(anv_device, device, _device);
116 struct anv_sampler *sampler;
117 uint32_t mag_filter, min_filter, max_anisotropy;
118
119 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
120
121 sampler = anv_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
122 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
123 if (!sampler)
124 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
125
126 if (pCreateInfo->maxAnisotropy > 1) {
127 mag_filter = MAPFILTER_ANISOTROPIC;
128 min_filter = MAPFILTER_ANISOTROPIC;
129 max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
130 } else {
131 mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
132 min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
133 max_anisotropy = RATIO21;
134 }
135
136 struct GEN7_SAMPLER_STATE sampler_state = {
137 .SamplerDisable = false,
138 .TextureBorderColorMode = DX10OGL,
139 .BaseMipLevel = 0.0,
140 .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipmapMode],
141 .MagModeFilter = mag_filter,
142 .MinModeFilter = min_filter,
143 .TextureLODBias = pCreateInfo->mipLodBias * 256,
144 .AnisotropicAlgorithm = EWAApproximation,
145 .MinLOD = pCreateInfo->minLod,
146 .MaxLOD = pCreateInfo->maxLod,
147 .ChromaKeyEnable = 0,
148 .ChromaKeyIndex = 0,
149 .ChromaKeyMode = 0,
150 .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
151 .CubeSurfaceControlMode = 0,
152
153 .BorderColorPointer =
154 device->border_colors.offset +
155 pCreateInfo->borderColor * sizeof(float) * 4,
156
157 .MaximumAnisotropy = max_anisotropy,
158 .RAddressMinFilterRoundingEnable = 0,
159 .RAddressMagFilterRoundingEnable = 0,
160 .VAddressMinFilterRoundingEnable = 0,
161 .VAddressMagFilterRoundingEnable = 0,
162 .UAddressMinFilterRoundingEnable = 0,
163 .UAddressMagFilterRoundingEnable = 0,
164 .TrilinearFilterQuality = 0,
165 .NonnormalizedCoordinateEnable = pCreateInfo->unnormalizedCoordinates,
166 .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeU],
167 .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeV],
168 .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeW],
169 };
170
171 GEN7_SAMPLER_STATE_pack(NULL, sampler->state, &sampler_state);
172
173 *pSampler = anv_sampler_to_handle(sampler);
174
175 return VK_SUCCESS;
176 }
177
178 static const uint8_t anv_halign[] = {
179 [4] = HALIGN_4,
180 [8] = HALIGN_8,
181 };
182
183 static const uint8_t anv_valign[] = {
184 [2] = VALIGN_2,
185 [4] = VALIGN_4,
186 };
187
188 GENX_FUNC(GEN7, GEN75) void
189 genX(image_view_init)(struct anv_image_view *iview,
190 struct anv_device *device,
191 const VkImageViewCreateInfo* pCreateInfo,
192 struct anv_cmd_buffer *cmd_buffer)
193 {
194 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
195
196 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
197
198 struct anv_surface *surface =
199 anv_image_get_surface_for_aspect_mask(image, range->aspectMask);
200
201 const struct anv_format *format =
202 anv_format_for_vk_format(pCreateInfo->format);
203
204 if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_2D)
205 anv_finishme("non-2D image views");
206
207 iview->image = image;
208 iview->bo = image->bo;
209 iview->offset = image->offset + surface->offset;
210 iview->format = anv_format_for_vk_format(pCreateInfo->format);
211
212 iview->extent = (VkExtent3D) {
213 .width = anv_minify(image->extent.width, range->baseMipLevel),
214 .height = anv_minify(image->extent.height, range->baseMipLevel),
215 .depth = anv_minify(image->extent.depth, range->baseMipLevel),
216 };
217
218 uint32_t depth = 1;
219 if (range->layerCount > 1) {
220 depth = range->layerCount;
221 } else if (image->extent.depth > 1) {
222 depth = image->extent.depth;
223 }
224
225 const struct isl_extent3d image_align_sa =
226 isl_surf_get_image_alignment_sa(&surface->isl);
227
228 struct GENX(RENDER_SURFACE_STATE) surface_state = {
229 .SurfaceType = anv_surftype(image, pCreateInfo->viewType, false),
230 .SurfaceArray = image->array_size > 1,
231 .SurfaceFormat = format->surface_format,
232 .SurfaceVerticalAlignment = anv_valign[image_align_sa.height],
233 .SurfaceHorizontalAlignment = anv_halign[image_align_sa.width],
234
235 /* From bspec (DevSNB, DevIVB): "Set Tile Walk to TILEWALK_XMAJOR if
236 * Tiled Surface is False."
237 */
238 .TiledSurface = surface->isl.tiling != ISL_TILING_LINEAR,
239 .TileWalk = surface->isl.tiling == ISL_TILING_Y0 ?
240 TILEWALK_YMAJOR : TILEWALK_XMAJOR,
241
242 .VerticalLineStride = 0,
243 .VerticalLineStrideOffset = 0,
244
245 .RenderCacheReadWriteMode = 0, /* TEMPLATE */
246
247 .Height = image->extent.height - 1,
248 .Width = image->extent.width - 1,
249 .Depth = depth - 1,
250 .SurfacePitch = surface->isl.row_pitch - 1,
251 .MinimumArrayElement = range->baseArrayLayer,
252 .NumberofMultisamples = MULTISAMPLECOUNT_1,
253 .XOffset = 0,
254 .YOffset = 0,
255
256 .SurfaceObjectControlState = GENX(MOCS),
257
258 .MIPCountLOD = 0, /* TEMPLATE */
259 .SurfaceMinLOD = 0, /* TEMPLATE */
260
261 .MCSEnable = false,
262 # if (ANV_IS_HASWELL)
263 .ShaderChannelSelectR = vk_to_gen_swizzle(pCreateInfo->components.r,
264 VK_COMPONENT_SWIZZLE_R),
265 .ShaderChannelSelectG = vk_to_gen_swizzle(pCreateInfo->components.g,
266 VK_COMPONENT_SWIZZLE_G),
267 .ShaderChannelSelectB = vk_to_gen_swizzle(pCreateInfo->components.b,
268 VK_COMPONENT_SWIZZLE_B),
269 .ShaderChannelSelectA = vk_to_gen_swizzle(pCreateInfo->components.a,
270 VK_COMPONENT_SWIZZLE_A),
271 # else /* XXX: Seriously? */
272 .RedClearColor = 0,
273 .GreenClearColor = 0,
274 .BlueClearColor = 0,
275 .AlphaClearColor = 0,
276 # endif
277 .ResourceMinLOD = 0.0,
278 .SurfaceBaseAddress = { NULL, iview->offset },
279 };
280
281 if (image->needs_nonrt_surface_state) {
282 iview->nonrt_surface_state = alloc_surface_state(device, cmd_buffer);
283
284 surface_state.RenderCacheReadWriteMode = false;
285
286 /* For non render target surfaces, the hardware interprets field
287 * MIPCount/LOD as MIPCount. The range of levels accessible by the
288 * sampler engine is [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
289 */
290 surface_state.SurfaceMinLOD = range->baseMipLevel;
291 surface_state.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
292
293 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->nonrt_surface_state.map,
294 &surface_state);
295
296 if (!device->info.has_llc)
297 anv_state_clflush(iview->nonrt_surface_state);
298 }
299
300 if (image->needs_color_rt_surface_state) {
301 iview->color_rt_surface_state = alloc_surface_state(device, cmd_buffer);
302
303 surface_state.RenderCacheReadWriteMode = 0; /* Write only */
304
305 /* For render target surfaces, the hardware interprets field MIPCount/LOD as
306 * LOD. The Broadwell PRM says:
307 *
308 * MIPCountLOD defines the LOD that will be rendered into.
309 * SurfaceMinLOD is ignored.
310 */
311 surface_state.MIPCountLOD = range->baseMipLevel;
312 surface_state.SurfaceMinLOD = 0;
313
314 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->color_rt_surface_state.map,
315 &surface_state);
316 if (!device->info.has_llc)
317 anv_state_clflush(iview->color_rt_surface_state);
318 }
319
320 if (image->needs_storage_surface_state) {
321 iview->storage_surface_state = alloc_surface_state(device, cmd_buffer);
322
323 surface_state.SurfaceType =
324 anv_surftype(image, pCreateInfo->viewType, true),
325
326 surface_state.SurfaceFormat =
327 isl_lower_storage_image_format(&device->isl_dev,
328 format->surface_format);
329
330 surface_state.SurfaceMinLOD = range->baseMipLevel;
331 surface_state.MIPCountLOD = MAX2(range->levelCount, 1) - 1;
332
333 GENX(RENDER_SURFACE_STATE_pack)(NULL, iview->storage_surface_state.map,
334 &surface_state);
335 }
336 }