15#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
16#include <vulkan/vulkan.hpp>
17VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
40 auto tmp_internal_retVal = cmd; \
41 if ((int32_t)tmp_internal_retVal < 0) { \
42 GPUError("VULKAN ERROR: %d: %s (%s: %d)", (int32_t)tmp_internal_retVal, "ERROR", __FILE__, __LINE__); \
43 throw std::runtime_error("Vulkan Failure"); \
56static int32_t checkVulkanLayersSupported(
const std::vector<const char*>& validationLayers)
58 std::vector<vk::LayerProperties> availableLayers = vk::enumerateInstanceLayerProperties();
59 for (
const char* layerName : validationLayers) {
60 bool layerFound =
false;
62 for (
const auto& layerProperties : availableLayers) {
63 if (strcmp(layerName, layerProperties.layerName) == 0) {
76static uint32_t findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties, vk::PhysicalDevice physDev)
78 vk::PhysicalDeviceMemoryProperties memProperties = physDev.getMemoryProperties();
80 for (uint32_t
i = 0;
i < memProperties.memoryTypeCount;
i++) {
81 if ((typeFilter & (1 <<
i)) && (memProperties.memoryTypes[
i].propertyFlags & properties) == properties) {
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];
99static vk::PresentModeKHR chooseSwapPresentMode(
const std::vector<vk::PresentModeKHR>& availablePresentModes, vk::PresentModeKHR desiredMode = vk::PresentModeKHR::eMailbox)
101 for (
const auto& availablePresentMode : availablePresentModes) {
102 if (availablePresentMode == desiredMode) {
103 return availablePresentMode;
106 static bool errorShown =
false;
109 GPUError(
"VULKAN ERROR: Desired present mode not available, using FIFO mode");
111 return vk::PresentModeKHR::eFifo;
116 if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
117 return capabilities.currentExtent;
121 vk::Extent2D actualExtent = {(uint32_t)
width, (uint32_t)
height};
122 actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
123 actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
128static vk::ShaderModule createShaderModule(
const char* code,
size_t size, vk::Device device)
130 vk::ShaderModuleCreateInfo createInfo{};
131 createInfo.codeSize =
size;
132 createInfo.pCode =
reinterpret_cast<const uint32_t*
>(code);
133 return device.createShaderModule(createInfo,
nullptr);
136static void cmdImageMemoryBarrier(vk::CommandBuffer cmdbuffer, vk::Image
image, vk::AccessFlags srcAccessMask, vk::AccessFlags dstAccessMask, vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::PipelineStageFlags srcStageMask, vk::PipelineStageFlags dstStageMask)
138 vk::ImageSubresourceRange
range{vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1};
139 vk::ImageMemoryBarrier barrier{};
140 barrier.srcAccessMask = srcAccessMask;
141 barrier.dstAccessMask = dstAccessMask;
142 barrier.oldLayout = oldLayout;
143 barrier.newLayout = newLayout;
144 barrier.image =
image;
145 barrier.subresourceRange =
range;
146 cmdbuffer.pipelineBarrier(srcStageMask, dstStageMask, {}, 0,
nullptr, 0,
nullptr, 1, &barrier);
158 vk::CommandBufferAllocateInfo allocInfo{};
159 allocInfo.level = vk::CommandBufferLevel::ePrimary;
161 allocInfo.commandBufferCount = 1;
162 vk::CommandBuffer commandBuffer =
mDevice.allocateCommandBuffers(allocInfo)[0];
163 vk::CommandBufferBeginInfo beginInfo{};
164 beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
165 commandBuffer.begin(beginInfo);
166 return commandBuffer;
172 vk::SubmitInfo submitInfo{};
173 submitInfo.commandBufferCount = 1;
174 submitInfo.pCommandBuffers = &commandBuffer;
175 static std::mutex fenceMutex;
177 std::lock_guard<std::mutex> guard(fenceMutex);
185static vk::ImageView createImageViewI(vk::Device device, vk::Image
image, vk::Format
format, vk::ImageAspectFlags aspectFlags = vk::ImageAspectFlagBits::eColor, uint32_t mipLevels = 1)
187 vk::ImageViewCreateInfo viewInfo{};
188 viewInfo.image =
image;
189 viewInfo.viewType = vk::ImageViewType::e2D;
191 viewInfo.subresourceRange.aspectMask = aspectFlags;
192 viewInfo.subresourceRange.baseMipLevel = 0;
193 viewInfo.subresourceRange.levelCount = mipLevels;
194 viewInfo.subresourceRange.baseArrayLayer = 0;
195 viewInfo.subresourceRange.layerCount = 1;
196 return device.createImageView(viewInfo,
nullptr);
199static 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)
201 vk::ImageCreateInfo imageInfo{};
202 imageInfo.imageType = vk::ImageType::e2D;
203 imageInfo.extent.width =
width;
204 imageInfo.extent.height =
height;
205 imageInfo.extent.depth = 1;
206 imageInfo.mipLevels = mipLevels;
207 imageInfo.arrayLayers = 1;
208 imageInfo.format =
format;
209 imageInfo.tiling = tiling;
210 imageInfo.initialLayout = layout;
211 imageInfo.usage =
usage;
212 imageInfo.samples = numSamples;
213 imageInfo.sharingMode = vk::SharingMode::eExclusive;
214 image = device.createImage(imageInfo);
216 vk::MemoryRequirements memRequirements;
217 memRequirements = device.getImageMemoryRequirements(
image);
219 vk::MemoryAllocateInfo allocInfo{};
220 allocInfo.allocationSize = memRequirements.size;
221 allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties, physicalDevice);
222 imageMemory = device.allocateMemory(allocInfo,
nullptr);
224 device.bindImageMemory(
image, imageMemory, 0);
227static uint32_t getMaxUsableSampleCount(vk::PhysicalDeviceProperties& physicalDeviceProperties)
229 vk::SampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts;
230 if (counts & vk::SampleCountFlagBits::e64) {
232 }
else if (counts & vk::SampleCountFlagBits::e32) {
234 }
else if (counts & vk::SampleCountFlagBits::e16) {
236 }
else if (counts & vk::SampleCountFlagBits::e8) {
238 }
else if (counts & vk::SampleCountFlagBits::e4) {
240 }
else if (counts & vk::SampleCountFlagBits::e2) {
246static vk::SampleCountFlagBits getMSAASamplesFlag(uint32_t msaa)
249 return vk::SampleCountFlagBits::e2;
250 }
else if (msaa == 4) {
251 return vk::SampleCountFlagBits::e4;
252 }
else if (msaa == 8) {
253 return vk::SampleCountFlagBits::e8;
254 }
else if (msaa == 16) {
255 return vk::SampleCountFlagBits::e16;
256 }
else if (msaa == 32) {
257 return vk::SampleCountFlagBits::e32;
258 }
else if (msaa == 64) {
259 return vk::SampleCountFlagBits::e64;
261 return vk::SampleCountFlagBits::e1;
264template <
class T,
class S>
265static inline void clearVector(T&
v,
S func,
bool downsize =
true)
267 std::for_each(
v.begin(),
v.end(),
func);
278 vk::PhysicalDeviceProperties deviceProperties = device.getProperties();
279 vk::PhysicalDeviceFeatures deviceFeatures = device.getFeatures();
280 vk::PhysicalDeviceMemoryProperties memoryProperties = device.getMemoryProperties();
281 if (!deviceFeatures.geometryShader || !deviceFeatures.wideLines || !deviceFeatures.largePoints) {
285 std::vector<vk::QueueFamilyProperties> queueFamilies = device.getQueueFamilyProperties();
287 for (uint32_t
i = 0;
i < queueFamilies.size();
i++) {
288 if (!(queueFamilies[
i].queueFlags & vk::QueueFlagBits::eGraphics)) {
291 vk::Bool32 presentSupport = device.getSurfaceSupportKHR(
i,
mSurface);
292 if (!presentSupport) {
300 GPUInfo(
"%s ignored due to missing queue properties", &deviceProperties.deviceName[0]);
304 std::vector<vk::ExtensionProperties> availableExtensions = device.enumerateDeviceExtensionProperties(
nullptr);
305 uint32_t extensionsFound = 0;
306 for (uint32_t
i = 0;
i < reqDeviceExtensions.size();
i++) {
307 for (uint32_t
j = 0;
j < availableExtensions.size();
j++) {
308 if (strcmp(reqDeviceExtensions[
i], availableExtensions[
j].extensionName) == 0) {
314 if (extensionsFound < reqDeviceExtensions.size()) {
315 GPUInfo(
"%s ignored due to missing extensions", &deviceProperties.deviceName[0]);
321 GPUInfo(
"%s ignored due to incompatible swap chain", &deviceProperties.deviceName[0]);
326 if (deviceProperties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
328 }
else if (deviceProperties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu) {
332 for (uint32_t
i = 0;
i < memoryProperties.memoryHeapCount;
i++) {
333 if (memoryProperties.memoryHeaps[
i].flags & vk::MemoryHeapFlagBits::eDeviceLocal) {
334 score += memoryProperties.memoryHeaps[
i].size;
343 VULKAN_HPP_DEFAULT_DISPATCHER.init();
344 vk::ApplicationInfo appInfo{};
345 appInfo.pApplicationName =
"GPU CA Standalone display";
346 appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
347 appInfo.pEngineName =
"GPU CI Standalone Engine";
348 appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
349 appInfo.apiVersion = VK_API_VERSION_1_0;
351 vk::InstanceCreateInfo instanceCreateInfo;
352 instanceCreateInfo.pApplicationInfo = &appInfo;
354 const char** frontendExtensions;
356 std::vector<const char*> reqInstanceExtensions(frontendExtensions, frontendExtensions + frontendExtensionCount);
358 const std::vector<const char*> reqValidationLayers = {
359 "VK_LAYER_KHRONOS_validation"};
360 auto debugCallback = [](vk::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity, vk::DebugUtilsMessageTypeFlagsEXT messageType,
const vk::DebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData) -> VkBool32 {
361 static int32_t throwOnError = getenv(
"GPUCA_VULKAN_VALIDATION_THROW") ? atoi(getenv(
"GPUCA_VULKAN_VALIDATION_THROW")) : 0;
362 static bool showVulkanValidationInfo = getenv(
"GPUCA_VULKAN_VALIDATION_INFO") && atoi(getenv(
"GPUCA_VULKAN_VALIDATION_INFO"));
363 switch (messageSeverity) {
364 case vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose:
365 if (showVulkanValidationInfo) {
366 GPUInfo(
"%s", pCallbackData->pMessage);
369 case vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning:
370 GPUWarning(
"%s", pCallbackData->pMessage);
371 if (throwOnError > 1) {
372 throw std::logic_error(
"break_on_validation_warning");
375 case vk::DebugUtilsMessageSeverityFlagBitsEXT::eError:
376 GPUError(
"%s", pCallbackData->pMessage);
378 throw std::logic_error(
"break_on_validation_error");
381 case vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo:
383 GPUInfo(
"%s", pCallbackData->pMessage);
388 vk::DebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
390 if (checkVulkanLayersSupported(reqValidationLayers)) {
391 throw std::runtime_error(
"Requested validation layer support not available");
393 reqInstanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
394 instanceCreateInfo.enabledLayerCount =
static_cast<uint32_t
>(reqValidationLayers.size());
395 instanceCreateInfo.ppEnabledLayerNames = reqValidationLayers.data();
396 instanceCreateInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo;
398 debugCreateInfo.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError;
399 debugCreateInfo.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance;
400 debugCreateInfo.pfnUserCallback = debugCallback;
401 debugCreateInfo.pUserData =
nullptr;
403 instanceCreateInfo.enabledLayerCount = 0;
406 instanceCreateInfo.enabledExtensionCount =
static_cast<uint32_t
>(reqInstanceExtensions.size());
407 instanceCreateInfo.ppEnabledExtensionNames = reqInstanceExtensions.data();
409 mInstance = vk::createInstance(instanceCreateInfo,
nullptr);
410 VULKAN_HPP_DEFAULT_DISPATCHER.init(
mInstance);
413 GPUInfo(
"Enabling Vulkan Validation Layers");
416 std::vector<vk::ExtensionProperties> extensions = vk::enumerateInstanceExtensionProperties(
nullptr);
418 std::cout <<
"available instance extensions: " << extensions.size() <<
"\n";
419 for (
const auto& extension : extensions) {
420 std::cout <<
'\t' << extension.extensionName <<
'\n';
425 throw std::runtime_error(
"Frontend does not provide Vulkan surface");
428 const std::vector<const char*> reqDeviceExtensions = {
429 VK_KHR_SWAPCHAIN_EXTENSION_NAME};
432 std::vector<vk::PhysicalDevice> devices =
mInstance.enumeratePhysicalDevices();
433 if (devices.size() == 0) {
434 throw std::runtime_error(
"No Vulkan device present!");
436 double bestScore = -1.;
437 for (uint32_t
i = 0;
i < devices.size();
i++) {
438 double score =
checkDevice(devices[
i], reqDeviceExtensions);
440 vk::PhysicalDeviceProperties deviceProperties = devices[
i].getProperties();
441 GPUInfo(
"Available Vulkan device %d: %s - Score %f",
i, &deviceProperties.deviceName[0], score);
443 if (score > bestScore && score > 0) {
449 if (
mDisplay->
cfg().vulkan.forceDevice < 0 ||
mDisplay->
cfg().vulkan.forceDevice >= (int32_t)devices.size()) {
450 throw std::runtime_error(
"Invalid Vulkan device selected");
455 throw std::runtime_error(
"All available Vulkan devices unsuited");
459 vk::PhysicalDeviceProperties deviceProperties =
mPhysicalDevice.getProperties();
460 vk::PhysicalDeviceFeatures deviceFeatures =
mPhysicalDevice.getFeatures();
461 vk::FormatProperties depth32FormatProperties =
mPhysicalDevice.getFormatProperties(vk::Format::eD32Sfloat);
462 vk::FormatProperties depth64FormatProperties =
mPhysicalDevice.getFormatProperties(vk::Format::eD32SfloatS8Uint);
464 GPUInfo(
"Using physical Vulkan device %s", &deviceProperties.deviceName[0]);
466 mZSupported = (bool)(depth32FormatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment);
467 mStencilSupported = (bool)(depth64FormatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment);
468 mCubicFilterSupported = (bool)(formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eSampledImageFilterCubicEXT);
474 vk::DeviceQueueCreateInfo queueCreateInfo{};
476 queueCreateInfo.queueCount = 1;
477 float queuePriority = 1.0f;
478 queueCreateInfo.pQueuePriorities = &queuePriority;
479 vk::DeviceCreateInfo deviceCreateInfo{};
480 deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
481 deviceCreateInfo.queueCreateInfoCount = 1;
482 deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
483 deviceCreateInfo.enabledExtensionCount =
static_cast<uint32_t
>(reqDeviceExtensions.size());
484 deviceCreateInfo.ppEnabledExtensionNames = reqDeviceExtensions.data();
485 deviceCreateInfo.enabledLayerCount = instanceCreateInfo.enabledLayerCount;
486 deviceCreateInfo.ppEnabledLayerNames = instanceCreateInfo.ppEnabledLayerNames;
488 VULKAN_HPP_DEFAULT_DISPATCHER.init(
mDevice);
491 vk::CommandPoolCreateInfo poolInfo{};
492 poolInfo.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
511 vk::CommandBufferAllocateInfo allocInfo{};
513 allocInfo.level = vk::CommandBufferLevel::ePrimary;
536 vk::SemaphoreCreateInfo semaphoreInfo{};
537 vk::FenceCreateInfo fenceInfo{};
538 fenceInfo.flags = vk::FenceCreateFlagBits::eSignaled;
553 fenceInfo.flags = {};
572 for (int32_t
j = 0;
j < 3;
j++) {
581 std::array<vk::DescriptorPoolSize, 2> poolSizes{};
582 poolSizes[0].type = vk::DescriptorType::eUniformBuffer;
584 poolSizes[1].type = vk::DescriptorType::eCombinedImageSampler;
586 vk::DescriptorPoolCreateInfo poolInfo{};
587 poolInfo.poolSizeCount = poolSizes.
size();
588 poolInfo.pPoolSizes = poolSizes.data();
592 vk::DescriptorSetLayoutBinding uboLayoutBindingMat{};
593 uboLayoutBindingMat.binding = 0;
594 uboLayoutBindingMat.descriptorType = vk::DescriptorType::eUniformBuffer;
595 uboLayoutBindingMat.descriptorCount = 1;
596 uboLayoutBindingMat.stageFlags = vk::ShaderStageFlagBits::eVertex;
597 vk::DescriptorSetLayoutBinding uboLayoutBindingCol = uboLayoutBindingMat;
598 uboLayoutBindingCol.binding = 1;
599 uboLayoutBindingCol.stageFlags = vk::ShaderStageFlagBits::eFragment;
600 vk::DescriptorSetLayoutBinding samplerLayoutBinding{};
601 samplerLayoutBinding.binding = 2;
602 samplerLayoutBinding.descriptorCount = 1;
603 samplerLayoutBinding.descriptorType = vk::DescriptorType::eCombinedImageSampler;
604 samplerLayoutBinding.stageFlags = vk::ShaderStageFlagBits::eFragment;
605 vk::DescriptorSetLayoutBinding bindings[3] = {uboLayoutBindingMat, uboLayoutBindingCol, samplerLayoutBinding};
607 vk::DescriptorSetLayoutCreateInfo layoutInfo{};
608 layoutInfo.bindingCount = 2;
609 layoutInfo.pBindings = bindings;
611 layoutInfo.bindingCount = 3;
614 vk::DescriptorSetAllocateInfo allocInfo{};
617 for (int32_t
j = 0;
j < 3;
j++) {
619 allocInfo.pSetLayouts = layouts.data();
622 for (int32_t k = 0; k < 2; k++) {
625 vk::DescriptorBufferInfo bufferInfo{};
626 bufferInfo.buffer = mUniformBuffers[
i].buffer;
627 bufferInfo.offset = 0;
628 bufferInfo.range = mUniformBuffers[
i].size;
630 vk::WriteDescriptorSet descriptorWrite{};
632 descriptorWrite.dstBinding = k;
633 descriptorWrite.dstArrayElement = 0;
634 descriptorWrite.descriptorType = vk::DescriptorType::eUniformBuffer;
635 descriptorWrite.descriptorCount = 1;
636 descriptorWrite.pBufferInfo = &bufferInfo;
637 descriptorWrite.pImageInfo =
nullptr;
638 descriptorWrite.pTexelBufferView =
nullptr;
639 mDevice.updateDescriptorSets(1, &descriptorWrite, 0,
nullptr);
654 for (int32_t
j = 0;
j < 3;
j++) {
662 vk::DescriptorImageInfo imageInfo{};
663 imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
666 vk::WriteDescriptorSet descriptorWrite{};
668 descriptorWrite.dstBinding = 2;
669 descriptorWrite.dstArrayElement = 0;
670 descriptorWrite.descriptorType = vk::DescriptorType::eCombinedImageSampler;
671 descriptorWrite.descriptorCount = 1;
672 descriptorWrite.pImageInfo = &imageInfo;
673 mDevice.updateDescriptorSets(1, &descriptorWrite, 0,
nullptr);
680 vk::SamplerCreateInfo samplerInfo{};
681 samplerInfo.magFilter = vk::Filter::eLinear;
682 samplerInfo.minFilter = vk::Filter::eLinear;
683 samplerInfo.addressModeU = vk::SamplerAddressMode::eRepeat;
684 samplerInfo.addressModeV = vk::SamplerAddressMode::eRepeat;
685 samplerInfo.addressModeW = vk::SamplerAddressMode::eRepeat;
686 samplerInfo.compareEnable =
false;
687 samplerInfo.compareOp = vk::CompareOp::eAlways;
688 samplerInfo.borderColor = vk::BorderColor::eIntOpaqueBlack;
689 samplerInfo.unnormalizedCoordinates =
false;
690 samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
691 samplerInfo.mipLodBias = 0.0f;
692 samplerInfo.minLod = 0.0f;
693 samplerInfo.maxLod = 0.0f;
725 vk::SwapchainCreateInfoKHR swapCreateInfo{};
727 swapCreateInfo.minImageCount = imageCount;
730 swapCreateInfo.imageExtent = extent;
731 swapCreateInfo.imageArrayLayers = 1;
732 swapCreateInfo.imageUsage = vk::ImageUsageFlagBits::eColorAttachment;
733 swapCreateInfo.imageSharingMode = vk::SharingMode::eExclusive;
734 swapCreateInfo.queueFamilyIndexCount = 0;
735 swapCreateInfo.pQueueFamilyIndices =
nullptr;
737 swapCreateInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
739 swapCreateInfo.clipped =
true;
740 swapCreateInfo.oldSwapchain = VkSwapchainKHR(VK_NULL_HANDLE);
742 swapCreateInfo.imageUsage |= vk::ImageUsageFlagBits::eTransferSrc;
745 swapCreateInfo.imageUsage |= vk::ImageUsageFlagBits::eTransferDst;
785 if (needUpdateOffscreenBuffers) {
787 if (needUpdateSwapChain) {
805 vk::AttachmentDescription colorAttachment{};
808 colorAttachment.loadOp = vk::AttachmentLoadOp::eClear;
809 colorAttachment.storeOp = vk::AttachmentStoreOp::eStore;
810 colorAttachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
811 colorAttachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
812 colorAttachment.initialLayout = vk::ImageLayout::eUndefined;
813 colorAttachment.finalLayout = (
mMSAASampleCount != vk::SampleCountFlagBits::e1 ||
mDownsampleFSAA) ? vk::ImageLayout::eColorAttachmentOptimal : vk::ImageLayout::ePresentSrcKHR;
814 vk::AttachmentDescription depthAttachment{};
815 depthAttachment.format = vk::Format::eD32Sfloat;
817 depthAttachment.loadOp = vk::AttachmentLoadOp::eClear;
818 depthAttachment.storeOp = vk::AttachmentStoreOp::eDontCare;
819 depthAttachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
820 depthAttachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
821 depthAttachment.initialLayout = vk::ImageLayout::eUndefined;
822 depthAttachment.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
823 vk::AttachmentDescription colorAttachmentResolve{};
825 colorAttachmentResolve.samples = vk::SampleCountFlagBits::e1;
826 colorAttachmentResolve.loadOp = vk::AttachmentLoadOp::eDontCare;
827 colorAttachmentResolve.storeOp = vk::AttachmentStoreOp::eStore;
828 colorAttachmentResolve.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
829 colorAttachmentResolve.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
830 colorAttachmentResolve.initialLayout = vk::ImageLayout::eUndefined;
831 colorAttachmentResolve.finalLayout =
mDownsampleFSAA ? vk::ImageLayout::eColorAttachmentOptimal : vk::ImageLayout::ePresentSrcKHR;
832 int32_t nAttachments = 0;
833 vk::AttachmentReference colorAttachmentRef{};
834 colorAttachmentRef.attachment = nAttachments++;
835 colorAttachmentRef.layout = vk::ImageLayout::eColorAttachmentOptimal;
836 vk::AttachmentReference depthAttachmentRef{};
838 depthAttachmentRef.layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
839 vk::AttachmentReference colorAttachmentResolveRef{};
841 colorAttachmentResolveRef.layout = vk::ImageLayout::eColorAttachmentOptimal;
842 vk::SubpassDescription subpass{};
843 subpass.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
844 subpass.colorAttachmentCount = 1;
845 subpass.pColorAttachments = &colorAttachmentRef;
846 vk::SubpassDependency dependency{};
847 dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
848 dependency.dstSubpass = 0;
849 dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests;
850 dependency.srcAccessMask = {};
851 dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests;
852 dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
854 std::vector<vk::AttachmentDescription>
attachments = {colorAttachment};
857 depthAttachmentRef.attachment = nAttachments++;
858 subpass.pDepthStencilAttachment = &depthAttachmentRef;
862 colorAttachmentResolveRef.attachment = nAttachments++;
863 subpass.pResolveAttachments = &colorAttachmentResolveRef;
866 vk::RenderPassCreateInfo renderPassInfo{};
867 renderPassInfo.attachmentCount =
attachments.size();
869 renderPassInfo.subpassCount = 1;
870 renderPassInfo.pSubpasses = &subpass;
871 renderPassInfo.dependencyCount = 1;
872 renderPassInfo.pDependencies = &dependency;
885 mZImages.resize(imageCountWithMixImages);
900 renderPassInfo.attachmentCount = 1;
901 renderPassInfo.pAttachments = &colorAttachment;
902 subpass.pDepthStencilAttachment =
nullptr;
903 subpass.pResolveAttachments =
nullptr;
905 dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
906 dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
907 dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
909 colorAttachment.loadOp = vk::AttachmentLoadOp::eLoad;
910 colorAttachment.initialLayout = vk::ImageLayout::ePresentSrcKHR;
911 colorAttachment.samples = vk::SampleCountFlagBits::e1;
912 colorAttachment.finalLayout = vk::ImageLayout::ePresentSrcKHR;
917 colorAttachment.initialLayout = vk::ImageLayout::eColorAttachmentOptimal;
918 colorAttachment.finalLayout =
mDownsampleFSAA ? vk::ImageLayout::eColorAttachmentOptimal : vk::ImageLayout::ePresentSrcKHR;
921 dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
922 dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
923 dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
928 for (uint32_t
i = 0;
i < imageCountWithMixImages;
i++) {
935 std::vector<vk::ImageView> att;
937 vk::ImageUsageFlags
usage = vk::ImageUsageFlagBits::eColorAttachment | (
i >=
mImageCount ? vk::ImageUsageFlagBits::eSampled : vk::ImageUsageFlagBits::eTransferSrc);
945 createImageI(
mDevice,
mPhysicalDevice,
mMSAAImages[
i].
image,
mMSAAImages[
i].
memory,
mRenderWidth,
mRenderHeight,
mSurfaceFormat.format, vk::ImageUsageFlagBits::eColorAttachment, vk::MemoryPropertyFlagBits::eDeviceLocal, vk::ImageTiling::eOptimal,
mMSAASampleCount);
952 createImageI(
mDevice,
mPhysicalDevice,
mZImages[
i].
image,
mZImages[
i].
memory,
mRenderWidth,
mRenderHeight, vk::Format::eD32Sfloat, vk::ImageUsageFlagBits::eDepthStencilAttachment, vk::MemoryPropertyFlagBits::eDeviceLocal, vk::ImageTiling::eOptimal,
mMSAASampleCount);
960 vk::FramebufferCreateInfo framebufferInfo{};
962 framebufferInfo.attachmentCount = att.size();
963 framebufferInfo.pAttachments = att.data();
966 framebufferInfo.layers = 1;
970 framebufferInfo.attachmentCount = 1;
979 framebufferInfo.attachmentCount = 1;
989 float vertices[6][4] = {
1029 vk::PipelineShaderStageCreateInfo shaderStages[2] = {vk::PipelineShaderStageCreateInfo{}, vk::PipelineShaderStageCreateInfo{}};
1030 vk::PipelineShaderStageCreateInfo& vertShaderStageInfo = shaderStages[0];
1031 vertShaderStageInfo.stage = vk::ShaderStageFlagBits::eVertex;
1033 vertShaderStageInfo.pName =
"main";
1034 vk::PipelineShaderStageCreateInfo& fragShaderStageInfo = shaderStages[1];
1035 fragShaderStageInfo.stage = vk::ShaderStageFlagBits::eFragment;
1037 fragShaderStageInfo.pName =
"main";
1039 vk::VertexInputBindingDescription bindingDescription{};
1040 bindingDescription.binding = 0;
1042 bindingDescription.inputRate = vk::VertexInputRate::eVertex;
1044 vk::VertexInputAttributeDescription attributeDescriptions{};
1045 attributeDescriptions.binding = 0;
1046 attributeDescriptions.location = 0;
1048 attributeDescriptions.offset = 0;
1050 vk::PipelineVertexInputStateCreateInfo vertexInputInfo{};
1051 vertexInputInfo.vertexBindingDescriptionCount = 1;
1052 vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
1053 vertexInputInfo.vertexAttributeDescriptionCount = 1;
1054 vertexInputInfo.pVertexAttributeDescriptions = &attributeDescriptions;
1055 vk::PipelineInputAssemblyStateCreateInfo inputAssembly{};
1057 inputAssembly.primitiveRestartEnable =
false;
1059 vk::Viewport viewport{};
1064 viewport.minDepth = 0.0f;
1065 viewport.maxDepth = 1.0f;
1067 vk::Rect2D scissor{};
1068 scissor.offset = vk::Offset2D{0, 0};
1071 vk::PipelineViewportStateCreateInfo viewportState{};
1072 viewportState.viewportCount = 1;
1073 viewportState.pViewports = &viewport;
1074 viewportState.scissorCount = 1;
1075 viewportState.pScissors = &scissor;
1077 vk::PipelineRasterizationStateCreateInfo rasterizer{};
1078 rasterizer.depthClampEnable =
false;
1079 rasterizer.rasterizerDiscardEnable =
false;
1080 rasterizer.polygonMode = vk::PolygonMode::eFill;
1082 rasterizer.cullMode = vk::CullModeFlagBits::eBack;
1083 rasterizer.frontFace = vk::FrontFace::eClockwise;
1084 rasterizer.depthBiasEnable =
false;
1085 rasterizer.depthBiasConstantFactor = 0.0f;
1086 rasterizer.depthBiasClamp = 0.0f;
1087 rasterizer.depthBiasSlopeFactor = 0.0f;
1089 vk::PipelineMultisampleStateCreateInfo multisampling{};
1090 multisampling.sampleShadingEnable =
false;
1092 multisampling.minSampleShading = 1.0f;
1093 multisampling.pSampleMask =
nullptr;
1094 multisampling.alphaToCoverageEnable =
false;
1095 multisampling.alphaToOneEnable =
false;
1097 vk::PipelineColorBlendAttachmentState colorBlendAttachment{};
1098 colorBlendAttachment.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
1100 colorBlendAttachment.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
1101 colorBlendAttachment.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha;
1102 colorBlendAttachment.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha;
1103 colorBlendAttachment.colorBlendOp = vk::BlendOp::eAdd;
1104 colorBlendAttachment.srcAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha;
1105 colorBlendAttachment.dstAlphaBlendFactor = vk::BlendFactor::eZero;
1106 colorBlendAttachment.alphaBlendOp = vk::BlendOp::eAdd;
1108 vk::PipelineColorBlendStateCreateInfo colorBlending{};
1109 colorBlending.logicOpEnable =
false;
1110 colorBlending.logicOp = vk::LogicOp::eCopy;
1111 colorBlending.attachmentCount = 1;
1112 colorBlending.pAttachments = &colorBlendAttachment;
1113 colorBlending.blendConstants[0] = 0.0f;
1114 colorBlending.blendConstants[1] = 0.0f;
1115 colorBlending.blendConstants[2] = 0.0f;
1116 colorBlending.blendConstants[3] = 0.0f;
1118 vk::PipelineDepthStencilStateCreateInfo depthStencil{};
1119 depthStencil.depthTestEnable =
true;
1120 depthStencil.depthWriteEnable =
true;
1121 depthStencil.depthCompareOp = vk::CompareOp::eLess;
1122 depthStencil.depthBoundsTestEnable =
false;
1123 depthStencil.stencilTestEnable =
false;
1125 vk::DynamicState dynamicStates[] = {vk::DynamicState::eLineWidth};
1126 vk::PipelineDynamicStateCreateInfo dynamicState{};
1127 dynamicState.dynamicStateCount = 1;
1128 dynamicState.pDynamicStates = dynamicStates;
1130 vk::PushConstantRange pushConstantRanges[2] = {vk::PushConstantRange{}, vk::PushConstantRange{}};
1131 pushConstantRanges[0].stageFlags = vk::ShaderStageFlagBits::eFragment;
1132 pushConstantRanges[0].offset = 0;
1133 pushConstantRanges[0].size =
sizeof(float) * 4;
1134 pushConstantRanges[1].stageFlags = vk::ShaderStageFlagBits::eVertex;
1135 pushConstantRanges[1].offset = pushConstantRanges[0].size;
1136 pushConstantRanges[1].size =
sizeof(float);
1137 vk::PipelineLayoutCreateInfo pipelineLayoutInfo{};
1138 pipelineLayoutInfo.setLayoutCount = 1;
1140 pipelineLayoutInfo.pushConstantRangeCount = 2;
1141 pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges;
1143 pipelineLayoutInfo.setLayoutCount = 1;
1147 vk::GraphicsPipelineCreateInfo pipelineInfo{};
1148 pipelineInfo.stageCount = 2;
1149 pipelineInfo.pVertexInputState = &vertexInputInfo;
1150 pipelineInfo.pInputAssemblyState = &inputAssembly;
1151 pipelineInfo.pViewportState = &viewportState;
1152 pipelineInfo.pRasterizationState = &rasterizer;
1153 pipelineInfo.pMultisampleState = &multisampling;
1155 pipelineInfo.pColorBlendState = &colorBlending;
1156 pipelineInfo.pDynamicState = &dynamicState;
1159 pipelineInfo.subpass = 0;
1160 pipelineInfo.pStages = shaderStages;
1161 pipelineInfo.basePipelineHandle = VkPipeline(VK_NULL_HANDLE);
1162 pipelineInfo.basePipelineIndex = -1;
1165 static constexpr vk::PrimitiveTopology
types[3] = {vk::PrimitiveTopology::ePointList, vk::PrimitiveTopology::eLineList, vk::PrimitiveTopology::eLineStrip};
1168 bindingDescription.stride = 4 *
sizeof(float);
1169 attributeDescriptions.format = vk::Format::eR32G32B32A32Sfloat;
1170 inputAssembly.topology = vk::PrimitiveTopology::eTriangleList;
1171 vertShaderStageInfo.module =
mShaders[
"vertexTexture"];
1172 fragShaderStageInfo.module =
mShaders[
"fragmentTexture"];
1175 pipelineInfo.pDepthStencilState =
nullptr;
1176 colorBlendAttachment.blendEnable =
true;
1177 multisampling.rasterizationSamples = vk::SampleCountFlagBits::e1;
1180 }
else if (
i == 3) {
1181 bindingDescription.stride = 4 *
sizeof(float);
1182 attributeDescriptions.format = vk::Format::eR32G32B32A32Sfloat;
1183 inputAssembly.topology = vk::PrimitiveTopology::eTriangleList;
1184 vertShaderStageInfo.module =
mShaders[
"vertexTexture"];
1185 fragShaderStageInfo.module =
mShaders[
"fragmentText"];
1188 pipelineInfo.pDepthStencilState =
nullptr;
1189 colorBlendAttachment.blendEnable =
true;
1190 multisampling.rasterizationSamples = vk::SampleCountFlagBits::e1;
1194 bindingDescription.stride = 3 *
sizeof(float);
1195 attributeDescriptions.format = vk::Format::eR32G32B32Sfloat;
1196 inputAssembly.topology =
types[
i];
1197 vertShaderStageInfo.module =
mShaders[
types[
i] == vk::PrimitiveTopology::ePointList ?
"vertexPoint" :
"vertex"];
1198 fragShaderStageInfo.module =
mShaders[
"fragment"];
1201 pipelineInfo.pDepthStencilState =
mZActive ? &depthStencil :
nullptr;
1202 colorBlendAttachment.blendEnable =
true;
1208 CHKERR(
mDevice.createGraphicsPipelines(VkPipelineCache(VK_NULL_HANDLE), 1, &pipelineInfo,
nullptr, &
mPipelines[
i]));
1214 commandBuffer.reset({});
1216 vk::CommandBufferBeginInfo beginInfo{};
1217 beginInfo.flags = {};
1218 commandBuffer.begin(beginInfo);
1220 vk::ClearValue clearValues[2];
1221 clearValues[0].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}};
1222 clearValues[1].depthStencil = vk::ClearDepthStencilValue{{1.0f, 0}};
1224 vk::RenderPassBeginInfo renderPassInfo{};
1227 renderPassInfo.renderArea.offset = vk::Offset2D{0, 0};
1229 renderPassInfo.clearValueCount =
mZActive ? 2 : 1;
1230 renderPassInfo.pClearValues = clearValues;
1231 commandBuffer.beginRenderPass(&renderPassInfo, vk::SubpassContents::eInline);
1233 vk::DeviceSize
offsets[] = {0};
1240 commandBuffer.endRenderPass();
1241 commandBuffer.end();
1253#define LOAD_SHADER(file, ext) \
1254 mShaders[#file] = createShaderModule(_binary_shaders_shaders_##file##_##ext##_spv_start, _binary_shaders_shaders_##file##_##ext##_spv_len, mDevice)
1268 clearVector(
mShaders, [&](
auto&
x) {
mDevice.destroyShaderModule(
x.second,
nullptr); });
1275 if (
buffer.deviceMemory != 1) {
1278 memcpy(dstData, srcData,
size);
1281 auto tmp =
createBuffer(
size, srcData, vk::BufferUsageFlagBits::eTransferSrc, 0);
1284 vk::BufferCopy copyRegion{};
1285 copyRegion.size =
size;
1286 commandBuffer.copyBuffer(tmp.buffer,
buffer.buffer, 1, ©Region);
1295 vk::MemoryPropertyFlags properties;
1297 properties |= vk::MemoryPropertyFlagBits::eDeviceLocal;
1299 if (deviceMemory == 0 || deviceMemory == 2) {
1300 properties |= (vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
1302 if (deviceMemory == 1) {
1303 type |= vk::BufferUsageFlagBits::eTransferDst;
1307 vk::BufferCreateInfo bufferInfo{};
1309 bufferInfo.usage =
type;
1310 bufferInfo.sharingMode = vk::SharingMode::eExclusive;
1313 vk::MemoryRequirements memRequirements;
1314 memRequirements =
mDevice.getBufferMemoryRequirements(
buffer.buffer);
1315 vk::MemoryAllocateInfo allocInfo{};
1316 allocInfo.allocationSize = memRequirements.size;
1317 allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties,
mPhysicalDevice);
1323 buffer.deviceMemory = deviceMemory;
1325 if (srcData !=
nullptr) {
1360 auto tmp =
createBuffer(srcSize, srcData, vk::BufferUsageFlagBits::eTransferSrc, 0);
1363 cmdImageMemoryBarrier(commandBuffer,
image.image, {}, vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer);
1364 vk::BufferImageCopy region{};
1365 region.bufferOffset = 0;
1366 region.bufferRowLength = 0;
1367 region.bufferImageHeight = 0;
1368 region.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1369 region.imageSubresource.mipLevel = 0;
1370 region.imageSubresource.baseArrayLayer = 0;
1371 region.imageSubresource.layerCount = 1;
1372 region.imageOffset = vk::Offset3D{0, 0, 0};
1373 region.imageExtent = vk::Extent3D{
image.sizex,
image.sizey, 1};
1374 commandBuffer.copyBufferToImage(tmp.buffer,
image.image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion);
1375 cmdImageMemoryBarrier(commandBuffer,
image.image, vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eShaderRead, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader);
1384 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);
1388 image.sizex = sizex;
1389 image.sizey = sizey;
1472 auto first = std::get<0>(
v);
1473 auto count = std::get<1>(
v);
1474 auto iSector = std::get<2>(
v);
1489 for (uint32_t k = 0; k <
count; k++) {
1503 if (includeMixImage == 0.f) {
1506 auto getImage = [&]() {
1507 vk::Fence fen = VkFence(VK_NULL_HANDLE);
1508 vk::Semaphore sem = VkSemaphore(VK_NULL_HANDLE);
1518 vk::Result
retVal = vk::Result::eSuccess;
1521 mustUpdateRendering =
true;
1526 if (!mustUpdateRendering) {
1527 GPUInfo(
"Pipeline out of data / suboptimal, recreating");
1541 const hmm_mat4 modelViewProj = proj * view;
1565 const vk::Fence noFence = VkFence(VK_NULL_HANDLE);
1567 vk::SubmitInfo submitInfo{};
1568 vk::PipelineStageFlags waitStages[] = {vk::PipelineStageFlagBits::eColorAttachmentOutput};
1570 submitInfo.waitSemaphoreCount = submitInfo.pWaitSemaphores !=
nullptr ? 1 : 0;
1571 submitInfo.pWaitDstStageMask = waitStages;
1572 submitInfo.commandBufferCount = 1;
1574 submitInfo.signalSemaphoreCount = 1;
1575 submitInfo.pSignalSemaphores = stageFinishedSemaphore;
1578 if (includeMixImage > 0.f) {
1580 submitInfo.pWaitSemaphores = stageFinishedSemaphore;
1581 waitStages[0] = {vk::PipelineStageFlagBits::eColorAttachmentOutput};
1582 submitInfo.waitSemaphoreCount = 1;
1585 submitInfo.pSignalSemaphores = stageFinishedSemaphore;
1592 submitInfo.pWaitSemaphores = stageFinishedSemaphore;
1593 waitStages[0] = {vk::PipelineStageFlagBits::eTransfer};
1594 submitInfo.waitSemaphoreCount = 1;
1596 submitInfo.pSignalSemaphores = stageFinishedSemaphore;
1610 submitInfo.pWaitSemaphores = stageFinishedSemaphore;
1611 waitStages[0] = {vk::PipelineStageFlagBits::eColorAttachmentOutput};
1612 submitInfo.waitSemaphoreCount = 1;
1615 submitInfo.pSignalSemaphores = stageFinishedSemaphore;
1620 vk::PresentInfoKHR presentInfo{};
1621 presentInfo.waitSemaphoreCount = 1;
1622 presentInfo.pWaitSemaphores = stageFinishedSemaphore;
1623 presentInfo.swapchainCount = 1;
1626 presentInfo.pResults =
nullptr;
1628 if (
retVal == vk::Result::eErrorOutOfDateKHR) {
1638 commandBuffer.reset({});
1639 vk::CommandBufferBeginInfo beginInfo{};
1640 beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
1641 commandBuffer.begin(beginInfo);
1643 cmdImageMemoryBarrier(commandBuffer,
mSwapChainImages[
mCurrentImageIndex], {}, vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer);
1644 cmdImageMemoryBarrier(commandBuffer,
mDownsampleImages[
mCurrentImageIndex].
image, vk::AccessFlagBits::eMemoryRead, vk::AccessFlagBits::eTransferRead, vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eTransferSrcOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer);
1646 vk::Offset3D blitSizeSrc;
1650 vk::Offset3D blitSizeDst;
1654 vk::ImageBlit imageBlitRegion{};
1655 imageBlitRegion.srcSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1656 imageBlitRegion.srcSubresource.layerCount = 1;
1657 imageBlitRegion.srcOffsets[1] = blitSizeSrc;
1658 imageBlitRegion.dstSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1659 imageBlitRegion.dstSubresource.layerCount = 1;
1660 imageBlitRegion.dstOffsets[1] = blitSizeDst;
1663 cmdImageMemoryBarrier(commandBuffer,
mSwapChainImages[
mCurrentImageIndex], vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eMemoryRead, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::ePresentSrcKHR, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer);
1664 cmdImageMemoryBarrier(commandBuffer,
mDownsampleImages[
mCurrentImageIndex].
image, vk::AccessFlagBits::eTransferRead, vk::AccessFlagBits::eMemoryRead, vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer);
1666 commandBuffer.end();
1686 vk::CommandBufferBeginInfo beginInfo{};
1687 beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
1690 vk::RenderPassBeginInfo renderPassInfo{};
1693 renderPassInfo.renderArea.offset = vk::Offset2D{0, 0};
1695 renderPassInfo.clearValueCount = 0;
1705 vk::DeviceSize
offsets[] = {0};
1724 commandBuffer.reset({});
1725 vk::CommandBufferBeginInfo beginInfo{};
1726 beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
1727 commandBuffer.begin(beginInfo);
1730 vk::ImageLayout srcLayout =
mDownsampleFSAA ? vk::ImageLayout::eColorAttachmentOptimal : vk::ImageLayout::ePresentSrcKHR;
1731 cmdImageMemoryBarrier(commandBuffer,
image, {}, vk::AccessFlagBits::eMemoryRead, srcLayout, vk::ImageLayout::eShaderReadOnlyOptimal, vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eFragmentShader);
1733 vk::RenderPassBeginInfo renderPassInfo{};
1736 renderPassInfo.renderArea.offset = vk::Offset2D{0, 0};
1738 renderPassInfo.clearValueCount = 0;
1739 commandBuffer.beginRenderPass(renderPassInfo, vk::SubpassContents::eInline);
1741 commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics,
mPipelines[4]);
1746 vk::DeviceSize
offsets[] = {0};
1749 commandBuffer.pushConstants(
mPipelineLayoutTexture, vk::ShaderStageFlagBits::eFragment, 0,
sizeof(mixSlaveImage), &mixSlaveImage);
1750 commandBuffer.draw(6, 1, 0, 0);
1752 commandBuffer.endRenderPass();
1753 commandBuffer.end();
1789 throw std::runtime_error(
"Incorrect symbol ID");
1793 if (sizex && sizey) {
1794 buffer.reset(
new char[sizex * sizey]);
1801 int32_t maxSizeX = 0, maxSizeY = 0, maxBigX = 0, maxBigY = 0, maxRowY = 0;
1805 maxSizeX = std::max(maxSizeX, symbol.size[0]);
1806 maxSizeY = std::max(maxSizeY, symbol.size[1]);
1809 int32_t sizex = nn * maxSizeX;
1810 int32_t sizey = nn * maxSizeY;
1811 std::unique_ptr<char[]> bigImage{
new char[sizex * sizey]};
1812 memset(bigImage.get(), 0, sizex * sizey);
1813 int32_t rowy = 0, colx = 0;
1816 if (colx + s.size[0] > sizex) {
1821 for (int32_t k = 0; k < s.size[1]; k++) {
1822 for (int32_t
j = 0;
j < s.size[0];
j++) {
1823 int8_t
val = s.data.get()[
j + k * s.size[0]];
1825 val =
val < 0 ? 0xFF : 0;
1827 bigImage.get()[(colx +
j) + (rowy + k) * sizex] =
val;
1832 s.x1 = colx + s.size[0];
1834 s.y1 = rowy + s.size[1];
1835 maxBigX = std::max(maxBigX, colx + s.size[0]);
1836 maxBigY = std::max(maxBigY, rowy + s.size[1]);
1837 maxRowY = std::max(maxRowY, s.size[1]);
1840 if (maxBigX != sizex) {
1841 for (int32_t
y = 1;
y < maxBigY;
y++) {
1842 memmove(bigImage.get() +
y * maxBigX, bigImage.get() +
y * sizex, maxBigX);
1861 vk::DescriptorImageInfo imageInfo{};
1862 imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
1866 vk::WriteDescriptorSet descriptorWrite{};
1868 descriptorWrite.dstBinding = 2;
1869 descriptorWrite.dstArrayElement = 0;
1870 descriptorWrite.descriptorType = vk::DescriptorType::eCombinedImageSampler;
1871 descriptorWrite.descriptorCount = 1;
1872 descriptorWrite.pImageInfo = &imageInfo;
1873 mDevice.updateDescriptorSets(1, &descriptorWrite, 0,
nullptr);
1888 for (
const char*
c = s; *
c;
c++) {
1890 GPUError(
"Trying to draw unsupported symbol: %d > %d\n", (int32_t)*
c, (int32_t)
mFontSymbols.size());
1896 float xpos =
x + sym.
offset[0] * scale;
1897 float ypos =
y - (sym.
size[1] - sym.
offset[1]) * scale;
1898 float w = sym.
size[0] * scale;
1899 float h = sym.
size[1] * scale;
1900 float vertices[6][4] = {
1918 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]) {
1919 c.back().nVertices += nVertices;
1930 static constexpr int32_t bytesPerPixel = 4;
1933 vk::Image dstImage, dstImage2, src2;
1934 vk::DeviceMemory dstImageMemory, dstImageMemory2;
1935 createImageI(
mDevice,
mPhysicalDevice, dstImage, dstImageMemory,
width,
height, vk::Format::eR8G8B8A8Unorm, vk::ImageUsageFlagBits::eTransferDst, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, vk::ImageTiling::eLinear);
1937 cmdImageMemoryBarrier(cmdBuffer,
image, vk::AccessFlagBits::eMemoryRead, vk::AccessFlagBits::eTransferRead, layout, vk::ImageLayout::eTransferSrcOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer);
1939 createImageI(
mDevice,
mPhysicalDevice, dstImage2, dstImageMemory2,
width,
height,
mSurfaceFormat.format, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst, vk::MemoryPropertyFlagBits::eDeviceLocal, vk::ImageTiling::eOptimal);
1940 cmdImageMemoryBarrier(cmdBuffer, dstImage2, {}, vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer);
1942 vk::Offset3D blitSizeDst = {(int32_t)
width, (int32_t)
height, 1};
1943 vk::ImageBlit imageBlitRegion{};
1944 imageBlitRegion.srcSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1945 imageBlitRegion.srcSubresource.layerCount = 1;
1946 imageBlitRegion.srcOffsets[1] = blitSizeSrc;
1947 imageBlitRegion.dstSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1948 imageBlitRegion.dstSubresource.layerCount = 1;
1949 imageBlitRegion.dstOffsets[1] = blitSizeDst;
1950 cmdBuffer.blitImage(
image, vk::ImageLayout::eTransferSrcOptimal, dstImage2, vk::ImageLayout::eTransferDstOptimal, 1, &imageBlitRegion, vk::Filter::eLinear);
1952 cmdImageMemoryBarrier(cmdBuffer, dstImage2, vk::AccessFlagBits::eMemoryRead, vk::AccessFlagBits::eTransferRead, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eTransferSrcOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer);
1957 cmdImageMemoryBarrier(cmdBuffer, dstImage, {}, vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer);
1958 vk::ImageCopy imageCopyRegion{};
1959 imageCopyRegion.srcSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1960 imageCopyRegion.srcSubresource.layerCount = 1;
1961 imageCopyRegion.dstSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
1962 imageCopyRegion.dstSubresource.layerCount = 1;
1963 imageCopyRegion.extent.width =
width;
1964 imageCopyRegion.extent.height =
height;
1965 imageCopyRegion.extent.depth = 1;
1966 cmdBuffer.copyImage(src2, vk::ImageLayout::eTransferSrcOptimal, dstImage, vk::ImageLayout::eTransferDstOptimal, 1, &imageCopyRegion);
1968 cmdImageMemoryBarrier(cmdBuffer, dstImage, vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eMemoryRead, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eGeneral, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer);
1969 cmdImageMemoryBarrier(cmdBuffer,
image, vk::AccessFlagBits::eTransferRead, vk::AccessFlagBits::eMemoryRead, vk::ImageLayout::eTransferSrcOptimal, layout, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer);
1972 vk::ImageSubresource subResource{vk::ImageAspectFlagBits::eColor, 0, 0};
1973 vk::SubresourceLayout subResourceLayout =
mDevice.getImageSubresourceLayout(dstImage, subResource);
1976 data += subResourceLayout.offset;
1980 mDevice.unmapMemory(dstImageMemory);
1981 mDevice.freeMemory(dstImageMemory,
nullptr);
1982 mDevice.destroyImage(dstImage,
nullptr);
1984 mDevice.freeMemory(dstImageMemory2,
nullptr);
1985 mDevice.destroyImage(dstImage2,
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::Fence > mInFlightFence
std::vector< vk::CommandBuffer > mCommandBuffersMix
vk::RenderPass mRenderPassTexture
std::vector< vk::CommandBuffer > mCommandBuffers
void setMixDescriptor(int32_t descriptorIndex, int32_t imageIndex)
std::vector< vk::Semaphore > mRenderFinishedSemaphore
vk::DescriptorPool mDescriptorPool
vk::DescriptorSetLayout mUniformDescriptor
VulkanBuffer mIndirectCommandBuffer
void prepareDraw(const hmm_mat4 &proj, const hmm_mat4 &view, bool requestScreenshot, bool toMixBuffer, float includeMixImage) override
std::vector< vk::Pipeline > mPipelines
vk::CommandBuffer mCurrentCommandBuffer
void createCommandBuffers()
void resizeScene(uint32_t width, uint32_t height) override
vk::Fence mSingleCommitFence
int32_t mCurrentCommandBufferLastPipeline
uint32_t DepthBits() override
void submitSingleTimeCommandBuffer(vk::CommandBuffer commandBuffer)
std::vector< VulkanImage > mDownsampleImages
void clearUniformLayoutsAndBuffers()
void writeToBuffer(VulkanBuffer &buffer, size_t size, const void *srcData)
std::vector< vk::ImageView > mSwapChainImageViews
std::vector< VulkanImage > mMSAAImages
void pointSizeFactor(float factor) override
std::vector< FontSymbolVulkan > mFontSymbols
vk::SwapchainKHR mSwapChain
int32_t InitBackendA() override
void clearImage(VulkanImage &image)
std::vector< vk::ImageView * > mRenderTargetView
std::vector< vk::Framebuffer > mFramebuffersTexture
void finishText() 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
std::vector< vk::Framebuffer > mFramebuffersText
void mixImages(vk::CommandBuffer cmdBuffer, float mixSlaveImage)
void clearVertexBuffers()
void createTextureSampler()
void recreateRendering(bool forScreenshot=false, bool forMixing=false)
std::vector< VulkanBuffer > mFontVertexBuffer
void endFillCommandBuffer(vk::CommandBuffer &commandBuffer)
uint32_t drawVertices(const vboList &v, const drawType t) override
vk::SurfaceFormatKHR mSurfaceFormat
bool mCommandBufferPerImage
std::vector< vk::CommandBuffer > mCommandBuffersDownsample
void ActivateColor(std::array< float, 4 > &color) override
std::vector< vk::Image > mSwapChainImages
void initializeTextDrawing() override
void clearBuffer(VulkanBuffer &buffer)
VulkanBuffer mMixingTextureVertexArray
std::vector< vk::Semaphore > mMixFinishedSemaphore
vk::Sampler mTextureSampler
std::vector< vk::Semaphore > mTextFinishedSemaphore
uint32_t mCurrentImageIndex
void updateFontTextureDescriptor()
void createUniformLayoutsAndBuffers()
void needRecordCommandBuffers()
std::vector< VulkanBuffer > mUniformBuffersMat[3]
double checkDevice(vk::PhysicalDevice device, const std::vector< const char * > &reqDeviceExtensions)
bool mCommandInfrastructureCreated
void updateSwapChainDetails(const vk::PhysicalDevice &device)
std::vector< VulkanImage > mMixImages
vk::CommandPool mCommandPool
void finishDraw(bool doScreenshot, bool toMixBuffer, float includeMixImage) override
bool mCubicFilterSupported
void writeToImage(VulkanImage &image, const void *srcData, size_t srcSize)
vk::RenderPass mRenderPass
void createSemaphoresAndFences()
std::vector< vk::DescriptorSet > mDescriptorSets[3]
vecpod< float > mFontVertexBufferHost
vk::PipelineLayout mPipelineLayout
void clearOffscreenBuffers()
vk::DescriptorSetLayout mUniformDescriptorTexture
bool mSwapchainImageReadable
void downsampleToFramebuffer(vk::CommandBuffer &commandBuffer)
void ExitBackendA() override
vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR &capabilities)
vk::RenderPass mRenderPassText
void clearSemaphoresAndFences()
~GPUDisplayBackendVulkan() override
std::vector< vk::Framebuffer > mFramebuffers
void readImageToPixels(vk::Image image, vk::ImageLayout layout, std::vector< char > &pixels)
VulkanImage createImage(uint32_t sizex, uint32_t sizey, const void *srcData=nullptr, size_t srcSize=0, vk::Format format=vk::Format::eR8G8B8A8Srgb)
std::vector< vk::Semaphore > mDownsampleFinishedSemaphore
std::vector< TextDrawCommand > mTextDrawCommands
void clearTextureSampler()
vk::PipelineLayout mPipelineLayoutTexture
SwapChainSupportDetails mSwapChainDetails
uint32_t mMaxMSAAsupported
std::unordered_map< std::string, vk::ShaderModule > mShaders
void finishFrame(bool doScreenshot, bool toMixBuffer, float includeMixImage) override
void createSwapChain(bool forScreenshot=false, bool forMixing=false)
std::vector< vk::Semaphore > mImageAvailableSemaphore
int32_t mCurrentBufferSet
void startFillCommandBuffer(vk::CommandBuffer &commandBuffer, uint32_t imageIndex, bool toMixBuffer=false)
std::vector< vk::CommandBuffer > mCommandBuffersTexture
vk::PhysicalDevice mPhysicalDevice
vk::DebugUtilsMessengerEXT mDebugMessenger
GPUDisplayBackendVulkan()
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()
std::vector< vk::CommandBuffer > mCommandBuffersText
bool mMustUpdateSwapChain
vk::PresentModeKHR mPresentMode
void loadDataToGPU(size_t totalVertizes) override
std::vector< VulkanBuffer > mUniformBuffersCol[3]
vecpod< DrawArraysIndirectCommand > mCmdBuffer
std::vector< int32_t > mIndirectSectorOffset
void fillIndirectCmdBuffer()
bool mFreetypeInitialized
std::vector< char > mScreenshotPixels
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()
GLuint GLsizei const GLuint const GLintptr * offsets
GLsizei GLenum GLenum * types
GLint GLsizei GLsizei height
GLint GLint GLsizei GLint GLenum GLenum type
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
GLsizei const GLenum * attachments
GLenum GLuint GLenum GLsizei const GLchar * buf
GLubyte GLubyte GLubyte GLubyte w
GLint GLint GLsizei GLint GLenum format
GLsizeiptr const void GLenum usage
#define QGET_LD_BINARY_SYMBOLS(filename)
std::vector< vk::SurfaceFormatKHR > formats
vk::SurfaceCapabilitiesKHR capabilities
std::vector< vk::PresentModeKHR > presentModes