【Vulkan 入門系列】創建幀緩沖、命令池、命令緩存,和獲取圖片(六)

這一節主要介紹創建幀緩沖(Framebuffer),創建命令池,創建命令緩存,和從文件加載 PNG 圖像數據,解碼為 RGBA 格式,并將像素數據暫存到 Vulkan 的 暫存緩沖區中。

一、創建幀緩沖

createFramebuffers 用于創建幀緩沖(Framebuffer)的核心部分,其功能是為交換鏈(Swap Chain)中的每個圖像視圖(Image View)創建對應的幀緩沖對象。

void HelloVK::initVulkan() {createInstance();createSurface();pickPhysicalDevice();createLogicalDeviceAndQueue();setupDebugMessenger();establishDisplaySizeIdentity();createSwapChain();createImageViews();createRenderPass();createDescriptorSetLayout();createGraphicsPipeline();createFramebuffers();...
}void HelloVK::createFramebuffers() {swapChainFramebuffers.resize(swapChainImageViews.size());for (size_t i = 0; i < swapChainImageViews.size(); i++) {VkImageView attachments[] = {swapChainImageViews[i]};VkFramebufferCreateInfo framebufferInfo{};framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;framebufferInfo.renderPass = renderPass;framebufferInfo.attachmentCount = 1;framebufferInfo.pAttachments = attachments;framebufferInfo.width = swapChainExtent.width;framebufferInfo.height = swapChainExtent.height;framebufferInfo.layers = 1;VK_CHECK(vkCreateFramebuffer(device, &framebufferInfo, nullptr,&swapChainFramebuffers[i]));}
}

1.1 調整幀緩沖數組大小

根據交換鏈圖像視圖的數量調整幀緩沖數組的大小,確保兩者一一對應。

swapChainFramebuffers.resize(swapChainImageViews.size());

1.2 遍歷交換鏈圖像視圖

對每個交換鏈圖像視圖創建對應的幀緩沖。

for (size_t i = 0; i < swapChainImageViews.size(); i++) {...}

1.3 定義附件

此處僅使用顏色附件(swapChainImageViews[i]),即渲染結果將寫入交換鏈圖像。若需要深度、模板測試,需額外添加對應的圖像視圖。

VkImageView attachments[] = {swapChainImageViews[i]};

1.4 配置幀緩沖創建信息

VkFramebufferCreateInfo framebufferInfo{};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = renderPass;           // 關聯的渲染流程
framebufferInfo.attachmentCount = 1;               // 附件數量
framebufferInfo.pAttachments = attachments;        // 附件數組指針
framebufferInfo.width = swapChainExtent.width;     // 幀緩沖寬度
framebufferInfo.height = swapChainExtent.height;    // 幀緩沖高度
framebufferInfo.layers = 1;                        // 層數(用于多視口/立體渲染)

關鍵參數

  • renderPass:幀緩沖必須與渲染流程兼容(即附件格式、數量與渲染流程定義一致)。
  • widthheight:必須與交換鏈圖像尺寸一致,否則渲染結果可能無效。
  • layers:通常為 1,用于多圖層渲染(如 VR 立體視圖)。

1.5 創建幀緩沖

vkCreateFramebuffer 創建實際的 Vulkan 幀緩沖對象。

VK_CHECK(vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]));

二、創建命令池

創建一個命令池,用于分配和管理命令緩沖的內存。命令緩沖用于記錄 GPU 執行的渲染或計算指令。

命令池與特定的隊列族(Queue Family)綁定,確保命令緩沖被提交到正確的硬件隊列(如圖形隊列)。

void HelloVK::initVulkan() {createInstance();createSurface();pickPhysicalDevice();createLogicalDeviceAndQueue();setupDebugMessenger();establishDisplaySizeIdentity();createSwapChain();createImageViews();createRenderPass();createDescriptorSetLayout();createGraphicsPipeline();createFramebuffers();createCommandPool();...
}void HelloVK::createCommandPool() {QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);VkCommandPoolCreateInfo poolInfo{};poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();VK_CHECK(vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool));
}

2.1 獲取隊列族索引 QueueFamilyIndices

