diff --git a/include/render/vulkan.h b/include/render/vulkan.h index fe29fd5b0..0611d3c28 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -273,14 +273,6 @@ struct wlr_vk_renderer { uint64_t last_timeline_point; struct wl_list buffers; // wlr_vk_shared_buffer.link } stage; - - struct { - bool initialized; - uint32_t drm_format; - uint32_t width, height; - VkImage dst_image; - VkDeviceMemory dst_img_memory; - } read_pixels_cache; }; // vertex shader push constant range data diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index 29fa9b591..33536cfc2 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -1105,11 +1105,6 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) { vkDestroyDescriptorSetLayout(dev->dev, renderer->output_ds_layout, NULL); vkDestroyCommandPool(dev->dev, renderer->command_pool, NULL); - if (renderer->read_pixels_cache.initialized) { - vkFreeMemory(dev->dev, renderer->read_pixels_cache.dst_img_memory, NULL); - vkDestroyImage(dev->dev, renderer->read_pixels_cache.dst_image, NULL); - } - struct wlr_vk_instance *ini = dev->instance; vulkan_device_destroy(dev); vulkan_instance_destroy(ini); @@ -1120,6 +1115,7 @@ static bool vulkan_read_pixels(struct wlr_renderer *wlr_renderer, uint32_t drm_format, uint32_t stride, uint32_t width, uint32_t height, uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, void *data) { + VkResult res; struct wlr_vk_renderer *vk_renderer = vulkan_get_renderer(wlr_renderer); VkDevice dev = vk_renderer->dev->dev; VkImage src_image = vk_renderer->current_render_buffer->image; @@ -1154,78 +1150,39 @@ static bool vulkan_read_pixels(struct wlr_renderer *wlr_renderer, return false; } - VkResult res; + VkImageCreateInfo image_create_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = VK_IMAGE_TYPE_2D, + .format = dst_format, + .extent.width = width, + .extent.height = height, + .extent.depth = 1, + .arrayLayers = 1, + .mipLevels = 1, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_LINEAR, + .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT + }; VkImage dst_image; - VkDeviceMemory dst_img_memory; - bool use_cached = vk_renderer->read_pixels_cache.initialized && - vk_renderer->read_pixels_cache.drm_format == drm_format && - vk_renderer->read_pixels_cache.width == width && - vk_renderer->read_pixels_cache.height == height; + res = vkCreateImage(dev, &image_create_info, NULL, &dst_image); + if (res != VK_SUCCESS) { + wlr_vk_error("vkCreateImage", res); + return false; + } - if (use_cached) { - dst_image = vk_renderer->read_pixels_cache.dst_image; - dst_img_memory = vk_renderer->read_pixels_cache.dst_img_memory; - } else { - VkImageCreateInfo image_create_info = { - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .imageType = VK_IMAGE_TYPE_2D, - .format = dst_format, - .extent.width = width, - .extent.height = height, - .extent.depth = 1, - .arrayLayers = 1, - .mipLevels = 1, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = VK_IMAGE_TILING_LINEAR, - .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT - }; - res = vkCreateImage(dev, &image_create_info, NULL, &dst_image); - if (res != VK_SUCCESS) { - wlr_vk_error("vkCreateImage", res); - return false; - } + VkMemoryRequirements mem_reqs; + vkGetImageMemoryRequirements(dev, dst_image, &mem_reqs); - VkMemoryRequirements mem_reqs; - vkGetImageMemoryRequirements(dev, dst_image, &mem_reqs); + struct wlr_vk_buffer_span buffer_span = vulkan_get_stage_span(vk_renderer, mem_reqs.size); + if (buffer_span.buffer == NULL) { + goto error; + } - int mem_type = vulkan_find_mem_type(vk_renderer->dev, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | - VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - mem_reqs.memoryTypeBits); - if (mem_type < 0) { - wlr_log(WLR_ERROR, "vulkan_read_pixels: could not find adequate memory type"); - goto destroy_image; - } - - VkMemoryAllocateInfo mem_alloc_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - }; - mem_alloc_info.allocationSize = mem_reqs.size; - mem_alloc_info.memoryTypeIndex = mem_type; - - res = vkAllocateMemory(dev, &mem_alloc_info, NULL, &dst_img_memory); - if (res != VK_SUCCESS) { - wlr_vk_error("vkAllocateMemory", res); - goto destroy_image; - } - res = vkBindImageMemory(dev, dst_image, dst_img_memory, 0); - if (res != VK_SUCCESS) { - wlr_vk_error("vkBindImageMemory", res); - goto free_memory; - } - - if (vk_renderer->read_pixels_cache.initialized) { - vkFreeMemory(dev, vk_renderer->read_pixels_cache.dst_img_memory, NULL); - vkDestroyImage(dev, vk_renderer->read_pixels_cache.dst_image, NULL); - } - vk_renderer->read_pixels_cache.initialized = true; - vk_renderer->read_pixels_cache.drm_format = drm_format; - vk_renderer->read_pixels_cache.dst_image = dst_image; - vk_renderer->read_pixels_cache.dst_img_memory = dst_img_memory; - vk_renderer->read_pixels_cache.width = width; - vk_renderer->read_pixels_cache.height = height; + res = vkBindImageMemory(dev, dst_image, buffer_span.buffer->memory, buffer_span.alloc.start); + if (res != VK_SUCCESS) { + wlr_vk_error("vkBindImageMemory", res); + goto error; } VkCommandBuffer cb = vulkan_record_stage_cb(vk_renderer); @@ -1310,7 +1267,7 @@ static bool vulkan_read_pixels(struct wlr_renderer *wlr_renderer, VK_ACCESS_MEMORY_READ_BIT); if (!vulkan_submit_stage_wait(vk_renderer)) { - return false; + goto error; } VkImageSubresource img_sub_res = { @@ -1322,10 +1279,10 @@ static bool vulkan_read_pixels(struct wlr_renderer *wlr_renderer, vkGetImageSubresourceLayout(dev, dst_image, &img_sub_res, &img_sub_layout); void *v; - res = vkMapMemory(dev, dst_img_memory, 0, VK_WHOLE_SIZE, 0, &v); + res = vkMapMemory(dev, buffer_span.buffer->memory, 0, VK_WHOLE_SIZE, 0, &v); if (res != VK_SUCCESS) { wlr_vk_error("vkMapMemory", res); - return false; + goto error; } const char *d = (const char *)v + img_sub_layout.offset; @@ -1340,14 +1297,12 @@ static bool vulkan_read_pixels(struct wlr_renderer *wlr_renderer, } } - vkUnmapMemory(dev, dst_img_memory); - // Don't need to free anything else, since memory and image are cached - return true; -free_memory: - vkFreeMemory(dev, dst_img_memory, NULL); -destroy_image: + vkUnmapMemory(dev, buffer_span.buffer->memory); vkDestroyImage(dev, dst_image, NULL); + return true; +error: + vkDestroyImage(dev, dst_image, NULL); return false; }