Skip to content

Commit e6aa20b

Browse files
committed
optimize vulkan render surfaces
- use optimal tiling for vulkan render surfaces - specify valid values for the vulkan image layout - remove old opaque fb casting workaround in vulkan render surface - call vkDeviceWaitIdle before present fb bc apparently on intel, something doesn't work with synchronization
1 parent d196cf8 commit e6aa20b

File tree

1 file changed

+29
-87
lines changed

1 file changed

+29
-87
lines changed

src/vk_gbm_render_surface.c

Lines changed: 29 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static VkFormat srgb_to_unorm_format(VkFormat vk_format) {
186186
}
187187
}
188188

189-
static int fb_init(struct fb *fb, struct gbm_device *gbm_device, struct vk_renderer *renderer, int width, int height, enum pixfmt pixel_format, uint64_t drm_modifier) {
189+
static int fb_init(struct fb *fb, struct gbm_device *gbm_device, struct vk_renderer *renderer, int width, int height, enum pixfmt pixel_format) {
190190
PFN_vkGetMemoryFdPropertiesKHR get_memory_fd_props;
191191
VkSubresourceLayout layout;
192192
VkDeviceMemory img_device_memory;
@@ -212,6 +212,17 @@ static int fb_init(struct fb *fb, struct gbm_device *gbm_device, struct vk_rende
212212
vk_format = srgb_to_unorm_format(vk_format);
213213
}
214214

215+
bo = gbm_bo_create(
216+
gbm_device,
217+
width, height,
218+
get_pixfmt_info(pixel_format)->gbm_format,
219+
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT
220+
);
221+
if (bo == NULL) {
222+
LOG_ERROR("Could not create GBM BO. gbm_bo_create: %s\n", strerror(errno));
223+
goto fail_destroy_image;
224+
}
225+
215226
ok = vkCreateImage(
216227
device,
217228
&(VkImageCreateInfo){
@@ -241,14 +252,14 @@ static int fb_init(struct fb *fb, struct gbm_device *gbm_device, struct vk_rende
241252
&(VkImageDrmFormatModifierExplicitCreateInfoEXT){
242253
.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
243254
.drmFormatModifierPlaneCount = 1,
244-
.drmFormatModifier = drm_modifier,
255+
.drmFormatModifier = gbm_bo_get_modifier(bo),
245256
.pPlaneLayouts =
246257
(VkSubresourceLayout[1]){
247258
{
248259
/// These are just dummy values, but they need to be there AFAIK
249-
.offset = 0,
250-
.size = 0,
251-
.rowPitch = 0,
260+
.offset = gbm_bo_get_offset(bo, 0),
261+
.size = gbm_bo_get_stride_for_plane(bo, 0) * gbm_bo_get_height(bo) + gbm_bo_get_offset(bo, 0),
262+
.rowPitch = gbm_bo_get_stride_for_plane(bo, 0),
252263
.arrayPitch = 0,
253264
.depthPitch = 0,
254265
},
@@ -277,20 +288,6 @@ static int fb_init(struct fb *fb, struct gbm_device *gbm_device, struct vk_rende
277288
&layout
278289
);
279290

280-
// Create a GBM BO with the actual memory we're going to use
281-
bo = gbm_bo_create_with_modifiers(
282-
gbm_device,
283-
width,
284-
height,
285-
get_pixfmt_info(pixel_format)->gbm_format,
286-
&drm_modifier,
287-
1
288-
);
289-
if (bo == NULL) {
290-
LOG_ERROR("Could not create GBM BO. gbm_bo_create_with_modifiers: %s\n", strerror(errno));
291-
goto fail_destroy_image;
292-
}
293-
294291
// Just some paranoid checks that the layout matches (had some issues with that initially)
295292
if (gbm_bo_get_offset(bo, 0) != layout.offset) {
296293
LOG_ERROR("GBM BO layout doesn't match image layout. This is probably a driver / kernel bug.\n");
@@ -428,11 +425,11 @@ static int fb_init(struct fb *fb, struct gbm_device *gbm_device, struct vk_rende
428425
fail_close_fd:
429426
close(fd);
430427

431-
fail_destroy_bo:
432-
gbm_bo_destroy(bo);
433-
434428
fail_destroy_image:
435429
vkDestroyImage(device, vkimg, NULL);
430+
431+
fail_destroy_bo:
432+
gbm_bo_destroy(bo);
436433
return EIO;
437434
}
438435

@@ -460,7 +457,7 @@ int vk_gbm_render_surface_init(
460457
}
461458

462459
for (int i = 0; i < ARRAY_SIZE(surface->fbs); i++) {
463-
ok = fb_init(surface->fbs + i, gbm_device, renderer, (int) size.x, (int) size.y, pixel_format, DRM_FORMAT_MOD_LINEAR);
460+
ok = fb_init(surface->fbs + i, gbm_device, renderer, (int) size.x, (int) size.y, pixel_format);
464461
if (ok != 0) {
465462
LOG_ERROR("Could not initialize vulkan GBM framebuffer.\n");
466463
goto fail_deinit_previous_fbs;
@@ -551,9 +548,6 @@ void vk_gbm_render_surface_deinit(struct surface *s) {
551548
struct gbm_bo_meta {
552549
struct drmdev *drmdev;
553550
uint32_t fb_id;
554-
bool has_opaque_fb;
555-
enum pixfmt opaque_pixel_format;
556-
uint32_t opaque_fb_id;
557551
};
558552

559553
static void on_destroy_gbm_bo_meta(struct gbm_bo *bo, void *meta_void) {
@@ -569,13 +563,6 @@ static void on_destroy_gbm_bo_meta(struct gbm_bo *bo, void *meta_void) {
569563
LOG_ERROR("Couldn't remove DRM framebuffer.\n");
570564
}
571565

572-
if (meta->has_opaque_fb && meta->opaque_fb_id != meta->fb_id) {
573-
ok = drmdev_rm_fb(meta->drmdev, meta->opaque_fb_id);
574-
if (ok != 0) {
575-
LOG_ERROR("Couldn't remove DRM framebuffer.\n");
576-
}
577-
}
578-
579566
drmdev_unref(meta->drmdev);
580567
free(meta);
581568
}
@@ -600,8 +587,8 @@ static int vk_gbm_render_surface_present_kms(struct surface *s, const struct fl_
600587
struct gbm_bo_meta *meta;
601588
struct drmdev *drmdev;
602589
struct gbm_bo *bo;
603-
enum pixfmt pixel_format, opaque_pixel_format;
604-
uint32_t fb_id, opaque_fb_id;
590+
enum pixfmt pixel_format;
591+
uint32_t fb_id;
605592
int ok;
606593

607594
vk_surface = CAST_THIS(s);
@@ -618,8 +605,6 @@ static int vk_gbm_render_surface_present_kms(struct surface *s, const struct fl_
618605
bo = vk_surface->front_fb->fb->bo;
619606
meta = gbm_bo_get_user_data(bo);
620607
if (meta == NULL) {
621-
bool has_opaque_fb;
622-
623608
meta = malloc(sizeof *meta);
624609
if (meta == NULL) {
625610
ok = ENOMEM;
@@ -638,8 +623,7 @@ static int vk_gbm_render_surface_present_kms(struct surface *s, const struct fl_
638623
gbm_bo_get_handle(bo).u32,
639624
gbm_bo_get_stride(bo),
640625
gbm_bo_get_offset(bo, 0),
641-
true, gbm_bo_get_modifier(bo),
642-
0
626+
true, gbm_bo_get_modifier(bo)
643627
);
644628
TRACER_END(vk_surface->surface.tracer, "drmdev_add_fb (non-opaque)");
645629

@@ -649,40 +633,8 @@ static int vk_gbm_render_surface_present_kms(struct surface *s, const struct fl_
649633
goto fail_free_meta;
650634
}
651635

652-
if (get_pixfmt_info(vk_surface->pixel_format)->is_opaque == false) {
653-
has_opaque_fb = false;
654-
opaque_pixel_format = pixfmt_opaque(vk_surface->pixel_format);
655-
if (get_pixfmt_info(opaque_pixel_format)->is_opaque) {
656-
657-
TRACER_BEGIN(vk_surface->surface.tracer, "drmdev_add_fb (opaque)");
658-
opaque_fb_id = drmdev_add_fb(
659-
drmdev,
660-
gbm_bo_get_width(bo),
661-
gbm_bo_get_height(bo),
662-
opaque_pixel_format,
663-
gbm_bo_get_handle(bo).u32,
664-
gbm_bo_get_stride(bo),
665-
gbm_bo_get_offset(bo, 0),
666-
true, gbm_bo_get_modifier(bo),
667-
0
668-
);
669-
TRACER_END(vk_surface->surface.tracer, "drmdev_add_fb (opaque)");
670-
671-
if (opaque_fb_id != 0) {
672-
has_opaque_fb = true;
673-
}
674-
}
675-
} else {
676-
has_opaque_fb = true;
677-
opaque_fb_id = fb_id;
678-
opaque_pixel_format = vk_surface->pixel_format;
679-
}
680-
681636
meta->drmdev = drmdev_ref(drmdev);
682637
meta->fb_id = fb_id;
683-
meta->has_opaque_fb = has_opaque_fb;
684-
meta->opaque_pixel_format = opaque_pixel_format;
685-
meta->opaque_fb_id = opaque_fb_id;
686638
gbm_bo_set_user_data(bo, meta, on_destroy_gbm_bo_meta);
687639
} else {
688640
// We can only add this GBM BO to a single KMS device as an fb right now.
@@ -708,29 +660,19 @@ static int vk_gbm_render_surface_present_kms(struct surface *s, const struct fl_
708660
// For example, on Pi 4, even though ARGB8888 is listed as supported for the primary plane,
709661
// rendering is completely off.
710662
// So we just cast our fb to an XRGB8888 framebuffer and scanout that instead.
711-
if (kms_req_builder_prefer_next_layer_opaque(builder)) {
712-
if (meta->has_opaque_fb) {
713-
fb_id = meta->opaque_fb_id;
714-
pixel_format = meta->opaque_pixel_format;
715-
} else {
716-
LOG_DEBUG("Bottom-most framebuffer layer should be opaque, but an opaque framebuffer couldn't be created.\n");
717-
LOG_DEBUG("Using non-opaque framebuffer instead, which can result in visual glitches.\n");
718-
fb_id = meta->fb_id;
719-
pixel_format = vk_surface->pixel_format;
720-
}
721-
} else {
722-
fb_id = meta->fb_id;
723-
pixel_format = vk_surface->pixel_format;
724-
}
663+
fb_id = meta->fb_id;
664+
pixel_format = vk_surface->pixel_format;
665+
666+
vkDeviceWaitIdle(vk_renderer_get_device(vk_surface->renderer));
725667

726668
TRACER_BEGIN(vk_surface->surface.tracer, "kms_req_builder_push_fb_layer");
727669
ok = kms_req_builder_push_fb_layer(
728670
builder,
729671
&(const struct kms_fb_layer) {
730672
.drm_fb_id = fb_id,
731673
.format = pixel_format,
732-
.has_modifier = false,
733-
.modifier = 0,
674+
.has_modifier = true,
675+
.modifier = gbm_bo_get_modifier(bo),
734676

735677
.dst_x = (int32_t) props->aa_rect.offset.x,
736678
.dst_y = (int32_t) props->aa_rect.offset.y,

0 commit comments

Comments
 (0)