15#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
16#include <vulkan/vulkan.hpp>
17VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
31#define GPUCA_DISPLAY_SHADER_TYPE_VULKAN
32#include "GPUDisplayLoadShaders.h"
37 auto tmp_internal_retVal = cmd; \
38 if ((int32_t)tmp_internal_retVal < 0) { \
39 GPUError("VULKAN ERROR: %d: %s (%s: %d)", (int32_t)tmp_internal_retVal, "ERROR", __FILE__, __LINE__); \
40 throw std::runtime_error("Vulkan Failure"); \
53static int32_t checkVulkanLayersSupported(
const std::vector<const char*>& validationLayers)
55 std::vector<vk::LayerProperties> availableLayers = vk::enumerateInstanceLayerProperties();
56 for (
const char* layerName : validationLayers) {
57 bool layerFound =
false;
59 for (
const auto& layerProperties : availableLayers) {
60 if (strcmp(layerName, layerProperties.layerName) == 0) {
73static uint32_t findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties, vk::PhysicalDevice physDev)
75 vk::PhysicalDeviceMemoryProperties memProperties = physDev.getMemoryProperties();
77 for (uint32_t
i = 0;
i < memProperties.memoryTypeCount;
i++) {
78 if ((typeFilter & (1 <<
i)) && (memProperties.memoryTypes[
i].propertyFlags & properties) == properties) {
82 if ((properties & vk::MemoryPropertyFlagBits::eDeviceLocal) && (properties & vk::MemoryPropertyFlagBits::eHostVisible)) {
83 return findMemoryType(typeFilter, properties & ~vk::MemoryPropertyFlags(vk::MemoryPropertyFlagBits::eDeviceLocal), physDev);
86 throw std::runtime_error(
"failed to find suitable memory type!");
89static vk::SurfaceFormatKHR chooseSwapSurfaceFormat(
const std::vector<vk::SurfaceFormatKHR>& availableFormats)
91 for (
const auto& availableFormat : availableFormats) {
92 if (availableFormat.format == vk::Format::eB8G8R8A8Unorm && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
93 return availableFormat;
96 return availableFormats[0];
104 return vk::PresentModeKHR::eFifo;
108 for (vk::PresentModeKHR
mode : {vk::PresentModeKHR::eImmediate, vk::PresentModeKHR::eMailbox, vk::PresentModeKHR::eFifoLatestReady, vk::PresentModeKHR::eFifo}) {
109 if ((
mode == vk::PresentModeKHR::eImmediate && vsync) || (
mode == vk::PresentModeKHR::eFifoLatestReady && !
mFifoLatestReadySupported) || std::find(available.begin(), available.end(),
mode) == available.end()) {
114 GPUError(
"VULKAN ERROR: Desired present mode %s not available, using %s", vsync ?
"MAILBOX" :
"IMMEDIATE", vk::to_string(
mode).c_str());
118 return vk::PresentModeKHR::eFifo;
123 if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
124 return capabilities.currentExtent;
128 vk::Extent2D actualExtent = {(uint32_t)
width, (uint32_t)
height};
129 actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
130 actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
135static void cmdImageMemoryBarrier(vk::CommandBuffer cmdbuffer, vk::Image
image, vk::PipelineStageFlags2 srcStageMask, vk::AccessFlags2 srcAccessMask, vk::PipelineStageFlags2 dstStageMask, vk::AccessFlags2 dstAccessMask, vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor)
137 vk::ImageMemoryBarrier2 barrier{srcStageMask, srcAccessMask, dstStageMask, dstAccessMask, oldLayout, newLayout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
image, {aspect, 0, 1, 0, 1}};
138 cmdbuffer.pipelineBarrier2(vk::DependencyInfo{{}, 0,
nullptr, 0,
nullptr, 1, &barrier});
141static void cmdBeginRendering(vk::CommandBuffer cmdbuffer, uint32_t
width, uint32_t
height,
const vk::RenderingAttachmentInfo&
color,
const vk::RenderingAttachmentInfo*
depth =
nullptr)
143 cmdbuffer.beginRendering(vk::RenderingInfo{{}, vk::Rect2D{{0, 0}, {
width,
height}}, 1, 0, 1, &
color,
depth});
144 vk::Viewport viewport{0.f, 0.f, (float)
width, (
float)
height, 0.f, 1.f};
146 cmdbuffer.setViewport(0, 1, &viewport);
147 cmdbuffer.setScissor(0, 1, &scissor);
150static void cmdBeginRenderingLoad(vk::CommandBuffer cmdbuffer, vk::Image
image, vk::ImageView view, uint32_t
width, uint32_t
height)
152 cmdImageMemoryBarrier(cmdbuffer,
image, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentRead | vk::AccessFlagBits2::eColorAttachmentWrite, vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eColorAttachmentOptimal);
153 cmdBeginRendering(cmdbuffer,
width,
height, vk::RenderingAttachmentInfo{view, vk::ImageLayout::eColorAttachmentOptimal});
165 vk::CommandBufferAllocateInfo allocInfo{};
166 allocInfo.level = vk::CommandBufferLevel::ePrimary;
168 allocInfo.commandBufferCount = 1;
169 vk::CommandBuffer commandBuffer =
mDevice.allocateCommandBuffers(allocInfo)[0];
170 vk::CommandBufferBeginInfo beginInfo{};
171 beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
172 commandBuffer.begin(beginInfo);
173 return commandBuffer;
176template <
class... Args>
180 if (timelineSignalValue) {
190 vk::CommandBufferSubmitInfo commandBufferInfo{commandBuffer};
191 vk::SemaphoreSubmitInfo signalInfo{
mTimelineSemaphore, 0, vk::PipelineStageFlagBits2::eAllCommands};
192 vk::SubmitInfo2 submitInfo{{}, 0,
nullptr, 1, &commandBufferInfo, 1, &signalInfo};
205static vk::ImageView createImageViewI(vk::Device device, vk::Image
image, vk::Format
format, vk::ImageAspectFlags aspectFlags = vk::ImageAspectFlagBits::eColor, uint32_t mipLevels = 1)
207 vk::ImageViewCreateInfo viewInfo{};
208 viewInfo.image =
image;
209 viewInfo.viewType = vk::ImageViewType::e2D;
211 viewInfo.subresourceRange.aspectMask = aspectFlags;
212 viewInfo.subresourceRange.baseMipLevel = 0;
213 viewInfo.subresourceRange.levelCount = mipLevels;
214 viewInfo.subresourceRange.baseArrayLayer = 0;
215 viewInfo.subresourceRange.layerCount = 1;
216 return device.createImageView(viewInfo,
nullptr);
219static void createImageI(vk::Device device, vk::PhysicalDevice physicalDevice, vk::Image&
image, vk::DeviceMemory& imageMemory, uint32_t
width, uint32_t
height, vk::Format
format, vk::ImageUsageFlags
usage, vk::MemoryPropertyFlags properties, vk::ImageTiling tiling = vk::ImageTiling::eOptimal, vk::SampleCountFlagBits numSamples = vk::SampleCountFlagBits::e1, vk::ImageLayout layout = vk::ImageLayout::eUndefined, uint32_t mipLevels = 1)
221 vk::ImageCreateInfo imageInfo{};
222 imageInfo.imageType = vk::ImageType::e2D;
223 imageInfo.extent.width =
width;
224 imageInfo.extent.height =
height;
225 imageInfo.extent.depth = 1;
226 imageInfo.mipLevels = mipLevels;
227 imageInfo.arrayLayers = 1;
228 imageInfo.format =
format;
229 imageInfo.tiling = tiling;
230 imageInfo.initialLayout = layout;
231 imageInfo.usage =
usage;
232 imageInfo.samples = numSamples;
233 imageInfo.sharingMode = vk::SharingMode::eExclusive;
234 image = device.createImage(imageInfo);
236 vk::MemoryRequirements memRequirements;
237 memRequirements = device.getImageMemoryRequirements(
image);
239 vk::MemoryAllocateInfo allocInfo{};
240 allocInfo.allocationSize = memRequirements.size;
241 allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties, physicalDevice);
242 imageMemory = device.allocateMemory(allocInfo,
nullptr);
244 device.bindImageMemory(
image, imageMemory, 0);
247static uint32_t getMaxUsableSampleCount(vk::PhysicalDeviceProperties& physicalDeviceProperties)
249 vk::SampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts;
250 if (counts & vk::SampleCountFlagBits::e64) {
252 }
else if (counts & vk::SampleCountFlagBits::e32) {
254 }
else if (counts & vk::SampleCountFlagBits::e16) {
256 }
else if (counts & vk::SampleCountFlagBits::e8) {
258 }
else if (counts & vk::SampleCountFlagBits::e4) {
260 }
else if (counts & vk::SampleCountFlagBits::e2) {
266static vk::SampleCountFlagBits getMSAASamplesFlag(uint32_t msaa)
269 return vk::SampleCountFlagBits::e2;
270 }
else if (msaa == 4) {
271 return vk::SampleCountFlagBits::e4;
272 }
else if (msaa == 8) {
273 return vk::SampleCountFlagBits::e8;
274 }
else if (msaa == 16) {
275 return vk::SampleCountFlagBits::e16;
276 }
else if (msaa == 32) {
277 return vk::SampleCountFlagBits::e32;
278 }
else if (msaa == 64) {
279 return vk::SampleCountFlagBits::e64;
281 return vk::SampleCountFlagBits::e1;
284template <
class T,
class S>
285static inline void clearVector(T&
v,
S func,
bool downsize =
true)
287 std::for_each(
v.begin(),
v.end(),
func);
296static bool hasFeatures(
const T& available,
const T& required)
298 const vk::Bool32*
a =
reinterpret_cast<const vk::Bool32*
>(
reinterpret_cast<const char*
>(&available) +
sizeof(VkBaseOutStructure));
299 const vk::Bool32*
r =
reinterpret_cast<const vk::Bool32*
>(
reinterpret_cast<const char*
>(&required) +
sizeof(VkBaseOutStructure));
300 for (
size_t i = 0;
i < (
sizeof(
T) -
sizeof(VkBaseOutStructure)) /
sizeof(vk::Bool32);
i++) {
309static bool hasFeatures(
const vk::StructureChain<T...>& available,
const vk::StructureChain<T...>& required)
311 return (hasFeatures(available.template get<T>(), required.template get<T>()) && ...);
315static void clearFeatures(vk::StructureChain<T...>&
chain)
317 ((memset(
reinterpret_cast<char*
>(&
chain.template get<T>()) +
sizeof(VkBaseOutStructure), 0,
sizeof(T) -
sizeof(VkBaseOutStructure))), ...);
321static bool enableOptionalFeature(vk::PhysicalDevice device,
const std::vector<vk::ExtensionProperties>& available, std::initializer_list<const char*> extensions, vk::Bool32 T::* feature,
T& featureStruct,
std::
vector<const
char*>& enabledExtensions,
void*&
chain)
323 for (
const char* ext : extensions) {
324 if (std::none_of(available.begin(), available.end(), [ext](
const auto& e) { return strcmp(ext, e.extensionName) == 0; })) {
327 if (!(device.getFeatures2<vk::PhysicalDeviceFeatures2, T>().template get<T>().*feature)) {
330 enabledExtensions.emplace_back(ext);
331 featureStruct.*feature = VK_TRUE;
332 featureStruct.pNext =
chain;
333 chain = &featureStruct;
340static vk::StructureChain<
T...> getFeatures(vk::PhysicalDevice device,
const vk::StructureChain<T...>&)
342 return device.getFeatures2<
T...>();
348 vk::PhysicalDeviceProperties deviceProperties = device.getProperties();
349 vk::PhysicalDeviceMemoryProperties memoryProperties = device.getMemoryProperties();
350 if (deviceProperties.apiVersion < VK_API_VERSION_1_4) {
352 GPUInfo(
"%s ignored, supports only Vulkan %u.%u", &deviceProperties.deviceName[0], VK_API_VERSION_MAJOR(deviceProperties.apiVersion), VK_API_VERSION_MINOR(deviceProperties.apiVersion));
357 std::vector<vk::ExtensionProperties> availableExtensions = device.enumerateDeviceExtensionProperties(
nullptr);
358 uint32_t extensionsFound = 0;
359 for (uint32_t
i = 0;
i < reqDeviceExtensions.size();
i++) {
360 for (uint32_t
j = 0;
j < availableExtensions.size();
j++) {
361 if (strcmp(reqDeviceExtensions[
i], availableExtensions[
j].extensionName) == 0) {
367 if (extensionsFound < reqDeviceExtensions.size()) {
369 GPUInfo(
"%s ignored due to missing extensions", &deviceProperties.deviceName[0]);
374 if (!hasFeatures(getFeatures(device, reqDeviceFeatures), reqDeviceFeatures)) {
376 GPUInfo(
"%s ignored due to missing features", &deviceProperties.deviceName[0]);
381 std::vector<vk::QueueFamilyProperties> queueFamilies = device.getQueueFamilyProperties();
383 for (uint32_t
i = 0;
i < queueFamilies.size();
i++) {
384 if (!(queueFamilies[
i].queueFlags & vk::QueueFlagBits::eGraphics)) {
387 vk::Bool32 presentSupport = device.getSurfaceSupportKHR(
i,
mSurface);
388 if (!presentSupport) {
397 GPUInfo(
"%s ignored due to missing queue properties", &deviceProperties.deviceName[0]);
405 GPUInfo(
"%s ignored due to incompatible swap chain", &deviceProperties.deviceName[0]);
411 if (deviceProperties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
413 }
else if (deviceProperties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu) {
417 for (uint32_t
i = 0;
i < memoryProperties.memoryHeapCount;
i++) {
418 if (memoryProperties.memoryHeaps[
i].flags & vk::MemoryHeapFlagBits::eDeviceLocal) {
419 score += memoryProperties.memoryHeaps[
i].size;
428 VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
429 vk::ApplicationInfo appInfo{};
430 appInfo.pApplicationName =
"GPU CA Standalone display";
431 appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
432 appInfo.pEngineName =
"GPU CI Standalone Engine";
433 appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
434 appInfo.apiVersion = VK_API_VERSION_1_4;
436 vk::InstanceCreateInfo instanceCreateInfo;
437 instanceCreateInfo.pApplicationInfo = &appInfo;
439 const char** frontendExtensions;
441 std::vector<const char*> reqInstanceExtensions(frontendExtensions, frontendExtensions + frontendExtensionCount);
442 reqInstanceExtensions.insert(reqInstanceExtensions.end(), {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, VK_KHR_SURFACE_MAINTENANCE_1_EXTENSION_NAME});
443 std::vector<vk::ExtensionProperties> availableInstanceExtensions = vk::enumerateInstanceExtensionProperties(
nullptr);
445 std::cout <<
"available instance extensions: " << availableInstanceExtensions.size() <<
"\n";
446 for (
const auto& extension : availableInstanceExtensions) {
447 std::cout <<
'\t' << extension.extensionName <<
'\n';
450 for (
const char* ext : reqInstanceExtensions) {
451 if (std::none_of(availableInstanceExtensions.begin(), availableInstanceExtensions.end(), [ext](
const auto& e) { return strcmp(ext, e.extensionName) == 0; })) {
452 throw std::runtime_error(std::string(
"Required Vulkan instance extension not available: ") + ext);
456 const std::vector<const char*> reqValidationLayers = {
"VK_LAYER_KHRONOS_validation"};
457 auto debugCallback = [](vk::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity, vk::DebugUtilsMessageTypeFlagsEXT messageType,
const vk::DebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData) -> VkBool32 {
458 static int32_t throwOnError = getenv(
"GPUCA_VULKAN_VALIDATION_THROW") ? atoi(getenv(
"GPUCA_VULKAN_VALIDATION_THROW")) : 0;
459 static bool showVulkanValidationInfo = getenv(
"GPUCA_VULKAN_VALIDATION_INFO") && atoi(getenv(
"GPUCA_VULKAN_VALIDATION_INFO"));
460 switch (messageSeverity) {
461 case vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose:
462 if (showVulkanValidationInfo) {
463 GPUInfo(
"%s", pCallbackData->pMessage);
466 case vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning:
467 GPUWarning(
"%s", pCallbackData->pMessage);
468 if (throwOnError > 1) {
469 throw std::logic_error(
"break_on_validation_warning");
472 case vk::DebugUtilsMessageSeverityFlagBitsEXT::eError:
473 GPUError(
"%s", pCallbackData->pMessage);
475 throw std::logic_error(
"break_on_validation_error");
478 case vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo:
480 GPUInfo(
"%s", pCallbackData->pMessage);
485 vk::DebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
487 if (checkVulkanLayersSupported(reqValidationLayers)) {
488 throw std::runtime_error(
"Requested validation layer support not available");
490 instanceCreateInfo.enabledLayerCount =
static_cast<uint32_t
>(reqValidationLayers.size());
491 instanceCreateInfo.ppEnabledLayerNames = reqValidationLayers.data();
492 instanceCreateInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo;
494 debugCreateInfo.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError;
495 debugCreateInfo.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance;
496 debugCreateInfo.pfnUserCallback = debugCallback;
497 debugCreateInfo.pUserData =
nullptr;
499 instanceCreateInfo.enabledLayerCount = 0;
502 instanceCreateInfo.enabledExtensionCount =
static_cast<uint32_t
>(reqInstanceExtensions.size());
503 instanceCreateInfo.ppEnabledExtensionNames = reqInstanceExtensions.data();
505 mInstance = vk::createInstance(instanceCreateInfo,
nullptr);
506 VULKAN_HPP_DEFAULT_DISPATCHER.init(
mInstance);
509 GPUInfo(
"Enabling Vulkan Validation Layers");
514 throw std::runtime_error(
"Frontend does not provide Vulkan surface");
517 const std::vector<const char*> reqDeviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, VK_KHR_PRESENT_ID_EXTENSION_NAME, VK_KHR_PRESENT_WAIT_EXTENSION_NAME};
519 clearFeatures(reqDeviceFeatures);
520 auto& reqFeatures10 = reqDeviceFeatures.get<vk::PhysicalDeviceFeatures2>().features;
521 reqFeatures10.geometryShader = reqFeatures10.wideLines = reqFeatures10.largePoints = reqFeatures10.multiDrawIndirect = VK_TRUE;
522 reqDeviceFeatures.get<vk::PhysicalDeviceVulkan12Features>().timelineSemaphore = VK_TRUE;
523 reqDeviceFeatures.get<vk::PhysicalDeviceVulkan14Features>().pushDescriptor = reqDeviceFeatures.get<vk::PhysicalDeviceVulkan14Features>().maintenance5 = VK_TRUE;
524 reqDeviceFeatures.get<vk::PhysicalDeviceVulkan13Features>().dynamicRendering = reqDeviceFeatures.get<vk::PhysicalDeviceVulkan13Features>().synchronization2 = VK_TRUE;
525 reqDeviceFeatures.get<vk::PhysicalDeviceVulkan13Features>().shaderDemoteToHelperInvocation = VK_TRUE;
526 reqDeviceFeatures.get<vk::PhysicalDeviceSwapchainMaintenance1FeaturesKHR>().swapchainMaintenance1 = VK_TRUE;
527 reqDeviceFeatures.get<vk::PhysicalDevicePresentIdFeaturesKHR>().presentId = VK_TRUE;
528 reqDeviceFeatures.get<vk::PhysicalDevicePresentWaitFeaturesKHR>().presentWait = VK_TRUE;
531 std::vector<vk::PhysicalDevice> devices =
mInstance.enumeratePhysicalDevices();
532 if (devices.size() == 0) {
533 throw std::runtime_error(
"No Vulkan device present!");
535 double bestScore = -1.;
536 for (uint32_t
i = 0;
i < devices.size();
i++) {
537 double score =
checkDevice(devices[
i], reqDeviceExtensions, reqDeviceFeatures);
539 vk::PhysicalDeviceProperties deviceProperties = devices[
i].getProperties();
540 GPUInfo(
"Available Vulkan device %d: %s - Score %f",
i, &deviceProperties.deviceName[0], score);
542 if (score > bestScore && score > 0) {
548 if (
mDisplay->
cfg().vulkan.forceDevice < 0 ||
mDisplay->
cfg().vulkan.forceDevice >= (int32_t)devices.size()) {
549 throw std::runtime_error(
"Invalid Vulkan device selected");
554 throw std::runtime_error(
"All available Vulkan devices unsuited");
557 throw std::runtime_error(
"Selected vulkan device is incompatible");
561 std::vector<const char*> deviceExtensions = reqDeviceExtensions;
562 void* featureChain = &reqDeviceFeatures.get<vk::PhysicalDeviceFeatures2>();
563 const std::vector<vk::ExtensionProperties> availableDeviceExtensions =
mPhysicalDevice.enumerateDeviceExtensionProperties(
nullptr);
564 vk::PhysicalDevicePresentModeFifoLatestReadyFeaturesKHR fifoLatestReadyFeatures{};
565 mFifoLatestReadySupported = enableOptionalFeature(
mPhysicalDevice, availableDeviceExtensions, {VK_KHR_PRESENT_MODE_FIFO_LATEST_READY_EXTENSION_NAME, VK_EXT_PRESENT_MODE_FIFO_LATEST_READY_EXTENSION_NAME}, &vk::PhysicalDevicePresentModeFifoLatestReadyFeaturesKHR::presentModeFifoLatestReady, fifoLatestReadyFeatures, deviceExtensions, featureChain);
568 vk::PhysicalDeviceProperties deviceProperties =
mPhysicalDevice.getProperties();
569 vk::FormatProperties depth32FormatProperties =
mPhysicalDevice.getFormatProperties(vk::Format::eD32Sfloat);
570 vk::FormatProperties depth64FormatProperties =
mPhysicalDevice.getFormatProperties(vk::Format::eD32SfloatS8Uint);
571 GPUInfo(
"Using physical Vulkan device %s", &deviceProperties.deviceName[0]);
576 mMaxRenderSize = std::min({deviceProperties.limits.maxImageDimension2D, deviceProperties.limits.maxFramebufferWidth, deviceProperties.limits.maxFramebufferHeight});
577 mZSupported = (bool)(depth32FormatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment);
578 mStencilSupported = (bool)(depth64FormatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment);
581 GPUInfo(
"Max MSAA: %d, 32 bit Z buffer %d, 32 bit Z buffer + stencil buffer %d, Mailbox present mode %d, FIFO latest ready present mode %d, smooth lines %d\n", (int32_t)
mMaxMSAAsupported, (int32_t)
mZSupported, (int32_t)
mStencilSupported, (int32_t)mailboxSupported, (int32_t)
mFifoLatestReadySupported, (int32_t)
mSmoothLinesSupported);
584 vk::DeviceQueueCreateInfo queueCreateInfo{};
586 queueCreateInfo.queueCount = 1;
587 float queuePriority = 1.0f;
588 queueCreateInfo.pQueuePriorities = &queuePriority;
589 vk::DeviceCreateInfo deviceCreateInfo{};
590 deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
591 deviceCreateInfo.queueCreateInfoCount = 1;
592 deviceCreateInfo.pNext = featureChain;
593 deviceCreateInfo.pEnabledFeatures =
nullptr;
594 deviceCreateInfo.enabledExtensionCount =
static_cast<uint32_t
>(deviceExtensions.size());
595 deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
597 VULKAN_HPP_DEFAULT_DISPATCHER.init(
mDevice);
600 vk::CommandPoolCreateInfo poolInfo{};
601 poolInfo.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
622 vk::CommandBufferAllocateInfo allocInfo{};
624 allocInfo.level = vk::CommandBufferLevel::ePrimary;
649 vk::SemaphoreCreateInfo semaphoreInfo{};
658 vk::SemaphoreTypeCreateInfo timelineTypeInfo{vk::SemaphoreType::eTimeline, 0};
659 semaphoreInfo.pNext = &timelineTypeInfo;
665 mPresentFences.emplace_back(
mDevice.createFence(vk::FenceCreateInfo{vk::FenceCreateFlagBits::eSignaled},
nullptr));
673 if (
retVal != vk::Result::eTimeout) {
691 for (int32_t
j = 0;
j < 3;
j++) {
698 vk::DescriptorSetLayoutBinding uboLayoutBindingMat{};
699 uboLayoutBindingMat.binding = 0;
700 uboLayoutBindingMat.descriptorType = vk::DescriptorType::eUniformBuffer;
701 uboLayoutBindingMat.descriptorCount = 1;
702 uboLayoutBindingMat.stageFlags = vk::ShaderStageFlagBits::eVertex;
703 vk::DescriptorSetLayoutBinding samplerLayoutBinding{};
704 samplerLayoutBinding.binding = 2;
705 samplerLayoutBinding.descriptorCount = 1;
706 samplerLayoutBinding.descriptorType = vk::DescriptorType::eCombinedImageSampler;
707 samplerLayoutBinding.stageFlags = vk::ShaderStageFlagBits::eFragment;
708 vk::DescriptorSetLayoutBinding bindings[2] = {uboLayoutBindingMat, samplerLayoutBinding};
710 vk::DescriptorSetLayoutCreateInfo layoutInfo{};
711 layoutInfo.flags = vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptor;
712 layoutInfo.bindingCount = 1;
713 layoutInfo.pBindings = bindings;
715 layoutInfo.bindingCount = 2;
725 for (int32_t
j = 0;
j < 3;
j++) {
732 vk::DescriptorBufferInfo bufferInfo{ubo.
buffer, 0, ubo.
size};
733 vk::DescriptorImageInfo imageInfo{
mTextureSampler, textureView, vk::ImageLayout::eShaderReadOnlyOptimal};
734 const vk::WriteDescriptorSet writes[2] = {{{}, 0, 0, 1, vk::DescriptorType::eUniformBuffer,
nullptr, &bufferInfo}, {{}, 2, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo}};
735 commandBuffer.pushDescriptorSet(vk::PipelineBindPoint::eGraphics, layout, 0, textureView ? 2 : 1, writes);
742 vk::SamplerCreateInfo samplerInfo{};
743 samplerInfo.magFilter = vk::Filter::eLinear;
744 samplerInfo.minFilter = vk::Filter::eLinear;
745 samplerInfo.addressModeU = vk::SamplerAddressMode::eRepeat;
746 samplerInfo.addressModeV = vk::SamplerAddressMode::eRepeat;
747 samplerInfo.addressModeW = vk::SamplerAddressMode::eRepeat;
748 samplerInfo.compareEnable =
false;
749 samplerInfo.compareOp = vk::CompareOp::eAlways;
750 samplerInfo.borderColor = vk::BorderColor::eIntOpaqueBlack;
751 samplerInfo.unnormalizedCoordinates =
false;
752 samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
753 samplerInfo.mipLodBias = 0.0f;
754 samplerInfo.minLod = 0.0f;
755 samplerInfo.maxLod = 0.0f;
772 GPUInfo(
"Vulkan present mode %s (VSync %d)", vk::to_string(
mPresentMode).c_str(), (int32_t)
mDisplay->
cfgR().drawQualityVSync);
784 vk::SwapchainCreateInfoKHR swapCreateInfo{};
786 swapCreateInfo.minImageCount = imageCount;
789 swapCreateInfo.imageExtent = extent;
790 swapCreateInfo.imageArrayLayers = 1;
791 swapCreateInfo.imageUsage = vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst;
792 swapCreateInfo.imageSharingMode = vk::SharingMode::eExclusive;
793 swapCreateInfo.queueFamilyIndexCount = 0;
794 swapCreateInfo.pQueueFamilyIndices =
nullptr;
796 swapCreateInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
798 swapCreateInfo.clipped =
true;
799 swapCreateInfo.oldSwapchain = oldSwapChain;
800 vk::SwapchainPresentScalingCreateInfoKHR scalingInfo{};
802 const vk::SurfacePresentModeKHR surfacePresentMode{
mPresentMode};
803 const auto caps =
mPhysicalDevice.getSurfaceCapabilities2KHR<vk::SurfaceCapabilities2KHR, vk::SurfacePresentScalingCapabilitiesKHR>(vk::PhysicalDeviceSurfaceInfo2KHR{
mSurface, &surfacePresentMode}).get<vk::SurfacePresentScalingCapabilitiesKHR>();
804 auto gravity = [](vk::PresentGravityFlagsKHR
f) {
return (
f & vk::PresentGravityFlagBitsKHR::eCentered) ? vk::PresentGravityFlagBitsKHR::eCentered : (
f & vk::PresentGravityFlagBitsKHR::eMin) ? vk::PresentGravityFlagBitsKHR::eMin
805 : vk::PresentGravityFlagsKHR(
f & vk::PresentGravityFlagBitsKHR::eMax); };
806 scalingInfo.scalingBehavior = (caps.supportedPresentScaling & vk::PresentScalingFlagBitsKHR::eAspectRatioStretch) ? vk::PresentScalingFlagBitsKHR::eAspectRatioStretch : vk::PresentScalingFlagsKHR(caps.supportedPresentScaling & vk::PresentScalingFlagBitsKHR::eStretch);
807 scalingInfo.presentGravityX = gravity(caps.supportedPresentGravityX);
808 scalingInfo.presentGravityY = gravity(caps.supportedPresentGravityY);
809 if (scalingInfo.scalingBehavior && scalingInfo.presentGravityX && scalingInfo.presentGravityY) {
810 swapCreateInfo.pNext = &scalingInfo;
817 mDevice.destroySwapchainKHR(oldSwapChain,
nullptr);
825 throw std::runtime_error(
"Too many swapchain images");
845 cmdImageMemoryBarrier(
mCommandBuffersPresent[
i],
mSwapChainImages[
i], vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::PipelineStageFlagBits2::eNone, vk::AccessFlagBits2::eNone, vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::ePresentSrcKHR);
853 if (!keepSwapChain) {
865 if (!needUpdateOffscreenBuffers && !smoothLinesChanged) {
872 if (needUpdateOffscreenBuffers) {
874 if (needUpdateSwapChain) {
909 mZImages.resize(imageCountWithMixImages);
915 for (uint32_t
i = 0;
i < imageCountWithMixImages;
i++) {
923 vk::ImageUsageFlags
usage = vk::ImageUsageFlagBits::eColorAttachment;
925 usage |= vk::ImageUsageFlagBits::eSampled;
928 usage |= vk::ImageUsageFlagBits::eTransferSrc;
939 createImageI(
mDevice,
mPhysicalDevice,
mMSAAImages[
i].
image,
mMSAAImages[
i].
memory,
mRenderWidth,
mRenderHeight,
mSurfaceFormat.format, vk::ImageUsageFlagBits::eColorAttachment, vk::MemoryPropertyFlagBits::eDeviceLocal, vk::ImageTiling::eOptimal,
mMSAASampleCount);
943 createImageI(
mDevice,
mPhysicalDevice,
mZImages[
i].
image,
mZImages[
i].
memory,
mRenderWidth,
mRenderHeight, vk::Format::eD32Sfloat, vk::ImageUsageFlagBits::eDepthStencilAttachment, vk::MemoryPropertyFlagBits::eDeviceLocal, vk::ImageTiling::eOptimal,
mMSAASampleCount);
949 float vertices[6][4] = {
978 vk::PipelineShaderStageCreateInfo shaderStages[2] = {vk::PipelineShaderStageCreateInfo{}, vk::PipelineShaderStageCreateInfo{}};
979 vk::PipelineShaderStageCreateInfo& vertShaderStageInfo = shaderStages[0];
980 vertShaderStageInfo.stage = vk::ShaderStageFlagBits::eVertex;
982 vertShaderStageInfo.pName =
"main";
983 vk::PipelineShaderStageCreateInfo& fragShaderStageInfo = shaderStages[1];
984 fragShaderStageInfo.stage = vk::ShaderStageFlagBits::eFragment;
986 fragShaderStageInfo.pName =
"main";
988 vk::VertexInputBindingDescription bindingDescription{};
989 bindingDescription.binding = 0;
991 bindingDescription.inputRate = vk::VertexInputRate::eVertex;
993 vk::VertexInputAttributeDescription attributeDescriptions{};
994 attributeDescriptions.binding = 0;
995 attributeDescriptions.location = 0;
997 attributeDescriptions.offset = 0;
999 vk::PipelineVertexInputStateCreateInfo vertexInputInfo{};
1000 vertexInputInfo.vertexBindingDescriptionCount = 1;
1001 vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
1002 vertexInputInfo.vertexAttributeDescriptionCount = 1;
1003 vertexInputInfo.pVertexAttributeDescriptions = &attributeDescriptions;
1004 vk::PipelineInputAssemblyStateCreateInfo inputAssembly{};
1006 inputAssembly.primitiveRestartEnable =
false;
1008 vk::PipelineViewportStateCreateInfo viewportState{};
1009 viewportState.viewportCount = 1;
1010 viewportState.scissorCount = 1;
1012 vk::PipelineRasterizationStateCreateInfo rasterizer{};
1013 rasterizer.depthClampEnable =
false;
1014 rasterizer.rasterizerDiscardEnable =
false;
1015 rasterizer.polygonMode = vk::PolygonMode::eFill;
1017 rasterizer.cullMode = vk::CullModeFlagBits::eBack;
1018 rasterizer.frontFace = vk::FrontFace::eClockwise;
1019 rasterizer.depthBiasEnable =
false;
1020 rasterizer.depthBiasConstantFactor = 0.0f;
1021 rasterizer.depthBiasClamp = 0.0f;
1022 rasterizer.depthBiasSlopeFactor = 0.0f;
1024 vk::PipelineMultisampleStateCreateInfo multisampling{};
1025 multisampling.sampleShadingEnable =
false;
1027 multisampling.minSampleShading = 1.0f;
1028 multisampling.pSampleMask =
nullptr;
1029 multisampling.alphaToCoverageEnable =
false;
1030 multisampling.alphaToOneEnable =
false;
1032 vk::PipelineColorBlendAttachmentState colorBlendAttachment{};
1033 colorBlendAttachment.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
1035 colorBlendAttachment.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
1036 colorBlendAttachment.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha;
1037 colorBlendAttachment.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha;
1038 colorBlendAttachment.colorBlendOp = vk::BlendOp::eAdd;
1039 colorBlendAttachment.srcAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha;
1040 colorBlendAttachment.dstAlphaBlendFactor = vk::BlendFactor::eZero;
1041 colorBlendAttachment.alphaBlendOp = vk::BlendOp::eAdd;
1043 vk::PipelineColorBlendStateCreateInfo colorBlending{};
1044 colorBlending.logicOpEnable =
false;
1045 colorBlending.logicOp = vk::LogicOp::eCopy;
1046 colorBlending.attachmentCount = 1;
1047 colorBlending.pAttachments = &colorBlendAttachment;
1048 colorBlending.blendConstants[0] = 0.0f;
1049 colorBlending.blendConstants[1] = 0.0f;
1050 colorBlending.blendConstants[2] = 0.0f;
1051 colorBlending.blendConstants[3] = 0.0f;
1053 vk::PipelineDepthStencilStateCreateInfo depthStencil{};
1054 depthStencil.depthTestEnable =
true;
1055 depthStencil.depthWriteEnable =
true;
1056 depthStencil.depthCompareOp = vk::CompareOp::eLess;
1057 depthStencil.depthBoundsTestEnable =
false;
1058 depthStencil.stencilTestEnable =
false;
1060 vk::DynamicState dynamicStates[] = {vk::DynamicState::eViewport, vk::DynamicState::eScissor, vk::DynamicState::eLineWidth};
1061 vk::PipelineDynamicStateCreateInfo dynamicState{};
1063 dynamicState.pDynamicStates = dynamicStates;
1065 vk::PushConstantRange pushConstantRanges[2] = {vk::PushConstantRange{}, vk::PushConstantRange{}};
1066 pushConstantRanges[0].stageFlags = vk::ShaderStageFlagBits::eFragment;
1067 pushConstantRanges[0].offset = 0;
1068 pushConstantRanges[0].size =
sizeof(float) * 4;
1069 pushConstantRanges[1].stageFlags = vk::ShaderStageFlagBits::eVertex;
1070 pushConstantRanges[1].offset = pushConstantRanges[0].size;
1071 pushConstantRanges[1].size = 4 *
sizeof(float);
1072 vk::PipelineLayoutCreateInfo pipelineLayoutInfo{};
1073 pipelineLayoutInfo.setLayoutCount = 1;
1075 pipelineLayoutInfo.pushConstantRangeCount = 2;
1076 pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges;
1078 pipelineLayoutInfo.setLayoutCount = 1;
1082 vk::GraphicsPipelineCreateInfo pipelineInfo{};
1083 pipelineInfo.stageCount = 2;
1084 pipelineInfo.pVertexInputState = &vertexInputInfo;
1085 pipelineInfo.pInputAssemblyState = &inputAssembly;
1086 pipelineInfo.pViewportState = &viewportState;
1087 pipelineInfo.pRasterizationState = &rasterizer;
1088 pipelineInfo.pMultisampleState = &multisampling;
1090 pipelineInfo.pColorBlendState = &colorBlending;
1091 pipelineInfo.pDynamicState = &dynamicState;
1093 vk::PipelineRenderingCreateInfo renderingInfo{0, 1, &
mSurfaceFormat.format};
1094 pipelineInfo.pNext = &renderingInfo;
1095 pipelineInfo.pStages = shaderStages;
1096 pipelineInfo.basePipelineHandle = VkPipeline(VK_NULL_HANDLE);
1097 pipelineInfo.basePipelineIndex = -1;
1100 vk::PipelineRasterizationLineStateCreateInfo smoothLineState{};
1101 smoothLineState.lineRasterizationMode = vk::LineRasterizationMode::eRectangularSmooth;
1104 static constexpr vk::PrimitiveTopology
types[3] = {vk::PrimitiveTopology::ePointList, vk::PrimitiveTopology::eLineList, vk::PrimitiveTopology::eLineStrip};
1107 rasterizer.pNext =
nullptr;
1108 rasterizer.cullMode = vk::CullModeFlagBits::eNone;
1109 vertexInputInfo.vertexBindingDescriptionCount = vertexInputInfo.vertexAttributeDescriptionCount = 0;
1110 inputAssembly.topology = vk::PrimitiveTopology::eTriangleList;
1111 vertShaderStageInfo.pNext = &
mShaders.at(
"vertexFullscreen");
1112 fragShaderStageInfo.pNext = &
mShaders.at(
"fragmentDownsample");
1113 dynamicState.dynamicStateCount = 2;
1115 renderingInfo.depthAttachmentFormat = vk::Format::eUndefined;
1116 pipelineInfo.pDepthStencilState =
nullptr;
1117 colorBlendAttachment.blendEnable =
false;
1118 multisampling.rasterizationSamples = vk::SampleCountFlagBits::e1;
1119 }
else if (
i == 4) {
1120 rasterizer.pNext =
nullptr;
1121 bindingDescription.stride = 4 *
sizeof(float);
1122 attributeDescriptions.format = vk::Format::eR32G32B32A32Sfloat;
1123 inputAssembly.topology = vk::PrimitiveTopology::eTriangleList;
1124 vertShaderStageInfo.pNext = &
mShaders.at(
"vertexTexture");
1125 fragShaderStageInfo.pNext = &
mShaders.at(
"fragmentTexture");
1126 dynamicState.dynamicStateCount = 2;
1128 renderingInfo.depthAttachmentFormat = vk::Format::eUndefined;
1129 pipelineInfo.pDepthStencilState =
nullptr;
1130 colorBlendAttachment.blendEnable =
true;
1131 multisampling.rasterizationSamples = vk::SampleCountFlagBits::e1;
1132 }
else if (
i == 3) {
1133 rasterizer.pNext =
nullptr;
1134 bindingDescription.stride = 4 *
sizeof(float);
1135 attributeDescriptions.format = vk::Format::eR32G32B32A32Sfloat;
1136 inputAssembly.topology = vk::PrimitiveTopology::eTriangleList;
1137 vertShaderStageInfo.pNext = &
mShaders.at(
"vertexTexture");
1138 fragShaderStageInfo.pNext = &
mShaders.at(
"fragmentText");
1139 dynamicState.dynamicStateCount = 2;
1141 renderingInfo.depthAttachmentFormat = vk::Format::eUndefined;
1142 pipelineInfo.pDepthStencilState =
nullptr;
1143 colorBlendAttachment.blendEnable =
true;
1144 multisampling.rasterizationSamples = vk::SampleCountFlagBits::e1;
1146 bindingDescription.stride = 3 *
sizeof(float);
1147 attributeDescriptions.format = vk::Format::eR32G32B32Sfloat;
1148 const uint32_t drawIdx =
i >= 5 ?
i - 5 :
i;
1149 inputAssembly.topology =
types[drawIdx];
1150 rasterizer.pNext =
mSmoothLines && (
i == 1 ||
i == 2) ? &smoothLineState :
nullptr;
1151 vertShaderStageInfo.pNext = &
mShaders.at(
i < 5 ? (drawIdx == 0 ?
"vertexPoint" :
"vertex") : (drawIdx == 0 ?
"vertexSmoothPoint" :
"vertexSmoothLine"));
1152 fragShaderStageInfo.pNext = &
mShaders.at(
i < 5 ?
"fragment" : (drawIdx == 0 ?
"fragmentSmoothPoint" :
"fragmentSmoothLine"));
1154 renderingInfo.depthAttachmentFormat =
mZActive ? vk::Format::eD32Sfloat : vk::Format::eUndefined;
1155 pipelineInfo.pDepthStencilState =
mZActive ? &depthStencil :
nullptr;
1156 dynamicState.dynamicStateCount = 3;
1157 colorBlendAttachment.blendEnable =
true;
1167 commandBuffer.reset({});
1169 vk::CommandBufferBeginInfo beginInfo{};
1170 beginInfo.flags = {};
1171 commandBuffer.begin(beginInfo);
1173 const uint32_t idx = toMixBuffer ? imageIndex +
mImageCount : imageIndex;
1175 const vk::PipelineStageFlags2 prevStages = vk::PipelineStageFlagBits2::eColorAttachmentOutput | vk::PipelineStageFlagBits2::eTransfer | vk::PipelineStageFlagBits2::eFragmentShader;
1176 cmdImageMemoryBarrier(commandBuffer,
mRenderTargetImage[idx], prevStages, vk::AccessFlagBits2::eColorAttachmentWrite | vk::AccessFlagBits2::eTransferWrite, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal);
1178 cmdImageMemoryBarrier(commandBuffer,
mMSAAImages[idx].
image, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal);
1181 const vk::PipelineStageFlags2 depthStages = vk::PipelineStageFlagBits2::eEarlyFragmentTests | vk::PipelineStageFlagBits2::eLateFragmentTests;
1182 cmdImageMemoryBarrier(commandBuffer,
mZImages[idx].
image, depthStages, vk::AccessFlagBits2::eDepthStencilAttachmentWrite, depthStages, vk::AccessFlagBits2::eDepthStencilAttachmentRead | vk::AccessFlagBits2::eDepthStencilAttachmentWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal, vk::ImageAspectFlagBits::eDepth);
1185 vk::RenderingAttachmentInfo colorAttachment{msaa ?
mMSAAImages[idx].view : *
mRenderTargetView[idx], vk::ImageLayout::eColorAttachmentOptimal};
1186 colorAttachment.loadOp = vk::AttachmentLoadOp::eClear;
1187 colorAttachment.storeOp = msaa ? vk::AttachmentStoreOp::eDontCare : vk::AttachmentStoreOp::eStore;
1188 colorAttachment.clearValue.color =
mDisplay->
cfgL().invertColors ? vk::ClearColorValue{std::array<float, 4>{1.0f, 1.0f, 1.0f, 1.0f}} : vk::ClearColorValue{std::array<float, 4>{0.0f, 0.0f, 0.0f, 1.0f}};
1190 colorAttachment.resolveMode = vk::ResolveModeFlagBits::eAverage;
1192 colorAttachment.resolveImageLayout = vk::ImageLayout::eColorAttachmentOptimal;
1194 vk::RenderingAttachmentInfo depthAttachment{
mZActive ?
mZImages[idx].view : vk::ImageView{}, vk::ImageLayout::eDepthStencilAttachmentOptimal};
1195 depthAttachment.loadOp = vk::AttachmentLoadOp::eClear;
1196 depthAttachment.storeOp = vk::AttachmentStoreOp::eDontCare;
1197 depthAttachment.clearValue.depthStencil = vk::ClearDepthStencilValue{1.0f, 0};
1200 vk::DeviceSize
offsets[] = {0};
1206 commandBuffer.pushConstants(
mPipelineLayout, vk::ShaderStageFlagBits::eVertex, 6 *
sizeof(
float),
sizeof(viewport), viewport);
1211 commandBuffer.endRendering();
1212 commandBuffer.end();
1224#define LOAD_SHADER(file, ext) \
1225 mShaders[#file] = vk::ShaderModuleCreateInfo { {}, _binary_vulkan_##file##_##ext##_spv_len, reinterpret_cast<const uint32_t*>(_binary_vulkan_##file##_##ext##_spv_start) }
1250 auto tmp =
createBuffer(
size, srcData, vk::BufferUsageFlagBits::eTransferSrc, 0);
1253 vk::BufferCopy copyRegion{};
1254 copyRegion.size =
size;
1255 commandBuffer.copyBuffer(tmp.buffer,
buffer.buffer, 1, ©Region);
1264 vk::MemoryPropertyFlags properties;
1266 properties |= vk::MemoryPropertyFlagBits::eDeviceLocal;
1268 if (deviceMemory == 0 || deviceMemory == 2) {
1269 properties |= (vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
1271 if (deviceMemory == 1) {
1272 type |= vk::BufferUsageFlagBits::eTransferDst;
1276 vk::BufferCreateInfo bufferInfo{};
1278 bufferInfo.usage =
type;
1279 bufferInfo.sharingMode = vk::SharingMode::eExclusive;
1282 vk::MemoryRequirements memRequirements;
1283 memRequirements =
mDevice.getBufferMemoryRequirements(
buffer.buffer);
1284 vk::MemoryAllocateInfo allocInfo{};
1285 allocInfo.allocationSize = memRequirements.size;
1286 allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties,
mPhysicalDevice);
1292 buffer.deviceMemory = deviceMemory;
1293 if (deviceMemory != 1) {
1297 if (srcData !=
nullptr) {
1326 auto tmp =
createBuffer(srcSize, srcData, vk::BufferUsageFlagBits::eTransferSrc, 0);
1329 cmdImageMemoryBarrier(commandBuffer,
image.image, vk::PipelineStageFlagBits2::eNone, vk::AccessFlagBits2::eNone, vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eTransferWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal);
1330 vk::BufferImageCopy region{};
1331 region.bufferOffset = 0;
1332 region.bufferRowLength = 0;
1333 region.bufferImageHeight = 0;
1334 region.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1335 region.imageSubresource.mipLevel = 0;
1336 region.imageSubresource.baseArrayLayer = 0;
1337 region.imageSubresource.layerCount = 1;
1338 region.imageOffset = vk::Offset3D{0, 0, 0};
1339 region.imageExtent = vk::Extent3D{
image.sizex,
image.sizey, 1};
1340 commandBuffer.copyBufferToImage(tmp.buffer,
image.image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion);
1341 cmdImageMemoryBarrier(commandBuffer,
image.image, vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eTransferWrite, vk::PipelineStageFlagBits2::eFragmentShader, vk::AccessFlagBits2::eShaderSampledRead, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal);
1350 createImageI(
mDevice,
mPhysicalDevice,
image.image,
image.memory, sizex, sizey,
format, vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled, vk::MemoryPropertyFlagBits::eDeviceLocal, vk::ImageTiling::eOptimal, vk::SampleCountFlagBits::e1);
1354 image.sizex = sizex;
1355 image.sizey = sizey;
1431 if (totalVertizes) {
1446 auto first = std::get<0>(
v);
1447 auto count = std::get<1>(
v);
1464 for (uint32_t k = 0; k <
count; k++) {
1481 if (includeMixImage == 0.f) {
1485 const vk::Result
retVal = (vk::Result)VULKAN_HPP_DEFAULT_DISPATCHER.vkWaitForPresentKHR(
static_cast<VkDevice
>(
mDevice),
static_cast<VkSwapchainKHR
>(
mSwapChain),
mLastPresentId - 1, 100'000'000);
1487 if (
retVal != vk::Result::eTimeout &&
retVal != vk::Result::eErrorOutOfDateKHR) {
1491 auto getImage = [&]() {
1495 vk::Result
retVal = vk::Result::eSuccess;
1500 if (!mustUpdateSwapChain) {
1502 if (
retVal == vk::Result::eErrorOutOfDateKHR) {
1506 if (mustUpdateSwapChain) {
1525 const hmm_mat4 modelViewProj = proj * view;
1526 static_assert(
sizeof(modelViewProj) ==
sizeof(
mLastMVP));
1549 if (
retVal == vk::Result::eSuboptimalKHR) {
1572 if (includeMixImage > 0.f) {
1582 vk::SubmitInfo2 submitInfo{{}, 1, &waitInfo};
1586 queueSubmit(
nullptr, 1, &submitInfo, VkFence(VK_NULL_HANDLE));
1594 submitInfo.waitSemaphoreInfoCount = 0;
1603 submitInfo.signalSemaphoreInfoCount = 2;
1604 submitInfo.pSignalSemaphoreInfos = signalInfos;
1607 vk::PresentInfoKHR presentInfo{};
1608 presentInfo.waitSemaphoreCount = 1;
1610 presentInfo.swapchainCount = 1;
1613 presentInfo.pResults =
nullptr;
1615 vk::PresentIdKHR presentIdInfo{1, &presentId};
1617 presentInfo.pNext = &presentIdInfo;
1620 vk::SwapchainPresentFenceInfoKHR presentFenceInfo{};
1623 presentInfo.pNext = &presentFenceInfo;
1631 if (
retVal != vk::Result::eErrorOutOfDateKHR) {
1639 commandBuffer.reset({});
1640 vk::CommandBufferBeginInfo beginInfo{};
1641 beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
1642 commandBuffer.begin(beginInfo);
1645 cmdImageMemoryBarrier(commandBuffer,
mSwapChainImages[
mCurrentImageIndex], vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eNone, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal);
1646 cmdImageMemoryBarrier(commandBuffer,
mDownsampleImages[
mCurrentImageIndex].
image, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::PipelineStageFlagBits2::eFragmentShader, vk::AccessFlagBits2::eShaderSampledRead, vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eShaderReadOnlyOptimal);
1648 commandBuffer.end();
1651 cmdImageMemoryBarrier(commandBuffer,
mSwapChainImages[
mCurrentImageIndex], vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eNone, vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eTransferWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal);
1652 cmdImageMemoryBarrier(commandBuffer,
mDownsampleImages[
mCurrentImageIndex].
image, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eTransferRead, vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eTransferSrcOptimal);
1654 vk::Offset3D blitSizeSrc;
1658 vk::Offset3D blitSizeDst;
1662 vk::ImageBlit imageBlitRegion{};
1663 imageBlitRegion.srcSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1664 imageBlitRegion.srcSubresource.layerCount = 1;
1665 imageBlitRegion.srcOffsets[1] = blitSizeSrc;
1666 imageBlitRegion.dstSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1667 imageBlitRegion.dstSubresource.layerCount = 1;
1668 imageBlitRegion.dstOffsets[1] = blitSizeDst;
1671 cmdImageMemoryBarrier(commandBuffer,
mSwapChainImages[
mCurrentImageIndex], vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eTransferWrite, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentRead | vk::AccessFlagBits2::eColorAttachmentWrite, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eColorAttachmentOptimal);
1673 commandBuffer.end();
1678 vk::RenderingAttachmentInfo colorAttachment{
dst, vk::ImageLayout::eColorAttachmentOptimal};
1679 colorAttachment.loadOp = vk::AttachmentLoadOp::eDontCare;
1680 cmdBeginRendering(commandBuffer,
width,
height, colorAttachment);
1681 commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics,
mPipelines[8]);
1683 commandBuffer.pushConstants(
mPipelineLayoutTexture, vk::ShaderStageFlagBits::eFragment, 0,
sizeof(factor), &factor);
1684 commandBuffer.draw(3, 1, 0, 0);
1685 commandBuffer.endRendering();
1707 vk::CommandBufferBeginInfo beginInfo{};
1708 beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
1715 if (fontBuffer.
size < fontBufferSize) {
1716 if (fontBuffer.
size) {
1719 fontBuffer =
createBuffer(std::max(fontBufferSize, 2 * fontBuffer.
size),
nullptr, vk::BufferUsageFlagBits::eVertexBuffer, 0);
1725 vk::DeviceSize
offsets[] = {0};
1746 commandBuffer.reset({});
1747 vk::CommandBufferBeginInfo beginInfo{};
1748 beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
1749 commandBuffer.begin(beginInfo);
1752 cmdImageMemoryBarrier(commandBuffer,
image, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::PipelineStageFlagBits2::eFragmentShader, vk::AccessFlagBits2::eShaderSampledRead, vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eShaderReadOnlyOptimal);
1755 commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics,
mPipelines[4]);
1757 vk::DeviceSize
offsets[] = {0};
1760 commandBuffer.pushConstants(
mPipelineLayoutTexture, vk::ShaderStageFlagBits::eFragment, 0,
sizeof(mixSlaveImage), &mixSlaveImage);
1761 commandBuffer.draw(6, 1, 0, 0);
1763 commandBuffer.endRendering();
1764 commandBuffer.end();
1817 throw std::runtime_error(
"Incorrect symbol ID");
1821 if (sizex && sizey) {
1822 buffer.reset(
new char[sizex * sizey]);
1829 int32_t maxSizeX = 0, maxSizeY = 0, maxBigX = 0, maxBigY = 0, maxRowY = 0;
1833 maxSizeX = std::max(maxSizeX, symbol.size[0]);
1834 maxSizeY = std::max(maxSizeY, symbol.size[1]);
1837 int32_t sizex = nn * maxSizeX;
1838 int32_t sizey = nn * maxSizeY;
1839 std::unique_ptr<char[]> bigImage{
new char[sizex * sizey]};
1840 memset(bigImage.get(), 0, sizex * sizey);
1841 int32_t rowy = 0, colx = 0;
1844 if (colx + s.size[0] > sizex) {
1849 for (int32_t k = 0; k < s.size[1]; k++) {
1850 for (int32_t
j = 0;
j < s.size[0];
j++) {
1851 int8_t
val = s.data.get()[
j + k * s.size[0]];
1853 val =
val < 0 ? 0xFF : 0;
1855 bigImage.get()[(colx +
j) + (rowy + k) * sizex] =
val;
1860 s.x1 = colx + s.size[0];
1862 s.y1 = rowy + s.size[1];
1863 maxBigX = std::max(maxBigX, colx + s.size[0]);
1864 maxBigY = std::max(maxBigY, rowy + s.size[1]);
1865 maxRowY = std::max(maxRowY, s.size[1]);
1868 if (maxBigX != sizex) {
1869 for (int32_t
y = 1;
y < maxBigY;
y++) {
1870 memmove(bigImage.get() +
y * maxBigX, bigImage.get() +
y * sizex, maxBigX);
1907 for (
const unsigned char*
c = (
const unsigned char*)s; *
c;
c++) {
1909 GPUError(
"Trying to draw unsupported symbol: %d > %d\n", (int32_t)*
c, (int32_t)
mFontSymbols.size());
1915 float xpos =
x + sym.
offset[0] * scale;
1916 float ypos =
y - (sym.
size[1] - sym.
offset[1]) * scale;
1917 float w = sym.
size[0] * scale;
1918 float h = sym.
size[1] * scale;
1919 float vertices[6][4] = {
1937 if (
c.size() &&
c.back().color[0] ==
color[0] &&
c.back().color[1] ==
color[1] &&
c.back().color[2] ==
color[2] &&
c.back().color[3] ==
color[3]) {
1938 c.back().nVertices += nVertices;
1948 if (
format != vk::Format::eB8G8R8A8Unorm &&
format != vk::Format::eB8G8R8A8Srgb &&
format != vk::Format::eR8G8B8A8Unorm &&
format != vk::Format::eR8G8B8A8Srgb) {
1949 GPUError(
"Screenshot not supported for swapchain format %s, only 8 bit BGRA / RGBA", vk::to_string(
format).c_str());
1955 static constexpr int32_t bytesPerPixel = 4;
1958 vk::Image dstImage,
src;
1959 vk::ImageView dstView;
1960 vk::DeviceMemory dstImageMemory;
1961 const bool scaled =
mDisplay->
cfgR().screenshotScaleFactor != 1;
1963 const bool shaderDownsample = scaled && factor != 1 && factor != 2;
1964 const vk::ImageLayout srcLayout = shaderDownsample ? vk::ImageLayout::eShaderReadOnlyOptimal : vk::ImageLayout::eTransferSrcOptimal;
1965 const vk::PipelineStageFlags2 srcStage = shaderDownsample ? vk::PipelineStageFlagBits2::eFragmentShader : vk::PipelineStageFlagBits2::eTransfer;
1968 cmdImageMemoryBarrier(cmdBuffer,
image, vk::PipelineStageFlagBits2::eColorAttachmentOutput | vk::PipelineStageFlagBits2::eTransfer | vk::PipelineStageFlagBits2::eFragmentShader, vk::AccessFlagBits2::eColorAttachmentWrite | vk::AccessFlagBits2::eTransferWrite, srcStage, shaderDownsample ? vk::AccessFlagBits2::eShaderSampledRead : vk::AccessFlagBits2::eTransferRead, layout, srcLayout);
1969 if (shaderDownsample) {
1970 createImageI(
mDevice,
mPhysicalDevice, dstImage, dstImageMemory,
width,
height,
mSurfaceFormat.format, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eDeviceLocal, vk::ImageTiling::eOptimal);
1972 cmdImageMemoryBarrier(cmdBuffer, dstImage, vk::PipelineStageFlagBits2::eNone, vk::AccessFlagBits2::eNone, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal);
1974 cmdImageMemoryBarrier(cmdBuffer, dstImage, vk::PipelineStageFlagBits2::eColorAttachmentOutput, vk::AccessFlagBits2::eColorAttachmentWrite, vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eTransferRead, vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eTransferSrcOptimal);
1976 }
else if (scaled) {
1977 createImageI(
mDevice,
mPhysicalDevice, dstImage, dstImageMemory,
width,
height,
mSurfaceFormat.format, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst, vk::MemoryPropertyFlagBits::eDeviceLocal, vk::ImageTiling::eOptimal);
1978 cmdImageMemoryBarrier(cmdBuffer, dstImage, vk::PipelineStageFlagBits2::eNone, vk::AccessFlagBits2::eNone, vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eTransferWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal);
1980 vk::Offset3D blitSizeDst = {(int32_t)
width, (int32_t)
height, 1};
1981 vk::ImageBlit imageBlitRegion{};
1982 imageBlitRegion.srcSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1983 imageBlitRegion.srcSubresource.layerCount = 1;
1984 imageBlitRegion.srcOffsets[1] = blitSizeSrc;
1985 imageBlitRegion.dstSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1986 imageBlitRegion.dstSubresource.layerCount = 1;
1987 imageBlitRegion.dstOffsets[1] = blitSizeDst;
1988 cmdBuffer.blitImage(
image, vk::ImageLayout::eTransferSrcOptimal, dstImage, vk::ImageLayout::eTransferDstOptimal, 1, &imageBlitRegion, vk::Filter::eLinear);
1990 cmdImageMemoryBarrier(cmdBuffer, dstImage, vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eTransferWrite, vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eTransferRead, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eTransferSrcOptimal);
1995 vk::BufferImageCopy copyRegion{};
1996 copyRegion.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1997 copyRegion.imageSubresource.layerCount = 1;
1998 copyRegion.imageExtent = vk::Extent3D{
width,
height, 1};
1999 cmdBuffer.copyImageToBuffer(
src, vk::ImageLayout::eTransferSrcOptimal, readBuffer.
buffer, 1, ©Region);
2001 vk::BufferMemoryBarrier2 hostBarrier{vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eTransferWrite, vk::PipelineStageFlagBits2::eHost, vk::AccessFlagBits2::eHostRead, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, readBuffer.
buffer, 0, VK_WHOLE_SIZE};
2002 cmdBuffer.pipelineBarrier2(vk::DependencyInfo{{}, 0,
nullptr, 1, &hostBarrier, 0,
nullptr});
2003 cmdImageMemoryBarrier(cmdBuffer,
image, srcStage, vk::AccessFlagBits2::eNone, vk::PipelineStageFlagBits2::eColorAttachmentOutput | vk::PipelineStageFlagBits2::eTransfer, vk::AccessFlagBits2::eNone, srcLayout, layout);
2006 const bool swapRB =
format == vk::Format::eR8G8B8A8Unorm ||
format == vk::Format::eR8G8B8A8Srgb;
2007 const char*
data = (
const char*)readBuffer.
mapped;
2012 for (uint32_t
j = 0;
j <
width;
j++) {
2013 std::swap(
dst[
j * bytesPerPixel],
dst[
j * bytesPerPixel + 2]);
2020 mDevice.destroyImageView(dstView,
nullptr);
2022 mDevice.freeMemory(dstImageMemory,
nullptr);
2023 mDevice.destroyImage(dstImage,
nullptr);
#define LOAD_SHADER(file, ext)
HMM_INLINE hmm_mat4 HMM_Orthographic(float Left, float Right, float Bottom, float Top, float Near, float Far)
Class for time synchronization of RawReader instances.
void OpenGLPrint(const char *s, float x, float y, float *color, float scale) override
vk::CommandBuffer getSingleTimeCommandBuffer()
std::vector< vk::CommandBuffer > mCommandBuffersMix
std::vector< vk::CommandBuffer > mCommandBuffers
std::vector< vk::Semaphore > mPresentSemaphore
vk::DescriptorSetLayout mUniformDescriptor
VulkanBuffer mIndirectCommandBuffer
std::vector< vk::Image > mRenderTargetImage
std::vector< vk::Pipeline > mPipelines
vk::CommandBuffer mCurrentCommandBuffer
void createCommandBuffers()
void resizeScene(uint32_t width, uint32_t height) override
bool mFifoLatestReadySupported
int32_t mCurrentCommandBufferLastPipeline
uint32_t DepthBits() override
void submitSingleTimeCommandBuffer(vk::CommandBuffer commandBuffer)
uint8_t mSwapChainSuboptimal
std::vector< VulkanImage > mDownsampleImages
void clearUniformLayoutsAndBuffers()
void writeToBuffer(VulkanBuffer &buffer, size_t size, const void *srcData)
std::vector< vk::ImageView > mSwapChainImageViews
std::vector< vk::CommandBufferSubmitInfo > mFrameCommandBuffers
std::vector< VulkanImage > mMSAAImages
void pointSizeFactor(float factor) override
uint32_t mUpdateUBOmixMatrix
std::vector< FontSymbolVulkan > mFontSymbols
vk::SwapchainKHR mSwapChain
int32_t InitBackendA() override
void clearImage(VulkanImage &image)
std::vector< vk::ImageView * > mRenderTargetView
vk::PipelineCache mPipelineCache
void finishText() override
bool prepareDraw(const hmm_mat4 &proj, const hmm_mat4 &view, bool requestScreenshot, bool toMixBuffer, float includeMixImage) override
void addFontSymbol(int32_t symbol, int32_t sizex, int32_t sizey, int32_t offsetx, int32_t offsety, int32_t advance, void *data) override
bool backendNeedRedraw() override
vk::SampleCountFlagBits mMSAASampleCount
void mixImages(vk::CommandBuffer cmdBuffer, float mixSlaveImage)
void clearVertexBuffers()
bool mSmoothLinesSupported
void createTextureSampler()
void recreateRendering(bool forScreenshot=false, bool forMixing=false)
std::vector< VulkanBuffer > mFontVertexBuffer
double checkDevice(vk::PhysicalDevice device, const std::vector< const char * > &reqDeviceExtensions, const FeatureChain &reqDeviceFeatures, bool silent=false)
void endFillCommandBuffer(vk::CommandBuffer &commandBuffer)
std::vector< uint64_t > mImageTimelineValue
uint32_t drawVertices(const vboList &v, const drawType t) override
vk::SurfaceFormatKHR mSurfaceFormat
std::vector< vk::CommandBuffer > mCommandBuffersPresent
std::vector< vk::CommandBuffer > mCommandBuffersDownsample
void ActivateColor(std::array< float, 4 > &color) override
std::vector< vk::Image > mSwapChainImages
uint32_t mUpdateUBOdrawMatrix
uint32_t mUpdateUBOtextMatrix
uint64_t queueSubmit(uint64_t *timelineSignalValue, Args &&... args)
void initializeTextDrawing() override
void clearBuffer(VulkanBuffer &buffer)
VulkanBuffer mMixingTextureVertexArray
vk::Sampler mTextureSampler
vk::Semaphore mTimelineSemaphore
uint32_t mCurrentImageIndex
void createUniformLayoutsAndBuffers()
void needRecordCommandBuffers()
std::vector< VulkanBuffer > mUniformBuffersMat[3]
bool mCommandInfrastructureCreated
void updateSwapChainDetails(const vk::PhysicalDevice &device)
void handleSwapChainResult(vk::Result retVal, uint8_t suboptimalBit)
std::vector< VulkanImage > mMixImages
std::vector< uint64_t > mFrameTimelineValue
vk::CommandPool mCommandPool
vk::StructureChain< vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan11Features, vk::PhysicalDeviceVulkan12Features, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceVulkan14Features, vk::PhysicalDeviceSwapchainMaintenance1FeaturesKHR, vk::PhysicalDevicePresentIdFeaturesKHR, vk::PhysicalDevicePresentWaitFeaturesKHR > FeatureChain
void finishDraw(bool doScreenshot, bool toMixBuffer, float includeMixImage) override
void writeToImage(VulkanImage &image, const void *srcData, size_t srcSize)
vecpod< float > mFontVertexBufferHost
vk::PresentModeKHR chooseSwapPresentMode()
vk::PipelineLayout mPipelineLayout
void clearOffscreenBuffers()
std::unordered_map< std::string, vk::ShaderModuleCreateInfo > mShaders
vk::DescriptorSetLayout mUniformDescriptorTexture
void downsampleToFramebuffer(vk::CommandBuffer &commandBuffer)
void createSwapChain(vk::SwapchainKHR oldSwapChain={})
void ExitBackendA() override
vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR &capabilities)
~GPUDisplayBackendVulkan() override
bool mPresentModeErrorShown
VulkanImage createImage(uint32_t sizex, uint32_t sizey, const void *srcData=nullptr, size_t srcSize=0, vk::Format format=vk::Format::eR8G8B8A8Srgb)
std::vector< TextDrawCommand > mTextDrawCommands
void clearTextureSampler()
vk::PipelineLayout mPipelineLayoutTexture
bool useSmoothLineShader() const
SwapChainSupportDetails mSwapChainDetails
uint32_t mMaxMSAAsupported
void cmdPushDescriptors(vk::CommandBuffer commandBuffer, vk::PipelineLayout layout, const VulkanBuffer &ubo, vk::ImageView textureView={})
void finishFrame(bool doScreenshot, bool toMixBuffer, float includeMixImage) override
bool mPresentModeForVSyncLimit
void clearSwapChain(bool keepSwapChain=false)
std::vector< vk::Semaphore > mImageAvailableSemaphore
void startFillCommandBuffer(vk::CommandBuffer &commandBuffer, uint32_t imageIndex, bool toMixBuffer=false)
void waitTimeline(uint64_t value)
std::vector< vk::CommandBuffer > mCommandBuffersTexture
vk::PhysicalDevice mPhysicalDevice
vk::DebugUtilsMessengerEXT mDebugMessenger
GPUDisplayBackendVulkan()
void clearFontSymbols() override
std::vector< vk::Fence > mPresentFences
void cmdDownsample(vk::CommandBuffer commandBuffer, vk::ImageView src, vk::ImageView dst, uint32_t width, uint32_t height, int32_t factor)
VulkanBuffer createBuffer(size_t size, const void *srcData=nullptr, vk::BufferUsageFlags type=vk::BufferUsageFlagBits::eVertexBuffer, int32_t deviceMemory=1)
std::vector< VulkanImage > mZImages
void createOffscreenBuffers(bool forScreenshot=false, bool forMixing=false)
bool mEnableValidationLayers
std::vector< bool > mCommandBufferUpToDate
void lineWidthFactor(float factor) override
void prepareText() override
void clearCommandBuffers()
void readImageToPixels(vk::Image image, vk::ImageView view, vk::ImageLayout layout, std::vector< char > &pixels)
std::vector< vk::CommandBuffer > mCommandBuffersText
bool mMustUpdateSwapChain
vk::PresentModeKHR mPresentMode
bool useNativeSmoothLines() const
void loadDataToGPU(size_t totalVertizes) override
int32_t fpsLimitMode() const
vecpod< DrawArraysIndirectCommand > mCmdBuffer
std::vector< int32_t > mIndirectSectorOffset
void fillIndirectCmdBuffer()
static constexpr float SMOOTH_LINE_EXTRA_WIDTH
bool mFreetypeInitialized
std::vector< char > mScreenshotPixels
static constexpr float SMOOTH_POINT_EXTRA_SIZE
backendTypes mBackendType
const char * mBackendName
float getDownsampleFactor(bool screenshot=false)
int32_t mDownsampleFactor
std::tuple< uint32_t, uint32_t, int32_t > vboList
virtual uint32_t getReqVulkanExtensions(const char **&p)
virtual void getSize(int32_t &width, int32_t &height)
virtual int32_t getVulkanSurface(void *instance, void *surface)
const GPUSettingsDisplayLight & cfgL() const
int32_t updateRenderPipeline() const
const GPUSettingsDisplayRenderer & cfgR() const
vecpod< vtx > * vertexBuffer()
bool drawTextInCompatMode() const
int32_t updateDrawCommands() const
GPUDisplayFrontend * frontend()
const vecpod< uint32_t > * vertexBufferCount() const
const GPUSettingsDisplay & cfg() const
vecpod< int32_t > * vertexBufferStart()
const GPUSettingsProcessing & GetProcessingSettings() const
GLuint GLsizei const GLuint const GLintptr * offsets
GLsizei GLenum GLenum * types
GLint GLsizei GLsizei height
GLsizei const GLfloat * value
GLint GLint GLsizei GLint GLenum GLenum type
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
GLint GLint GLsizei GLsizei GLsizei depth
GLboolean GLboolean GLboolean GLboolean a
GLubyte GLubyte GLubyte GLubyte w
GLint GLint GLsizei GLint GLenum format
GLsizeiptr const void GLenum usage
std::vector< T, fair::mq::pmr::polymorphic_allocator< T > > vector
std::vector< vk::SurfaceFormatKHR > formats
vk::SurfaceCapabilitiesKHR capabilities
std::vector< vk::PresentModeKHR > presentModes