findQueueFamilies 函數在前面已經詳細分析過,用于尋找物理設備支持的圖形隊列族和呈現隊列族。

2.2 配置命令池創建信息

VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
  • sType:指定結構體類型為命令池創建信息。
  • flags:控制命令池的行為,此處設置為 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,允許單個命令緩沖通過 vkResetCommandBuffer 重置,而無需重置整個命令池。
  • queueFamilyIndex:指定命令池關聯的隊列族索引(此處為圖形隊列族),確保命令緩沖提交到正確的隊列。

2.3 創建命令池

vkCreateCommandPool 調用 Vulkan API 創建命令池。

VK_CHECK(vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool));

三、創建命令緩存

從已創建的命令池(commandPool)中分配一組主命令緩沖(Primary Command Buffers),用于記錄 GPU 執行的渲染指令。

使用 MAX_FRAMES_IN_FLIGHT 控制幀的并發數量(如雙緩沖或三緩沖),避免 CPU 和 GPU 之間的資源競爭。

void HelloVK::initVulkan() {createInstance();createSurface();pickPhysicalDevice();createLogicalDeviceAndQueue();setupDebugMessenger();establishDisplaySizeIdentity();createSwapChain();createImageViews();createRenderPass();createDescriptorSetLayout();createGraphicsPipeline();createFramebuffers();createCommandPool();createCommandBuffer()...
}void HelloVK::createCommandBuffer() {commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);VkCommandBufferAllocateInfo allocInfo{};allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;allocInfo.commandPool = commandPool;allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;allocInfo.commandBufferCount = commandBuffers.size();VK_CHECK(vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()));
}

3.1 調整命令緩沖數組大小

根據預定義的 MAX_FRAMES_IN_FLIGHT(代碼內設置為 2)設置命令緩沖數組的大小。每個飛行的幀需要一個獨立的命令緩沖,確保 CPU 在錄制下一幀時不會覆蓋正在被 GPU 處理的幀數據。

commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);

3.2 配置命令緩沖分配信息

VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = commandPool;                // 關聯的命令池
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;  // 主命令緩沖級別
allocInfo.commandBufferCount = commandBuffers.size(); // 分配的緩沖數量

關鍵參數

  • commandPool:指定從哪個命令池分配內存。命令池的類型需與后續提交的隊列兼容。
  • level:設置為 VK_COMMAND_BUFFER_LEVEL_PRIMARY,表示分配的是主命令緩沖(可直接提交到隊列)。
級別用途
VK_COMMAND_BUFFER_LEVEL_PRIMARY直接提交到隊列,可調用次級緩沖。適用于每幀的主要渲染指令。
VK_COMMAND_BUFFER_LEVEL_SECONDARY嵌入到主緩沖中,需通過主緩沖執行。適用于復用指令或并行錄制。
  • commandBufferCount:需要分配的緩沖數量,與 MAX_FRAMES_IN_FLIGHT 一致。

3.3 分配命令緩沖

vkAllocateCommandBuffers 從命令池中分配指定數量的命令緩沖。

VK_CHECK(vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()));

3.4 核心概念

3.4.1 主命令緩沖(Primary Command Buffer)
  • 直接提交到隊列:主緩沖可獨立提交到隊列執行,通常包含完整的渲染指令序列。
  • 次級緩沖的依賴:次級緩沖(SECONDARY)需通過 vkCmdExecuteCommands 在主緩沖中調用,適用于復用指令或并行錄制。
3.4.2 幀并發控制(MAX_FRAMES_IN_FLIGHT)
  • 雙緩沖/三緩沖:通過設置 2 或 3 個緩沖,允許 CPU 準備下一幀數據的同時,GPU 處理當前幀,避免資源沖突。
  • 同步機制:需配合信號量(Semaphore)或柵欄(Fence)確保幀的正確同步。
3.4.3 命令池與緩沖的關系
  • 內存管理:命令池負責底層內存分配,緩沖的生命周期由其所屬池控制。
  • 重置行為:若命令池創建時指定了 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,可單獨重置緩沖,否則需重置整個池。

