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, ®ion);
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, ®ion,
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