VkDescriptorSet


	void setupDescriptorPool()
	{
		// We need to tell the API the number of max. requested descriptors per type
		VkDescriptorPoolSize typeCounts[1];
		// This example only uses one descriptor type (uniform buffer) and only requests one descriptor of this type
		typeCounts[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
		typeCounts[0].descriptorCount = 1;
		// For additional types you need to add new entries in the type count list
		// E.g. for two combined image samplers :
		// typeCounts[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
		// typeCounts[1].descriptorCount = 2;

		// Create the global descriptor pool
		// All descriptors used in this example are allocated from this pool
		VkDescriptorPoolCreateInfo descriptorPoolInfo = {};
		descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
		descriptorPoolInfo.pNext = nullptr;
		descriptorPoolInfo.poolSizeCount = 1;
		descriptorPoolInfo.pPoolSizes = typeCounts;
		// Set the max. number of descriptor sets that can be requested from this pool (requesting beyond this limit will result in an error)
		descriptorPoolInfo.maxSets = 1;

		VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
	}

	void setupDescriptorSetLayout()
	{
		// Setup layout of descriptors used in this example
		// Basically connects the different shader stages to descriptors for binding uniform buffers, image samplers, etc.
		// So every shader binding should map to one descriptor set layout binding

		// Binding 0: Uniform buffer (Vertex shader)
		VkDescriptorSetLayoutBinding layoutBinding = {};
		layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
		layoutBinding.descriptorCount = 1;
		layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
		layoutBinding.pImmutableSamplers = nullptr;

		VkDescriptorSetLayoutCreateInfo descriptorLayout = {};
		descriptorLayout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
		descriptorLayout.pNext = nullptr;
		descriptorLayout.bindingCount = 1;
		descriptorLayout.pBindings = &layoutBinding;

		VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));

		// Create the pipeline layout that is used to generate the rendering pipelines that are based on this descriptor set layout
		// In a more complex scenario you would have different pipeline layouts for different descriptor set layouts that could be reused
		VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {};
		pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
		pPipelineLayoutCreateInfo.pNext = nullptr;
		pPipelineLayoutCreateInfo.setLayoutCount = 1;
		pPipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayout;

		VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout));
	}

	void setupDescriptorSet()
	{
		// Allocate a new descriptor set from the global descriptor pool
		VkDescriptorSetAllocateInfo allocInfo = {};
		allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
		allocInfo.descriptorPool = descriptorPool;
		allocInfo.descriptorSetCount = 1;
		allocInfo.pSetLayouts = &descriptorSetLayout;

		VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));

		// Update the descriptor set determining the shader binding points
		// For every binding point used in a shader there needs to be one
		// descriptor set matching that binding point

		VkWriteDescriptorSet writeDescriptorSet = {};

		// Binding 0 : Uniform buffer
		writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
		writeDescriptorSet.dstSet = descriptorSet;
		writeDescriptorSet.descriptorCount = 1;
		writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
		writeDescriptorSet.pBufferInfo = &uniformBufferVS.descriptor;
		// Binds this uniform buffer to binding point 0
		writeDescriptorSet.dstBinding = 0;

		vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
	}
