Merge remote-tracking branch 'mesa-public/master' into vulkan
[mesa.git] / src / vulkan / gen8_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 "gen8_pack.h"
33
34 void
35 gen8_fill_buffer_surface_state(void *state, const struct anv_format *format,
36 uint32_t offset, uint32_t range, uint32_t stride)
37 {
38 uint32_t num_elements = range / stride;
39
40 struct GEN8_RENDER_SURFACE_STATE surface_state = {
41 .SurfaceType = SURFTYPE_BUFFER,
42 .SurfaceArray = false,
43 .SurfaceFormat = format->surface_format,
44 .SurfaceVerticalAlignment = VALIGN4,
45 .SurfaceHorizontalAlignment = HALIGN4,
46 .TileMode = LINEAR,
47 .SamplerL2BypassModeDisable = true,
48 .RenderCacheReadWriteMode = WriteOnlyCache,
49 .MemoryObjectControlState = GEN8_MOCS,
50 .Height = ((num_elements - 1) >> 7) & 0x3fff,
51 .Width = (num_elements - 1) & 0x7f,
52 .Depth = ((num_elements - 1) >> 21) & 0x3f,
53 .SurfacePitch = stride - 1,
54 .NumberofMultisamples = MULTISAMPLECOUNT_1,
55 .ShaderChannelSelectRed = SCS_RED,
56 .ShaderChannelSelectGreen = SCS_GREEN,
57 .ShaderChannelSelectBlue = SCS_BLUE,
58 .ShaderChannelSelectAlpha = SCS_ALPHA,
59 /* FIXME: We assume that the image must be bound at this time. */
60 .SurfaceBaseAddress = { NULL, offset },
61 };
62
63 GEN8_RENDER_SURFACE_STATE_pack(NULL, state, &surface_state);
64 }
65
66 static const uint8_t anv_halign[] = {
67 [4] = HALIGN4,
68 [8] = HALIGN8,
69 [16] = HALIGN16,
70 };
71
72 static const uint8_t anv_valign[] = {
73 [4] = VALIGN4,
74 [8] = VALIGN8,
75 [16] = VALIGN16,
76 };
77
78 static struct anv_state
79 gen8_alloc_surface_state(struct anv_device *device,
80 struct anv_cmd_buffer *cmd_buffer)
81 {
82 if (cmd_buffer) {
83 return anv_cmd_buffer_alloc_surface_state(cmd_buffer);
84 } else {
85 return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
86 }
87 }
88
89 void
90 gen8_image_view_init(struct anv_image_view *iview,
91 struct anv_device *device,
92 const VkImageViewCreateInfo* pCreateInfo,
93 struct anv_cmd_buffer *cmd_buffer)
94 {
95 ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
96
97 const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
98
99 struct anv_surface *surface =
100 anv_image_get_surface_for_aspect_mask(image, range->aspectMask);
101
102 uint32_t depth = 1; /* RENDER_SURFACE_STATE::Depth */
103 uint32_t rt_view_extent = 1; /* RENDER_SURFACE_STATE::RenderTargetViewExtent */
104
105 const struct anv_format *format_info =
106 anv_format_for_vk_format(pCreateInfo->format);
107
108 iview->image = image;
109 iview->bo = image->bo;
110 iview->offset = image->offset + surface->offset;
111 iview->format = format_info;
112
113 iview->extent = (VkExtent3D) {
114 .width = anv_minify(image->extent.width, range->baseMipLevel),
115 .height = anv_minify(image->extent.height, range->baseMipLevel),
116 .depth = anv_minify(image->extent.depth, range->baseMipLevel),
117 };
118
119 switch (image->type) {
120 case VK_IMAGE_TYPE_1D:
121 case VK_IMAGE_TYPE_2D:
122 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
123 *
124 * For SURFTYPE_1D, 2D, and CUBE: The range of this field is reduced
125 * by one for each increase from zero of Minimum Array Element. For
126 * example, if Minimum Array Element is set to 1024 on a 2D surface,
127 * the range of this field is reduced to [0,1023].
128 */
129 depth = range->arraySize;
130
131 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
132 *
133 * For Render Target and Typed Dataport 1D and 2D Surfaces:
134 * This field must be set to the same value as the Depth field.
135 */
136 rt_view_extent = depth;
137 break;
138 case VK_IMAGE_TYPE_3D:
139 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth:
140 *
141 * If the volume texture is MIP-mapped, this field specifies the
142 * depth of the base MIP level.
143 */
144 depth = image->extent.depth;
145
146 /* From the Broadwell PRM >> RENDER_SURFACE_STATE::RenderTargetViewExtent:
147 *
148 * For Render Target and Typed Dataport 3D Surfaces: This field
149 * indicates the extent of the accessible 'R' coordinates minus 1 on
150 * the LOD currently being rendered to.
151 */
152 rt_view_extent = iview->extent.depth;
153 break;
154 default:
155 unreachable(!"bad VkImageType");
156 }
157
158 static const uint32_t vk_to_gen_swizzle[] = {
159 [VK_CHANNEL_SWIZZLE_ZERO] = SCS_ZERO,
160 [VK_CHANNEL_SWIZZLE_ONE] = SCS_ONE,
161 [VK_CHANNEL_SWIZZLE_R] = SCS_RED,
162 [VK_CHANNEL_SWIZZLE_G] = SCS_GREEN,
163 [VK_CHANNEL_SWIZZLE_B] = SCS_BLUE,
164 [VK_CHANNEL_SWIZZLE_A] = SCS_ALPHA
165 };
166
167 static const uint8_t isl_to_gen_tiling[] = {
168 [ISL_TILING_LINEAR] = LINEAR,
169 [ISL_TILING_X] = XMAJOR,
170 [ISL_TILING_Y] = YMAJOR,
171 [ISL_TILING_Yf] = YMAJOR,
172 [ISL_TILING_Ys] = YMAJOR,
173 [ISL_TILING_W] = WMAJOR,
174 };
175
176 struct GEN8_RENDER_SURFACE_STATE surface_state = {
177 .SurfaceType = image->surface_type,
178 .SurfaceArray = image->array_size > 1,
179 .SurfaceFormat = format_info->surface_format,
180 .SurfaceVerticalAlignment = anv_valign[surface->v_align],
181 .SurfaceHorizontalAlignment = anv_halign[surface->h_align],
182 .TileMode = isl_to_gen_tiling[surface->tiling],
183 .VerticalLineStride = 0,
184 .VerticalLineStrideOffset = 0,
185 .SamplerL2BypassModeDisable = true,
186 .RenderCacheReadWriteMode = WriteOnlyCache,
187 .MemoryObjectControlState = GEN8_MOCS,
188
189 /* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
190 * RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
191 * both Base Mip Level fields nonzero".
192 */
193 .BaseMipLevel = 0.0,
194
195 .SurfaceQPitch = surface->qpitch >> 2,
196 .Height = image->extent.height - 1,
197 .Width = image->extent.width - 1,
198 .Depth = depth - 1,
199 .SurfacePitch = surface->stride - 1,
200 .RenderTargetViewExtent = rt_view_extent - 1,
201 .MinimumArrayElement = range->baseArrayLayer,
202 .NumberofMultisamples = MULTISAMPLECOUNT_1,
203 .XOffset = 0,
204 .YOffset = 0,
205
206 .MIPCountLOD = 0, /* TEMPLATE */
207 .SurfaceMinLOD = 0, /* TEMPLATE */
208
209 .AuxiliarySurfaceMode = AUX_NONE,
210 .RedClearColor = 0,
211 .GreenClearColor = 0,
212 .BlueClearColor = 0,
213 .AlphaClearColor = 0,
214 .ShaderChannelSelectRed = vk_to_gen_swizzle[pCreateInfo->channels.r],
215 .ShaderChannelSelectGreen = vk_to_gen_swizzle[pCreateInfo->channels.g],
216 .ShaderChannelSelectBlue = vk_to_gen_swizzle[pCreateInfo->channels.b],
217 .ShaderChannelSelectAlpha = vk_to_gen_swizzle[pCreateInfo->channels.a],
218 .ResourceMinLOD = 0.0,
219 .SurfaceBaseAddress = { NULL, iview->offset },
220 };
221
222 if (image->needs_nonrt_surface_state) {
223 iview->nonrt_surface_state =
224 gen8_alloc_surface_state(device, cmd_buffer);
225
226 /* For non render target surfaces, the hardware interprets field
227 * MIPCount/LOD as MIPCount. The range of levels accessible by the
228 * sampler engine is [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
229 */
230 surface_state.SurfaceMinLOD = range->baseMipLevel;
231 surface_state.MIPCountLOD = range->mipLevels - 1;
232
233 GEN8_RENDER_SURFACE_STATE_pack(NULL, iview->nonrt_surface_state.map,
234 &surface_state);
235 }
236
237 if (image->needs_color_rt_surface_state) {
238 iview->color_rt_surface_state =
239 gen8_alloc_surface_state(device, cmd_buffer);
240
241 /* For render target surfaces, the hardware interprets field
242 * MIPCount/LOD as LOD. The Broadwell PRM says:
243 *
244 * MIPCountLOD defines the LOD that will be rendered into.
245 * SurfaceMinLOD is ignored.
246 */
247 surface_state.MIPCountLOD = range->baseMipLevel;
248 surface_state.SurfaceMinLOD = 0;
249
250 GEN8_RENDER_SURFACE_STATE_pack(NULL, iview->color_rt_surface_state.map,
251 &surface_state);
252 }
253 }
254
255 VkResult gen8_CreateSampler(
256 VkDevice _device,
257 const VkSamplerCreateInfo* pCreateInfo,
258 VkSampler* pSampler)
259 {
260 ANV_FROM_HANDLE(anv_device, device, _device);
261 struct anv_sampler *sampler;
262 uint32_t mag_filter, min_filter, max_anisotropy;
263
264 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
265
266 sampler = anv_device_alloc(device, sizeof(*sampler), 8,
267 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
268 if (!sampler)
269 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
270
271 static const uint32_t vk_to_gen_tex_filter[] = {
272 [VK_TEX_FILTER_NEAREST] = MAPFILTER_NEAREST,
273 [VK_TEX_FILTER_LINEAR] = MAPFILTER_LINEAR
274 };
275
276 static const uint32_t vk_to_gen_mipmap_mode[] = {
277 [VK_TEX_MIPMAP_MODE_BASE] = MIPFILTER_NONE,
278 [VK_TEX_MIPMAP_MODE_NEAREST] = MIPFILTER_NEAREST,
279 [VK_TEX_MIPMAP_MODE_LINEAR] = MIPFILTER_LINEAR
280 };
281
282 static const uint32_t vk_to_gen_tex_address[] = {
283 [VK_TEX_ADDRESS_MODE_WRAP] = TCM_WRAP,
284 [VK_TEX_ADDRESS_MODE_MIRROR] = TCM_MIRROR,
285 [VK_TEX_ADDRESS_MODE_CLAMP] = TCM_CLAMP,
286 [VK_TEX_ADDRESS_MODE_MIRROR_ONCE] = TCM_MIRROR_ONCE,
287 [VK_TEX_ADDRESS_MODE_CLAMP_BORDER] = TCM_CLAMP_BORDER,
288 };
289
290 static const uint32_t vk_to_gen_compare_op[] = {
291 [VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
292 [VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
293 [VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
294 [VK_COMPARE_OP_LESS_EQUAL] = PREFILTEROPLEQUAL,
295 [VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
296 [VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
297 [VK_COMPARE_OP_GREATER_EQUAL] = PREFILTEROPGEQUAL,
298 [VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
299 };
300
301 if (pCreateInfo->maxAnisotropy > 1) {
302 mag_filter = MAPFILTER_ANISOTROPIC;
303 min_filter = MAPFILTER_ANISOTROPIC;
304 max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
305 } else {
306 mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
307 min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
308 max_anisotropy = RATIO21;
309 }
310
311 struct GEN8_SAMPLER_STATE sampler_state = {
312 .SamplerDisable = false,
313 .TextureBorderColorMode = DX10OGL,
314 .LODPreClampMode = 0,
315 .BaseMipLevel = 0.0,
316 .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipMode],
317 .MagModeFilter = mag_filter,
318 .MinModeFilter = min_filter,
319 .TextureLODBias = anv_clamp_f(pCreateInfo->mipLodBias, -16, 15.996),
320 .AnisotropicAlgorithm = EWAApproximation,
321 .MinLOD = anv_clamp_f(pCreateInfo->minLod, 0, 14),
322 .MaxLOD = anv_clamp_f(pCreateInfo->maxLod, 0, 14),
323 .ChromaKeyEnable = 0,
324 .ChromaKeyIndex = 0,
325 .ChromaKeyMode = 0,
326 .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
327 .CubeSurfaceControlMode = 0,
328
329 .IndirectStatePointer =
330 device->border_colors.offset +
331 pCreateInfo->borderColor * sizeof(float) * 4,
332
333 .LODClampMagnificationMode = MIPNONE,
334 .MaximumAnisotropy = max_anisotropy,
335 .RAddressMinFilterRoundingEnable = 0,
336 .RAddressMagFilterRoundingEnable = 0,
337 .VAddressMinFilterRoundingEnable = 0,
338 .VAddressMagFilterRoundingEnable = 0,
339 .UAddressMinFilterRoundingEnable = 0,
340 .UAddressMagFilterRoundingEnable = 0,
341 .TrilinearFilterQuality = 0,
342 .NonnormalizedCoordinateEnable = pCreateInfo->unnormalizedCoordinates,
343 .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeU],
344 .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeV],
345 .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeW],
346 };
347
348 GEN8_SAMPLER_STATE_pack(NULL, sampler->state, &sampler_state);
349
350 *pSampler = anv_sampler_to_handle(sampler);
351
352 return VK_SUCCESS;
353 }