Logical Address->Linear Address->Physical Address

本文深入解析了段描述符和页目录表在计算机内存管理中的关键角色,包括它们的结构、功能以及如何在处理器层面实现地址转换。通过详细解释每个字段的作用,读者能更好地理解现代操作系统如何高效地管理内存资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

3 registers for starting pos:

LDTR, GDTR( register for starting addr of DT)

---段描述符
每个段由一个8字节(64位)的段描述符来描述,他表示段的各项属性。段描述符放在叫全局描述符表(Global Descriptor Table:GDT )或局部描述符表(Local Descriptor Table:LDT)中。GDT和LDT可以理解为数组。而段选择符里的索引是用于选择在这个数组当中的元素。
如:GDT[index],表示GDT中第index个段描述符。


CPU当中有两个特殊控制器gdtr和ldtr分别存储GDT和LDT的地址

CR3(control register for starting addr of Page directory)

 内核先将当前任务的页目录表的物理地址填入cr3寄存器。

 

Descriptor table structure:

Base address: A 32-bit integer that defines the starting location of the segment in the 4 GByte
linear address space.
Privilege level: Each segment can be assigned a privilege level between 0 and 3, where 0 is the
most privileged, usually for operating system kernel code. If a program with a higher-numbered
privilege level tries to access a segment having a lower-numbered privilege level, a processor fault
is generated.
Segment type: Indicates the type of segment and specifies the type of access that can be made
to the segment and the direction the segment can grow (up or down). Data (including Stack) segments
can be read-only or read/write and can grow either up or down. Code segments can be
execute-only or execute/read-only.
Segment present flag: This bit indicates whether the segment is currently present in physical
memory.
Granularity flag: Determines the interpretation of the Segment limit field. If the bit is clear,
the segment limit is interpreted in byte units. If the bit is set, the segment limit is interpreted in
4096-byte units.
Segment limit: This 20-bit integer specifies the size of the segment. It is interpreted in one of
the following two ways, depending on the Granularity flag:
• The number of bytes in the segment, ranging from 1 to 1 MByte.
• The number of 4096-byte units, permitting the segment size to range from 4 KByte to 4 GByte.

 

 

 

 

Descriptor table structure:

Page directory: An array of up to 1024 32-bit page-directory entries.
• Page table: An array of up to 1024 32-bit page-table entries.
• Page: A 4 KByte or 4 MByte address space.
To simplify the following discussion, we will assume that 4 KByte pages are used:
A linear address is divided into three fields: a pointer to a page-directory entry, a pointer to a
page-table entry, and an offset into a page frame. Control register (CR3) contains the starting
address of the page directory. The following steps are carried out by the processor when translating
a linear address to a physical address, as shown in Figure 11–9:
1. The linear address references a location in the linear address space.
2. The 10-bit directory field in the linear address is an index to a page-directory entry. The pagedirectory
entry contains the base address of a page table.
3. The 10-bit table field in the linear address is an index into the page table identified by the
page-directory entry. The page-table entry at that position contains the base location of a page
in physical memory.
4. The 12-bit offset field in the linear address is added

 

 

#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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值