3f5771219f66354a0b071951d51dc9f449e823d5
[mesa.git] / src / gallium / drivers / swr / swr_context.cpp
1 /****************************************************************************
2 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
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 "swr_context.h"
25 #include "swr_memory.h"
26 #include "swr_screen.h"
27 #include "swr_resource.h"
28 #include "swr_scratch.h"
29 #include "swr_query.h"
30 #include "swr_fence.h"
31
32 #include "util/u_memory.h"
33 #include "util/u_inlines.h"
34 #include "util/u_format.h"
35 #include "util/u_atomic.h"
36
37 extern "C" {
38 #include "util/u_transfer.h"
39 #include "util/u_surface.h"
40 }
41
42 #include "api.h"
43 #include "backend.h"
44
45 static struct pipe_surface *
46 swr_create_surface(struct pipe_context *pipe,
47 struct pipe_resource *pt,
48 const struct pipe_surface *surf_tmpl)
49 {
50 struct pipe_surface *ps;
51
52 ps = CALLOC_STRUCT(pipe_surface);
53 if (ps) {
54 pipe_reference_init(&ps->reference, 1);
55 pipe_resource_reference(&ps->texture, pt);
56 ps->context = pipe;
57 ps->format = surf_tmpl->format;
58 if (pt->target != PIPE_BUFFER) {
59 assert(surf_tmpl->u.tex.level <= pt->last_level);
60 ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
61 ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
62 ps->u.tex.level = surf_tmpl->u.tex.level;
63 ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
64 ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
65 if (ps->u.tex.first_layer != ps->u.tex.last_layer) {
66 debug_printf("creating surface with multiple layers, rendering "
67 "to first layer only\n");
68 }
69 } else {
70 /* setting width as number of elements should get us correct
71 * renderbuffer width */
72 ps->width = surf_tmpl->u.buf.last_element
73 - surf_tmpl->u.buf.first_element + 1;
74 ps->height = pt->height0;
75 ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
76 ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
77 assert(ps->u.buf.first_element <= ps->u.buf.last_element);
78 assert(ps->u.buf.last_element < ps->width);
79 }
80 }
81 return ps;
82 }
83
84 static void
85 swr_surface_destroy(struct pipe_context *pipe, struct pipe_surface *surf)
86 {
87 assert(surf->texture);
88 struct pipe_resource *resource = surf->texture;
89
90 /* If the resource has been drawn to, store tiles. */
91 swr_store_dirty_resource(pipe, resource, SWR_TILE_RESOLVED);
92
93 pipe_resource_reference(&resource, NULL);
94 FREE(surf);
95 }
96
97
98 static void *
99 swr_transfer_map(struct pipe_context *pipe,
100 struct pipe_resource *resource,
101 unsigned level,
102 unsigned usage,
103 const struct pipe_box *box,
104 struct pipe_transfer **transfer)
105 {
106 struct swr_screen *screen = swr_screen(pipe->screen);
107 struct swr_resource *spr = swr_resource(resource);
108 struct pipe_transfer *pt;
109 enum pipe_format format = resource->format;
110
111 assert(resource);
112 assert(level <= resource->last_level);
113
114 /* If mapping an attached rendertarget, store tiles to surface and set
115 * postStoreTileState to SWR_TILE_INVALID so tiles get reloaded on next use
116 * and nothing needs to be done at unmap. */
117 swr_store_dirty_resource(pipe, resource, SWR_TILE_INVALID);
118
119 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
120 /* If resource is in use, finish fence before mapping.
121 * Unless requested not to block, then if not done return NULL map */
122 if (usage & PIPE_TRANSFER_DONTBLOCK) {
123 if (swr_is_fence_pending(screen->flush_fence))
124 return NULL;
125 } else {
126 if (spr->status) {
127 /* But, if there's no fence pending, submit one.
128 * XXX: Remove once draw timestamps are finished. */
129 if (!swr_is_fence_pending(screen->flush_fence))
130 swr_fence_submit(swr_context(pipe), screen->flush_fence);
131
132 swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0);
133 swr_resource_unused(resource);
134 }
135 }
136 }
137
138 pt = CALLOC_STRUCT(pipe_transfer);
139 if (!pt)
140 return NULL;
141 pipe_resource_reference(&pt->resource, resource);
142 pt->level = level;
143 pt->box = *box;
144 pt->stride = spr->row_stride[level];
145 pt->layer_stride = spr->img_stride[level];
146
147 /* if we're mapping the depth/stencil, copy in stencil */
148 if (spr->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT
149 && spr->has_stencil) {
150 for (unsigned i = 0; i < spr->alignedWidth * spr->alignedHeight; i++) {
151 spr->swr.pBaseAddress[4 * i + 3] = spr->secondary.pBaseAddress[i];
152 }
153 } else if (spr->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
154 && spr->has_stencil) {
155 for (unsigned i = 0; i < spr->alignedWidth * spr->alignedHeight; i++) {
156 spr->swr.pBaseAddress[8 * i + 4] = spr->secondary.pBaseAddress[i];
157 }
158 }
159
160 unsigned offset = box->z * pt->layer_stride +
161 util_format_get_nblocksy(format, box->y) * pt->stride +
162 util_format_get_stride(format, box->x);
163
164 *transfer = pt;
165
166 return spr->swr.pBaseAddress + offset + spr->mip_offsets[level];
167 }
168
169 static void
170 swr_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer)
171 {
172 assert(transfer->resource);
173
174 struct swr_resource *res = swr_resource(transfer->resource);
175 /* if we're mapping the depth/stencil, copy out stencil */
176 if (res->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT
177 && res->has_stencil) {
178 for (unsigned i = 0; i < res->alignedWidth * res->alignedHeight; i++) {
179 res->secondary.pBaseAddress[i] = res->swr.pBaseAddress[4 * i + 3];
180 }
181 } else if (res->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
182 && res->has_stencil) {
183 for (unsigned i = 0; i < res->alignedWidth * res->alignedHeight; i++) {
184 res->secondary.pBaseAddress[i] = res->swr.pBaseAddress[8 * i + 4];
185 }
186 }
187
188 pipe_resource_reference(&transfer->resource, NULL);
189 FREE(transfer);
190 }
191
192
193 static void
194 swr_resource_copy(struct pipe_context *pipe,
195 struct pipe_resource *dst,
196 unsigned dst_level,
197 unsigned dstx,
198 unsigned dsty,
199 unsigned dstz,
200 struct pipe_resource *src,
201 unsigned src_level,
202 const struct pipe_box *src_box)
203 {
204 struct swr_screen *screen = swr_screen(pipe->screen);
205
206 /* If either the src or dst is a renderTarget, store tiles before copy */
207 swr_store_dirty_resource(pipe, src, SWR_TILE_RESOLVED);
208 swr_store_dirty_resource(pipe, dst, SWR_TILE_RESOLVED);
209
210 swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0);
211 swr_resource_unused(src);
212 swr_resource_unused(dst);
213
214 if ((dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER)
215 || (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER)) {
216 util_resource_copy_region(
217 pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box);
218 return;
219 }
220
221 debug_printf("unhandled swr_resource_copy\n");
222 }
223
224
225 static void
226 swr_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info)
227 {
228 struct swr_context *ctx = swr_context(pipe);
229 struct pipe_blit_info info = *blit_info;
230
231 if (blit_info->render_condition_enable && !swr_check_render_cond(pipe))
232 return;
233
234 if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1
235 && !util_format_is_depth_or_stencil(info.src.resource->format)
236 && !util_format_is_pure_integer(info.src.resource->format)) {
237 debug_printf("swr: color resolve unimplemented\n");
238 return;
239 }
240
241 if (util_try_blit_via_copy_region(pipe, &info)) {
242 return; /* done */
243 }
244
245 if (info.mask & PIPE_MASK_S) {
246 debug_printf("swr: cannot blit stencil, skipping\n");
247 info.mask &= ~PIPE_MASK_S;
248 }
249
250 if (!util_blitter_is_blit_supported(ctx->blitter, &info)) {
251 debug_printf("swr: blit unsupported %s -> %s\n",
252 util_format_short_name(info.src.resource->format),
253 util_format_short_name(info.dst.resource->format));
254 return;
255 }
256
257 /* XXX turn off occlusion and streamout queries */
258
259 util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffer);
260 util_blitter_save_vertex_elements(ctx->blitter, (void *)ctx->velems);
261 util_blitter_save_vertex_shader(ctx->blitter, (void *)ctx->vs);
262 /*util_blitter_save_geometry_shader(ctx->blitter, (void*)ctx->gs);*/
263 util_blitter_save_so_targets(
264 ctx->blitter,
265 ctx->num_so_targets,
266 (struct pipe_stream_output_target **)ctx->so_targets);
267 util_blitter_save_rasterizer(ctx->blitter, (void *)ctx->rasterizer);
268 util_blitter_save_viewport(ctx->blitter, &ctx->viewport);
269 util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
270 util_blitter_save_fragment_shader(ctx->blitter, ctx->fs);
271 util_blitter_save_blend(ctx->blitter, (void *)ctx->blend);
272 util_blitter_save_depth_stencil_alpha(ctx->blitter,
273 (void *)ctx->depth_stencil);
274 util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
275 util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask);
276 util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer);
277 util_blitter_save_fragment_sampler_states(
278 ctx->blitter,
279 ctx->num_samplers[PIPE_SHADER_FRAGMENT],
280 (void **)ctx->samplers[PIPE_SHADER_FRAGMENT]);
281 util_blitter_save_fragment_sampler_views(
282 ctx->blitter,
283 ctx->num_sampler_views[PIPE_SHADER_FRAGMENT],
284 ctx->sampler_views[PIPE_SHADER_FRAGMENT]);
285 util_blitter_save_render_condition(ctx->blitter,
286 ctx->render_cond_query,
287 ctx->render_cond_cond,
288 ctx->render_cond_mode);
289
290 util_blitter_blit(ctx->blitter, &info);
291 }
292
293
294 static void
295 swr_destroy(struct pipe_context *pipe)
296 {
297 struct swr_context *ctx = swr_context(pipe);
298 struct swr_screen *screen = swr_screen(pipe->screen);
299
300 if (ctx->blitter)
301 util_blitter_destroy(ctx->blitter);
302
303 /* Idle core before deleting context */
304 SwrWaitForIdle(ctx->swrContext);
305
306 for (unsigned i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
307 pipe_surface_reference(&ctx->framebuffer.cbufs[i], NULL);
308 }
309
310 pipe_surface_reference(&ctx->framebuffer.zsbuf, NULL);
311
312 for (unsigned i = 0; i < ARRAY_SIZE(ctx->sampler_views[0]); i++) {
313 pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_FRAGMENT][i], NULL);
314 }
315
316 for (unsigned i = 0; i < ARRAY_SIZE(ctx->sampler_views[0]); i++) {
317 pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_VERTEX][i], NULL);
318 }
319
320 if (ctx->swrContext)
321 SwrDestroyContext(ctx->swrContext);
322
323 delete ctx->blendJIT;
324
325 swr_destroy_scratch_buffers(ctx);
326
327 /* Only update screen->pipe if current context is being destroyed */
328 assert(screen);
329 if (screen->pipe == pipe)
330 screen->pipe = NULL;
331
332 FREE(ctx);
333 }
334
335
336 static void
337 swr_render_condition(struct pipe_context *pipe,
338 struct pipe_query *query,
339 boolean condition,
340 uint mode)
341 {
342 struct swr_context *ctx = swr_context(pipe);
343
344 ctx->render_cond_query = query;
345 ctx->render_cond_mode = mode;
346 ctx->render_cond_cond = condition;
347 }
348
349 static void
350 swr_UpdateStats(HANDLE hPrivateContext, const SWR_STATS *pStats)
351 {
352 swr_draw_context *pDC = (swr_draw_context*)hPrivateContext;
353
354 if (!pDC)
355 return;
356
357 struct swr_query_result *pqr = (struct swr_query_result *)pDC->pStats;
358
359 SWR_STATS *pSwrStats = &pqr->core;
360
361 pSwrStats->DepthPassCount += pStats->DepthPassCount;
362 pSwrStats->PsInvocations += pStats->PsInvocations;
363 pSwrStats->CsInvocations += pStats->CsInvocations;
364 }
365
366 static void
367 swr_UpdateStatsFE(HANDLE hPrivateContext, const SWR_STATS_FE *pStats)
368 {
369 swr_draw_context *pDC = (swr_draw_context*)hPrivateContext;
370
371 if (!pDC)
372 return;
373
374 struct swr_query_result *pqr = (struct swr_query_result *)pDC->pStats;
375
376 SWR_STATS_FE *pSwrStats = &pqr->coreFE;
377 p_atomic_add(&pSwrStats->IaVertices, pStats->IaVertices);
378 p_atomic_add(&pSwrStats->IaPrimitives, pStats->IaPrimitives);
379 p_atomic_add(&pSwrStats->VsInvocations, pStats->VsInvocations);
380 p_atomic_add(&pSwrStats->HsInvocations, pStats->HsInvocations);
381 p_atomic_add(&pSwrStats->DsInvocations, pStats->DsInvocations);
382 p_atomic_add(&pSwrStats->GsInvocations, pStats->GsInvocations);
383 p_atomic_add(&pSwrStats->CInvocations, pStats->CInvocations);
384 p_atomic_add(&pSwrStats->CPrimitives, pStats->CPrimitives);
385 p_atomic_add(&pSwrStats->GsPrimitives, pStats->GsPrimitives);
386
387 for (unsigned i = 0; i < 4; i++) {
388 p_atomic_add(&pSwrStats->SoPrimStorageNeeded[i],
389 pStats->SoPrimStorageNeeded[i]);
390 p_atomic_add(&pSwrStats->SoNumPrimsWritten[i],
391 pStats->SoNumPrimsWritten[i]);
392 }
393 }
394
395 struct pipe_context *
396 swr_create_context(struct pipe_screen *p_screen, void *priv, unsigned flags)
397 {
398 struct swr_context *ctx = CALLOC_STRUCT(swr_context);
399 ctx->blendJIT =
400 new std::unordered_map<BLEND_COMPILE_STATE, PFN_BLEND_JIT_FUNC>;
401
402 SWR_CREATECONTEXT_INFO createInfo;
403 memset(&createInfo, 0, sizeof(createInfo));
404 createInfo.privateStateSize = sizeof(swr_draw_context);
405 createInfo.pfnLoadTile = swr_LoadHotTile;
406 createInfo.pfnStoreTile = swr_StoreHotTile;
407 createInfo.pfnClearTile = swr_StoreHotTileClear;
408 createInfo.pfnUpdateStats = swr_UpdateStats;
409 createInfo.pfnUpdateStatsFE = swr_UpdateStatsFE;
410 ctx->swrContext = SwrCreateContext(&createInfo);
411
412 /* Init Load/Store/ClearTiles Tables */
413 swr_InitMemoryModule();
414
415 InitBackendFuncTables();
416
417 if (ctx->swrContext == NULL)
418 goto fail;
419
420 ctx->pipe.screen = p_screen;
421 ctx->pipe.destroy = swr_destroy;
422 ctx->pipe.priv = priv;
423 ctx->pipe.create_surface = swr_create_surface;
424 ctx->pipe.surface_destroy = swr_surface_destroy;
425 ctx->pipe.transfer_map = swr_transfer_map;
426 ctx->pipe.transfer_unmap = swr_transfer_unmap;
427
428 ctx->pipe.transfer_flush_region = u_default_transfer_flush_region;
429 ctx->pipe.buffer_subdata = u_default_buffer_subdata;
430 ctx->pipe.texture_subdata = u_default_texture_subdata;
431
432 ctx->pipe.resource_copy_region = swr_resource_copy;
433 ctx->pipe.render_condition = swr_render_condition;
434
435 swr_state_init(&ctx->pipe);
436 swr_clear_init(&ctx->pipe);
437 swr_draw_init(&ctx->pipe);
438 swr_query_init(&ctx->pipe);
439
440 ctx->pipe.blit = swr_blit;
441 ctx->blitter = util_blitter_create(&ctx->pipe);
442 if (!ctx->blitter)
443 goto fail;
444
445 swr_init_scratch_buffers(ctx);
446
447 return &ctx->pipe;
448
449 fail:
450 /* Should really validate the init steps and fail gracefully */
451 swr_destroy(&ctx->pipe);
452 return NULL;
453 }