• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "zink_context.h"
2 #include "zink_helpers.h"
3 #include "zink_resource.h"
4 #include "zink_screen.h"
5 
6 #include "util/u_blitter.h"
7 #include "util/u_surface.h"
8 #include "util/format/u_format.h"
9 
10 static bool
blit_resolve(struct zink_context * ctx,const struct pipe_blit_info * info)11 blit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info)
12 {
13    if (util_format_get_mask(info->dst.format) != info->mask ||
14        util_format_get_mask(info->src.format) != info->mask ||
15        util_format_is_depth_or_stencil(info->dst.format) ||
16        info->scissor_enable ||
17        info->alpha_blend)
18       return false;
19 
20    if (info->src.box.width != info->dst.box.width ||
21        info->src.box.height != info->dst.box.height ||
22        info->src.box.depth != info->dst.box.depth)
23       return false;
24 
25    if (info->render_condition_enable &&
26        ctx->render_condition_active)
27       return false;
28 
29    struct zink_resource *src = zink_resource(info->src.resource);
30    struct zink_resource *dst = zink_resource(info->dst.resource);
31 
32    struct zink_screen *screen = zink_screen(ctx->base.screen);
33    if (src->format != zink_get_format(screen, info->src.format) ||
34        dst->format != zink_get_format(screen, info->dst.format))
35       return false;
36 
37    struct zink_batch *batch = zink_batch_no_rp(ctx);
38 
39    zink_batch_reference_resource_rw(batch, src, false);
40    zink_batch_reference_resource_rw(batch, dst, true);
41 
42    zink_resource_setup_transfer_layouts(batch, src, dst);
43 
44    VkImageResolve region = {};
45 
46    region.srcSubresource.aspectMask = src->aspect;
47    region.srcSubresource.mipLevel = info->src.level;
48    region.srcOffset.x = info->src.box.x;
49    region.srcOffset.y = info->src.box.y;
50 
51    if (src->base.array_size > 1) {
52       region.srcOffset.z = 0;
53       region.srcSubresource.baseArrayLayer = info->src.box.z;
54       region.srcSubresource.layerCount = info->src.box.depth;
55    } else {
56       assert(info->src.box.depth == 1);
57       region.srcOffset.z = info->src.box.z;
58       region.srcSubresource.baseArrayLayer = 0;
59       region.srcSubresource.layerCount = 1;
60    }
61 
62    region.dstSubresource.aspectMask = dst->aspect;
63    region.dstSubresource.mipLevel = info->dst.level;
64    region.dstOffset.x = info->dst.box.x;
65    region.dstOffset.y = info->dst.box.y;
66 
67    if (dst->base.array_size > 1) {
68       region.dstOffset.z = 0;
69       region.dstSubresource.baseArrayLayer = info->dst.box.z;
70       region.dstSubresource.layerCount = info->dst.box.depth;
71    } else {
72       assert(info->dst.box.depth == 1);
73       region.dstOffset.z = info->dst.box.z;
74       region.dstSubresource.baseArrayLayer = 0;
75       region.dstSubresource.layerCount = 1;
76    }
77 
78    region.extent.width = info->dst.box.width;
79    region.extent.height = info->dst.box.height;
80    region.extent.depth = info->dst.box.depth;
81    vkCmdResolveImage(batch->cmdbuf, src->image, src->layout,
82                      dst->image, dst->layout,
83                      1, &region);
84 
85    return true;
86 }
87 
88 static bool
blit_native(struct zink_context * ctx,const struct pipe_blit_info * info)89 blit_native(struct zink_context *ctx, const struct pipe_blit_info *info)
90 {
91    if (util_format_get_mask(info->dst.format) != info->mask ||
92        util_format_get_mask(info->src.format) != info->mask ||
93        info->scissor_enable ||
94        info->alpha_blend)
95       return false;
96 
97    if (info->render_condition_enable &&
98        ctx->render_condition_active)
99       return false;
100 
101    if (util_format_is_depth_or_stencil(info->dst.format) &&
102        info->dst.format != info->src.format)
103       return false;
104 
105    /* vkCmdBlitImage must not be used for multisampled source or destination images. */
106    if (info->src.resource->nr_samples > 1 || info->dst.resource->nr_samples > 1)
107       return false;
108 
109    struct zink_resource *src = zink_resource(info->src.resource);
110    struct zink_resource *dst = zink_resource(info->dst.resource);
111 
112    struct zink_screen *screen = zink_screen(ctx->base.screen);
113    if (src->format != zink_get_format(screen, info->src.format) ||
114        dst->format != zink_get_format(screen, info->dst.format))
115       return false;
116 
117    struct zink_batch *batch = zink_batch_no_rp(ctx);
118    zink_batch_reference_resource_rw(batch, src, false);
119    zink_batch_reference_resource_rw(batch, dst, true);
120 
121    zink_resource_setup_transfer_layouts(batch, src, dst);
122 
123    VkImageBlit region = {};
124    region.srcSubresource.aspectMask = src->aspect;
125    region.srcSubresource.mipLevel = info->src.level;
126    region.srcOffsets[0].x = info->src.box.x;
127    region.srcOffsets[0].y = info->src.box.y;
128    region.srcOffsets[1].x = info->src.box.x + info->src.box.width;
129    region.srcOffsets[1].y = info->src.box.y + info->src.box.height;
130 
131    if (src->base.array_size > 1) {
132       region.srcOffsets[0].z = 0;
133       region.srcOffsets[1].z = 1;
134       region.srcSubresource.baseArrayLayer = info->src.box.z;
135       region.srcSubresource.layerCount = info->src.box.depth;
136    } else {
137       region.srcOffsets[0].z = info->src.box.z;
138       region.srcOffsets[1].z = info->src.box.z + info->src.box.depth;
139       region.srcSubresource.baseArrayLayer = 0;
140       region.srcSubresource.layerCount = 1;
141    }
142 
143    region.dstSubresource.aspectMask = dst->aspect;
144    region.dstSubresource.mipLevel = info->dst.level;
145    region.dstOffsets[0].x = info->dst.box.x;
146    region.dstOffsets[0].y = info->dst.box.y;
147    region.dstOffsets[1].x = info->dst.box.x + info->dst.box.width;
148    region.dstOffsets[1].y = info->dst.box.y + info->dst.box.height;
149 
150    if (dst->base.array_size > 1) {
151       region.dstOffsets[0].z = 0;
152       region.dstOffsets[1].z = 1;
153       region.dstSubresource.baseArrayLayer = info->dst.box.z;
154       region.dstSubresource.layerCount = info->dst.box.depth;
155    } else {
156       region.dstOffsets[0].z = info->dst.box.z;
157       region.dstOffsets[1].z = info->dst.box.z + info->dst.box.depth;
158       region.dstSubresource.baseArrayLayer = 0;
159       region.dstSubresource.layerCount = 1;
160    }
161 
162    vkCmdBlitImage(batch->cmdbuf, src->image, src->layout,
163                   dst->image, dst->layout,
164                   1, &region,
165                   zink_filter(info->filter));
166 
167    return true;
168 }
169 
170 void
zink_blit(struct pipe_context * pctx,const struct pipe_blit_info * info)171 zink_blit(struct pipe_context *pctx,
172           const struct pipe_blit_info *info)
173 {
174    struct zink_context *ctx = zink_context(pctx);
175    if (info->src.resource->nr_samples > 1 &&
176        info->dst.resource->nr_samples <= 1) {
177       if (blit_resolve(ctx, info))
178          return;
179    } else {
180       if (blit_native(ctx, info))
181          return;
182    }
183 
184    struct zink_resource *src = zink_resource(info->src.resource);
185    struct zink_resource *dst = zink_resource(info->dst.resource);
186    /* if we're copying between resources with matching aspects then we can probably just copy_region */
187    if (src->aspect == dst->aspect && util_try_blit_via_copy_region(pctx, info))
188       return;
189 
190    if (!util_blitter_is_blit_supported(ctx->blitter, info)) {
191       debug_printf("blit unsupported %s -> %s\n",
192               util_format_short_name(info->src.resource->format),
193               util_format_short_name(info->dst.resource->format));
194       return;
195    }
196 
197    util_blitter_save_blend(ctx->blitter, ctx->gfx_pipeline_state.blend_state);
198    util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->dsa_state);
199    util_blitter_save_vertex_elements(ctx->blitter, ctx->element_state);
200    util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
201    util_blitter_save_rasterizer(ctx->blitter, ctx->rast_state);
202    util_blitter_save_fragment_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_FRAGMENT]);
203    util_blitter_save_vertex_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_VERTEX]);
204    util_blitter_save_geometry_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_GEOMETRY]);
205    util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state);
206    util_blitter_save_viewport(ctx->blitter, ctx->viewport_states);
207    util_blitter_save_scissor(ctx->blitter, ctx->scissor_states);
208    util_blitter_save_fragment_sampler_states(ctx->blitter,
209                                              ctx->num_samplers[PIPE_SHADER_FRAGMENT],
210                                              ctx->sampler_states[PIPE_SHADER_FRAGMENT]);
211    util_blitter_save_fragment_sampler_views(ctx->blitter,
212                                             ctx->num_image_views[PIPE_SHADER_FRAGMENT],
213                                             ctx->image_views[PIPE_SHADER_FRAGMENT]);
214    util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->ubos[PIPE_SHADER_FRAGMENT]);
215    util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->buffers);
216    util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask);
217    util_blitter_save_so_targets(ctx->blitter, ctx->num_so_targets, ctx->so_targets);
218 
219    util_blitter_blit(ctx->blitter, info);
220 }
221