zink: set primitive restart cap
[mesa.git] / src / gallium / drivers / zink / zink_blit.c
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
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 info->render_condition_enable)
19 return false;
20
21 struct zink_resource *src = zink_resource(info->src.resource);
22 struct zink_resource *dst = zink_resource(info->dst.resource);
23
24 struct zink_screen *screen = zink_screen(ctx->base.screen);
25 if (src->format != zink_get_format(screen, info->src.format) ||
26 dst->format != zink_get_format(screen, info->dst.format))
27 return false;
28
29 struct zink_batch *batch = zink_batch_no_rp(ctx);
30
31 zink_batch_reference_resoure(batch, src);
32 zink_batch_reference_resoure(batch, dst);
33
34 if (src->layout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
35 zink_resource_barrier(batch->cmdbuf, src, src->aspect,
36 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
37
38 if (dst->layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
39 zink_resource_barrier(batch->cmdbuf, dst, dst->aspect,
40 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
41
42 VkImageResolve region = {};
43
44 region.srcSubresource.aspectMask = src->aspect;
45 region.srcSubresource.mipLevel = info->src.level;
46 region.srcSubresource.baseArrayLayer = 0; // no clue
47 region.srcSubresource.layerCount = 1; // no clue
48 region.srcOffset.x = info->src.box.x;
49 region.srcOffset.y = info->src.box.y;
50 region.srcOffset.z = info->src.box.z;
51
52 region.dstSubresource.aspectMask = dst->aspect;
53 region.dstSubresource.mipLevel = info->dst.level;
54 region.dstSubresource.baseArrayLayer = 0; // no clue
55 region.dstSubresource.layerCount = 1; // no clue
56 region.dstOffset.x = info->dst.box.x;
57 region.dstOffset.y = info->dst.box.y;
58 region.dstOffset.z = info->dst.box.z;
59
60 region.extent.width = info->dst.box.width;
61 region.extent.height = info->dst.box.height;
62 region.extent.depth = info->dst.box.depth;
63 vkCmdResolveImage(batch->cmdbuf, src->image, src->layout,
64 dst->image, dst->layout,
65 1, &region);
66
67 return true;
68 }
69
70 static bool
71 blit_native(struct zink_context *ctx, const struct pipe_blit_info *info)
72 {
73 if (util_format_get_mask(info->dst.format) != info->mask ||
74 util_format_get_mask(info->src.format) != info->mask ||
75 info->scissor_enable ||
76 info->alpha_blend ||
77 info->render_condition_enable)
78 return false;
79
80 if (util_format_is_depth_or_stencil(info->dst.format) &&
81 info->dst.format != info->src.format)
82 return false;
83
84 /* vkCmdBlitImage must not be used for multisampled source or destination images. */
85 if (info->src.resource->nr_samples > 1 || info->dst.resource->nr_samples > 1)
86 return false;
87
88 struct zink_resource *src = zink_resource(info->src.resource);
89 struct zink_resource *dst = zink_resource(info->dst.resource);
90
91 struct zink_screen *screen = zink_screen(ctx->base.screen);
92 if (src->format != zink_get_format(screen, info->src.format) ||
93 dst->format != zink_get_format(screen, info->dst.format))
94 return false;
95
96 struct zink_batch *batch = zink_batch_no_rp(ctx);
97 zink_batch_reference_resoure(batch, src);
98 zink_batch_reference_resoure(batch, dst);
99
100 if (src == dst) {
101 /* The Vulkan 1.1 specification says the following about valid usage
102 * of vkCmdBlitImage:
103 *
104 * "srcImageLayout must be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
105 * VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL"
106 *
107 * and:
108 *
109 * "dstImageLayout must be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
110 * VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL"
111 *
112 * Since we cant have the same image in two states at the same time,
113 * we're effectively left with VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR or
114 * VK_IMAGE_LAYOUT_GENERAL. And since this isn't a present-related
115 * operation, VK_IMAGE_LAYOUT_GENERAL seems most appropriate.
116 */
117 if (src->layout != VK_IMAGE_LAYOUT_GENERAL)
118 zink_resource_barrier(batch->cmdbuf, src, src->aspect,
119 VK_IMAGE_LAYOUT_GENERAL);
120 } else {
121 if (src->layout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
122 zink_resource_barrier(batch->cmdbuf, src, src->aspect,
123 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
124
125 if (dst->layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
126 zink_resource_barrier(batch->cmdbuf, dst, dst->aspect,
127 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
128 }
129
130 VkImageBlit region = {};
131 region.srcSubresource.aspectMask = src->aspect;
132 region.srcSubresource.mipLevel = info->src.level;
133 region.srcOffsets[0].x = info->src.box.x;
134 region.srcOffsets[0].y = info->src.box.y;
135 region.srcOffsets[1].x = info->src.box.x + info->src.box.width;
136 region.srcOffsets[1].y = info->src.box.y + info->src.box.height;
137
138 if (src->base.array_size > 1) {
139 region.srcOffsets[0].z = 0;
140 region.srcOffsets[1].z = 1;
141 region.srcSubresource.baseArrayLayer = info->src.box.z;
142 region.srcSubresource.layerCount = info->src.box.depth;
143 } else {
144 region.srcOffsets[0].z = info->src.box.z;
145 region.srcOffsets[1].z = info->src.box.z + info->src.box.depth;
146 region.srcSubresource.baseArrayLayer = 0;
147 region.srcSubresource.layerCount = 1;
148 }
149
150 region.dstSubresource.aspectMask = dst->aspect;
151 region.dstSubresource.mipLevel = info->dst.level;
152 region.dstOffsets[0].x = info->dst.box.x;
153 region.dstOffsets[0].y = info->dst.box.y;
154 region.dstOffsets[1].x = info->dst.box.x + info->dst.box.width;
155 region.dstOffsets[1].y = info->dst.box.y + info->dst.box.height;
156
157 if (dst->base.array_size > 1) {
158 region.dstOffsets[0].z = 0;
159 region.dstOffsets[1].z = 1;
160 region.dstSubresource.baseArrayLayer = info->dst.box.z;
161 region.dstSubresource.layerCount = info->dst.box.depth;
162 } else {
163 region.dstOffsets[0].z = info->dst.box.z;
164 region.dstOffsets[1].z = info->dst.box.z + info->dst.box.depth;
165 region.dstSubresource.baseArrayLayer = 0;
166 region.dstSubresource.layerCount = 1;
167 }
168
169 vkCmdBlitImage(batch->cmdbuf, src->image, src->layout,
170 dst->image, dst->layout,
171 1, &region,
172 zink_filter(info->filter));
173
174 return true;
175 }
176
177 void
178 zink_blit(struct pipe_context *pctx,
179 const struct pipe_blit_info *info)
180 {
181 struct zink_context *ctx = zink_context(pctx);
182 if (info->src.resource->nr_samples > 1 &&
183 info->dst.resource->nr_samples <= 1) {
184 if (blit_resolve(ctx, info))
185 return;
186 } else {
187 if (blit_native(ctx, info))
188 return;
189 }
190
191 struct zink_resource *src = zink_resource(info->src.resource);
192 struct zink_resource *dst = zink_resource(info->dst.resource);
193 /* if we're copying between resources with matching aspects then we can probably just copy_region */
194 if (src->aspect == dst->aspect && util_try_blit_via_copy_region(pctx, info))
195 return;
196
197 if (!util_blitter_is_blit_supported(ctx->blitter, info)) {
198 debug_printf("blit unsupported %s -> %s\n",
199 util_format_short_name(info->src.resource->format),
200 util_format_short_name(info->dst.resource->format));
201 return;
202 }
203
204 util_blitter_save_blend(ctx->blitter, ctx->gfx_pipeline_state.blend_state);
205 util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->gfx_pipeline_state.depth_stencil_alpha_state);
206 util_blitter_save_vertex_elements(ctx->blitter, ctx->element_state);
207 util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
208 util_blitter_save_rasterizer(ctx->blitter, ctx->rast_state);
209 util_blitter_save_fragment_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_FRAGMENT]);
210 util_blitter_save_vertex_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_VERTEX]);
211 util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state);
212 util_blitter_save_viewport(ctx->blitter, ctx->viewport_states);
213 util_blitter_save_scissor(ctx->blitter, ctx->scissor_states);
214 util_blitter_save_fragment_sampler_states(ctx->blitter,
215 ctx->num_samplers[PIPE_SHADER_FRAGMENT],
216 ctx->sampler_states[PIPE_SHADER_FRAGMENT]);
217 util_blitter_save_fragment_sampler_views(ctx->blitter,
218 ctx->num_image_views[PIPE_SHADER_FRAGMENT],
219 ctx->image_views[PIPE_SHADER_FRAGMENT]);
220 util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->ubos[PIPE_SHADER_FRAGMENT]);
221 util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->buffers);
222 util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask);
223 util_blitter_save_so_targets(ctx->blitter, ctx->num_so_targets, ctx->so_targets);
224
225 util_blitter_blit(ctx->blitter, info);
226 }