validation layer: vkDestroyImageView(): can't be called on VkImageView 0x130000000013 that is currently in use by VkFramebuffer 0x140000000014. The Vulkan spec states: All submitted commands that refer to imageView must have completed execution (https://vulkan.lunarg.com/doc/view/1.4.321.1/windows/antora/spec/latest/chapters/resources.html#VUID-vkDestroyImageView-imageView-01026) validation layer: vkDestroyPipeline(): can't be called on VkPipeline 0xf000000000f that is currently in use by VkCommandBuffer 0x20d72b77d00. The Vulkan spec states: All submitted commands that refer to pipeline must have completed execution (https://vulkan.lunarg.com/doc/view/1.4.321.1/windows/antora/spec/latest/chapters/pipelines.html#VUID-vkDestroyPipeline-pipeline-00765) validation layer: vkDestroyRenderPass(): can't be called on VkRenderPass 0xa000000000a that is currently in use by VkCommandBuffer 0x20d72b77d00. The Vulkan spec states: All submitted commands that refer to renderPass must have completed execution (https://vulkan.lunarg.com/doc/view/1.4.321.1/windows/antora/spec/latest/chapters/renderpass.html#VUID-vkDestroyRenderPass-renderPass-00873) validation layer: vkDestroyBuffer(): can't be called on VkBuffer 0x250000000025 that is currently in use by VkDescriptorSet 0x2c000000002c. The Vulkan spec states: All submitted commands that refer to buffer, either directly or via a VkBufferView, must have completed execution (https://vulkan.lunarg.com/doc/view/1.4.321.1/windows/antora/spec/latest/chapters/resources.html#VUID-vkDestroyBuffer-buffer-00922)
11-10
#include <cstdlib> #include <dlfcn.h> #include "VulkanGraphics.h" #include "imgui_impl_vulkan.h" #include <vulkan/vulkan_android.h> #include <android/native_window.h> #include <unistd.h> #ifndef NDEBUG static void check_vk_result(VkResult err) { if (err == 0) return; fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err); if (err < 0) abort(); } #else static void check_vk_result(VkResult err) { } #endif VkPhysicalDevice VulkanGraphics::SetupVulkan_SelectPhysicalDevice() { uint32_t gpu_count; VkResult err = vkEnumeratePhysicalDevices(m_Instance, &gpu_count, nullptr); check_vk_result(err); IM_ASSERT(gpu_count > 0); ImVector<VkPhysicalDevice> gpus; gpus.resize(gpu_count); err = vkEnumeratePhysicalDevices(m_Instance, &gpu_count, gpus.Data); check_vk_result(err); // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple // dedicated GPUs) is out of scope of this sample. for (VkPhysicalDevice &device: gpus) { VkPhysicalDeviceProperties properties; vkGetPhysicalDeviceProperties(device, &properties); if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) return device; } // Use first GPU (Integrated) is a Discrete one is not available. if (gpu_count > 0) return gpus[0]; return VK_NULL_HANDLE; } bool VulkanGraphics::Create(ANativeWindow *Window, int m_Width, int m_Height) { this->m_Window = Window; if (InitVulkan() != 1) { fprintf(stderr, "Vulkan is not supported %s\n", dlerror()); abort(); } wd = std::make_unique<ImGui_ImplVulkanH_Window>(); //为imgui加载vulkan函数 void *libvulkan = dlopen("libvulkan.so", RTLD_NOW); ImGui_ImplVulkan_LoadFunctions([](const char *function_name, void *handle) -> PFN_vkVoidFunction { return reinterpret_cast<PFN_vkVoidFunction>(dlsym(handle, function_name)); }, libvulkan); VkResult err; // Create Vulkan Instance { const char *instance_extensions[] = { "VK_KHR_surface", "VK_KHR_android_surface", }; VkApplicationInfo appInfo = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pNext = nullptr, .pApplicationName = "pApplicationName", .applicationVersion = VK_MAKE_VERSION(1, 0, 0), .pEngineName = "pEngineName", .engineVersion = VK_MAKE_VERSION(1, 0, 0), .apiVersion = VK_MAKE_VERSION(1, 1, 0), }; VkInstanceCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; create_info.pApplicationInfo = &appInfo; create_info.enabledExtensionCount = sizeof(instance_extensions) / sizeof(instance_extensions[0]); create_info.ppEnabledExtensionNames = instance_extensions; #ifdef IMGUI_VULKAN_DEBUG_REPORT // Enabling validation layers const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; create_info.enabledLayerCount = 1; create_info.ppEnabledLayerNames = layers; // Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it) const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1)); memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*)); extensions_ext[extensions_count] = "VK_EXT_debug_report"; create_info.enabledExtensionCount = extensions_count + 1; create_info.ppEnabledExtensionNames = extensions_ext; // Create Vulkan Instance err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); check_vk_result(err); free(extensions_ext); // Get the function pointer (required for any extensions) auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL); // Setup the debug report callback VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; debug_report_ci.pfnCallback = debug_report; debug_report_ci.pUserData = NULL; err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport); check_vk_result(err); #else // Create Vulkan Instance without any debug feature err = vkCreateInstance(&create_info, m_Allocator, &m_Instance); check_vk_result(err); IM_UNUSED(m_DebugReport); #endif } // Select Physical Device (GPU) m_PhysicalDevice = SetupVulkan_SelectPhysicalDevice(); // Select graphics queue family { uint32_t count; vkGetPhysicalDeviceQueueFamilyProperties(m_PhysicalDevice, &count, nullptr); VkQueueFamilyProperties *queues = (VkQueueFamilyProperties *) malloc(sizeof(VkQueueFamilyProperties) * count); vkGetPhysicalDeviceQueueFamilyProperties(m_PhysicalDevice, &count, queues); for (uint32_t i = 0; i < count; i++) if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { m_QueueFamily = i; break; } free(queues); IM_ASSERT(m_QueueFamily != (uint32_t) -1); } // Create Logical Device (with 1 queue) { ImVector<const char *> device_extensions; device_extensions.push_back("VK_KHR_swapchain"); // Enumerate physical device extension uint32_t properties_count; ImVector<VkExtensionProperties> properties; vkEnumerateDeviceExtensionProperties(m_PhysicalDevice, nullptr, &properties_count, nullptr); properties.resize(properties_count); vkEnumerateDeviceExtensionProperties(m_PhysicalDevice, nullptr, &properties_count, properties.Data); #ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); #endif const float queue_priority[] = {1.0f}; VkDeviceQueueCreateInfo queue_info[1] = {}; queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_info[0].queueFamilyIndex = m_QueueFamily; queue_info[0].queueCount = 1; queue_info[0].pQueuePriorities = queue_priority; VkDeviceCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]); create_info.pQueueCreateInfos = queue_info; create_info.enabledExtensionCount = (uint32_t) device_extensions.Size; create_info.ppEnabledExtensionNames = device_extensions.Data; err = vkCreateDevice(m_PhysicalDevice, &create_info, m_Allocator, &m_Device); check_vk_result(err); vkGetDeviceQueue(m_Device, m_QueueFamily, 0, &m_Queue); } // Create Descriptor Pool { VkDescriptorPoolSize pool_sizes[] = { {VK_DESCRIPTOR_TYPE_SAMPLER, 1000}, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000}, {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000}, {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000}, {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000}, {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000}, {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000} }; VkDescriptorPoolCreateInfo pool_info = {}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes); pool_info.poolSizeCount = (uint32_t) IM_ARRAYSIZE(pool_sizes); pool_info.pPoolSizes = pool_sizes; err = vkCreateDescriptorPool(m_Device, &pool_info, m_Allocator, &m_DescriptorPool); check_vk_result(err); } { // Create Window Surface VkSurfaceKHR surface; VkAndroidSurfaceCreateInfoKHR createInfo{ .sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, .pNext = nullptr, .flags = 0, .window = m_Window}; err = vkCreateAndroidSurfaceKHR(m_Instance, &createInfo, m_Allocator, &surface); check_vk_result(err); wd->Surface = surface; // Check for WSI support VkBool32 res; vkGetPhysicalDeviceSurfaceSupportKHR(m_PhysicalDevice, m_QueueFamily, wd->Surface, &res); if (res != VK_TRUE) { fprintf(stderr, "Error no WSI support on physical device 0\n"); exit(-1); } // Select Surface Format const VkFormat requestSurfaceImageFormat[] = {VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM}; const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(m_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t) IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); // 呈现模式 // 代码中已有逻辑,无需修改,只需确保不定义APP_USE_UNLIMITED_FRAME_RATE #ifndef APP_USE_UNLIMITED_FRAME_RATE VkPresentModeKHR present_modes[] = {VK_PRESENT_MODE_FIFO_KHR}; // 垂直同步模式 #endif wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(m_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes)); //printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode); // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(m_MinImageCount >= 2); // 在调用 ImGui_ImplVulkanH_CreateOrResizeWindow 前添加 m_MinImageCount = 2; // 双缓冲,或根据屏幕刷新率设置为3(三缓冲) ImGui_ImplVulkanH_CreateOrResizeWindow(m_Instance, m_PhysicalDevice, m_Device, wd.get(), m_QueueFamily, m_Allocator, (int) m_Width, (int) m_Height, m_MinImageCount); } return true; } void VulkanGraphics::Setup() { ImGui_ImplVulkan_InitInfo init_info = {}; init_info.Instance = m_Instance; init_info.PhysicalDevice = m_PhysicalDevice; init_info.Device = m_Device; init_info.QueueFamily = m_QueueFamily; init_info.Queue = m_Queue; init_info.PipelineCache = m_PipelineCache; init_info.DescriptorPool = m_DescriptorPool; init_info.RenderPass = wd->RenderPass; init_info.Subpass = 0; init_info.MinImageCount = m_MinImageCount; init_info.ImageCount = wd->ImageCount; init_info.MSAASamples = VK_SAMPLE_COUNT_2_BIT; init_info.Allocator = m_Allocator; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info); } void VulkanGraphics::PrepareFrame(bool resize) { if (m_SwapChainRebuild || resize) { int width = ANativeWindow_getWidth(m_Window); int height = ANativeWindow_getHeight(m_Window); if (m_LastWidth == 0 || m_LastHeight == 0) { m_LastWidth = width; m_LastHeight = height; } if (width > 0 && height > 0) { if (width != m_LastWidth || height != m_LastHeight) { //切屏休息半秒 usleep(500000); m_LastWidth = width; m_LastHeight = height; ImGui_ImplVulkan_SetMinImageCount(m_MinImageCount); ImGui_ImplVulkanH_CreateOrResizeWindow(m_Instance, m_PhysicalDevice, m_Device, wd.get(), m_QueueFamily, m_Allocator, width, height, m_MinImageCount); wd->FrameIndex = 0; m_SwapChainRebuild = false; } } } ImGui_ImplVulkan_NewFrame(); } void VulkanGraphics::Render(ImDrawData *drawData) { VkResult err; VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; err = vkAcquireNextImageKHR(m_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); if (err == VK_ERROR_OUT_OF_DATE_KHR /*|| err == VK_SUBOPTIMAL_KHR*/) { m_SwapChainRebuild = true; return; } //check_vk_result(err); ImGui_ImplVulkanH_Frame *fd = &wd->Frames[wd->FrameIndex]; { err = vkWaitForFences(m_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking check_vk_result(err); err = vkResetFences(m_Device, 1, &fd->Fence); check_vk_result(err); } { err = vkResetCommandPool(m_Device, fd->CommandPool, 0); check_vk_result(err); VkCommandBufferBeginInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; err = vkBeginCommandBuffer(fd->CommandBuffer, &info); check_vk_result(err); } { //透明 默认已经是0了 //memset(wd->ClearValue.color.float32, 0, sizeof(wd->ClearValue.color.float32)); VkRenderPassBeginInfo info = {}; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; info.renderPass = wd->RenderPass; info.framebuffer = fd->Framebuffer; info.renderArea.extent.width = wd->Width; info.renderArea.extent.height = wd->Height; info.clearValueCount = 1; info.pClearValues = &wd->ClearValue; vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE); } // Record dear imgui primitives into command buffer ImGui_ImplVulkan_RenderDrawData(drawData, fd->CommandBuffer); // Submit command buffer vkCmdEndRenderPass(fd->CommandBuffer); { VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; info.waitSemaphoreCount = 1; info.pWaitSemaphores = &image_acquired_semaphore; info.pWaitDstStageMask = &wait_stage; info.commandBufferCount = 1; info.pCommandBuffers = &fd->CommandBuffer; info.signalSemaphoreCount = 1; info.pSignalSemaphores = &render_complete_semaphore; err = vkEndCommandBuffer(fd->CommandBuffer); check_vk_result(err); err = vkQueueSubmit(m_Queue, 1, &info, fd->Fence); check_vk_result(err); } { if (m_SwapChainRebuild) return; VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; VkPresentInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; info.waitSemaphoreCount = 1; info.pWaitSemaphores = &render_complete_semaphore; info.swapchainCount = 1; info.pSwapchains = &wd->Swapchain; info.pImageIndices = &wd->FrameIndex; VkResult err = vkQueuePresentKHR(m_Queue, &info); if (err == VK_ERROR_OUT_OF_DATE_KHR /*|| err == VK_SUBOPTIMAL_KHR*/) { m_SwapChainRebuild = true; return; } //check_vk_result(err); wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores } } void VulkanGraphics::PrepareShutdown() { VkResult err = vkDeviceWaitIdle(m_Device); check_vk_result(err); ImGui_ImplVulkan_Shutdown(); } //==========// void VulkanGraphics::Cleanup() { ImGui_ImplVulkanH_DestroyWindow(m_Instance, m_Device, wd.get(), m_Allocator); vkDestroyDescriptorPool(m_Device, m_DescriptorPool, m_Allocator); #ifdef APP_USE_VULKAN_DEBUG_REPORT // Remove the debug report callback auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); #endif // APP_USE_VULKAN_DEBUG_REPORT vkDestroyDevice(m_Device, m_Allocator); vkDestroyInstance(m_Instance, m_Allocator); } //清理释放 // Helper function to find Vulkan memory type bits. See ImGui_ImplVulkan_MemoryType() in imgui_impl_vulkan.cpp uint32_t VulkanGraphics::findMemoryType(uint32_t type_filter, VkMemoryPropertyFlags properties) { VkPhysicalDeviceMemoryProperties mem_properties; vkGetPhysicalDeviceMemoryProperties(m_PhysicalDevice, &mem_properties); for (uint32_t i = 0; i < mem_properties.memoryTypeCount; i++) if ((type_filter & (1 << i)) && (mem_properties.memoryTypes[i].propertyFlags & properties) == properties) return i; return 0xFFFFFFFF; // Unable to find memoryType } BaseTexData *VulkanGraphics::LoadTexture(BaseTexData *tex, void *pixel_data) { auto *tex_data = new VulkanTextureData(); tex_data->Width = tex->Width; tex_data->Height = tex->Height; tex_data->Channels = tex->Channels; // tex_data->UserData= // Calculate allocation size (in number of bytes) size_t image_size = tex_data->Width * tex_data->Height * tex_data->Channels; VkResult err; // Create the Vulkan image. { VkImageCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; info.imageType = VK_IMAGE_TYPE_2D; info.format = VK_FORMAT_R8G8B8A8_UNORM; info.extent.width = tex_data->Width; info.extent.height = tex_data->Height; info.extent.depth = 1; info.mipLevels = 1; info.arrayLayers = 1; info.samples = VK_SAMPLE_COUNT_2_BIT; info.tiling = VK_IMAGE_TILING_OPTIMAL; info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; err = vkCreateImage(m_Device, &info, m_Allocator, &tex_data->Image); check_vk_result(err); VkMemoryRequirements req; vkGetImageMemoryRequirements(m_Device, tex_data->Image, &req); VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.allocationSize = req.size; alloc_info.memoryTypeIndex = findMemoryType(req.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); err = vkAllocateMemory(m_Device, &alloc_info, m_Allocator, &tex_data->ImageMemory); check_vk_result(err); err = vkBindImageMemory(m_Device, tex_data->Image, tex_data->ImageMemory, 0); check_vk_result(err); } // Create the Image View { VkImageViewCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; info.image = tex_data->Image; info.viewType = VK_IMAGE_VIEW_TYPE_2D; info.format = VK_FORMAT_R8G8B8A8_UNORM; info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; info.subresourceRange.levelCount = 1; info.subresourceRange.layerCount = 1; err = vkCreateImageView(m_Device, &info, m_Allocator, &tex_data->ImageView); check_vk_result(err); } // Create Sampler { VkSamplerCreateInfo sampler_info{}; sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; sampler_info.magFilter = VK_FILTER_LINEAR; sampler_info.minFilter = VK_FILTER_LINEAR; sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; // outside image bounds just use border color sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; sampler_info.minLod = -1000; sampler_info.maxLod = 1000; sampler_info.maxAnisotropy = 1.0f; err = vkCreateSampler(m_Device, &sampler_info, m_Allocator, &tex_data->Sampler); check_vk_result(err); } // Create Descriptor Set using ImGUI's implementation tex_data->DS = (void *) ImGui_ImplVulkan_AddTexture(tex_data->Sampler, tex_data->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); // Create Upload Buffer { VkBufferCreateInfo buffer_info = {}; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_info.size = image_size; buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; err = vkCreateBuffer(m_Device, &buffer_info, m_Allocator, &tex_data->UploadBuffer); check_vk_result(err); VkMemoryRequirements req; vkGetBufferMemoryRequirements(m_Device, tex_data->UploadBuffer, &req); VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.allocationSize = req.size; alloc_info.memoryTypeIndex = findMemoryType(req.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); err = vkAllocateMemory(m_Device, &alloc_info, m_Allocator, &tex_data->UploadBufferMemory); check_vk_result(err); err = vkBindBufferMemory(m_Device, tex_data->UploadBuffer, tex_data->UploadBufferMemory, 0); check_vk_result(err); } // Upload to Buffer: { void *map = NULL; err = vkMapMemory(m_Device, tex_data->UploadBufferMemory, 0, image_size, 0, &map); check_vk_result(err); memcpy(map, pixel_data, image_size); VkMappedMemoryRange range[1] = {}; range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; range[0].memory = tex_data->UploadBufferMemory; range[0].size = image_size; err = vkFlushMappedMemoryRanges(m_Device, 1, range); check_vk_result(err); vkUnmapMemory(m_Device, tex_data->UploadBufferMemory); } // Create a command buffer that will perform following steps when hit in the command queue. // TODO: this works in the example, but may need input if this is an acceptable way to access the pool/create the command buffer. VkCommandPool command_pool = wd->Frames[wd->FrameIndex].CommandPool; VkCommandBuffer command_buffer; { VkCommandBufferAllocateInfo alloc_info{}; alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; alloc_info.commandPool = command_pool; alloc_info.commandBufferCount = 1; err = vkAllocateCommandBuffers(m_Device, &alloc_info, &command_buffer); check_vk_result(err); VkCommandBufferBeginInfo begin_info = {}; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; err = vkBeginCommandBuffer(command_buffer, &begin_info); check_vk_result(err); } // Copy to Image { VkImageMemoryBarrier copy_barrier[1] = {}; copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; copy_barrier[0].image = tex_data->Image; copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; copy_barrier[0].subresourceRange.levelCount = 1; copy_barrier[0].subresourceRange.layerCount = 1; vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier); VkBufferImageCopy region = {}; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.layerCount = 1; region.imageExtent.width = tex_data->Width; region.imageExtent.height = tex_data->Height; region.imageExtent.depth = 1; vkCmdCopyBufferToImage(command_buffer, tex_data->UploadBuffer, tex_data->Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); VkImageMemoryBarrier use_barrier[1] = {}; use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; use_barrier[0].image = tex_data->Image; use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; use_barrier[0].subresourceRange.levelCount = 1; use_barrier[0].subresourceRange.layerCount = 1; vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier); } // End command buffer { VkSubmitInfo end_info = {}; end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; end_info.commandBufferCount = 1; end_info.pCommandBuffers = &command_buffer; err = vkEndCommandBuffer(command_buffer); check_vk_result(err); err = vkQueueSubmit(m_Queue, 1, &end_info, VK_NULL_HANDLE); check_vk_result(err); err = vkDeviceWaitIdle(m_Device); check_vk_result(err); } return tex_data; } void VulkanGraphics::RemoveTexture(BaseTexData *tex) { auto *tex_data = (VulkanTextureData *) (tex); vkFreeMemory(m_Device, tex_data->UploadBufferMemory, nullptr); vkDestroyBuffer(m_Device, tex_data->UploadBuffer, nullptr); vkDestroySampler(m_Device, tex_data->Sampler, nullptr); vkDestroyImageView(m_Device, tex_data->ImageView, nullptr); vkDestroyImage(m_Device, tex_data->Image, nullptr); vkFreeMemory(m_Device, tex_data->ImageMemory, nullptr); ImGui_ImplVulkan_RemoveTexture((VkDescriptorSet) tex_data->DS); delete tex_data; } TextureInfo VulkanGraphics::ImAgeHeadFile(const unsigned char *buf, int len) { TextureInfo ret_data{0}; BaseTexData tex_data{}; tex_data.Channels = 4; //unsigned char *image_data = loadFunc(&tex_data); unsigned char *image_data = stbi_load_from_memory((const stbi_uc *) buf, len, &tex_data.Width, &tex_data.Height, nullptr, tex_data.Channels); if (image_data == nullptr) return ret_data; auto result = LoadTexture(&tex_data, image_data); stbi_image_free(image_data); ret_data.textureId = (ImTextureID)result->DS; ret_data.w = tex_data.Width; ret_data.h = tex_data.Height; return ret_data; } 怎么改成 3 合缓冲
07-24
标题基于Python的汽车之家网站舆情分析系统研究AI更换标题第1章引言阐述汽车之家网站舆情分析的研究背景、意义、国内外研究现状、论文方法及创新点。1.1研究背景与意义说明汽车之家网站舆情分析对汽车行业及消费者的重要性。1.2国内外研究现状概述国内外在汽车舆情分析领域的研究进展与成果。1.3论文方法及创新点介绍本文采用的研究方法及相较于前人的创新之处。第2章相关理论总结和评述舆情分析、Python编程及网络爬虫相关理论。2.1舆情分析理论阐述舆情分析的基本概念、流程及关键技术。2.2Python编程基础介绍Python语言特点及其在数据分析中的应用。2.3网络爬虫技术说明网络爬虫的原理及在舆情数据收集中的应用。第3章系统设计详细描述基于Python的汽车之家网站舆情分析系统的设计方案。3.1系统架构设计给出系统的整体架构,包括数据收集、处理、分析及展示模块。3.2数据收集模块设计介绍如何利用网络爬虫技术收集汽车之家网站的舆情数据。3.3数据处理与分析模块设计阐述数据处理流程及舆情分析算法的选择与实现。第4章系统实现与测试介绍系统的实现过程及测试方法,确保系统稳定可靠。4.1系统实现环境列出系统实现所需的软件、硬件环境及开发工具。4.2系统实现过程详细描述系统各模块的实现步骤及代码实现细节。4.3系统测试方法介绍系统测试的方法、测试用例及测试结果分析。第5章研究结果与分析呈现系统运行结果,分析舆情数据,提出见解。5.1舆情数据可视化展示通过图表等形式展示舆情数据的分布、趋势等特征。5.2舆情分析结果解读对舆情分析结果进行解读,提出对汽车行业的见解。5.3对比方法分析将本系统与其他舆情分析系统进行对比,分析优劣。第6章结论与展望总结研究成果,提出未来研究方向。6.1研究结论概括本文的主要研究成果及对汽车之家网站舆情分析的贡献。6.2展望指出系统存在的不足及未来改进方向,展望舆情
【磁场】扩展卡尔曼滤波器用于利用高斯过程回归进行磁场SLAM研究(Matlab代码实现)内容概要:本文介绍了利用扩展卡尔曼滤波器(EKF)结合高斯过程回归(GPR)进行磁场辅助的SLAM(同步定位与地图构建)研究,并提供了完整的Matlab代码实现。该方法通过高斯过程回归对磁场空间进行建模,有效捕捉磁场分布的非线性特征,同时利用扩展卡尔曼滤波器融合传感器数据,实现移动机器人在复杂环境中的精确定位与地图构建。研究重点在于提升室内等无GPS环境下定位系统的精度与鲁棒性,尤其适用于磁场特征明显的场景。文中详细阐述了算法原理、数学模型构建、状态估计流程及仿真实验设计。; 适合人群:具备一定Matlab编程基础,熟悉机器人感知、导航或状态估计相关理论的研究生、科研人员及从事SLAM算法开发的工程师。; 使用场景及目标:①应用于室内机器人、AGV等在缺乏GPS信号环境下的高精度定位与地图构建;②为磁场SLAM系统的设计与优化提供算法参考和技术验证平台;③帮助研究人员深入理解EKF与GPR在非线性系统中的融合机制及实际应用方法。; 阅读建议:建议读者结合Matlab代码逐模块分析算法实现细节,重点关注高斯过程回归的训练与预测过程以及EKF的状态更新逻辑,可通过替换实际磁场数据进行实验验证,进一步拓展至多源传感器融合场景。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值