zink: enable conditional rendering if available
[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/format/u_format.h"
8
9 static bool
10 blit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info)
11 {
12 if (util_format_get_mask(info->dst.format) != info->mask ||
13 util_format_get_mask(info->src.format) != info->mask ||
14 info->scissor_enable ||
15 info->alpha_blend)
16 return false;
17
18 struct zink_resource *src = zink_resource(info->src.resource);
19 struct zink_resource *dst = zink_resource(info->dst.resource);
20
21 struct zink_screen *screen = zink_screen(ctx->base.screen);
22 if (src->format != zink_get_format(screen, info->src.format) ||
23 dst->format != zink_get_format(screen, info->dst.format))
24 return false;
25
26 struct zink_batch *batch = zink_batch_no_rp(ctx);
27
28 zink_batch_reference_resoure(batch, src);
29 zink_batch_reference_resoure(batch, dst);
30
31 if (src->layout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
32 zink_resource_barrier(batch->cmdbuf, src, src->aspect,
33 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
34
35 if (dst->layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
36 zink_resource_barrier(batch->cmdbuf, dst, dst->aspect,
37 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
38
39 VkImageResolve region = {};
40
41 region.srcSubresource.aspectMask = src->aspect;
42 region.srcSubresource.mipLevel = info->src.level;
43 region.srcSubresource.baseArrayLayer = 0; // no clue
44 region.srcSubresource.layerCount = 1; // no clue
45 region.srcOffset.x = info->src.box.x;
46 region.srcOffset.y = info->src.box.y;
47 region.srcOffset.z = info->src.box.z;
48
49 region.dstSubresource.aspectMask = dst->aspect;
50 region.dstSubresource.mipLevel = info->dst.level;
51 region.dstSubresource.baseArrayLayer = 0; // no clue
52 region.dstSubresource.layerCount = 1; // no clue
53 region.dstOffset.x = info->dst.box.x;
54 region.dstOffset.y = info->dst.box.y;
55 region.dstOffset.z = info->dst.box.z;
56
57 region.extent.width = info->dst.box.width;
58 region.extent.height = info->dst.box.height;
59 region.extent.depth = info->dst.box.depth;
60 vkCmdResolveImage(batch->cmdbuf, src->image, src->layout,
61 dst->image, dst->layout,
62 1, &region);
63
64 return true;
65 }
66
67 static bool
68 blit_native(struct zink_context *ctx, const struct pipe_blit_info *info)
69 {
70 if (util_format_get_mask(info->dst.format) != info->mask ||
71 util_format_get_mask(info->src.format) != info->mask ||
72 info->scissor_enable ||
73 info->alpha_blend ||
74 info->render_condition_enable)
75 return false;
76
77 if (util_format_is_depth_or_stencil(info->dst.format) &&
78 info->dst.format != info->src.format)
79 return false;
80
81 struct zink_resource *src = zink_resource(info->src.resource);
82 struct zink_resource *dst = zink_resource(info->dst.resource);
83
84 struct zink_screen *screen = zink_screen(ctx->base.screen);
85 if (src->format != zink_get_format(screen, info->src.format) ||
86 dst->format != zink_get_format(screen, info->dst.format))
87 return false;
88
89 struct zink_batch *batch = zink_batch_no_rp(ctx);
90 zink_batch_reference_resoure(batch, src);
91 zink_batch_reference_resoure(batch, dst);
92
93 if (src->layout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
94 zink_resource_barrier(batch->cmdbuf, src, src->aspect,
95 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
96
97 if (dst->layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
98 zink_resource_barrier(batch->cmdbuf, dst, dst->aspect,
99 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
100
101 VkImageBlit region = {};
102 region.srcSubresource.aspectMask = src->aspect;
103 region.srcSubresource.mipLevel = info->src.level;
104 region.srcOffsets[0].x = info->src.box.x;
105 region.srcOffsets[0].y = info->src.box.y;
106 region.srcOffsets[1].x = info->src.box.x + info->src.box.width;
107 region.srcOffsets[1].y = info->src.box.y + info->src.box.height;
108
109 if (src->base.array_size > 1) {
110 region.srcOffsets[0].z = 0;
111 region.srcOffsets[1].z = 1;
112 region.srcSubresource.baseArrayLayer = info->src.box.z;
113 region.srcSubresource.layerCount = info->src.box.depth;
114 } else {
115 region.srcOffsets[0].z = info->src.box.z;
116 region.srcOffsets[1].z = info->src.box.z + info->src.box.depth;
117 region.srcSubresource.baseArrayLayer = 0;
118 region.srcSubresource.layerCount = 1;
119 }
120
121 region.dstSubresource.aspectMask = dst->aspect;
122 region.dstSubresource.mipLevel = info->dst.level;
123 region.dstOffsets[0].x = info->dst.box.x;
124 region.dstOffsets[0].y = info->dst.box.y;
125 region.dstOffsets[1].x = info->dst.box.x + info->dst.box.width;
126 region.dstOffsets[1].y = info->dst.box.y + info->dst.box.height;
127
128 if (dst->base.array_size > 1) {
129 region.dstOffsets[0].z = 0;
130 region.dstOffsets[1].z = 1;
131 region.dstSubresource.baseArrayLayer = info->dst.box.z;
132 region.dstSubresource.layerCount = info->dst.box.depth;
133 } else {
134 region.dstOffsets[0].z = info->dst.box.z;
135 region.dstOffsets[1].z = info->dst.box.z + info->dst.box.depth;
136 region.dstSubresource.baseArrayLayer = 0;
137 region.dstSubresource.layerCount = 1;
138 }
139
140 vkCmdBlitImage(batch->cmdbuf, src->image, src->layout,
141 dst->image, dst->layout,
142 1, &region,
143 zink_filter(info->filter));
144
145 return true;
146 }
147
148 void
149 zink_blit(struct pipe_context *pctx,
150 const struct pipe_blit_info *info)
151 {
152 struct zink_context *ctx = zink_context(pctx);
153 if (info->src.resource->nr_samples > 1 &&
154 info->dst.resource->nr_samples <= 1) {
155 if (blit_resolve(ctx, info))
156 return;
157 } else {
158 if (blit_native(ctx, info))
159 return;
160 }
161
162 if (!util_blitter_is_blit_supported(ctx->blitter, info)) {
163 debug_printf("blit unsupported %s -> %s\n",
164 util_format_short_name(info->src.resource->format),
165 util_format_short_name(info->dst.resource->format));
166 return;
167 }
168
169 util_blitter_save_blend(ctx->blitter, ctx->gfx_pipeline_state.blend_state);
170 util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->gfx_pipeline_state.depth_stencil_alpha_state);
171 util_blitter_save_vertex_elements(ctx->blitter, ctx->element_state);
172 util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
173 util_blitter_save_rasterizer(ctx->blitter, ctx->rast_state);
174 util_blitter_save_fragment_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_FRAGMENT]);
175 util_blitter_save_vertex_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_VERTEX]);
176 util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state);
177 util_blitter_save_viewport(ctx->blitter, ctx->viewport_states);
178 util_blitter_save_scissor(ctx->blitter, ctx->scissor_states);
179 util_blitter_save_fragment_sampler_states(ctx->blitter,
180 ctx->num_samplers[PIPE_SHADER_FRAGMENT],
181 ctx->sampler_states[PIPE_SHADER_FRAGMENT]);
182 util_blitter_save_fragment_sampler_views(ctx->blitter,
183 ctx->num_image_views[PIPE_SHADER_FRAGMENT],
184 ctx->image_views[PIPE_SHADER_FRAGMENT]);
185 util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->ubos[PIPE_SHADER_FRAGMENT]);
186 util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->buffers);
187 util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask);
188
189 util_blitter_blit(ctx->blitter, info);
190 }