Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "gpu/vulkan/vulkan_surface.h" | 5 #include "gpu/vulkan/vulkan_surface.h" |
| 6 | 6 |
| 7 #include <vulkan/vulkan.h> | |
| 8 | |
| 9 #include "base/macros.h" | |
| 10 #include "gpu/vulkan/vulkan_command_buffer.h" | |
| 7 #include "gpu/vulkan/vulkan_implementation.h" | 11 #include "gpu/vulkan/vulkan_implementation.h" |
| 12 #include "gpu/vulkan/vulkan_swap_chain.h" | |
| 13 | |
| 14 #if defined(VK_USE_PLATFORM_XLIB_KHR) | |
| 15 #include "ui/gfx/x/x11_types.h" | |
| 16 #endif // defined(VK_USE_PLATFORM_XLIB_KHR) | |
| 8 | 17 |
| 9 namespace gfx { | 18 namespace gfx { |
| 10 | 19 |
| 11 VulkanSurface::VulkanSurface() {} | 20 namespace { |
| 21 const VkDeviceSize kFormatSize[] = { | |
| 22 4, // SURFACE_ARGB8888, | |
| 23 2, // SURFACE_RGB565, | |
| 24 4, // SURFACE_OSMESA_BGRA, | |
| 25 4, // SURFACE_OSMESA_RGBA, | |
| 26 }; | |
| 27 static_assert(arraysize(kFormatSize) == VulkanSurface::NUM_SURFACE_FORMATS, | |
| 28 "Array size for kFormatSize must match surface formats."); | |
| 29 | |
| 30 const VkFormat kNativeVkFormat[] = { | |
| 31 VK_FORMAT_B8G8R8A8_UNORM, // SURFACE_ARGB8888, | |
| 32 VK_FORMAT_R5G6B5_UNORM_PACK16, // SURFACE_RGB565, | |
| 33 VK_FORMAT_B8G8R8A8_UNORM, // SURFACE_OSMESA_BGRA, | |
| 34 VK_FORMAT_B8G8R8A8_UNORM, // SURFACE_OSMESA_RGBA, | |
| 35 }; | |
| 36 static_assert(arraysize(kNativeVkFormat) == VulkanSurface::NUM_SURFACE_FORMATS, | |
| 37 "Array size for kNativeVkFormat must match surface formats."); | |
| 38 | |
| 39 const VkComponentMapping kFormatMapping[] = { | |
| 40 // SURFACE_ARGB8888, | |
| 41 {VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, | |
| 42 VK_COMPONENT_SWIZZLE_B}, | |
| 43 | |
| 44 // SURFACE_RGB565, | |
| 45 {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, | |
| 46 VK_COMPONENT_SWIZZLE_ONE}, | |
| 47 | |
| 48 // SURFACE_OSMESA_BGRA, | |
| 49 {VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, | |
| 50 VK_COMPONENT_SWIZZLE_A}, | |
| 51 | |
| 52 // SURFACE_OSMESA_RGBA, | |
| 53 {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, | |
| 54 VK_COMPONENT_SWIZZLE_A}, | |
| 55 }; | |
| 56 static_assert(arraysize(kFormatMapping) == VulkanSurface::NUM_SURFACE_FORMATS, | |
| 57 "Array size for kFormatMapping must match surface formats."); | |
| 58 | |
| 59 } // namespace | |
| 60 | |
| 61 class VulkanWSISurface : public VulkanSurface { | |
| 62 public: | |
| 63 VulkanWSISurface(gfx::AcceleratedWidget window) : window_(window) {} | |
|
piman
2016/03/09 01:25:34
nit: explicit
David Yen
2016/03/10 01:39:49
Done.
| |
| 64 | |
| 65 ~VulkanWSISurface() override { | |
| 66 DCHECK_EQ(static_cast<VkSurfaceKHR>(VK_NULL_HANDLE), surface_); | |
| 67 } | |
| 68 | |
| 69 bool Initialize(VulkanSurface::Format format) override { | |
| 70 DCHECK(format >= 0 && format < NUM_SURFACE_FORMATS); | |
| 71 #if defined(VK_USE_PLATFORM_XLIB_KHR) | |
| 72 VkXlibSurfaceCreateInfoKHR surface_create_info = {}; | |
| 73 surface_create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; | |
| 74 surface_create_info.dpy = gfx::GetXDisplay(); | |
| 75 surface_create_info.window = window_; | |
| 76 vkCreateXlibSurfaceKHR(GetVulkanInstance(), &surface_create_info, nullptr, | |
| 77 &surface_); | |
| 78 #else | |
| 79 #error Unsupported Vulkan Platform. | |
| 80 #endif | |
| 81 | |
| 82 // Get list of supported formats. | |
| 83 uint32_t format_count = 0; | |
| 84 VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR( | |
| 85 GetVulkanPhysicalDevice(), surface_, &format_count, nullptr); | |
| 86 if (VK_SUCCESS != result) { | |
| 87 LOG(ERROR) << "vkGetPhysicalDeviceSurfaceFormatsKHR() failed: " << result; | |
|
piman
2016/03/09 01:25:34
nit: DLOG
David Yen
2016/03/10 01:39:48
Done.
| |
| 88 return false; | |
| 89 } | |
| 90 | |
| 91 std::vector<VkSurfaceFormatKHR> formats(format_count); | |
| 92 result = vkGetPhysicalDeviceSurfaceFormatsKHR( | |
| 93 GetVulkanPhysicalDevice(), surface_, &format_count, formats.data()); | |
| 94 if (VK_SUCCESS != result) { | |
| 95 LOG(ERROR) << "vkGetPhysicalDeviceSurfaceFormatsKHR() failed: " << result; | |
| 96 return false; | |
| 97 } | |
| 98 | |
| 99 const VkFormat preferred_format = kNativeVkFormat[format]; | |
| 100 if (formats.size() == 1 && VK_FORMAT_UNDEFINED == formats[0].format) { | |
| 101 surface_format_.format = preferred_format; | |
| 102 surface_format_.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; | |
| 103 } else { | |
| 104 bool format_set = false; | |
| 105 for (VkSurfaceFormatKHR supported_format : formats) { | |
| 106 if (supported_format.format == preferred_format) { | |
| 107 surface_format_ = supported_format; | |
| 108 format_set = true; | |
| 109 break; | |
| 110 } | |
| 111 } | |
| 112 if (!format_set) { | |
| 113 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.
| |
| 114 surface_format_.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 // Get Surface Information. | |
| 119 VkSurfaceCapabilitiesKHR surface_caps; | |
| 120 result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR( | |
| 121 GetVulkanPhysicalDevice(), surface_, &surface_caps); | |
| 122 if (VK_SUCCESS != result) { | |
| 123 LOG(ERROR) << "vkGetPhysicalDeviceSurfaceCapabilitiesKHR() failed: " | |
|
piman
2016/03/09 01:25:34
nit: DLOG
David Yen
2016/03/10 01:39:49
Done.
| |
| 124 << result; | |
| 125 return false; | |
| 126 } | |
| 127 | |
| 128 // These are actual surfaces so the current extent should be defined. | |
| 129 DCHECK_NE(UINT_MAX, surface_caps.currentExtent.width); | |
| 130 DCHECK_NE(UINT_MAX, surface_caps.currentExtent.height); | |
| 131 size_ = gfx::Size(surface_caps.currentExtent.width, | |
| 132 surface_caps.currentExtent.height); | |
| 133 | |
| 134 // The next part of the setup process needs to submit commands, we create | |
| 135 // a temporary command buffer to do these submissions. | |
| 136 scoped_ptr<VulkanCommandBuffer> command_buffer = | |
| 137 CreatePrimaryCommandBuffer(); | |
| 138 | |
| 139 bool success = false; | |
| 140 do { | |
| 141 { | |
| 142 ScopedSingleUseCommandBufferRecorder recorder(*command_buffer); | |
| 143 | |
| 144 // Create Swapchain. | |
| 145 if (!swap_chain_.Initialize(recorder.handle(), surface_, surface_caps, | |
| 146 surface_format_, kFormatMapping[format])) { | |
| 147 break; | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 if (!command_buffer->Submit()) { | |
| 152 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.
| |
| 153 break; | |
| 154 } | |
| 155 | |
| 156 // TODO(dyen): Look into if it's worth inserting a fence or event here | |
| 157 // 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
| |
| 158 result = vkQueueWaitIdle(GetVulkanQueue()); | |
| 159 if (VK_SUCCESS != result) { | |
| 160 LOG(ERROR) << "vkQueueWaitIdle() failed: " << result; | |
|
piman
2016/03/09 01:25:34
nit: DLOG
David Yen
2016/03/10 01:39:49
Done.
| |
| 161 break; | |
| 162 } | |
| 163 | |
| 164 success = true; | |
| 165 } while (false); | |
| 166 | |
| 167 command_buffer->Destroy(); | |
| 168 return success; | |
| 169 } | |
| 170 | |
| 171 void Destroy() override { | |
| 172 swap_chain_.Destroy(); | |
| 173 vkDestroySurfaceKHR(GetVulkanInstance(), surface_, nullptr); | |
| 174 surface_ = VK_NULL_HANDLE; | |
| 175 } | |
| 176 | |
| 177 protected: | |
| 178 gfx::AcceleratedWidget window_; | |
| 179 gfx::Size size_; | |
| 180 VkSurfaceKHR surface_ = VK_NULL_HANDLE; | |
| 181 VkSurfaceFormatKHR surface_format_ = {}; | |
| 182 VulkanSwapChain swap_chain_; | |
| 183 }; | |
| 184 | |
| 185 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.
| |
| 186 public: | |
| 187 VulkanBufferSurface(const gfx::Size& size) : size_(size) {} | |
| 188 | |
| 189 ~VulkanBufferSurface() override { | |
| 190 DCHECK_EQ(static_cast<VkBuffer>(VK_NULL_HANDLE), buffer_); | |
| 191 } | |
| 192 | |
| 193 bool Initialize(VulkanSurface::Format format) override { | |
| 194 VkBufferCreateInfo buffer_create_info = {}; | |
| 195 buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | |
| 196 buffer_create_info.size = kFormatSize[format] * size_.GetArea(); | |
| 197 buffer_create_info.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | | |
| 198 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; | |
| 199 buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | |
| 200 | |
| 201 VkResult result = vkCreateBuffer(GetVulkanDevice(), &buffer_create_info, | |
| 202 nullptr, &buffer_); | |
| 203 if (VK_SUCCESS != result) { | |
| 204 LOG(ERROR) << "Could not create VkBuffer (" << size_.width() << "x" | |
| 205 << size_.height() << "x" << kFormatSize[format] | |
| 206 << "): " << result; | |
| 207 return false; | |
| 208 } | |
| 209 return true; | |
| 210 } | |
| 211 | |
| 212 void Destroy() override { | |
| 213 vkDestroyBuffer(GetVulkanDevice(), buffer_, nullptr); | |
| 214 buffer_ = VK_NULL_HANDLE; | |
| 215 } | |
| 216 | |
| 217 protected: | |
| 218 gfx::Size size_; | |
| 219 VkBuffer buffer_ = VK_NULL_HANDLE; | |
| 220 }; | |
| 12 | 221 |
| 13 // static | 222 // static |
| 14 bool VulkanSurface::InitializeOneOff() { | 223 bool VulkanSurface::InitializeOneOff() { |
| 15 if (!InitializeVulkan()) | 224 if (!InitializeVulkan()) |
| 16 return false; | 225 return false; |
| 17 | 226 |
| 18 return true; | 227 return true; |
| 19 } | 228 } |
| 20 | 229 |
| 21 VulkanSurface::~VulkanSurface() {} | 230 VulkanSurface::~VulkanSurface() {} |
| 22 | 231 |
| 232 // static | |
| 233 scoped_ptr<gfx::VulkanSurface> VulkanSurface::CreateViewSurface( | |
| 234 gfx::AcceleratedWidget window) { | |
| 235 return scoped_ptr<gfx::VulkanSurface>(new VulkanWSISurface(window)); | |
| 236 } | |
| 237 | |
| 238 // static | |
| 239 scoped_ptr<gfx::VulkanSurface> VulkanSurface::CreateOffscreenSurface( | |
| 240 const gfx::Size& size) { | |
| 241 return scoped_ptr<gfx::VulkanSurface>(new VulkanBufferSurface(size)); | |
| 242 } | |
| 243 | |
| 244 VulkanSurface::VulkanSurface() {} | |
| 245 | |
| 23 } // namespace gfx | 246 } // namespace gfx |
| OLD | NEW |