Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(391)

Unified Diff: gpu/vulkan/vulkan_surface.cc

Issue 1776453003: Added initial implementation of Vulkan Render Passes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gn_vulkan
Patch Set: Ensure vulkan handles all initialized to null, check destruction in destructor Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: gpu/vulkan/vulkan_surface.cc
diff --git a/gpu/vulkan/vulkan_surface.cc b/gpu/vulkan/vulkan_surface.cc
index b340a69d77af6e30c10ad08486483ed8603178c7..dc42bd4019641b4717d421872e285dbf1a444146 100644
--- a/gpu/vulkan/vulkan_surface.cc
+++ b/gpu/vulkan/vulkan_surface.cc
@@ -4,11 +4,220 @@
#include "gpu/vulkan/vulkan_surface.h"
+#include <vulkan/vulkan.h>
+
+#include "base/macros.h"
+#include "gpu/vulkan/vulkan_command_buffer.h"
#include "gpu/vulkan/vulkan_implementation.h"
+#include "gpu/vulkan/vulkan_swap_chain.h"
+
+#if defined(VK_USE_PLATFORM_XLIB_KHR)
+#include "ui/gfx/x/x11_types.h"
+#endif // defined(VK_USE_PLATFORM_XLIB_KHR)
namespace gfx {
-VulkanSurface::VulkanSurface() {}
+namespace {
+const VkDeviceSize kFormatSize[] = {
+ 4, // SURFACE_ARGB8888,
+ 2, // SURFACE_RGB565,
+ 4, // SURFACE_OSMESA_BGRA,
+ 4, // SURFACE_OSMESA_RGBA,
+};
+static_assert(arraysize(kFormatSize) == VulkanSurface::NUM_SURFACE_FORMATS,
+ "Array size for kFormatSize must match surface formats.");
+
+const VkFormat kNativeVkFormat[] = {
+ VK_FORMAT_B8G8R8A8_UNORM, // SURFACE_ARGB8888,
+ VK_FORMAT_R5G6B5_UNORM_PACK16, // SURFACE_RGB565,
+ VK_FORMAT_B8G8R8A8_UNORM, // SURFACE_OSMESA_BGRA,
+ VK_FORMAT_B8G8R8A8_UNORM, // SURFACE_OSMESA_RGBA,
+};
+static_assert(arraysize(kNativeVkFormat) == VulkanSurface::NUM_SURFACE_FORMATS,
+ "Array size for kNativeVkFormat must match surface formats.");
+
+const VkComponentMapping kFormatMapping[] = {
+ // SURFACE_ARGB8888,
+ {VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
+ VK_COMPONENT_SWIZZLE_B},
+
+ // SURFACE_RGB565,
+ {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B,
+ VK_COMPONENT_SWIZZLE_ONE},
+
+ // SURFACE_OSMESA_BGRA,
+ {VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R,
+ VK_COMPONENT_SWIZZLE_A},
+
+ // SURFACE_OSMESA_RGBA,
+ {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B,
+ VK_COMPONENT_SWIZZLE_A},
+};
+static_assert(arraysize(kFormatMapping) == VulkanSurface::NUM_SURFACE_FORMATS,
+ "Array size for kFormatMapping must match surface formats.");
+
+} // namespace
+
+class VulkanWSISurface : public VulkanSurface {
+ public:
+ VulkanWSISurface(gfx::AcceleratedWidget window) : window_(window) {}
piman 2016/03/09 01:25:34 nit: explicit
David Yen 2016/03/10 01:39:49 Done.
+
+ ~VulkanWSISurface() override {
+ DCHECK_EQ(static_cast<VkSurfaceKHR>(VK_NULL_HANDLE), surface_);
+ }
+
+ bool Initialize(VulkanSurface::Format format) override {
+ DCHECK(format >= 0 && format < NUM_SURFACE_FORMATS);
+#if defined(VK_USE_PLATFORM_XLIB_KHR)
+ VkXlibSurfaceCreateInfoKHR surface_create_info = {};
+ surface_create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
+ surface_create_info.dpy = gfx::GetXDisplay();
+ surface_create_info.window = window_;
+ vkCreateXlibSurfaceKHR(GetVulkanInstance(), &surface_create_info, nullptr,
+ &surface_);
+#else
+#error Unsupported Vulkan Platform.
+#endif
+
+ // Get list of supported formats.
+ uint32_t format_count = 0;
+ VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(
+ GetVulkanPhysicalDevice(), surface_, &format_count, nullptr);
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "vkGetPhysicalDeviceSurfaceFormatsKHR() failed: " << result;
piman 2016/03/09 01:25:34 nit: DLOG
David Yen 2016/03/10 01:39:48 Done.
+ return false;
+ }
+
+ std::vector<VkSurfaceFormatKHR> formats(format_count);
+ result = vkGetPhysicalDeviceSurfaceFormatsKHR(
+ GetVulkanPhysicalDevice(), surface_, &format_count, formats.data());
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "vkGetPhysicalDeviceSurfaceFormatsKHR() failed: " << result;
+ return false;
+ }
+
+ const VkFormat preferred_format = kNativeVkFormat[format];
+ if (formats.size() == 1 && VK_FORMAT_UNDEFINED == formats[0].format) {
+ surface_format_.format = preferred_format;
+ surface_format_.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ } else {
+ bool format_set = false;
+ for (VkSurfaceFormatKHR supported_format : formats) {
+ if (supported_format.format == preferred_format) {
+ surface_format_ = supported_format;
+ format_set = true;
+ break;
+ }
+ }
+ if (!format_set) {
+ surface_format_.format = VK_FORMAT_B8G8R8A8_UNORM;
piman 2016/03/09 01:25:34 There's no guarantee that this is supported. If we
David Yen 2016/03/10 01:39:49 Done.
+ surface_format_.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ }
+ }
+
+ // Get Surface Information.
+ VkSurfaceCapabilitiesKHR surface_caps;
+ result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
+ GetVulkanPhysicalDevice(), surface_, &surface_caps);
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "vkGetPhysicalDeviceSurfaceCapabilitiesKHR() failed: "
piman 2016/03/09 01:25:34 nit: DLOG
David Yen 2016/03/10 01:39:49 Done.
+ << result;
+ return false;
+ }
+
+ // These are actual surfaces so the current extent should be defined.
+ DCHECK_NE(UINT_MAX, surface_caps.currentExtent.width);
+ DCHECK_NE(UINT_MAX, surface_caps.currentExtent.height);
+ size_ = gfx::Size(surface_caps.currentExtent.width,
+ surface_caps.currentExtent.height);
+
+ // The next part of the setup process needs to submit commands, we create
+ // a temporary command buffer to do these submissions.
+ scoped_ptr<VulkanCommandBuffer> command_buffer =
+ CreatePrimaryCommandBuffer();
+
+ bool success = false;
+ do {
+ {
+ ScopedSingleUseCommandBufferRecorder recorder(*command_buffer);
+
+ // Create Swapchain.
+ if (!swap_chain_.Initialize(recorder.handle(), surface_, surface_caps,
+ surface_format_, kFormatMapping[format])) {
+ break;
+ }
+ }
+
+ if (!command_buffer->Submit()) {
+ LOG(ERROR) << "Failed to submit command buffer commands.";
piman 2016/03/09 01:25:34 nit: DLOG
David Yen 2016/03/10 01:39:49 Done.
+ break;
+ }
+
+ // TODO(dyen): Look into if it's worth inserting a fence or event here
+ // and keeping around the command buffer until it's done.
piman 2016/03/09 01:25:34 We'll definitely want some facility to do that - d
David Yen 2016/03/10 01:39:48 After thinking through this more, I now have this
+ result = vkQueueWaitIdle(GetVulkanQueue());
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "vkQueueWaitIdle() failed: " << result;
piman 2016/03/09 01:25:34 nit: DLOG
David Yen 2016/03/10 01:39:49 Done.
+ break;
+ }
+
+ success = true;
+ } while (false);
+
+ command_buffer->Destroy();
+ return success;
+ }
+
+ void Destroy() override {
+ swap_chain_.Destroy();
+ vkDestroySurfaceKHR(GetVulkanInstance(), surface_, nullptr);
+ surface_ = VK_NULL_HANDLE;
+ }
+
+ protected:
+ gfx::AcceleratedWidget window_;
+ gfx::Size size_;
+ VkSurfaceKHR surface_ = VK_NULL_HANDLE;
+ VkSurfaceFormatKHR surface_format_ = {};
+ VulkanSwapChain swap_chain_;
+};
+
+class VulkanBufferSurface : public VulkanSurface {
piman 2016/03/09 01:25:34 I don't think this is useful - you can't use a VkB
David Yen 2016/03/10 01:39:48 Deleted.
+ public:
+ VulkanBufferSurface(const gfx::Size& size) : size_(size) {}
+
+ ~VulkanBufferSurface() override {
+ DCHECK_EQ(static_cast<VkBuffer>(VK_NULL_HANDLE), buffer_);
+ }
+
+ bool Initialize(VulkanSurface::Format format) override {
+ VkBufferCreateInfo buffer_create_info = {};
+ buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buffer_create_info.size = kFormatSize[format] * size_.GetArea();
+ buffer_create_info.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
+ VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
+ buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+ VkResult result = vkCreateBuffer(GetVulkanDevice(), &buffer_create_info,
+ nullptr, &buffer_);
+ if (VK_SUCCESS != result) {
+ LOG(ERROR) << "Could not create VkBuffer (" << size_.width() << "x"
+ << size_.height() << "x" << kFormatSize[format]
+ << "): " << result;
+ return false;
+ }
+ return true;
+ }
+
+ void Destroy() override {
+ vkDestroyBuffer(GetVulkanDevice(), buffer_, nullptr);
+ buffer_ = VK_NULL_HANDLE;
+ }
+
+ protected:
+ gfx::Size size_;
+ VkBuffer buffer_ = VK_NULL_HANDLE;
+};
// static
bool VulkanSurface::InitializeOneOff() {
@@ -20,4 +229,18 @@ bool VulkanSurface::InitializeOneOff() {
VulkanSurface::~VulkanSurface() {}
+// static
+scoped_ptr<gfx::VulkanSurface> VulkanSurface::CreateViewSurface(
+ gfx::AcceleratedWidget window) {
+ return scoped_ptr<gfx::VulkanSurface>(new VulkanWSISurface(window));
+}
+
+// static
+scoped_ptr<gfx::VulkanSurface> VulkanSurface::CreateOffscreenSurface(
+ const gfx::Size& size) {
+ return scoped_ptr<gfx::VulkanSurface>(new VulkanBufferSurface(size));
+}
+
+VulkanSurface::VulkanSurface() {}
+
} // namespace gfx

Powered by Google App Engine
This is Rietveld 408576698