3.5 完整工作流程示例

  1. 初始化階段:創建命令池 → 分配命令緩沖。
  2. 渲染循環:
    • 等待前一幀完成(通過柵欄)。
    • 重置命令緩沖 → 錄制渲染指令(如綁定管線、繪制調用)。
    • 提交命令緩沖到隊列 → 呈現交換鏈圖像。
  3. 清理階段:銷毀命令池(自動釋放所有關聯的緩沖)。

四、獲取圖片

從文件加載 PNG 圖像數據,解碼為 RGBA 格式,并將像素數據暫存到 Vulkan 的 暫存緩沖區(Staging Buffer) 中,為后續將數據復制到 GPU 專用的紋理圖像做準備。

void HelloVK::initVulkan() {createInstance();createSurface();pickPhysicalDevice();createLogicalDeviceAndQueue();setupDebugMessenger();establishDisplaySizeIdentity();createSwapChain();createImageViews();createRenderPass();createDescriptorSetLayout();createGraphicsPipeline();createFramebuffers();createCommandPool();decodeImage();...
}void HelloVK::decodeImage() {std::vector<uint8_t> imageData = LoadBinaryFileToVector("texture.png",assetManager);if (imageData.size() == 0) {LOGE("Fail to load image.");return;}// Make sure we have an alpha channel, not all hardware can do linear filtering of RGB888.const int requiredChannels = 4;unsigned char* decodedData = stbi_load_from_memory(imageData.data(),imageData.size(), &textureWidth, &textureHeight, &textureChannels, requiredChannels);if (decodedData == nullptr) {LOGE("Fail to load image to memory, %s", stbi_failure_reason());return;}if (textureChannels != requiredChannels) {textureChannels = requiredChannels;}size_t imageSize = textureWidth * textureHeight * textureChannels;VkBufferCreateInfo createInfo{};createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;createInfo.size = imageSize;createInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;VK_CHECK(vkCreateBuffer(device, &createInfo, nullptr, &stagingBuffer));VkMemoryRequirements memRequirements;vkGetBufferMemoryRequirements(device, stagingBuffer, &memRequirements);VkMemoryAllocateInfo allocInfo{};allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;allocInfo.allocationSize = memRequirements.size;allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits,VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &stagingMemory));VK_CHECK(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0));uint8_t *data;VK_CHECK(vkMapMemory(device, stagingMemory, 0, memRequirements.size, 0,(void **)&data));memcpy(data, decodedData, imageSize);vkUnmapMemory(device, stagingMemory);stbi_image_free(decodedData);
}

4.1 加載圖像文件到內存

調用 LoadBinaryFileToVector 將文件內容讀取到字節數組 imageData。若文件加載失敗(如路徑錯誤或文件不存在),記錄錯誤并退出。

std::vector<uint8_t> imageData = LoadBinaryFileToVector("texture.png", assetManager);
if (imageData.size() == 0) {LOGE("Fail to load image.");return;
}

4.2 解碼圖像數據

使用 STB 圖像庫中的函數 stbi_load_from_memory 從內存解碼圖像。

const int requiredChannels = 4;
unsigned char* decodedData = stbi_load_from_memory(imageData.data(), imageData.size(), &textureWidth, &textureHeight, &textureChannels, requiredChannels
);
if (decodedData == nullptr) {LOGE("Fail to load image to memory, %s", stbi_failure_reason());return;
}if (textureChannels != requiredChannels) {textureChannels = requiredChannels; // 強制設為 4
}
  • requiredChannels = 4:強制解碼為 RGBA 格式(4 通道),確保兼容性(某些 GPU 對 RGB 格式的線性過濾支持不佳)。
  • 輸出參數:textureWidthtextureHeight(圖像尺寸)、textureChannels(實際解碼的通道數)。

4.3 計算圖像數據大小

size_t imageSize = textureWidth * textureHeight * textureChannels; // 總字節數

4.4 創建暫存緩沖區

暫存緩沖區作為 CPU 與 GPU 之間的數據傳輸橋梁。后續需通過傳輸命令將數據從此緩沖區復制到 GPU 專用的紋理圖像。

VkBufferCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
createInfo.size = imageSize;                           // 緩沖區大小
createInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;   // 用途:傳輸源
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;    // 獨占訪問模式
VK_CHECK(vkCreateBuffer(device, &createInfo, nullptr, &stagingBuffer));

