一、簡介
相比於顯示卡內部讀取資料,單純從cpu訪問記憶體資料的方式效能不是最佳的。最佳的方式是採用vk_memory_property_device_local_bit標誌位,通常來說用在專用的圖形卡,cpu是無法訪問的。
二、臨時緩衝區
建立臨時緩衝區:
比較理想的實現方式是建立輔助函式來完成。如下建立函式createbuffer以及createvertexbuffer:
void createbuffer(vkdevicesize size, vkbufferusageflags usage, vkmemorypropertyflags properties, vkbuffer& buffer, vkdevicememory& buffermemory) ;
bufferinfo.stype = vk_structure_type_buffer_create_info;
bufferinfo.size = size;
bufferinfo.usage = usage;
bufferinfo.sharingmode = vk_sharing_mode_exclusive;
if (vkcreatebuffer(device, &bufferinfo, nullptr, &buffer) != vk_success)
vkmemoryrequirements memrequirements;
vkgetbuffermemoryrequirements(device, buffer, &memrequirements);
vkmemoryallocateinfo allocinfo = {};
allocinfo.stype = vk_structure_type_memory_allocate_info;
allocinfo.allocationsize = memrequirements.size;
allocinfo.memorytypeindex = findmemorytype(memrequirements.memorytypebits, properties);
if (vkallocatememory(device, &allocinfo, nullptr, &buffermemory) != vk_success)
vkbindbuffermemory(device, buffer, buffermemory, 0);
}該函式需要傳遞緩衝區大小,記憶體屬性和usage最終建立不同型別的緩衝區。最後兩個引數儲存輸出的控制代碼。
void createvertexbuffer()
使用臨時緩衝區:
現在改變createvertexbuffer函式,僅僅使用host緩衝區作為臨時緩衝區,並且使用device緩衝區作為最終的頂點緩衝區:
void createvertexbuffer()
使用stagingbuffer來劃分stagingbuffermemory緩衝區用來對映、拷貝頂點資料。
使用命令緩衝區執行記憶體傳輸的操作命令,就像繪製命令一樣。因此我們需要分配乙個臨時命令緩衝區。或許在這裡希望為短期的緩衝區分別建立command pool,那麼可以考慮記憶體分配的優化策略,在command pool生成期間使用vk_command_pool_create_transient_bit標誌位。
void copybuffer(vkbuffer srcbuffer, vkbuffer dstbuffer, vkdevicesize size) ;
allocinfo.stype = vk_structure_type_command_buffer_allocate_info;
allocinfo.level = vk_command_buffer_level_primary;
allocinfo.commandpool = commandpool;
allocinfo.commandbuffercount = 1;
vkcommandbuffer commandbuffer;
vkallocatecommandbuffers(device, &allocinfo, &commandbuffer);
}立即使用命令緩衝過去進行記錄:
vkcommandbufferbegininfo begininfo = {};
begininfo.stype = vk_structure_type_command_buffer_begin_info;
begininfo.flags = vk_command_buffer_usage_one_time_submit_bit;
vkbegincommandbuffer(commandbuffer, &begininfo);
應用於繪製命令緩衝區的vk_command_buffer_usage_simultaneous_use_bit標誌位在此不必要,因為我們之需要使用一次命令緩衝區,等待該函式返回,直到複製操作完成。
vkbuffercopy copyregion = {};
copyregion.srcoffset = 0; // optional
copyregion.dstoffset = 0; // optional
copyregion.size = size;
vkcmdcopybuffer(commandbuffer, srcbuffer, dstbuffer, 1, region);
緩衝區內容使用vkcmdcopybuffer命令傳輸。它使用source和destination緩衝區及乙個緩衝區拷貝的區域作為引數。這個區域被定義在vkbuffercopy結構體中,描述源緩衝區的偏移量,目標緩衝區的偏移量和對應的大小。與vkmapmemory命令不同,這裡不可以指定vk_whole_size。
vkendcommandbuffer(commandbuffer);
此命令緩衝區僅包含拷貝命令,因此我們可以在此之後停止記錄。現在執行命令緩衝區完成傳輸:
vksubmitinfo submitinfo = {};
submitinfo.stype = vk_structure_type_submit_info;
submitinfo.commandbuffercount = 1;
submitinfo.pcommandbuffers = &commandbuffer;
vkqueuesubmit(graphicsqueue, 1, &submitinfo, vk_null_handle);
vkqueuewaitidle(graphicsqueue);
與繪製命令不同的是,這個時候我們不需要等待任何事件。我們只是想立即在緩衝區執行傳輸命令。這裡有同樣有兩個方式等待傳輸命令完成。我們可以使用vkwaitforfences等待柵欄fence,或者只是使用vkqueuewaitidle等待傳輸佇列狀態變為idle。乙個柵欄允許安排多個連續的傳輸操作,而不是一次執行乙個。這給了驅動程式更多的優化空間。
vkfreecommandbuffers(device, commandpool, 1, &commandbuffer);
不要忘記清理用於傳輸命令的命令緩衝區。
我們可以從createvertexbuffer函式中呼叫copybuffer,拷貝頂點資料到裝置緩衝區中:
createbuffer(buffersize, vk_buffer_usage_transfer_dst_bit | vk_buffer_usage_vertex_buffer_bit, vk_memory_property_device_local_bit, vertexbuffer, vertexbuffermemory);
copybuffer(stagingbuffer, vertexbuffer, buffersize)
當從暫存緩衝區拷貝資料到圖形卡裝置緩衝區完畢後,我們應該清理它:
…copybuffer(stagingbuffer, vertexbuffer, buffersize);
vkdestroybuffer(device, stagingbuffer, nullptr);
vkfreememory(device, stagingbuffermemory, nullptr);
}
輸入緩衝區與輸出緩衝區
本博文通過一段程式來理解輸入緩衝區與輸出緩衝區。程式如下 author wanghao created time thu 17 may 2018 06 03 12 ampdt file name test.c description include int main int argc,const c...
使用者程序緩衝區和核心緩衝區
常常聽到有程式設計師會跟你討論 我們在讀寫檔案的時候,系統是有快取的 但實際上有一部分人把使用者程序緩衝區和系統空間的緩衝區的概念混淆了,包括這兩種緩衝區的用法和所要解決的問題,還有其它類似的概念。本文就來區分一下不同的緩衝區概念 主要針對類unix平台 使用者程序和作業系統的關係 首先我用一張圖來...
php 緩衝區,PHP的輸出緩衝區
1 什麼是緩衝區?緩衝區的作用是把輸入或者輸出的內容先放進記憶體,而不顯示或者讀取,最本質的作用就是協調高速cpu和相對緩慢的io裝置 磁碟等 的運作。2 php在執行的時候,在什麼地方有用到緩衝區?當執行php的時候,如果碰到了echo print r之類的會輸出資料的 php就會將要輸出的資料放...