1 #include "zink_context.h"
2 #include "zink_helpers.h"
3 #include "zink_resource.h"
4 #include "zink_screen.h"
6 #include "util/u_blitter.h"
7 #include "util/u_surface.h"
8 #include "util/format/u_format.h"
11 blit_resolve(struct zink_context
*ctx
, const struct pipe_blit_info
*info
)
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
||
18 info
->render_condition_enable
)
21 struct zink_resource
*src
= zink_resource(info
->src
.resource
);
22 struct zink_resource
*dst
= zink_resource(info
->dst
.resource
);
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
))
29 struct zink_batch
*batch
= zink_batch_no_rp(ctx
);
31 zink_batch_reference_resoure(batch
, src
);
32 zink_batch_reference_resoure(batch
, dst
);
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
);
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
);
42 VkImageResolve region
= {};
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
;
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
;
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
,
71 blit_native(struct zink_context
*ctx
, const struct pipe_blit_info
*info
)
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
||
77 info
->render_condition_enable
)
80 if (util_format_is_depth_or_stencil(info
->dst
.format
) &&
81 info
->dst
.format
!= info
->src
.format
)
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)
88 struct zink_resource
*src
= zink_resource(info
->src
.resource
);
89 struct zink_resource
*dst
= zink_resource(info
->dst
.resource
);
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
))
96 struct zink_batch
*batch
= zink_batch_no_rp(ctx
);
97 zink_batch_reference_resoure(batch
, src
);
98 zink_batch_reference_resoure(batch
, dst
);
101 /* The Vulkan 1.1 specification says the following about valid usage
104 * "srcImageLayout must be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
105 * VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL"
109 * "dstImageLayout must be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
110 * VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL"
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.
117 if (src
->layout
!= VK_IMAGE_LAYOUT_GENERAL
)
118 zink_resource_barrier(batch
->cmdbuf
, src
, src
->aspect
,
119 VK_IMAGE_LAYOUT_GENERAL
);
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
);
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
);
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
;
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
;
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;
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
;
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
;
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;
169 vkCmdBlitImage(batch
->cmdbuf
, src
->image
, src
->layout
,
170 dst
->image
, dst
->layout
,
172 zink_filter(info
->filter
));
178 zink_blit(struct pipe_context
*pctx
,
179 const struct pipe_blit_info
*info
)
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
))
187 if (blit_native(ctx
, info
))
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
))
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
));
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
);
225 util_blitter_blit(ctx
->blitter
, info
);