diff options
author | Chih-Wei Huang <cwhuang@linux.org.tw> | 2016-12-07 13:01:00 +0800 |
---|---|---|
committer | Chih-Wei Huang <cwhuang@linux.org.tw> | 2016-12-07 13:01:00 +0800 |
commit | dffabc025cca524fecb7a03d0f65ec9c628025f8 (patch) | |
tree | 5335b24b2139be60b6f244037b7358df68acaa27 | |
parent | 524121d42bfdf8c1bd3565bd2adb0ffd7b52713f (diff) | |
parent | 2722144beddac0aa7065b478502c7c3a1f2a5451 (diff) | |
download | external_mesa3d-dffabc025cca524fecb7a03d0f65ec9c628025f8.zip external_mesa3d-dffabc025cca524fecb7a03d0f65ec9c628025f8.tar.gz external_mesa3d-dffabc025cca524fecb7a03d0f65ec9c628025f8.tar.bz2 |
Merge remote-tracking branch 'mesa/13.0' into nougat-x86
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | docs/relnotes/13.0.2.html | 189 | ||||
-rw-r--r-- | src/amd/common/ac_nir_to_llvm.c | 9 | ||||
-rw-r--r-- | src/amd/vulkan/radv_device.c | 18 | ||||
-rw-r--r-- | src/amd/vulkan/radv_image.c | 14 | ||||
-rw-r--r-- | src/amd/vulkan/radv_meta_clear.c | 2 | ||||
-rw-r--r-- | src/vulkan/wsi/Makefile.sources | 3 | ||||
-rw-r--r-- | src/vulkan/wsi/wsi_common.h | 1 | ||||
-rw-r--r-- | src/vulkan/wsi/wsi_common_queue.h | 154 | ||||
-rw-r--r-- | src/vulkan/wsi/wsi_common_wayland.c | 6 | ||||
-rw-r--r-- | src/vulkan/wsi/wsi_common_x11.c | 241 |
11 files changed, 596 insertions, 43 deletions
@@ -1 +1 @@ -13.0.1 +13.0.2 diff --git a/docs/relnotes/13.0.2.html b/docs/relnotes/13.0.2.html new file mode 100644 index 0000000..2f50199 --- /dev/null +++ b/docs/relnotes/13.0.2.html @@ -0,0 +1,189 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html lang="en"> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> + <title>Mesa Release Notes</title> + <link rel="stylesheet" type="text/css" href="../mesa.css"> +</head> +<body> + +<div class="header"> + <h1>The Mesa 3D Graphics Library</h1> +</div> + +<iframe src="../contents.html"></iframe> +<div class="content"> + +<h1>Mesa 13.0.2 Release Notes / November 28, 2016</h1> + +<p> +Mesa 13.0.2 is a bug fix release which fixes bugs found since the 13.0.1 release. +</p> +<p> +Mesa 13.0.2 implements the OpenGL 4.4 API, but the version reported by +glGetString(GL_VERSION) or glGetIntegerv(GL_MAJOR_VERSION) / +glGetIntegerv(GL_MINOR_VERSION) depends on the particular driver being used. +Some drivers don't support all the features required in OpenGL 4.4. OpenGL +4.4 is <strong>only</strong> available if requested at context creation +because compatibility contexts are not supported. +</p> + + +<h2>SHA256 checksums</h2> +<pre> +6014233a5db6032ab8de4881384871bbe029de684502707794ce7b3e6beec308 mesa-13.0.2.tar.gz +a6ed622645f4ed61da418bf65adde5bcc4bb79023c36ba7d6b45b389da4416d5 mesa-13.0.2.tar.xz +</pre> + + +<h2>New features</h2> +<p>None</p> + + +<h2>Bug fixes</h2> + +<ul> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=97321">Bug 97321</a> - Query INFO_LOG_LENGTH for empty info log should return 0</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=97420">Bug 97420</a> - "#version 0" crashes glsl_compiler</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=98632">Bug 98632</a> - Fix build on Hurd without PATH_MAX</li> + +</ul> + + +<h2>Changes</h2> + +<p>Ben Widawsky (3):</p> +<ul> + <li>i965: Add some APL and KBL SKU strings</li> + <li>i965: Reorder PCI ID list to match release order</li> + <li>i965/glk: Add basic Geminilake support</li> +</ul> + +<p>Dave Airlie (14):</p> +<ul> + <li>radv: fix texturesamples to handle single sample case</li> + <li>wsi: fix VK_INCOMPLETE for vkGetSwapchainImagesKHR</li> + <li>radv: don't crash on null swapchain destroy.</li> + <li>ac/nir/llvm: fix channel in texture gather lowering code.</li> + <li>radv: make sure to flush input attachments correctly.</li> + <li>radv: fix image view creation for depth and stencil only</li> + <li>radv: spir-v allows texture size query with and without lod.</li> + <li>vulkan/wsi/x11: handle timeouts properly in next image acquire (v1.1)</li> + <li>vulkan/wsi: store present mode in swapchain base class</li> + <li>vulkan/wsi/x11: add support for IMMEDIATE present mode</li> + <li>radv: fix texel fetch offset with 2d arrays.</li> + <li>radv/si: fix optimal micro tile selection</li> + <li>radv/ac/llvm: shadow samplers only return one value.</li> + <li>radv: fix 3D clears with baseMiplevel</li> +</ul> + +<p>Eduardo Lima Mitev (2):</p> +<ul> + <li>vulkan/wsi/x11: Fix behavior of vkGetPhysicalDeviceSurfaceFormatsKHR</li> + <li>vulkan/wsi/x11: Fix behavior of vkGetPhysicalDeviceSurfacePresentModesKHR</li> +</ul> + +<p>Emil Velikov (5):</p> +<ul> + <li>docs: add sha256 checksums for 13.0.1</li> + <li>cherry-ignore: add reverted LLVM_LIBDIR patch</li> + <li>anv: fix enumeration of properties</li> + <li>radv: honour the number of properties available</li> + <li>Update version to 13.0.2</li> +</ul> + +<p>Eric Anholt (3):</p> +<ul> + <li>vc4: Don't abort when a shader compile fails.</li> + <li>vc4: Clamp the shadow comparison value.</li> + <li>vc4: Fix register class handling of DDX/DDY arguments.</li> +</ul> + +<p>Gwan-gyeong Mun (2):</p> +<ul> + <li>util/disk_cache: close a previously opened handle in disk_cache_put (v2)</li> + <li>anv: Fix unintentional integer overflow in anv_CreateDmaBufImageINTEL</li> +</ul> + +<p>Iago Toral Quiroga (1):</p> +<ul> + <li>anv/format: handle unsupported formats properly</li> +</ul> + +<p>Ian Romanick (2):</p> +<ul> + <li>glcpp: Handle '#version 0' and other invalid values</li> + <li>glsl: Parse 0 as a preprocessor INTCONSTANT</li> +</ul> + +<p>Jason Ekstrand (15):</p> +<ul> + <li>anv/gen8: Stall when needed in Cmd(Set|Reset)Event</li> + <li>anv/wsi: Set the fence to signaled in AcquireNextImageKHR</li> + <li>anv: Rework fences</li> + <li>vulkan/wsi/wayland: Include pthread.h</li> + <li>vulkan/wsi/wayland: Clean up some error handling paths</li> + <li>vulkan/wsi: Report the correct min/maxImageCount</li> + <li>i965/gs: Allow primitive id to be a system value</li> + <li>anv: Handle null in all destructors</li> + <li>anv/fence: Handle ANV_FENCE_CREATE_SIGNALED_BIT</li> + <li>nir/spirv: Fix handling of gl_PrimitiveId</li> + <li>anv/blorp: Ignore clears for attachments first used as resolve destinations</li> + <li>anv: Implement a depth stall restriction on gen7</li> + <li>anv/cmd_buffer: Handle running out of binding tables in compute shaders</li> + <li>anv/cmd_buffer: Emit a CS stall before setting a CS pipeline</li> + <li>vulkan/wsi/x11: Implement FIFO mode.</li> +</ul> + +<p>Jordan Justen (2):</p> +<ul> + <li>isl: Fix height calculation in isl_msaa_interleaved_scale_px_to_sa</li> + <li>i965/hsw: Set integer mode in sampling state for stencil texturing</li> +</ul> + +<p>Kenneth Graunke (4):</p> +<ul> + <li>intel: Set min_ds_entries on Broxton.</li> + <li>i965: Fix compute shader crash.</li> + <li>mesa: Drop PATH_MAX usage.</li> + <li>i965: Fix GS push inputs with enhanced layouts.</li> +</ul> + +<p>Kevin Strasser (1):</p> +<ul> + <li>vulkan/wsi: Add a thread-safe queue implementation</li> +</ul> + +<p>Lionel Landwerlin (1):</p> +<ul> + <li>anv: fix multi level clears with VK_REMAINING_MIP_LEVELS</li> +</ul> + +<p>Lucas Stach (1):</p> +<ul> + <li>gbm: request correct version of the DRI2_FENCE extension</li> +</ul> + +<p>Nicolai Hähnle (2):</p> +<ul> + <li>radeonsi: store group_size_variable in struct si_compute</li> + <li>glsl/lower_output_reads: fix geometry shader output handling with conditional emit</li> +</ul> + +<p>Steinar H. Gunderson (1):</p> +<ul> + <li>Fix races during _mesa_HashWalk().</li> +</ul> + +<p>Tapani Pälli (1):</p> +<ul> + <li>mesa: fix empty program log length</li> +</ul> + + +</div> +</body> +</html> diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c index 31d7b6e..0daef08 100644 --- a/src/amd/common/ac_nir_to_llvm.c +++ b/src/amd/common/ac_nir_to_llvm.c @@ -3517,12 +3517,13 @@ static void visit_tex(struct nir_to_llvm_context *ctx, nir_tex_instr *instr) if (offsets && instr->op == nir_texop_txf) { nir_const_value *const_offset = nir_src_as_const_value(instr->src[const_src].src); - + int num_offsets = instr->src[const_src].src.ssa->num_components; assert(const_offset); - if (instr->coord_components > 2) + num_offsets = MIN2(num_offsets, instr->coord_components); + if (num_offsets > 2) address[2] = LLVMBuildAdd(ctx->builder, address[2], LLVMConstInt(ctx->i32, const_offset->i32[2], false), ""); - if (instr->coord_components > 1) + if (num_offsets > 1) address[1] = LLVMBuildAdd(ctx->builder, address[1], LLVMConstInt(ctx->i32, const_offset->i32[1], false), ""); address[0] = LLVMBuildAdd(ctx->builder, @@ -3544,6 +3545,8 @@ static void visit_tex(struct nir_to_llvm_context *ctx, nir_tex_instr *instr) if (instr->op == nir_texop_query_levels) result = LLVMBuildExtractElement(ctx->builder, result, LLVMConstInt(ctx->i32, 3, false), ""); + else if (instr->is_shadow && instr->op != nir_texop_txs && instr->op != nir_texop_lod) + result = LLVMBuildExtractElement(ctx->builder, result, ctx->i32zero, ""); else if (instr->op == nir_texop_txs && instr->sampler_dim == GLSL_SAMPLER_DIM_CUBE && instr->is_array) { diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index 4a924ea..94a2ef0 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -659,17 +659,15 @@ VkResult radv_EnumerateInstanceExtensionProperties( uint32_t* pPropertyCount, VkExtensionProperties* pProperties) { - unsigned i; if (pProperties == NULL) { *pPropertyCount = ARRAY_SIZE(global_extensions); return VK_SUCCESS; } - for (i = 0; i < *pPropertyCount; i++) - memcpy(&pProperties[i], &global_extensions[i], sizeof(VkExtensionProperties)); + *pPropertyCount = MIN2(*pPropertyCount, ARRAY_SIZE(global_extensions)); + typed_memcpy(pProperties, global_extensions, *pPropertyCount); - *pPropertyCount = i; - if (i < ARRAY_SIZE(global_extensions)) + if (*pPropertyCount < ARRAY_SIZE(global_extensions)) return VK_INCOMPLETE; return VK_SUCCESS; @@ -681,19 +679,17 @@ VkResult radv_EnumerateDeviceExtensionProperties( uint32_t* pPropertyCount, VkExtensionProperties* pProperties) { - unsigned i; - if (pProperties == NULL) { *pPropertyCount = ARRAY_SIZE(device_extensions); return VK_SUCCESS; } - for (i = 0; i < *pPropertyCount; i++) - memcpy(&pProperties[i], &device_extensions[i], sizeof(VkExtensionProperties)); + *pPropertyCount = MIN2(*pPropertyCount, ARRAY_SIZE(device_extensions)); + typed_memcpy(pProperties, device_extensions, *pPropertyCount); - *pPropertyCount = i; - if (i < ARRAY_SIZE(device_extensions)) + if (*pPropertyCount < ARRAY_SIZE(device_extensions)) return VK_INCOMPLETE; + return VK_SUCCESS; } diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c index 3099d83..9649158 100644 --- a/src/amd/vulkan/radv_image.c +++ b/src/amd/vulkan/radv_image.c @@ -831,29 +831,29 @@ void radv_image_set_optimal_micro_tile_mode(struct radv_device *device, switch (micro_tile_mode) { case 0: /* displayable */ switch (image->surface.bpe) { - case 8: + case 1: image->surface.tiling_index[0] = 10; break; - case 16: + case 2: image->surface.tiling_index[0] = 11; break; - default: /* 32, 64 */ + default: /* 4, 8 */ image->surface.tiling_index[0] = 12; break; } break; case 1: /* thin */ switch (image->surface.bpe) { - case 8: + case 1: image->surface.tiling_index[0] = 14; break; - case 16: + case 2: image->surface.tiling_index[0] = 15; break; - case 32: + case 4: image->surface.tiling_index[0] = 16; break; - default: /* 64, 128 */ + default: /* 8, 16 */ image->surface.tiling_index[0] = 17; break; } diff --git a/src/amd/vulkan/radv_meta_clear.c b/src/amd/vulkan/radv_meta_clear.c index 7e3e5f4..a347703 100644 --- a/src/amd/vulkan/radv_meta_clear.c +++ b/src/amd/vulkan/radv_meta_clear.c @@ -998,7 +998,7 @@ radv_cmd_clear_image(struct radv_cmd_buffer *cmd_buffer, const VkImageSubresourceRange *range = &ranges[r]; for (uint32_t l = 0; l < radv_get_levelCount(image, range); ++l) { const uint32_t layer_count = image->type == VK_IMAGE_TYPE_3D ? - radv_minify(image->extent.depth, l) : + radv_minify(image->extent.depth, range->baseMipLevel + l) : radv_get_layerCount(image, range); for (uint32_t s = 0; s < layer_count; ++s) { struct radv_image_view iview; diff --git a/src/vulkan/wsi/Makefile.sources b/src/vulkan/wsi/Makefile.sources index 3139e6d..50660f9 100644 --- a/src/vulkan/wsi/Makefile.sources +++ b/src/vulkan/wsi/Makefile.sources @@ -1,6 +1,7 @@ VULKAN_WSI_FILES := \ - wsi_common.h + wsi_common.h \ + wsi_common_queue.h VULKAN_WSI_WAYLAND_FILES := \ wsi_common_wayland.c \ diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h index ee67511..a1f5a40 100644 --- a/src/vulkan/wsi/wsi_common.h +++ b/src/vulkan/wsi/wsi_common.h @@ -53,6 +53,7 @@ struct wsi_swapchain { VkAllocationCallbacks alloc; const struct wsi_image_fns *image_fns; VkFence fences[3]; + VkPresentModeKHR present_mode; VkResult (*destroy)(struct wsi_swapchain *swapchain, const VkAllocationCallbacks *pAllocator); diff --git a/src/vulkan/wsi/wsi_common_queue.h b/src/vulkan/wsi/wsi_common_queue.h new file mode 100644 index 0000000..0e72c8d --- /dev/null +++ b/src/vulkan/wsi/wsi_common_queue.h @@ -0,0 +1,154 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef VULKAN_WSI_COMMON_QUEUE_H +#define VULKAN_WSI_COMMON_QUEUE_H + +#include <time.h> +#include <pthread.h> +#include "util/u_vector.h" + +struct wsi_queue { + struct u_vector vector; + pthread_mutex_t mutex; + pthread_cond_t cond; +}; + +static inline int +wsi_queue_init(struct wsi_queue *queue, int length) +{ + int ret; + + uint32_t length_pow2 = 4; + while (length_pow2 < length) + length_pow2 *= 2; + + ret = u_vector_init(&queue->vector, sizeof(uint32_t), + sizeof(uint32_t) * length_pow2); + if (!ret) + return ENOMEM; + + pthread_condattr_t condattr; + ret = pthread_condattr_init(&condattr); + if (ret) + goto fail_vector; + + ret = pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); + if (ret) + goto fail_condattr; + + ret = pthread_cond_init(&queue->cond, &condattr); + if (ret) + goto fail_condattr; + + ret = pthread_mutex_init(&queue->mutex, NULL); + if (ret) + goto fail_cond; + + return 0; + +fail_cond: + pthread_cond_destroy(&queue->cond); +fail_condattr: + pthread_condattr_destroy(&condattr); +fail_vector: + u_vector_finish(&queue->vector); + + return ret; +} + +static inline void +wsi_queue_destroy(struct wsi_queue *queue) +{ + u_vector_finish(&queue->vector); + pthread_mutex_destroy(&queue->mutex); + pthread_cond_destroy(&queue->cond); +} + +static inline void +wsi_queue_push(struct wsi_queue *queue, uint32_t index) +{ + uint32_t *elem; + + pthread_mutex_lock(&queue->mutex); + + if (u_vector_length(&queue->vector) == 0) + pthread_cond_signal(&queue->cond); + + elem = u_vector_add(&queue->vector); + *elem = index; + + pthread_mutex_unlock(&queue->mutex); +} + +#define NSEC_PER_SEC 1000000000 +#define INT_TYPE_MAX(type) ((1ull << (sizeof(type) * 8 - 1)) - 1) + +static inline VkResult +wsi_queue_pull(struct wsi_queue *queue, uint32_t *index, uint64_t timeout) +{ + VkResult result; + int32_t ret; + + pthread_mutex_lock(&queue->mutex); + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + uint32_t abs_nsec = now.tv_nsec + timeout % NSEC_PER_SEC; + uint64_t abs_sec = now.tv_sec + (abs_nsec / NSEC_PER_SEC) + + (timeout / NSEC_PER_SEC); + abs_nsec %= NSEC_PER_SEC; + + /* Avoid roll-over in tv_sec on 32-bit systems if the user provided timeout + * is UINT64_MAX + */ + struct timespec abstime; + abstime.tv_nsec = abs_nsec; + abstime.tv_sec = MIN2(abs_sec, INT_TYPE_MAX(abstime.tv_sec)); + + while (u_vector_length(&queue->vector) == 0) { + ret = pthread_cond_timedwait(&queue->cond, &queue->mutex, &abstime); + if (ret == 0) { + continue; + } else if (ret == ETIMEDOUT) { + result = VK_TIMEOUT; + goto end; + } else { + /* Something went badly wrong */ + result = VK_ERROR_OUT_OF_DATE_KHR; + goto end; + } + } + + uint32_t *elem = u_vector_remove(&queue->vector); + *index = *elem; + result = VK_SUCCESS; + +end: + pthread_mutex_unlock(&queue->mutex); + + return result; +} + +#endif /* VULKAN_WSI_COMMON_QUEUE_H */ diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c index a8130ce..f6c218b 100644 --- a/src/vulkan/wsi/wsi_common_wayland.c +++ b/src/vulkan/wsi/wsi_common_wayland.c @@ -576,7 +576,7 @@ wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain, { struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain; - if (chain->present_mode == VK_PRESENT_MODE_FIFO_KHR) { + if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) { while (!chain->fifo_ready) { int ret = wl_display_dispatch_queue(chain->display->display, chain->queue); @@ -589,7 +589,7 @@ wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain, wl_surface_attach(chain->surface, chain->images[image_index].buffer, 0, 0); wl_surface_damage(chain->surface, 0, 0, INT32_MAX, INT32_MAX); - if (chain->present_mode == VK_PRESENT_MODE_FIFO_KHR) { + if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) { struct wl_callback *frame = wl_surface_frame(chain->surface); wl_proxy_set_queue((struct wl_proxy *)frame, chain->queue); wl_callback_add_listener(frame, &frame_listener, chain); @@ -717,12 +717,12 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, chain->base.acquire_next_image = wsi_wl_swapchain_acquire_next_image; chain->base.queue_present = wsi_wl_swapchain_queue_present; chain->base.image_fns = image_fns; + chain->base.present_mode = pCreateInfo->presentMode; chain->surface = surface->surface; chain->extent = pCreateInfo->imageExtent; chain->vk_format = pCreateInfo->imageFormat; chain->drm_format = wl_drm_format_for_vk_format(chain->vk_format, alpha); - chain->present_mode = pCreateInfo->presentMode; chain->fifo_ready = true; chain->image_count = num_images; diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 09718eb..8e0043f 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -34,10 +34,12 @@ #include <errno.h> #include <string.h> +#include <poll.h> #include "util/hash_table.h" #include "wsi_common.h" #include "wsi_common_x11.h" +#include "wsi_common_queue.h" #define typed_memcpy(dest, src, count) ({ \ static_assert(sizeof(*src) == sizeof(*dest), ""); \ @@ -142,7 +144,9 @@ static const VkSurfaceFormatKHR formats[] = { }; static const VkPresentModeKHR present_modes[] = { + VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR, + VK_PRESENT_MODE_FIFO_KHR, }; static xcb_screen_t * @@ -488,8 +492,15 @@ struct x11_swapchain { xcb_present_event_t event_id; xcb_special_event_t * special_event; uint64_t send_sbc; + uint64_t last_present_msc; uint32_t stamp; + bool threaded; + VkResult status; + struct wsi_queue present_queue; + struct wsi_queue acquire_queue; + pthread_t queue_manager; + struct x11_image images[0]; }; @@ -540,6 +551,8 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain, for (unsigned i = 0; i < chain->image_count; i++) { if (chain->images[i].pixmap == idle->pixmap) { chain->images[i].busy = false; + if (chain->threaded) + wsi_queue_push(&chain->acquire_queue, i); break; } } @@ -547,7 +560,13 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain, break; } - case XCB_PRESENT_COMPLETE_NOTIFY: + case XCB_PRESENT_EVENT_COMPLETE_NOTIFY: { + xcb_present_complete_notify_event_t *complete = (void *) event; + if (complete->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) + chain->last_present_msc = complete->msc; + break; + } + default: break; } @@ -555,14 +574,33 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain, return VK_SUCCESS; } -static VkResult -x11_acquire_next_image(struct wsi_swapchain *anv_chain, - uint64_t timeout, - VkSemaphore semaphore, - uint32_t *image_index) + +static uint64_t wsi_get_current_time(void) { - struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain; + uint64_t current_time; + struct timespec tv; + + clock_gettime(CLOCK_MONOTONIC, &tv); + current_time = tv.tv_nsec + tv.tv_sec*1000000000ull; + return current_time; +} + +static uint64_t wsi_get_absolute_timeout(uint64_t timeout) +{ + uint64_t current_time = wsi_get_current_time(); + + timeout = MIN2(UINT64_MAX - current_time, timeout); + + return current_time + timeout; +} +static VkResult +x11_acquire_next_image_poll_x11(struct x11_swapchain *chain, + uint32_t *image_index, uint64_t timeout) +{ + xcb_generic_event_t *event; + struct pollfd pfds; + uint64_t atimeout; while (1) { for (uint32_t i = 0; i < chain->image_count; i++) { if (!chain->images[i].busy) { @@ -575,10 +613,39 @@ x11_acquire_next_image(struct wsi_swapchain *anv_chain, } xcb_flush(chain->conn); - xcb_generic_event_t *event = - xcb_wait_for_special_event(chain->conn, chain->special_event); - if (!event) - return VK_ERROR_OUT_OF_DATE_KHR; + + if (timeout == UINT64_MAX) { + event = xcb_wait_for_special_event(chain->conn, chain->special_event); + if (!event) + return VK_ERROR_OUT_OF_DATE_KHR; + } else { + event = xcb_poll_for_special_event(chain->conn, chain->special_event); + if (!event) { + int ret; + if (timeout == 0) + return VK_NOT_READY; + + atimeout = wsi_get_absolute_timeout(timeout); + + pfds.fd = xcb_get_file_descriptor(chain->conn); + pfds.events = POLLIN; + ret = poll(&pfds, 1, timeout / 1000 / 1000); + if (ret == 0) + return VK_TIMEOUT; + if (ret == -1) + return VK_ERROR_OUT_OF_DATE_KHR; + + /* If a non-special event happens, the fd will still + * poll. So recalculate the timeout now just in case. + */ + uint64_t current_time = wsi_get_current_time(); + if (atimeout > current_time) + timeout = atimeout - current_time; + else + timeout = 0; + continue; + } + } VkResult result = x11_handle_dri3_present_event(chain, (void *)event); free(event); @@ -588,21 +655,43 @@ x11_acquire_next_image(struct wsi_swapchain *anv_chain, } static VkResult -x11_queue_present(struct wsi_swapchain *anv_chain, - uint32_t image_index) +x11_acquire_next_image_from_queue(struct x11_swapchain *chain, + uint32_t *image_index_out, uint64_t timeout) +{ + assert(chain->threaded); + + uint32_t image_index; + VkResult result = wsi_queue_pull(&chain->acquire_queue, + &image_index, timeout); + if (result != VK_SUCCESS) { + return result; + } else if (chain->status != VK_SUCCESS) { + return chain->status; + } + + assert(image_index < chain->image_count); + xshmfence_await(chain->images[image_index].shm_fence); + + *image_index_out = image_index; + + return VK_SUCCESS; +} + +static VkResult +x11_present_to_x11(struct x11_swapchain *chain, uint32_t image_index, + uint32_t target_msc) { - struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain; struct x11_image *image = &chain->images[image_index]; assert(image_index < chain->image_count); uint32_t options = XCB_PRESENT_OPTION_NONE; - int64_t target_msc = 0; int64_t divisor = 0; int64_t remainder = 0; - options |= XCB_PRESENT_OPTION_ASYNC; + if (chain->base.present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) + options |= XCB_PRESENT_OPTION_ASYNC; xshmfence_reset(image->shm_fence); @@ -632,6 +721,82 @@ x11_queue_present(struct wsi_swapchain *anv_chain, } static VkResult +x11_acquire_next_image(struct wsi_swapchain *anv_chain, + uint64_t timeout, + VkSemaphore semaphore, + uint32_t *image_index) +{ + struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain; + + if (chain->threaded) { + return x11_acquire_next_image_from_queue(chain, image_index, timeout); + } else { + return x11_acquire_next_image_poll_x11(chain, image_index, timeout); + } +} + +static VkResult +x11_queue_present(struct wsi_swapchain *anv_chain, + uint32_t image_index) +{ + struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain; + + if (chain->threaded) { + wsi_queue_push(&chain->present_queue, image_index); + return chain->status; + } else { + return x11_present_to_x11(chain, image_index, 0); + } +} + +static void * +x11_manage_fifo_queues(void *state) +{ + struct x11_swapchain *chain = state; + VkResult result; + + assert(chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR); + + while (chain->status == VK_SUCCESS) { + /* It should be safe to unconditionally block here. Later in the loop + * we blocks until the previous present has landed on-screen. At that + * point, we should have received IDLE_NOTIFY on all images presented + * before that point so the client should be able to acquire any image + * other than the currently presented one. + */ + uint32_t image_index; + result = wsi_queue_pull(&chain->present_queue, &image_index, INT64_MAX); + if (result != VK_SUCCESS) { + goto fail; + } else if (chain->status != VK_SUCCESS) { + return NULL; + } + + uint64_t target_msc = chain->last_present_msc + 1; + result = x11_present_to_x11(chain, image_index, target_msc); + if (result != VK_SUCCESS) + goto fail; + + while (chain->last_present_msc < target_msc) { + xcb_generic_event_t *event = + xcb_wait_for_special_event(chain->conn, chain->special_event); + if (!event) + goto fail; + + result = x11_handle_dri3_present_event(chain, (void *)event); + if (result != VK_SUCCESS) + goto fail; + } + } + +fail: + chain->status = result; + wsi_queue_push(&chain->acquire_queue, UINT32_MAX); + + return NULL; +} + +static VkResult x11_image_init(VkDevice device_h, struct x11_swapchain *chain, const VkSwapchainCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks* pAllocator, @@ -729,6 +894,15 @@ x11_swapchain_destroy(struct wsi_swapchain *anv_chain, for (uint32_t i = 0; i < chain->image_count; i++) x11_image_finish(chain, pAllocator, &chain->images[i]); + if (chain->threaded) { + chain->status = VK_ERROR_OUT_OF_DATE_KHR; + /* Push a UINT32_MAX to wake up the manager */ + wsi_queue_push(&chain->present_queue, UINT32_MAX); + pthread_join(chain->queue_manager, NULL); + wsi_queue_destroy(&chain->acquire_queue); + wsi_queue_destroy(&chain->present_queue); + } + xcb_unregister_for_special_event(chain->conn, chain->special_event); vk_free(pAllocator, chain); @@ -773,12 +947,16 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, chain->base.acquire_next_image = x11_acquire_next_image; chain->base.queue_present = x11_queue_present; chain->base.image_fns = image_fns; + chain->base.present_mode = pCreateInfo->presentMode; chain->conn = conn; chain->window = window; chain->depth = geometry->depth; chain->extent = pCreateInfo->imageExtent; chain->image_count = num_images; chain->send_sbc = 0; + chain->last_present_msc = 0; + chain->threaded = false; + chain->status = VK_SUCCESS; free(geometry); @@ -817,6 +995,37 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, goto fail_init_images; } + if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) { + chain->threaded = true; + + /* Initialize our queues. We make them image_count + 1 because we will + * occasionally use UINT32_MAX to signal the other thread that an error + * has occurred and we don't want an overflow. + */ + int ret; + ret = wsi_queue_init(&chain->acquire_queue, chain->image_count + 1); + if (ret) { + goto fail_init_images; + } + + ret = wsi_queue_init(&chain->present_queue, chain->image_count + 1); + if (ret) { + wsi_queue_destroy(&chain->acquire_queue); + goto fail_init_images; + } + + for (unsigned i = 0; i < chain->image_count; i++) + wsi_queue_push(&chain->acquire_queue, i); + + ret = pthread_create(&chain->queue_manager, NULL, + x11_manage_fifo_queues, chain); + if (ret) { + wsi_queue_destroy(&chain->present_queue); + wsi_queue_destroy(&chain->acquire_queue); + goto fail_init_images; + } + } + *swapchain_out = &chain->base; return VK_SUCCESS; |