1 /****************************************************************************
2 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
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:
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
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
22 ***************************************************************************/
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"
32 #include "util/u_memory.h"
33 #include "util/u_inlines.h"
34 #include "util/u_format.h"
35 #include "util/u_atomic.h"
38 #include "util/u_transfer.h"
39 #include "util/u_surface.h"
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
)
50 struct pipe_surface
*ps
;
52 ps
= CALLOC_STRUCT(pipe_surface
);
54 pipe_reference_init(&ps
->reference
, 1);
55 pipe_resource_reference(&ps
->texture
, pt
);
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");
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
);
85 swr_surface_destroy(struct pipe_context
*pipe
, struct pipe_surface
*surf
)
87 assert(surf
->texture
);
88 struct pipe_resource
*resource
= surf
->texture
;
90 /* If the resource has been drawn to, store tiles. */
91 swr_store_dirty_resource(pipe
, resource
, SWR_TILE_RESOLVED
);
93 pipe_resource_reference(&resource
, NULL
);
99 swr_transfer_map(struct pipe_context
*pipe
,
100 struct pipe_resource
*resource
,
103 const struct pipe_box
*box
,
104 struct pipe_transfer
**transfer
)
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
;
112 assert(level
<= resource
->last_level
);
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
);
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
))
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
);
132 swr_fence_finish(pipe
->screen
, NULL
, screen
->flush_fence
, 0);
133 swr_resource_unused(resource
);
138 pt
= CALLOC_STRUCT(pipe_transfer
);
141 pipe_resource_reference(&pt
->resource
, resource
);
144 pt
->stride
= spr
->row_stride
[level
];
145 pt
->layer_stride
= spr
->img_stride
[level
];
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
];
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
];
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
);
166 return spr
->swr
.pBaseAddress
+ offset
+ spr
->mip_offsets
[level
];
170 swr_transfer_unmap(struct pipe_context
*pipe
, struct pipe_transfer
*transfer
)
172 assert(transfer
->resource
);
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];
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];
188 pipe_resource_reference(&transfer
->resource
, NULL
);
194 swr_resource_copy(struct pipe_context
*pipe
,
195 struct pipe_resource
*dst
,
200 struct pipe_resource
*src
,
202 const struct pipe_box
*src_box
)
204 struct swr_screen
*screen
= swr_screen(pipe
->screen
);
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
);
210 swr_fence_finish(pipe
->screen
, NULL
, screen
->flush_fence
, 0);
211 swr_resource_unused(src
);
212 swr_resource_unused(dst
);
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
);
221 debug_printf("unhandled swr_resource_copy\n");
226 swr_blit(struct pipe_context
*pipe
, const struct pipe_blit_info
*blit_info
)
228 struct swr_context
*ctx
= swr_context(pipe
);
229 struct pipe_blit_info info
= *blit_info
;
231 if (blit_info
->render_condition_enable
&& !swr_check_render_cond(pipe
))
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");
241 if (util_try_blit_via_copy_region(pipe
, &info
)) {
245 if (info
.mask
& PIPE_MASK_S
) {
246 debug_printf("swr: cannot blit stencil, skipping\n");
247 info
.mask
&= ~PIPE_MASK_S
;
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
));
257 /* XXX turn off occlusion and streamout queries */
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(
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(
279 ctx
->num_samplers
[PIPE_SHADER_FRAGMENT
],
280 (void **)ctx
->samplers
[PIPE_SHADER_FRAGMENT
]);
281 util_blitter_save_fragment_sampler_views(
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
);
290 util_blitter_blit(ctx
->blitter
, &info
);
295 swr_destroy(struct pipe_context
*pipe
)
297 struct swr_context
*ctx
= swr_context(pipe
);
298 struct swr_screen
*screen
= swr_screen(pipe
->screen
);
301 util_blitter_destroy(ctx
->blitter
);
303 /* Idle core before deleting context */
304 SwrWaitForIdle(ctx
->swrContext
);
306 for (unsigned i
= 0; i
< PIPE_MAX_COLOR_BUFS
; i
++) {
307 pipe_surface_reference(&ctx
->framebuffer
.cbufs
[i
], NULL
);
310 pipe_surface_reference(&ctx
->framebuffer
.zsbuf
, NULL
);
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
);
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
);
321 SwrDestroyContext(ctx
->swrContext
);
323 delete ctx
->blendJIT
;
325 swr_destroy_scratch_buffers(ctx
);
327 /* Only update screen->pipe if current context is being destroyed */
329 if (screen
->pipe
== pipe
)
337 swr_render_condition(struct pipe_context
*pipe
,
338 struct pipe_query
*query
,
342 struct swr_context
*ctx
= swr_context(pipe
);
344 ctx
->render_cond_query
= query
;
345 ctx
->render_cond_mode
= mode
;
346 ctx
->render_cond_cond
= condition
;
350 swr_UpdateStats(HANDLE hPrivateContext
, const SWR_STATS
*pStats
)
352 swr_draw_context
*pDC
= (swr_draw_context
*)hPrivateContext
;
357 struct swr_query_result
*pqr
= (struct swr_query_result
*)pDC
->pStats
;
359 SWR_STATS
*pSwrStats
= &pqr
->core
;
361 pSwrStats
->DepthPassCount
+= pStats
->DepthPassCount
;
362 pSwrStats
->PsInvocations
+= pStats
->PsInvocations
;
363 pSwrStats
->CsInvocations
+= pStats
->CsInvocations
;
367 swr_UpdateStatsFE(HANDLE hPrivateContext
, const SWR_STATS_FE
*pStats
)
369 swr_draw_context
*pDC
= (swr_draw_context
*)hPrivateContext
;
374 struct swr_query_result
*pqr
= (struct swr_query_result
*)pDC
->pStats
;
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
);
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
]);
395 struct pipe_context
*
396 swr_create_context(struct pipe_screen
*p_screen
, void *priv
, unsigned flags
)
398 struct swr_context
*ctx
= CALLOC_STRUCT(swr_context
);
400 new std::unordered_map
<BLEND_COMPILE_STATE
, PFN_BLEND_JIT_FUNC
>;
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
);
412 /* Init Load/Store/ClearTiles Tables */
413 swr_InitMemoryModule();
415 InitBackendFuncTables();
417 if (ctx
->swrContext
== NULL
)
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
;
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
;
432 ctx
->pipe
.resource_copy_region
= swr_resource_copy
;
433 ctx
->pipe
.render_condition
= swr_render_condition
;
435 swr_state_init(&ctx
->pipe
);
436 swr_clear_init(&ctx
->pipe
);
437 swr_draw_init(&ctx
->pipe
);
438 swr_query_init(&ctx
->pipe
);
440 ctx
->pipe
.blit
= swr_blit
;
441 ctx
->blitter
= util_blitter_create(&ctx
->pipe
);
445 swr_init_scratch_buffers(ctx
);
450 /* Should really validate the init steps and fail gracefully */
451 swr_destroy(&ctx
->pipe
);