關鍵參數

  • usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT:標記為傳輸源。
  • sharingMode = VK_SHARING_MODE_EXCLUSIVE:緩沖區僅由圖形隊列獨占使用(無需多隊列共享)。

4.5 查詢內存需求

調用 vkGetBufferMemoryRequirements 獲取緩沖區的內存需求(大小、對齊、內存類型掩碼)。

VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, stagingBuffer, &memRequirements);

4.6 分配暫存內存

調用 vkAllocateMemory 用于分配暫存內存。

VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits,VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
);
VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &stagingMemory));
  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT:內存可被 CPU 直接訪問(通過 vkMapMemory)。
  • VK_MEMORY_PROPERTY_HOST_COHERENT_BIT:確保 CPU 與 GPU 內存訪問的自動一致性(無需手動刷新緩存)。

findMemoryType 用于找到符合特定緩沖區內存要求的內存堆的索引。Vulkan 將這些要求以位集的形式管理,在這種情況下通過 uint32_t 來表示。

uint32_t HelloVK::findMemoryType(uint32_t typeFilter,VkMemoryPropertyFlags properties) {VkPhysicalDeviceMemoryProperties memProperties;vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags &properties) == properties) {return i;}}assert(false);  // failed to find suitable memory type!return -1;
}
  1. 調用 vkGetPhysicalDeviceMemoryProperties 獲取物理設備的內存信息,包括內存類型(memoryTypes)和內存堆(memoryHeaps)。
  2. 遍歷所有可用的內存類型(通常數量較小)。
  3. typeFilter & (1 << i) 檢查第 i 位是否為 1。若為真,表示內存類型 i 是候選類型。
  4. (memProperties.memoryTypes[i].propertyFlags & properties) == properties 確保內存類型的屬性(propertyFlags)包含 properties 的所有標志。例如,若 properties 要求內存同時是主機可見和一致的,則內存類型必須同時具備這兩個屬性。
  5. 返回第一個滿足條件的內存類型索引。
  6. 若未找到合適內存類型,觸發斷言錯誤(調試模式下終止程序),并返回無效值 -1。

4.7 綁定內存到緩沖區

將分配的內存與緩沖區關聯,偏移量設為 0(從內存起始位置綁定)。

VK_CHECK(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0));

4.8 映射內存并拷貝數據

uint8_t *data;
VK_CHECK(vkMapMemory(device, stagingMemory, 0, memRequirements.size, 0, (void **)&data));
memcpy(data, decodedData, imageSize);
vkUnmapMemory(device, stagingMemory);
  1. vkMapMemory 將 GPU 內存映射到 CPU 可訪問的指針 data
  2. memcpy 將解碼后的像素數據復制到映射的內存中。
  3. vkUnmapMemory 解除映射,確保數據寫入完成。

4.9 釋放解碼數據

STB 庫要求手動釋放解碼后的像素數據,避免內存泄漏。

stbi_image_free(decodedData);

4.10 關鍵概念

4.10.1 暫存緩沖區(Staging Buffer)

GPU 專用內存通常無法直接被 CPU 訪問,需通過暫存緩沖區中轉。

典型流程

  1. CPU 將數據寫入暫存緩沖區。
  2. 提交傳輸命令(如 vkCmdCopyBufferToImage),將數據復制到設備本地紋理。
  3. 銷毀暫存資源。
4.10.2 內存一致性

HOST_COHERENT_BIT:確保 CPU 寫入的數據立即可被 GPU 讀取(無緩存同步問題)。若無此標志需手動調用 vkFlushMappedMemoryRangesvkInvalidateMappedMemoryRanges 刷新緩存。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/902789.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/902789.shtml
英文地址,請注明出處:http://en.pswp.cn/news/902789.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ubuntu的普通用戶相關配置

1.切換到普通用戶下&#xff0c;不出現&#xff0c;用戶名主機ip, 環境變量被破壞&#xff0c; 參考&#xff1a;一文教你快速修改ubuntu終端顯示的主機名和用戶名_ubuntu終端名稱-CSDN博客 2.如果登陸進去無法使用ls,cd&#xff0c;vi等命令 2.1 環境變量 如果 PATH 被清空…

