Use separate magma connection for display
MA-199 #done
Change-Id: Ia8377ee8cdbe4586ba396ab96af7deef0aea52cc
diff --git a/src/intel/vulkan/anv_magma.cc b/src/intel/vulkan/anv_magma.cc
index d8ee2a5..0f4f225 100644
--- a/src/intel/vulkan/anv_magma.cc
+++ b/src/intel/vulkan/anv_magma.cc
@@ -20,8 +20,7 @@
int anv_gem_connect(anv_device* device)
{
- device->connection =
- magma_open(device->fd, MAGMA_CAPABILITY_RENDERING | MAGMA_CAPABILITY_DISPLAY);
+ device->connection = magma_open(device->fd, MAGMA_CAPABILITY_RENDERING);
if (!device->connection)
return DRET_MSG(-1, "magma_system_open failed");
diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 72c1e89..be5440d 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -33,7 +33,9 @@
#include "anv_wsi_magma.h"
static const struct wsi_magma_callbacks wsi_magma_cbs = {
- .get_magma_connection = anv_wsi_magma_get_connection,
+ .get_render_connection = anv_wsi_magma_get_render_connection,
+ .open_display_connection = anv_wsi_magma_open_display_connection,
+ .close_display_connection = anv_wsi_magma_close_display_connection,
.create_wsi_image = anv_wsi_magma_image_create,
.free_wsi_image = anv_wsi_magma_image_free,
};
diff --git a/src/intel/vulkan/anv_wsi_magma.cc b/src/intel/vulkan/anv_wsi_magma.cc
index 13a7c80..2bd5a9b 100644
--- a/src/intel/vulkan/anv_wsi_magma.cc
+++ b/src/intel/vulkan/anv_wsi_magma.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "anv_wsi_magma.h"
+#include "magma.h"
#include "wsi_common_magma.h"
#include "anv_private.h"
@@ -29,11 +30,21 @@
pSurface);
}
-void* anv_wsi_magma_get_connection(VkDevice device)
+void* anv_wsi_magma_get_render_connection(VkDevice device)
{
return anv_device_from_handle(device)->connection;
}
+void* anv_wsi_magma_open_display_connection(VkDevice device)
+{
+ return magma_open(anv_device_from_handle(device)->fd, MAGMA_CAPABILITY_DISPLAY);
+}
+
+void anv_wsi_magma_close_display_connection(void* connection)
+{
+ magma_close(reinterpret_cast<magma_connection_t*>(connection));
+}
+
VkResult anv_wsi_magma_image_create(VkDevice device_h, const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkImage* image_p,
VkDeviceMemory* memory_p, uint32_t* size, uint32_t* offset,
diff --git a/src/intel/vulkan/anv_wsi_magma.h b/src/intel/vulkan/anv_wsi_magma.h
index da51ef5..872e0b9 100644
--- a/src/intel/vulkan/anv_wsi_magma.h
+++ b/src/intel/vulkan/anv_wsi_magma.h
@@ -11,7 +11,10 @@
extern "C" {
#endif
-void* anv_wsi_magma_get_connection(VkDevice device);
+void* anv_wsi_magma_get_render_connection(VkDevice device);
+
+void* anv_wsi_magma_open_display_connection(VkDevice device);
+void anv_wsi_magma_close_display_connection(void* connection);
VkResult anv_wsi_magma_image_create(VkDevice device_h, const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkImage* image_p,
diff --git a/src/intel/vulkan/tests/test_wsi_magma.cc b/src/intel/vulkan/tests/test_wsi_magma.cc
index a0bcf9a..2a96634 100644
--- a/src/intel/vulkan/tests/test_wsi_magma.cc
+++ b/src/intel/vulkan/tests/test_wsi_magma.cc
@@ -10,6 +10,8 @@
class TestWsiMagma {
public:
+ ~TestWsiMagma();
+
bool Init();
bool Run(uint32_t frame_count);
@@ -18,7 +20,7 @@
VkDevice device_;
VkSurfaceKHR surface_;
VkExtent2D extent_;
- VkSwapchainKHR swapchain_;
+ VkSwapchainKHR swapchain_ = VK_NULL_HANDLE;
VkQueue queue_;
PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR_;
@@ -305,6 +307,12 @@
return true;
}
+TestWsiMagma::~TestWsiMagma()
+{
+ if (swapchain_ != VK_NULL_HANDLE)
+ fpDestroySwapchainKHR_(device_, swapchain_, nullptr);
+}
+
int main(int argc, char** argv)
{
VulkanShimInit();
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index b1a1d19..271c800 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -103,7 +103,9 @@
};
struct wsi_magma_callbacks {
- void* (*get_magma_connection)(VkDevice device);
+ void* (*get_render_connection)(VkDevice device);
+ void* (*open_display_connection)(VkDevice device);
+ void (*close_display_connection)(void* connection);
VkResult (*create_wsi_image)(VkDevice device_h, const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkImage* image_p,
VkDeviceMemory* memory_p, uint32_t* size_p, uint32_t* offset_p,
diff --git a/src/vulkan/wsi/wsi_common_magma.cc b/src/vulkan/wsi/wsi_common_magma.cc
index 89aceaf..2010b24 100644
--- a/src/vulkan/wsi/wsi_common_magma.cc
+++ b/src/vulkan/wsi/wsi_common_magma.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <functional>
#include <memory>
#include <vector>
@@ -32,56 +33,96 @@
public:
WsiMagma(const wsi_magma_callbacks* callbacks) : callbacks_(callbacks) {}
- magma_connection_t* connection(VkDevice device)
- {
- return reinterpret_cast<magma_connection_t*>(callbacks_->get_magma_connection(device));
- }
-
const wsi_magma_callbacks* callbacks() { return callbacks_; }
private:
const wsi_magma_callbacks* callbacks_;
};
+typedef std::unique_ptr<magma_connection_t, std::function<void(magma_connection_t*)>>
+ magma_connection_unique_ptr_t;
+
+class WsiMagmaConnections {
+public:
+ WsiMagmaConnections(magma_connection_t* render_connection,
+ magma_connection_t* display_connection, const wsi_magma_callbacks* callbacks)
+ : callbacks_(callbacks), render_connection_(render_connection),
+ display_connection_(display_connection, [callbacks](magma_connection_t* connection) {
+ callbacks->close_display_connection(connection);
+ })
+ {
+ }
+
+ magma_connection_t* render_connection() { return render_connection_; }
+
+ magma_connection_t* display_connection() { return display_connection_.get(); }
+
+ static std::unique_ptr<WsiMagmaConnections> Create(const wsi_magma_callbacks* callbacks,
+ VkDevice device)
+ {
+ auto render_connection =
+ reinterpret_cast<magma_connection_t*>(callbacks->get_render_connection(device));
+ if (!render_connection)
+ return DRETP(nullptr, "null render connection");
+
+ auto display_connection =
+ reinterpret_cast<magma_connection_t*>(callbacks->open_display_connection(device));
+ if (!display_connection)
+ return DRETP(nullptr, "null display connection");
+
+ return std::make_unique<WsiMagmaConnections>(render_connection, display_connection,
+ callbacks);
+ }
+
+private:
+ const wsi_magma_callbacks* callbacks_; // not owned
+ magma_connection_t* render_connection_; // not owned
+ magma_connection_unique_ptr_t display_connection_;
+};
+
//////////////////////////////////////////////////////////////////////////////
class MagmaImage {
public:
static std::unique_ptr<MagmaImage> Create(VkDevice device, const wsi_magma_callbacks* callbacks,
- magma_connection_t* connection,
+ std::shared_ptr<WsiMagmaConnections> connections,
const VkSwapchainCreateInfoKHR* create_info,
const VkAllocationCallbacks* pAllocator);
- ~MagmaImage() { callbacks_->free_wsi_image(device_, allocator_, image_, device_memory_); }
+ ~MagmaImage();
- magma_buffer_t buffer_handle() { return buffer_handle_; }
+ magma_buffer_t display_buffer() { return display_buffer_; }
+
+ magma_semaphore_t display_semaphore() { return display_semaphore_; }
VkImage image() { return image_; }
- magma_semaphore_t semaphore() { return semaphore_; }
-
private:
MagmaImage(VkDevice device, const wsi_magma_callbacks* callbacks,
- const VkAllocationCallbacks* allocator, magma_buffer_t buffer_handle, VkImage image,
- VkDeviceMemory device_memory, magma_semaphore_t semaphore)
- : device_(device), allocator_(allocator), callbacks_(callbacks),
- buffer_handle_(buffer_handle), image_(image), device_memory_(device_memory),
- semaphore_(semaphore)
+ std::shared_ptr<WsiMagmaConnections> connections, magma_buffer_t render_buffer,
+ magma_buffer_t display_buffer, magma_semaphore_t render_semaphore,
+ magma_semaphore_t display_semaphore, VkImage image, VkDeviceMemory device_memory,
+ const VkAllocationCallbacks* allocator)
+ : device_(device), image_(image), device_memory_(device_memory), callbacks_(callbacks),
+ connections_(std::move(connections)), render_buffer_(render_buffer),
+ display_buffer_(display_buffer), render_semaphore_(render_semaphore),
+ display_semaphore_(display_semaphore), allocator_(allocator)
{
}
VkDevice device_;
- const VkAllocationCallbacks* allocator_;
- const wsi_magma_callbacks* callbacks_;
- magma_buffer_t buffer_handle_;
VkImage image_;
VkDeviceMemory device_memory_;
- magma_semaphore_t semaphore_;
+ const wsi_magma_callbacks* callbacks_;
+ std::shared_ptr<WsiMagmaConnections> connections_;
+ magma_buffer_t render_buffer_, display_buffer_; // render_buffer is not owned
+ magma_semaphore_t render_semaphore_, display_semaphore_;
+ const VkAllocationCallbacks* allocator_;
};
std::unique_ptr<MagmaImage> MagmaImage::Create(VkDevice device,
const wsi_magma_callbacks* callbacks,
- magma_connection_t* connection,
+ std::shared_ptr<WsiMagmaConnections> connections,
const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* allocator)
{
@@ -89,34 +130,63 @@
uint32_t row_pitch;
uint32_t offset;
uint32_t bpp = 32;
- magma_buffer_t buffer_handle;
+ magma_buffer_t render_buffer, display_buffer;
+ magma_semaphore_t render_semaphore, display_semaphore;
+ uint32_t buffer_handle, semaphore_handle;
uint32_t size;
VkImage image;
VkDeviceMemory device_memory;
result = callbacks->create_wsi_image(device, pCreateInfo, allocator, &image, &device_memory,
- &size, &offset, &row_pitch, &buffer_handle);
+ &size, &offset, &row_pitch, &render_buffer);
if (result != VK_SUCCESS)
return DRETP(nullptr, "create_wsi_image failed");
- magma_semaphore_t semaphore;
- magma_status_t status = magma_create_semaphore(connection, &semaphore);
+ magma_status_t status =
+ magma_export(connections->render_connection(), render_buffer, &buffer_handle);
+ if (status != MAGMA_STATUS_OK)
+ return DRETP(nullptr, "failed to export buffer");
+
+ status = magma_import(connections->display_connection(), buffer_handle, &display_buffer);
+ if (status != MAGMA_STATUS_OK)
+ return DRETP(nullptr, "failed to import buffer");
+
+ status = magma_create_semaphore(connections->render_connection(), &render_semaphore);
if (status != MAGMA_STATUS_OK)
return DRETP(nullptr, "failed to create semaphore");
- magma_signal_semaphore(semaphore);
+ status = magma_export_semaphore(connections->render_connection(), render_semaphore,
+ &semaphore_handle);
+ if (status != MAGMA_STATUS_OK)
+ return DRETP(nullptr, "failed to export semaphore");
- auto magma_image = std::unique_ptr<MagmaImage>(new MagmaImage(
- device, callbacks, allocator, buffer_handle, image, device_memory, semaphore));
+ status = magma_import_semaphore(connections->display_connection(), semaphore_handle,
+ &display_semaphore);
+ if (status != MAGMA_STATUS_OK)
+ return DRETP(nullptr, "failed to import semaphore");
- return magma_image;
+ magma_signal_semaphore(display_semaphore);
+
+ return std::unique_ptr<MagmaImage>(
+ new MagmaImage(device, callbacks, std::move(connections), render_buffer, display_buffer,
+ render_semaphore, display_semaphore, image, device_memory, allocator));
+}
+
+MagmaImage::~MagmaImage()
+{
+ callbacks_->free_wsi_image(device_, allocator_, image_, device_memory_);
+
+ magma_free(connections_->display_connection(), display_buffer_);
+ magma_destroy_semaphore(connections_->render_connection(), render_semaphore_);
+ magma_destroy_semaphore(connections_->display_connection(), display_semaphore_);
}
//////////////////////////////////////////////////////////////////////////////
class MagmaSwapchain : public wsi_swapchain {
public:
- MagmaSwapchain(VkDevice device, magma_connection_t* connection) : connection_(connection)
+ MagmaSwapchain(VkDevice device, std::shared_ptr<WsiMagmaConnections> connections)
+ : connections_(connections)
{
// Default-initialize the anv_swapchain base
wsi_swapchain* base = static_cast<wsi_swapchain*>(this);
@@ -133,7 +203,9 @@
this->queue_present = QueuePresent;
}
- magma_connection_t* connection() { return connection_; }
+ magma_connection_t* display_connection() { return connections_->display_connection(); }
+
+ magma_connection_t* render_connection() { return connections_->render_connection(); }
uint32_t image_count() { return images_.size(); }
@@ -173,9 +245,6 @@
return VK_SUCCESS;
}
- // Note - semaphore is supposed to be signalled when the image is no longer accessed by the
- // presentation engine.
- // Intel's mesa vulkan driver appears to ignore all semaphores (MA-110).
static VkResult AcquireNextImage(wsi_swapchain* wsi_chain, uint64_t timeout,
VkSemaphore semaphore, uint32_t* pImageIndex)
{
@@ -183,9 +252,10 @@
uint32_t index = chain->next_index_;
MagmaImage* image = chain->get_image(index);
- DLOG("AcquireNextImage semaphore id 0x%" PRIx64, magma_get_semaphore_id(image->semaphore()));
+ DLOG("AcquireNextImage semaphore id 0x%" PRIx64,
+ magma_get_semaphore_id(image->display_semaphore()));
- magma_status_t status = magma_wait_semaphore(image->semaphore(), timeout);
+ magma_status_t status = magma_wait_semaphore(image->display_semaphore(), timeout);
if (status == MAGMA_STATUS_TIMED_OUT) {
DLOG("timeout waiting for image semaphore");
return VK_TIMEOUT;
@@ -198,7 +268,7 @@
*pImageIndex = index;
DLOG("AcquireNextImage returning index %u id 0x%" PRIx64, *pImageIndex,
- magma_get_buffer_id(image->buffer_handle()));
+ magma_get_buffer_id(image->display_buffer()));
return VK_SUCCESS;
}
@@ -210,12 +280,34 @@
MagmaImage* image = magma_swapchain->get_image(image_index);
DLOG("QueuePresent image_index %u id 0x%" PRIx64, image_index,
- magma_get_buffer_id(image->buffer_handle()));
+ magma_get_buffer_id(image->display_buffer()));
- magma_semaphore_t signal_semaphores[1]{image->semaphore()};
- magma_display_page_flip(
- magma_swapchain->connection(), image->buffer_handle(), wait_semaphore_count,
- reinterpret_cast<const magma_semaphore_t*>(wait_semaphores), 1, signal_semaphores);
+ magma_semaphore_t display_semaphores[wait_semaphore_count];
+ magma_status_t status;
+
+ for (uint32_t i = 0; i < wait_semaphore_count; i++) {
+ uint32_t semaphore_handle;
+ status = magma_export_semaphore(
+ magma_swapchain->render_connection(),
+ reinterpret_cast<const magma_semaphore_t*>(wait_semaphores)[i], &semaphore_handle);
+ if (status != MAGMA_STATUS_OK) {
+ DLOG("Failed to export wait semaphore");
+ continue;
+ }
+ magma_semaphore_t semaphore;
+ status = magma_import_semaphore(magma_swapchain->display_connection(), semaphore_handle,
+ &display_semaphores[i]);
+ if (status != MAGMA_STATUS_OK)
+ DLOG("failed to import wait semaphore");
+ }
+
+ magma_semaphore_t signal_semaphores[1]{image->display_semaphore()};
+ magma_display_page_flip(magma_swapchain->display_connection(), image->display_buffer(),
+ wait_semaphore_count, display_semaphores, 1, signal_semaphores);
+
+ for (uint32_t i = 0; i < wait_semaphore_count; i++) {
+ magma_destroy_semaphore(magma_swapchain->display_connection(), display_semaphores[i]);
+ }
return VK_SUCCESS;
}
@@ -231,7 +323,7 @@
static constexpr uint32_t kMagic = 0x6D617377; // 'masw'
const uint32_t magic_ = kMagic;
- magma_connection_t* connection_;
+ std::shared_ptr<WsiMagmaConnections> connections_;
std::vector<std::unique_ptr<MagmaImage>> images_;
uint32_t next_index_ = 0;
};
@@ -323,13 +415,20 @@
assert(wsi_magma);
// TODO(MA-115): use pAllocator here and for images (and elsewhere in magma?)
- auto chain = std::make_unique<MagmaSwapchain>(device, wsi_magma->connection(device));
+ auto connections = std::shared_ptr<WsiMagmaConnections>(
+ WsiMagmaConnections::Create(wsi_magma->callbacks(), device));
+ if (!connections) {
+ DLOG("failed to create connections");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+
+ auto chain = std::make_unique<MagmaSwapchain>(device, connections);
uint32_t num_images = pCreateInfo->minImageCount;
for (uint32_t i = 0; i < num_images; i++) {
- std::unique_ptr<MagmaImage> image = MagmaImage::Create(
- device, wsi_magma->callbacks(), wsi_magma->connection(device), pCreateInfo, pAllocator);
+ std::unique_ptr<MagmaImage> image =
+ MagmaImage::Create(device, wsi_magma->callbacks(), connections, pCreateInfo, pAllocator);
if (!image)
return VK_ERROR_OUT_OF_DEVICE_MEMORY;