From a33ddd54ac8557bf49b204573c3088f748d3e61a Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Sat, 1 Apr 2023 15:27:43 -0300 Subject: gsk/vulkan/image: Cosmetics --- gsk/vulkan/gskvulkanimage.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gsk/vulkan/gskvulkanimage.c b/gsk/vulkan/gskvulkanimage.c index b74eb76fb0..b6d4eee548 100644 --- a/gsk/vulkan/gskvulkanimage.c +++ b/gsk/vulkan/gskvulkanimage.c @@ -355,7 +355,7 @@ gsk_vulkan_image_new_from_data_via_staging_buffer (GskVulkanUploader *uploader, .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = gsk_vulkan_buffer_get_buffer(staging), + .buffer = gsk_vulkan_buffer_get_buffer (staging), .offset = 0, .size = buffer_size, }); @@ -570,7 +570,6 @@ gsk_vulkan_image_new_for_framebuffer (GdkVulkanContext *context, { GskVulkanImage *self; - self = gsk_vulkan_image_new (context, width, height, -- cgit v1.2.1 From 724d07ef8a4a5150640acdc164d933487bbab9c5 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Sat, 1 Apr 2023 15:33:10 -0300 Subject: gsk/vulkan/image: Use UNDEFINED for initial layout When creating an image using gsk_vulkan_image_new_for_framebuffer(), it passes VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. However, this is a mistake. The spec demands that the initial layout must be either VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED. Apparently this was an oversight from commit b97fb751469, since the commit message even documents that, and all other calls pass either VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED. Create framebuffer images using VK_IMAGE_LAYOUT_UNDEFINED, which is what was originally expected. --- gsk/vulkan/gskvulkanimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gsk/vulkan/gskvulkanimage.c b/gsk/vulkan/gskvulkanimage.c index b6d4eee548..102d5281bc 100644 --- a/gsk/vulkan/gskvulkanimage.c +++ b/gsk/vulkan/gskvulkanimage.c @@ -575,7 +575,7 @@ gsk_vulkan_image_new_for_framebuffer (GdkVulkanContext *context, height, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_UNDEFINED, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); -- cgit v1.2.1 From 57587c00b493b2a2cf3ce3d4d5064fb4cda14c39 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Wed, 22 Mar 2023 23:01:10 -0300 Subject: gsk/vulkanimage: Set buffer row length and height This doesn't make any difference now, but will allow us to copy subregions more easily. This is not obvious, but here's a quick explanation: Leaving 'bufferRowLength' and 'bufferImageHeight' implies that Vulkan will assume the size passed in the 'imageExtent' field. Right now, this assumption is correct - the only user of this function is the glyph cache, and it only copies and uploads exact rects. Next commits will change that assumption, so we must pass 'buffer*' fields, and tell Vulkan, "this part of the buffer represents an image of width x height, and I want the subregion (x, y, smallerWidth, smallerHeight) of this image". --- gsk/vulkan/gskvulkanimage.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gsk/vulkan/gskvulkanimage.c b/gsk/vulkan/gskvulkanimage.c index 102d5281bc..075e2501f4 100644 --- a/gsk/vulkan/gskvulkanimage.c +++ b/gsk/vulkan/gskvulkanimage.c @@ -722,6 +722,8 @@ gsk_vulkan_image_upload_regions (GskVulkanImage *self, } bufferImageCopy[i].bufferOffset = offset; + bufferImageCopy[i].bufferRowLength = regions[i].width; + bufferImageCopy[i].bufferImageHeight = regions[i].height; bufferImageCopy[i].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferImageCopy[i].imageSubresource.mipLevel = 0; bufferImageCopy[i].imageSubresource.baseArrayLayer = 0; -- cgit v1.2.1 From 56c643306ae4771df9ee5ac6befe7f932aa22783 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Sat, 1 Apr 2023 16:09:06 -0300 Subject: gsk/vulkan/glyphcache: Ceil glyph surface size This is what GL does, and for a reason: it can lead to width or height for very small glyphs. Also, switch to dividing by a float (1024.0) instead of an integer (1024). --- gsk/vulkan/gskvulkanglyphcache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gsk/vulkan/gskvulkanglyphcache.c b/gsk/vulkan/gskvulkanglyphcache.c index 15db38d9aa..ab623b9445 100644 --- a/gsk/vulkan/gskvulkanglyphcache.c +++ b/gsk/vulkan/gskvulkanglyphcache.c @@ -261,8 +261,8 @@ render_glyph (Atlas *atlas, PangoGlyphInfo gi; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - value->draw_width * key->scale / 1024, - value->draw_height * key->scale / 1024); + ceil (value->draw_width * key->scale / 1024.0), + ceil (value->draw_height * key->scale / 1024.0)); cairo_surface_set_device_scale (surface, key->scale / 1024.0, key->scale / 1024.0); cr = cairo_create (surface); -- cgit v1.2.1 From 840c72d74db5d3b04c3d7d706c8cd092e3963580 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Sun, 2 Apr 2023 18:23:21 -0300 Subject: gsk/vulkan/buffer: Pass aligned memory value This was a tricky one to figure out, but it's pretty simple to understand (I hope!). So, this AMD card I'm using requires buffer memory sizes to be aligned to 16 bytes. Intel is aligned to 4 bytes I think, but AMD - or at least this AMD model in particular - uses 16 bytes for alignment. When creating a a particular texture (I did not determin which one specifically!) a buffer of size 1276 bytes is requested. 1276 / 16 = 79.75, which is clearly not aligned to the required 16 bytes. We request Vulkan to create a buffer of 1276 bytes for us, it figures out that it's not aligned, and creates a buffer of 1280 bytes, which is aligned. The extra 4 bytes are wasted, but that's okay. We immediately query this buffer for this exact information, using vkGetBufferMemoryRequirements(), and proceed to create actual memory to back this buffer up. The buffer tells us we must use 1280 bytes, so we pass 1280 bytes and everyone is happy, right? Of course not. We pass 1276 bytes, and Vulkan is subtly unhappy at us. Fix that by passing the value that Vulkan asks us to use, i.e., the size returned by vkGetBufferMemoryRequirements(). --- gsk/vulkan/gskvulkanbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gsk/vulkan/gskvulkanbuffer.c b/gsk/vulkan/gskvulkanbuffer.c index b73907faea..21ce89bd31 100644 --- a/gsk/vulkan/gskvulkanbuffer.c +++ b/gsk/vulkan/gskvulkanbuffer.c @@ -46,7 +46,7 @@ gsk_vulkan_buffer_new_internal (GdkVulkanContext *context, self->memory = gsk_vulkan_memory_new (context, requirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - size); + requirements.size); GSK_VK_CHECK (vkBindBufferMemory, gdk_vulkan_context_get_device (context), self->vk_buffer, -- cgit v1.2.1 From a2a05acc6b82416ed2165d33b351c08fe0b8147b Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Sun, 2 Apr 2023 19:18:24 -0300 Subject: gsk/vulkan/renderer: Pass appropriate clip region This part of the Vulkan renderer is almost exactly equal to the GL renderer, and the GL renderer already does that since at least 2a38cecd3351. Copy that into the Vulkan renderer. A nice side effect from this commit is that resizing a window now actually works again. Sneak in a trivial cleanup by using a variable to hold the draw index. --- gsk/vulkan/gskvulkanrenderer.c | 59 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/gsk/vulkan/gskvulkanrenderer.c b/gsk/vulkan/gskvulkanrenderer.c index 8f4fa13bf5..b634a2b761 100644 --- a/gsk/vulkan/gskvulkanrenderer.c +++ b/gsk/vulkan/gskvulkanrenderer.c @@ -70,6 +70,55 @@ struct _GskVulkanRendererClass G_DEFINE_TYPE (GskVulkanRenderer, gsk_vulkan_renderer, GSK_TYPE_RENDERER) +static cairo_region_t * +get_render_region (GskVulkanRenderer *self) +{ + const cairo_region_t *damage; + cairo_region_t *render_region; + cairo_region_t *scaled_damage; + GdkRectangle whole_surface; + GdkRectangle extents; + GdkSurface *surface; + int scale; + + render_region = NULL; + surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self->vulkan)); + scale = gdk_surface_get_scale_factor (surface); + + whole_surface.x = 0; + whole_surface.y = 0; + whole_surface.width = gdk_surface_get_width (surface); + whole_surface.height = gdk_surface_get_height (surface); + + damage = gdk_draw_context_get_frame_region (GDK_DRAW_CONTEXT (self->vulkan)); + scaled_damage = cairo_region_create (); + for (int i = 0; i < cairo_region_num_rectangles (damage); i++) + { + cairo_rectangle_int_t rect; + cairo_region_get_rectangle (damage, i, &rect); + cairo_region_union_rectangle (scaled_damage, &(cairo_rectangle_int_t) { + .x = rect.x * scale, + .y = rect.y * scale, + .width = rect.width * scale, + .height = rect.height * scale, + }); + } + + if (cairo_region_contains_rectangle (scaled_damage, &whole_surface) == CAIRO_REGION_OVERLAP_IN) + goto out; + + cairo_region_get_extents (scaled_damage, &extents); + if (gdk_rectangle_equal (&extents, &whole_surface)) + goto out; + + render_region = cairo_region_create_rectangle (&extents); + +out: + g_clear_pointer (&scaled_damage, cairo_region_destroy); + + return g_steal_pointer (&render_region); +} + static void gsk_vulkan_renderer_free_targets (GskVulkanRenderer *self) { @@ -239,11 +288,12 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, { GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); GskVulkanRender *render; - const cairo_region_t *clip; + cairo_region_t *render_region; #ifdef G_ENABLE_DEBUG GskProfiler *profiler; gint64 cpu_time; #endif + uint32_t draw_index; #ifdef G_ENABLE_DEBUG profiler = gsk_renderer_get_profiler (renderer); @@ -256,8 +306,9 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->vulkan), region); render = self->render; - clip = gdk_draw_context_get_frame_region (GDK_DRAW_CONTEXT (self->vulkan)); - gsk_vulkan_render_reset (render, self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)], NULL, clip); + render_region = get_render_region (self); + draw_index = gdk_vulkan_context_get_draw_index (self->vulkan); + gsk_vulkan_render_reset (render, self->targets[draw_index], NULL, render_region); gsk_vulkan_render_add_node (render, root); @@ -275,6 +326,8 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, #endif gdk_draw_context_end_frame (GDK_DRAW_CONTEXT (self->vulkan)); + + g_clear_pointer (&render_region, cairo_region_destroy); } static void -- cgit v1.2.1 From dde029c3d1427e15ef522006967fad2766b28898 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 3 Apr 2023 08:54:34 -0300 Subject: gsk/vulkan: Cosmetics No functional changes. Use a variable that already exists instead of calling gdk_draw_context_get_surface() again. Cleanup some newlines. --- gsk/vulkan/gskvulkanrender.c | 8 ++++---- gsk/vulkan/gskvulkanrenderer.c | 7 +------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/gsk/vulkan/gskvulkanrender.c b/gsk/vulkan/gskvulkanrender.c index 3264daa2b8..b0d4f1f10a 100644 --- a/gsk/vulkan/gskvulkanrender.c +++ b/gsk/vulkan/gskvulkanrender.c @@ -68,7 +68,7 @@ gsk_vulkan_render_setup (GskVulkanRender *self, const graphene_rect_t *rect, const cairo_region_t *clip) { - GdkSurface *window = gsk_renderer_get_surface (self->renderer); + GdkSurface *surface = gsk_renderer_get_surface (self->renderer); self->target = g_object_ref (target); @@ -79,10 +79,10 @@ gsk_vulkan_render_setup (GskVulkanRender *self, } else { - self->scale_factor = gdk_surface_get_scale_factor (gsk_renderer_get_surface (self->renderer)); + self->scale_factor = gdk_surface_get_scale_factor (surface); self->viewport = GRAPHENE_RECT_INIT (0, 0, - gdk_surface_get_width (window) * self->scale_factor, - gdk_surface_get_height (window) * self->scale_factor); + gdk_surface_get_width (surface) * self->scale_factor, + gdk_surface_get_height (surface) * self->scale_factor); } if (clip) { diff --git a/gsk/vulkan/gskvulkanrenderer.c b/gsk/vulkan/gskvulkanrenderer.c index b634a2b761..217cdab717 100644 --- a/gsk/vulkan/gskvulkanrenderer.c +++ b/gsk/vulkan/gskvulkanrenderer.c @@ -249,11 +249,8 @@ gsk_vulkan_renderer_render_texture (GskRenderer *renderer, ceil (viewport->size.height)); gsk_vulkan_render_reset (render, image, viewport, NULL); - gsk_vulkan_render_add_node (render, root); - gsk_vulkan_render_upload (render); - gsk_vulkan_render_draw (render); texture = gsk_vulkan_render_download_target (render); @@ -308,12 +305,10 @@ gsk_vulkan_renderer_render (GskRenderer *renderer, render_region = get_render_region (self); draw_index = gdk_vulkan_context_get_draw_index (self->vulkan); - gsk_vulkan_render_reset (render, self->targets[draw_index], NULL, render_region); + gsk_vulkan_render_reset (render, self->targets[draw_index], NULL, render_region); gsk_vulkan_render_add_node (render, root); - gsk_vulkan_render_upload (render); - gsk_vulkan_render_draw (render); #ifdef G_ENABLE_DEBUG -- cgit v1.2.1 From db1d2781007cb5a9e5ff4d03305743351286da11 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 3 Apr 2023 10:06:18 -0300 Subject: gsk/vulkan/renderpass: Don't scale scissor and render area The rects passed to the clip region are in buffer coordinates, and must not be scaled. Consider the following scenario: Wayland, with a 1024x768@2 window. That gives us a 2048x1536 raw image. To setup the Vulkan render pass code, we'd scale 2048x1536 *again*, to an unreasonable 4196x3072, which is (1) incorrect and (2) really incorrect and (3) can lead to crashes at best, full GPU resets at worst - and a GPU reset is incredibly not fun! Now that we pass the right clip regions at the right coordinates at all times, remove the extra scaling from the render pass. --- gsk/vulkan/gskvulkanrenderpass.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index 458d2b1fa4..24432ddd06 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -2258,8 +2258,8 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, 0, 1, &(VkRect2D) { - { rect.x * self->scale_x, rect.y * self->scale_y }, - { rect.width * self->scale_x, rect.height * self->scale_y } + { rect.x, rect.y }, + { rect.width, rect.height } }); vkCmdBeginRenderPass (command_buffer, @@ -2268,8 +2268,8 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, .renderPass = self->render_pass, .framebuffer = gsk_vulkan_render_get_framebuffer (render, self->target), .renderArea = { - { rect.x * self->scale_x, rect.y * self->scale_y }, - { rect.width * self->scale_x, rect.height * self->scale_y } + { rect.x, rect.y }, + { rect.width, rect.height } }, .clearValueCount = 1, .pClearValues = (VkClearValue [1]) { -- cgit v1.2.1 From 5c27a0dd2bd2a1ea15e583b4447f6160d7079814 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 3 Apr 2023 10:39:25 -0300 Subject: vulkan: Support fractional scaling Basically what GL does, but without any debug or feature flag to gatekeep it, since the Vulkan backend itself is experimental already. Ceil surface sizes, and floor coordinates, to the fractional scale value. --- gdk/gdkvulkancontext.c | 19 +++++++++++-------- gsk/vulkan/gskvulkanrender.c | 16 ++++++++-------- gsk/vulkan/gskvulkanrenderer.c | 20 ++++++++++---------- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index 3f669bfc4d..f1f41ce6c9 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -26,6 +26,7 @@ #include "gdkdisplayprivate.h" #include +#include /** * GdkVulkanContext: @@ -339,8 +340,10 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context, */ if (capabilities.currentExtent.width == -1 || capabilities.currentExtent.height == -1) { - capabilities.currentExtent.width = MAX (1, gdk_surface_get_width (surface) * gdk_surface_get_scale_factor (surface)); - capabilities.currentExtent.height = MAX (1, gdk_surface_get_height (surface) * gdk_surface_get_scale_factor (surface)); + double scale = gdk_surface_get_scale (surface); + + capabilities.currentExtent.width = MAX (1, (int) ceil (gdk_surface_get_width (surface) * scale)); + capabilities.currentExtent.height = MAX (1, (int) ceil (gdk_surface_get_height (surface) * scale)); } res = GDK_VK_CHECK (vkCreateSwapchainKHR, device, @@ -475,10 +478,10 @@ gdk_vulkan_context_end_frame (GdkDrawContext *draw_context, VkPresentRegionsKHR *regionsptr = VK_NULL_HANDLE; VkPresentRegionsKHR regions; VkRectLayerKHR *rectangles; + double scale; int n_regions; - int scale; - scale = gdk_surface_get_scale_factor (surface); + scale = gdk_surface_get_scale (surface); n_regions = cairo_region_num_rectangles (painted); rectangles = g_alloca (sizeof (VkRectLayerKHR) * n_regions); @@ -490,10 +493,10 @@ gdk_vulkan_context_end_frame (GdkDrawContext *draw_context, rectangles[i] = (VkRectLayerKHR) { .layer = 0, - .offset.x = r.x * scale, - .offset.y = r.y * scale, - .extent.width = r.width * scale, - .extent.height = r.height * scale, + .offset.x = (int) floor (r.x * scale), + .offset.y = (int) floor (r.y * scale), + .extent.width = (int) ceil (r.width * scale), + .extent.height = (int) ceil (r.height * scale), }; } diff --git a/gsk/vulkan/gskvulkanrender.c b/gsk/vulkan/gskvulkanrender.c index b0d4f1f10a..586678c2e4 100644 --- a/gsk/vulkan/gskvulkanrender.c +++ b/gsk/vulkan/gskvulkanrender.c @@ -31,7 +31,7 @@ struct _GskVulkanRender GskRenderer *renderer; GdkVulkanContext *vulkan; - int scale_factor; + double scale; graphene_rect_t viewport; cairo_region_t *clip; @@ -75,14 +75,14 @@ gsk_vulkan_render_setup (GskVulkanRender *self, if (rect) { self->viewport = *rect; - self->scale_factor = 1; + self->scale = 1.0; } else { - self->scale_factor = gdk_surface_get_scale_factor (surface); + self->scale = gdk_surface_get_scale (surface); self->viewport = GRAPHENE_RECT_INIT (0, 0, - gdk_surface_get_width (surface) * self->scale_factor, - gdk_surface_get_height (surface) * self->scale_factor); + (int) ceil (gdk_surface_get_width (surface) * self->scale), + (int) ceil (gdk_surface_get_height (surface) * self->scale)); } if (clip) { @@ -340,12 +340,12 @@ gsk_vulkan_render_add_node (GskVulkanRender *self, GskVulkanRenderPass *pass; graphene_matrix_t mv; - graphene_matrix_init_scale (&mv, self->scale_factor, self->scale_factor, 1.0); + graphene_matrix_init_scale (&mv, self->scale, self->scale, 1.0); pass = gsk_vulkan_render_pass_new (self->vulkan, self->target, - self->scale_factor, - self->scale_factor, + self->scale, + self->scale, &mv, &self->viewport, self->clip, diff --git a/gsk/vulkan/gskvulkanrenderer.c b/gsk/vulkan/gskvulkanrenderer.c index 217cdab717..71ec47b543 100644 --- a/gsk/vulkan/gskvulkanrenderer.c +++ b/gsk/vulkan/gskvulkanrenderer.c @@ -79,11 +79,11 @@ get_render_region (GskVulkanRenderer *self) GdkRectangle whole_surface; GdkRectangle extents; GdkSurface *surface; - int scale; + double scale; render_region = NULL; surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self->vulkan)); - scale = gdk_surface_get_scale_factor (surface); + scale = gdk_surface_get_scale (surface); whole_surface.x = 0; whole_surface.y = 0; @@ -97,10 +97,10 @@ get_render_region (GskVulkanRenderer *self) cairo_rectangle_int_t rect; cairo_region_get_rectangle (damage, i, &rect); cairo_region_union_rectangle (scaled_damage, &(cairo_rectangle_int_t) { - .x = rect.x * scale, - .y = rect.y * scale, - .width = rect.width * scale, - .height = rect.height * scale, + .x = (int) floor (rect.x * scale), + .y = (int) floor (rect.y * scale), + .width = (int) ceil ((rect.x + rect.width) * scale) - floor (rect.x * scale), + .height = (int) ceil ((rect.y + rect.height) * scale) - floor (rect.y * scale), }); } @@ -138,7 +138,7 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context, GskVulkanRenderer *self) { GdkSurface *window; - int scale_factor; + double scale; gsize width, height; guint i; @@ -148,9 +148,9 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context, self->targets = g_new (GskVulkanImage *, self->n_targets); window = gsk_renderer_get_surface (GSK_RENDERER (self)); - scale_factor = gdk_surface_get_scale_factor (window); - width = gdk_surface_get_width (window) * scale_factor; - height = gdk_surface_get_height (window) * scale_factor; + scale = gdk_surface_get_scale (window); + width = (int) ceil (gdk_surface_get_width (window) * scale); + height = (int) ceil (gdk_surface_get_height (window) * scale); for (i = 0; i < self->n_targets; i++) { -- cgit v1.2.1