騰訊云×數語科技:Datablau DDM (AI智能版)上架云應用!

在數據爆炸式增長的時代&#xff0c;傳統的數據建模方式已難以滿足企業對敏捷性、智能化、自動化的需求。數語科技聯合騰訊云推出的 Datablau DDM 數據建模平臺&#xff08;AI智能版&#xff09;&#xff0c;基于AI語義建模技術&#xff0c;深度融合騰訊混元大模型能力&#xf…

Spark-streaming(一)

Spark-Streaming概述 Spark Streaming 用于流式數據的處理。 和 Spark 基于 RDD 的概念很相似&#xff0c;Spark Streaming 使用離散化流(discretized stream)作為抽象表示&#xff0c;叫作 DStream。 DStream 是隨時間推移而收到的數據的序列。 Spark-Streaming的特點&…

CS144 Lab 6 實戰記錄:構建 IP 路由器

1 實驗背景與目標 在 CS144 的 Lab 6 中&#xff0c;我們需要在之前實現的 NetworkInterface&#xff08;Lab 5&#xff09;基礎上構建一個完整的 IP 路由器。路由器的主要任務是根據路由表將接收到的 IP 數據報轉發到正確的網絡接口&#xff0c;并發送給正確的下一跳&#xf…

【網絡安全】社會工程學策略

1. 社會工程學簡介 社會工程攻擊是威脅行為者常用的攻擊方式。這是因為&#xff0c;誘騙人們提供訪問權限、信息或金錢通常比利用軟件或網絡漏洞更容易。 您可能還記得&#xff0c;社會工程學是一種利用人為錯誤來獲取私人信息、訪問權限或貴重物品的操縱技術。它是一個涵蓋性…

【含文檔+PPT+源碼】基于SpringBoot的開放實驗管理平臺設計與實現

項目介紹 本課程演示的是一款基于SpringBoot的開放實驗管理平臺設計與實現&#xff0c;主要針對計算機相關專業的正在做畢設的學生與需要項目實戰練習的 Java 學習者。 1.包含&#xff1a;項目源碼、項目文檔、數據庫腳本、軟件工具等所有資料 2.帶你從零開始部署運行本套系統…

鴻蒙NEXT開發定位工具類 (WGS-84坐標系)(ArkTs)

