int sample_main(int argc, char *argv[]) { VkResult U_ASSERT_ONLY res; struct sample_info info = {}; char sample_title[] = "Pipeline Cache"; const bool depthPresent = true; process_command_line_args(info, argc, argv); init_global_layer_properties(info); init_instance_extension_names(info); init_device_extension_names(info); init_instance(info, sample_title); init_enumerate_device(info); init_window_size(info, 500, 500); init_connection(info); init_window(info); init_swapchain_extension(info); init_device(info); init_command_pool(info); init_command_buffer(info); execute_begin_command_buffer(info); init_device_queue(info); init_swap_chain(info); init_depth_buffer(info); init_texture(info, "blue.ppm"); init_uniform_buffer(info); init_descriptor_and_pipeline_layouts(info, true); init_renderpass(info, depthPresent); init_shaders(info, vertShaderText, fragShaderText); init_framebuffers(info, depthPresent); init_vertex_buffer(info, g_vb_texture_Data, sizeof(g_vb_texture_Data), sizeof(g_vb_texture_Data[0]), true); init_descriptor_pool(info, true); init_descriptor_set(info, true); /* VULKAN_KEY_START */ // Check disk for existing cache data size_t startCacheSize = 0; void *startCacheData = nullptr; std::string directoryName = get_file_directory(); std::string readFileName = directoryName + "pipeline_cache_data.bin"; FILE *pReadFile = fopen(readFileName.c_str(), "rb"); if (pReadFile) { // Determine cache size fseek(pReadFile, 0, SEEK_END); startCacheSize = ftell(pReadFile); rewind(pReadFile); // Allocate memory to hold the initial cache data startCacheData = (char *)malloc(sizeof(char) * startCacheSize); if (startCacheData == nullptr) { fputs("Memory error", stderr); exit(EXIT_FAILURE); } // Read the data into our buffer size_t result = fread(startCacheData, 1, startCacheSize, pReadFile); if (result != startCacheSize) { fputs("Reading error", stderr); free(startCacheData); exit(EXIT_FAILURE); } // Clean up and print results fclose(pReadFile); printf(" Pipeline cache HIT!\n"); printf(" cacheData loaded from %s\n", readFileName.c_str()); } else { // No cache found on disk printf(" Pipeline cache miss!\n"); } if (startCacheData != nullptr) { // clang-format off // // Check for cache validity // // TODO: Update this as the spec evolves. The fields are not defined by the header. // // The code below supports SDK 0.10 Vulkan spec, which contains the following table: // // Offset Size Meaning // ------ ------------ ------------------------------------------------------------------ // 0 4 a device ID equal to VkPhysicalDeviceProperties::DeviceId written // as a stream of bytes, with the least significant byte first // // 4 VK_UUID_SIZE a pipeline cache ID equal to VkPhysicalDeviceProperties::pipelineCacheUUID // // // The code must be updated for latest Vulkan spec, which contains the following table: // // Offset Size Meaning // ------ ------------ ------------------------------------------------------------------ // 0 4 length in bytes of the entire pipeline cache header written as a // stream of bytes, with the least significant byte first // 4 4 a VkPipelineCacheHeaderVersion value written as a stream of bytes, // with the least significant byte first // 8 4 a vendor ID equal to VkPhysicalDeviceProperties::vendorID written // as a stream of bytes, with the least significant byte first // 12 4 a device ID equal to VkPhysicalDeviceProperties::deviceID written // as a stream of bytes, with the least significant byte first // 16 VK_UUID_SIZE a pipeline cache ID equal to VkPhysicalDeviceProperties::pipelineCacheUUID // // clang-format on uint32_t headerLength = 0; uint32_t cacheHeaderVersion = 0; uint32_t vendorID = 0; uint32_t deviceID = 0; uint8_t pipelineCacheUUID[VK_UUID_SIZE] = {}; memcpy(&headerLength, (uint8_t *)startCacheData + 0, 4); memcpy(&cacheHeaderVersion, (uint8_t *)startCacheData + 4, 4); memcpy(&vendorID, (uint8_t *)startCacheData + 8, 4); memcpy(&deviceID, (uint8_t *)startCacheData + 12, 4); memcpy(pipelineCacheUUID, (uint8_t *)startCacheData + 16, VK_UUID_SIZE); // Check each field and report bad values before freeing existing cache bool badCache = false; if (headerLength <= 0) { badCache = true; printf(" Bad header length in %s.\n", readFileName.c_str()); printf(" Cache contains: 0x%.8x\n", headerLength); } if (cacheHeaderVersion != VK_PIPELINE_CACHE_HEADER_VERSION_ONE) { badCache = true; printf(" Unsupported cache header version in %s.\n", readFileName.c_str()); printf(" Cache contains: 0x%.8x\n", cacheHeaderVersion); } if (vendorID != info.gpu_props.vendorID) { badCache = true; printf(" Vendor ID mismatch in %s.\n", readFileName.c_str()); printf(" Cache contains: 0x%.8x\n", vendorID); printf(" Driver expects: 0x%.8x\n", info.gpu_props.vendorID); } if (deviceID != info.gpu_props.deviceID) { badCache = true; printf(" Device ID mismatch in %s.\n", readFileName.c_str()); printf(" Cache contains: 0x%.8x\n", deviceID); printf(" Driver expects: 0x%.8x\n", info.gpu_props.deviceID); } if (memcmp(pipelineCacheUUID, info.gpu_props.pipelineCacheUUID, sizeof(pipelineCacheUUID)) != 0) { badCache = true; printf(" UUID mismatch in %s.\n", readFileName.c_str()); printf(" Cache contains: "); print_UUID(pipelineCacheUUID); printf("\n"); printf(" Driver expects: "); print_UUID(info.gpu_props.pipelineCacheUUID); printf("\n"); } if (badCache) { // Don't submit initial cache data if any version info is incorrect free(startCacheData); startCacheSize = 0; startCacheData = nullptr; // And clear out the old cache file for use in next run printf(" Deleting cache entry %s to repopulate.\n", readFileName.c_str()); if (remove(readFileName.c_str()) != 0) { fputs("Reading error", stderr); exit(EXIT_FAILURE); } } } // Feed the initial cache data into pipeline creation VkPipelineCacheCreateInfo pipelineCache; pipelineCache.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; pipelineCache.pNext = NULL; pipelineCache.initialDataSize = startCacheSize; pipelineCache.pInitialData = startCacheData; pipelineCache.flags = 0; res = vkCreatePipelineCache(info.device, &pipelineCache, nullptr, &info.pipelineCache); assert(res == VK_SUCCESS); // Free our initialData now that pipeline has been created free(startCacheData); // Time (roughly) taken to create the graphics pipeline timestamp_t start = get_milliseconds(); init_pipeline(info, depthPresent); timestamp_t elapsed = get_milliseconds() - start; printf(" vkCreateGraphicsPipeline time: %0.f ms\n", (double)elapsed); // Begin standard draw stuff init_presentable_image(info); VkClearValue clear_values[2]; init_clear_color_and_depth(info, clear_values); VkRenderPassBeginInfo rp_begin; init_render_pass_begin_info(info, rp_begin); rp_begin.clearValueCount = 2; rp_begin.pClearValues = clear_values; vkCmdBeginRenderPass(info.cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline); vkCmdBindDescriptorSets(info.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, info.pipeline_layout, 0, NUM_DESCRIPTOR_SETS, info.desc_set.data(), 0, NULL); const VkDeviceSize offsets[1] = {0}; vkCmdBindVertexBuffers(info.cmd, 0, 1, &info.vertex_buffer.buf, offsets); init_viewports(info); init_scissors(info); vkCmdDraw(info.cmd, 12 * 3, 1, 0, 0); vkCmdEndRenderPass(info.cmd); execute_pre_present_barrier(info); res = vkEndCommandBuffer(info.cmd); assert(res == VK_SUCCESS); VkFence drawFence = {}; init_fence(info, drawFence); VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; VkSubmitInfo submit_info = {}; init_submit_info(info, submit_info, pipe_stage_flags); /* Queue the command buffer for execution */ res = vkQueueSubmit(info.queue, 1, &submit_info, drawFence); assert(res == VK_SUCCESS); /* Now present the image in the window */ VkPresentInfoKHR present = {}; init_present_info(info, present); /* Make sure command buffer is finished before presenting */ do { res = vkWaitForFences(info.device, 1, &drawFence, VK_TRUE, FENCE_TIMEOUT); } while (res == VK_TIMEOUT); assert(res == VK_SUCCESS); res = vkQueuePresentKHR(info.queue, &present); assert(res == VK_SUCCESS); wait_seconds(1); if (info.save_images) write_ppm(info, "pipeline_cache"); // End standard draw stuff if (startCacheData) { // TODO: Create another pipeline, preferably different from the first // one and merge it here. Then store the merged one. } // Store away the cache that we've populated. This could conceivably happen // earlier, depends on when the pipeline cache stops being populated // internally. size_t endCacheSize = 0; void *endCacheData = nullptr; // Call with nullptr to get cache size res = vkGetPipelineCacheData(info.device, info.pipelineCache, &endCacheSize, nullptr); assert(res == VK_SUCCESS); // Allocate memory to hold the populated cache data endCacheData = (char *)malloc(sizeof(char) * endCacheSize); if (!endCacheData) { fputs("Memory error", stderr); exit(EXIT_FAILURE); } // Call again with pointer to buffer res = vkGetPipelineCacheData(info.device, info.pipelineCache, &endCacheSize, endCacheData); assert(res == VK_SUCCESS); // Write the file to disk, overwriting whatever was there FILE *pWriteFile; std::string writeFileName = directoryName + "pipeline_cache_data.bin"; pWriteFile = fopen(writeFileName.c_str(), "wb"); if (pWriteFile) { fwrite(endCacheData, sizeof(char), endCacheSize, pWriteFile); fclose(pWriteFile); printf(" cacheData written to %s\n", writeFileName.c_str()); } else { // Something bad happened printf(" Unable to write cache data to disk!\n"); } /* VULKAN_KEY_END */ vkDestroyFence(info.device, drawFence, NULL); vkDestroySemaphore(info.device, info.presentCompleteSemaphore, NULL); destroy_pipeline(info); destroy_pipeline_cache(info); destroy_textures(info); destroy_descriptor_pool(info); destroy_vertex_buffer(info); destroy_framebuffers(info); destroy_shaders(info); destroy_renderpass(info); destroy_descriptor_and_pipeline_layouts(info); destroy_uniform_buffer(info); destroy_depth_buffer(info); destroy_swap_chain(info); destroy_command_buffer(info); destroy_command_pool(info); destroy_device(info); destroy_window(info); destroy_instance(info); return 0; }
/* print the extX file system support block information */ void print_super_block(struct super_block sb) { const char *help[]={ "文件系统总的i-节点数", "文件系统总块数", "文件系统预保留的快数", "空闲快数", "空闲i-节点数", "0号快组起始快号", "快大小(此值为1024左移动位数)", "片段大小(与快大小字段相同)", "每个快组所包含快数", "每个快组所包含片段数", "每个快组i-节点数", "最后挂载时间", "最后写入时间", "当前挂载数", "最大挂载数", "签名标志53EF", "文件系统状态(1-正常,3-有错误)", "错误处理方式", "辅版本级别", "最后进行一致性检查时间", "一致性检查间隔时间", "创建本文件系统的操作系统(0-linux)", "主版本级别(1-动态)", "默认UID保留块", "默认GID保留块", "第一个非保留i-节点", "每个i-节点结构大小", "本超级块所在的块组号", "兼容特征标志(0x10-自调节大小)", "非兼容特征标志", "只读兼容特征标志(1-稀疏超级快和组描述符表)", "文件系统ID", "卷名", "最后挂载路径", "位图使用运算法则", "文件再分配块数", "目录再分配块数", "未使用", "日志ID", "日志i-节点", "日志设备", "孤立i-节点表头", "未使用", }; char data[50][50]; memset(data,0,sizeof(data)); int i=0; format_print(data[i++],0x00,0x03,sb.total_Node); format_print(data[i++],0x04,0x07,sb.total_Blocks); format_print(data[i++],0x08,0x0B,sb.retain_Blcoks); format_print(data[i++],0x0C,0x0F,sb.free_Blocks); format_print(data[i++],0x10,0x13,sb.free_Node); format_print(data[i++],0x14,0x17,sb.No_0_Block); format_print_Ex(data[i++],0x18,0x1B,sb.block_Size,1024 << sb.block_Size); format_print_Ex(data[i++],0x1C,0x1F,sb.part_Size,1024 << sb.part_Size); format_print(data[i++],0x20,0x23,sb.block_Group_Blocks); format_print(data[i++],0x24,0x27,sb.block_Group_Parts); format_print(data[i++],0x28,0x2B,sb.block_Group_Nodes); format_print_Ex_t(data[i++],0x2C,0x2F,sb.last_Mount_Time); format_print_Ex_t(data[i++],0x30,0x33,sb.last_Write_Time); format_print(data[i++],0x34,0x35,sb.current_Mounts); format_print(data[i++],0x36,0x37,sb.max_Mounts); format_print(data[i++],0x38,0x39,sb.signature_Logo); format_print(data[i++],0x3A,0x3B,sb.filesystem_State); format_print(data[i++],0x3C,0x3D,sb.err_deal_with); format_print(data[i++],0x3E,0X3F,sb.assist_Version); format_print_Ex_t(data[i++],0x40,0x43,sb.last_Check_Time); format_print(data[i++],0x44,0x47,sb.check_Interval_Time); format_print(data[i++],0x48,0x4B,sb.create_os); format_print(data[i++],0x4C,0x4F,sb.main_Version); format_print(data[i++],0x50,0x51,sb.UID_Block); format_print(data[i++],0x52,0x53,sb.GID_Block); format_print(data[i++],0x54,0x57,sb.No_1_Noretain_Node); format_print(data[i++],0x58,0x59,sb.node_Size); format_print(data[i++],0x5A,0x5B,sb.super_Block_Group); format_print(data[i++],0x5C,0x5F,sb.signature_Compatible); format_print(data[i++],0x60,0x63,sb.signature_Uncompatible); format_print(data[i++],0x64,0x67,sb.signature_Readonly_Compatible); //char data format_print_s(data[i++],0x68,0x77,"no print now"/*sb.filesytem_ID*/); format_print_s(data[i++],0x78,0x87,sb.volume_Name); format_print_s(data[i++],0x88,0xC7,sb.last_Mount_Path); format_print(data[i++],0xC8,0xCB,sb.bitmap_rules); format_print(data[i++],0xCC,0xCC,sb.file_Redistribution_Blocks); format_print(data[i++],0xCD,0xCD,sb.dir_Redistribution_Blocks); format_print(data[i++],0xCE,0xCF,sb.no_Used1); //char data format_print_s(data[i++],0xD0,0xDF,sb.log_ID); format_print(data[i++],0xE0,0xE3,sb.log_Node); format_print(data[i++],0xE4,0xE7,sb.log_drive); format_print(data[i++],0xE8,0xEB,sb.isolate_Node_Table_Head); format_print_s(data[i++],0xEC,0x3FF,"no print now"/*sb.no_Used2*/); int count=i,max=0,tmp; for ( i=0;i<count;i++){ tmp=strlen(data[i]); max=max < tmp? tmp:max;} printf("文件系统UUID: %s\n",print_UUID(sb.filesytem_ID)); for ( i=0;i<count;i++) { printf("%s",data[i]); for (tmp=max-strlen(data[i])+3;tmp>0;tmp--) printf(" "); printf("%s\n",help[i]); } }