import geoLocationManager from ohos.geoLocationManager; import { BusinessError, Callback } from ohos.base; import { LogUtil } from ./LogUtil; import { PermissionUtil } from ./PermissionUtil; import { map, mapCommon } from kit.MapKit; /*** 定位工具類 (WGS-8…

SSM從入門到上手-全面講解SSM框架的使用.

一、SSM框架整合 將Spring、Spring MVC和MyBatis結合在一起&#xff0c;形成一個高效且易于維護的Web應用程序架構。具體整合的方式如下&#xff1a; Spring管理Bean&#xff1a;Spring負責管理所有的Java對象&#xff0c;包括Service層、DAO層等。通過Spring的IoC容器進行依賴…

學員答題pk知識競賽小程序怎么做

制作學員答題PK知識競賽小程序&#xff0c;主要有以下步驟&#xff1a; 一、規劃設計 明確需求&#xff1a;確定小程序的使用場景是校園知識競賽、培訓機構考核還是企業內部培訓等。答題功能&#xff0c;規定答題的具體規則&#xff0c;包括題目類型&#xff08;單選、多選、…

視頻分析設備平臺EasyCVR視頻技術驅動下,監控上墻全組件解析與組網應用方案

隨著數字化進程的加速推進&#xff0c;視頻監控技術在工業、商業、社區等諸多領域得到了廣泛應用。盡管不同場景對監控功能的具體需求存在差異&#xff0c;但底層硬件架構具有顯著的共性特征。實際部署中&#xff0c;僅需依據網絡環境等實際情況&#xff0c;靈活調整設備的連接…

idea使用docker插件一鍵部署項目

一、首先保證我們電腦上已經安裝了docker docker -v查看docker版本&#xff0c;如果不能識別&#xff0c;需要先下載docker destop&#xff0c;在官網下載正常安裝即可。 安裝成功就可以使用docker 命令了 二、idea下載docker插件并配置docker參數 我是通過tcp連接docker服務…

SQL Tuning Advisor

什么是SQL Tuning Advisor STA可以用來優化那些已經被發現的高負載SQL. 默認情況下, Oracle數據庫在自動維護窗口中自動認證那些有問題的SQL并且執行優化建議&#xff0c;找尋提升高負載SQL執行計劃性能的方法. ** 如何查看自動優化維護窗口產生的報告? ** SQL> set ser…

uniapp-商城-31-shop頁面中的 我的訂單

前面的章節講了很多關于頁面 布局 的知識。 現在來看看其他欄目&#xff0c;我的訂單頁面。 1 頁面樣式圖 基本的樣式包含shop頁面 我的訂單 點擊我的訂單&#xff0c;跳轉到訂單頁面 點擊訂單的每一條訂單&#xff0c;跳轉到訂單詳情 2、創建訂單頁面 2.1 創建sub頁面文件…

深入探討JavaScript性能瓶頸與優化實戰指南

JavaScript作為現代Web開發的核心語言,其性能直接影響用戶體驗與業務指標。隨著2025年前端應用的復雜性持續增加,性能優化已成為開發者必須掌握的核心技能。本文將從性能瓶頸分析、優化策略、工具使用三個維度,結合實戰案例,系統梳理JavaScript性能優化的關鍵路徑。 一、Ja…

基于AI與drawio的圖表生成技術及其在學術研究中的應用前景分析

一、研究背景與沖突 在當今數字化時代&#xff0c;學術研究與信息傳播的方式發生了深刻變革。隨著數據量的爆炸式增長以及研究內容的日益復雜&#xff0c;高效、精準地呈現研究成果變得至關重要。圖表作為一種直觀、簡潔且信息承載量大的表達方式&#xff0c;在學術研究中扮演著…

uniapp 仿小紅書輪播圖效果

通過對小紅書的輪播圖分析&#xff0c;可得出以下總結&#xff1a; 1.單張圖片時容器根據圖片像素定高 2.多圖時輪播圖容器高度以首圖為錨點 3.比首圖長則固高左右留白 4.比首圖短則固寬上下留白 代碼如下&#xff1a; <template><view> <!--輪播--><s…

【ORACLE】記錄一些ORACLE的merge into語句的BUG

【ORACLE】記錄一些ORACLE的merge into語句的BUG 一、自相矛盾-DML重啟動行為差異,違反acid原則 發現版本&#xff1a;10g ~ 23ai 這個用例在我之前的文章里有提過&#xff0c;ORACLE和PG系關于并發事務行為有一個非常大的差異&#xff0c;就是ORACLE在某些并發沖突的場景下會…

2025上海車展:光峰科技全球首發“靈境”智能車載光學系統

當AI為光賦予思想&#xff0c;汽車將會變成什么樣&#xff1f;深圳光峰科技為您揭曉答案。 2025年4月23日&#xff0c;在剛剛開幕的“2025上海車展”上&#xff0c;全球領先的激光核心器件公司光峰科技舉辦了主題為“AI光影盛宴&#xff0c;智享未來出行”的媒體發布會&#x…

密碼學的hash函數,哈希碰撞, collision resistance, BTC用到的SHA-256簡介

密碼學中的哈希函數、哈希碰撞、抗碰撞性&#xff08;collision resistance&#xff09;以及比特幣中使用的 SHA-256 的簡明介紹&#xff1a; &#x1f9e9; 一、哈希函數&#xff08;Hash Function&#xff09; 定義&#xff1a; 哈希函數是一種將任意長度的輸入&#xff08;…

unity TEngine學習4

上一篇我們學習了UI部分&#xff0c;這一篇我們學習其他部分&#xff0c;按照老規矩還是先打開官方文檔 ResourceModule 在官方文檔里介紹了當前加載的設置&#xff0c;但是我們是小白看不懂&#xff0c;那就不管他內部怎么實現的&#xff0c;我們主要看下面的代碼給的方法&am…