mem*_*tha 4 c++ shader glsl vulkan
特尔;博士:
编译的 spirv 着色器在内联运行时编译的 spirv 工作时崩溃,使用修改后的示例进行测试。崩溃发生在 vulkan 代码的深处。是什么赋予了?
细节:
我在使用编译的 spirv 着色器时遇到问题。我采用了“draw-textured-cube”示例,将其提取到具有成对 cmake 的独立环境和对util.cpp的最小编辑以调整数据目录的路径。它编译并按预期工作。
然后我从static const文件开头的cstrings 中提取着色器代码并将它们移动到它们自己的文件中。我将调用替换为init_shaders仅读取文件并使用与init_shaders. 我使用从原始示例CMakeLists.txt 中未使用的函数中获取的选项将 glsl 编译到 spirv 中。
它现在因创建管道时的访问冲突而崩溃(完整的错误文本如下)。无论有没有验证层,Debug 和 Release 版本的结果都相同。在 Visual Studio 中逐步执行程序集显示错误发生在创建管道调用深处至少 16 层(其中 acall或非本地jmp构成一个层,因为这些很可能是功能障碍)。
Unhandled exception at 0x000000006894A525 (nvoglv64.dll) in main.exe: 0xC0000005: Access violation writing location 0x00000080A3CAA530. occurred
(确切的地址正如人们所期望的那样变化。)
SDK 中包含的任何示例都使用在运行时编译为 spirv 的内联 glsl,但都有与此类似的注释(来自纹理立方体示例):
/* For this sample, we'll start with GLSL so the shader function is plain */
/* and then use the glslang GLSLtoSPV utility to convert it to SPIR-V for */
/* the driver. We do this for clarity rather than using pre-compiled */
/* SPIR-V */
Run Code Online (Sandbox Code Playgroud)
这似乎表明进行着色器的“正确”方法是使用预编译,但我们没有提供有关如何完成此操作的工作示例/示例。我看过其他地方,但找不到一个相当简单(<10,000 行)的示例来说明如何编译读取和显示 spv 着色器。
我对问题所在的最佳猜测是:1)glslValidator 编译错误;2)我读错了;3) 使用它们需要不同的选项(例如,着色器模块创建信息)然后是运行时编译的着色器。无论如何,我已经开始希望 vulkan 有更好的错误捕获功能。
显然,在任何地方使用内联 glsl 将是一种解决方法,如果这就是它所需要的,我可以制作一堆.cpp文件,每个着色器只有一个大 cstring,以运行时初始加载为代价,但确实应该有更好的解决方案。
主机系统是 windows 7 (x64),与程序所需的资源相比,资源过多。我的目标是 windows linux 和(如果可能)mac,所以任何排除 android、ios、控制台等的解决方案对我来说都很好。
主.cpp:
/*
* Vulkan Samples
*
* Copyright (C) 2015-2016 Valve Corporation
* Copyright (C) 2015-2016 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
VULKAN_SAMPLE_SHORT_DESCRIPTION
Draw Textured Cube
*/
/* This is part of the draw cube progression */
#include <util_init.hpp>
#include <assert.h>
#include <string.h>
#include <cstdlib>
#include "cube_data.h"
FILE* logfile;
#define FAIL {line = __LINE__; goto fail;}
unsigned int * loadSprv(const char* filename, size_t* codelen) {
struct stat fstat;
size_t len, offset = 0, read;
if (stat(filename, &fstat))
return NULL;
*codelen = len = fstat.st_size;
union {
unsigned int * ret;
unsigned char * bytes;
};
bytes = (unsigned char *)malloc((1 + len / 4) * 4 + 1);//padded to 32 bit barrier to accomodate unsigned int type
if (!ret) return NULL;
FILE* src = fopen(filename, "r");
if (!src) {
free(ret);
return NULL;
}
read = fread(bytes, 1, len, src);
while (read > 0 && len >= 0) {
len -= read;
offset += read;
read = fread(bytes + offset, 1, len, src);
}
bytes[offset] = 0;//null term, probably unneeded
fclose(src);
return ret;
}
int sample_main(int argc, char *argv[]) {
VkResult U_ASSERT_ONLY res = VK_SUCCESS;
struct sample_info info = {};
char sample_title[] = "Draw Textured Cube";
const bool depthPresent = true;
logfile = fopen("runtime.log", "w");
uint64_t line = 0;
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);
init_uniform_buffer(info);
init_descriptor_and_pipeline_layouts(info, true);
init_renderpass(info, depthPresent);
//init_shaders(info, vertShaderText, fragShaderText);
{
//|-X init_glslang (empty function on everything that's not android)
info.shaderStages[0] = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL, 0,
VK_SHADER_STAGE_VERTEX_BIT, VK_NULL_HANDLE, "main", NULL};
VkShaderModuleCreateInfo moduleCreateInfo = {VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, NULL, 0,
0, NULL};
moduleCreateInfo.pCode = loadSprv("shaders\\sample.vert.spv", &moduleCreateInfo.codeSize);
if(!moduleCreateInfo.pCode) FAIL;
res = vkCreateShaderModule(info.device, &moduleCreateInfo, NULL, &info.shaderStages[0].module);
free((void*)moduleCreateInfo.pCode);
if (res) FAIL;
info.shaderStages[1] = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL, 0,
VK_SHADER_STAGE_FRAGMENT_BIT, VK_NULL_HANDLE, "main", NULL };
moduleCreateInfo.pCode = loadSprv("shaders\\sample.frag.spv", &moduleCreateInfo.codeSize);
res = vkCreateShaderModule(info.device, &moduleCreateInfo, NULL, &info.shaderStages[1].module);
free((void*)moduleCreateInfo.pCode);
if (res) FAIL;
}
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);
init_pipeline_cache(info);
init_pipeline(info, depthPresent);
/* VULKAN_KEY_START */
VkClearValue clear_values[2];
clear_values[0].color.float32[0] = 0.2f;
clear_values[0].color.float32[1] = 0.2f;
clear_values[0].color.float32[2] = 0.2f;
clear_values[0].color.float32[3] = 0.2f;
clear_values[1].depthStencil.depth = 1.0f;
clear_values[1].depthStencil.stencil = 0;
VkSemaphore imageAcquiredSemaphore;
VkSemaphoreCreateInfo imageAcquiredSemaphoreCreateInfo;
imageAcquiredSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
imageAcquiredSemaphoreCreateInfo.pNext = NULL;
imageAcquiredSemaphoreCreateInfo.flags = 0;
res = vkCreateSemaphore(info.device, &imageAcquiredSemaphoreCreateInfo, NULL, &imageAcquiredSemaphore);
assert(res == VK_SUCCESS);
// Get the index of the next available swapchain image:
res = vkAcquireNextImageKHR(info.device, info.swap_chain, UINT64_MAX, imageAcquiredSemaphore, VK_NULL_HANDLE,
&info.current_buffer);
// TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
// return codes
assert(res == VK_SUCCESS);
VkRenderPassBeginInfo rp_begin;
rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rp_begin.pNext = NULL;
rp_begin.renderPass = info.render_pass;
rp_begin.framebuffer = info.framebuffers[info.current_buffer];
rp_begin.renderArea.offset.x = 0;
rp_begin.renderArea.offset.y = 0;
rp_begin.renderArea.extent.width = info.width;
rp_begin.renderArea.extent.height = info.height;
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);
res = vkEndCommandBuffer(info.cmd);
assert(res == VK_SUCCESS);
const VkCommandBuffer cmd_bufs[] = { info.cmd };
VkFenceCreateInfo fenceInfo;
VkFence drawFence;
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.pNext = NULL;
fenceInfo.flags = 0;
vkCreateFence(info.device, &fenceInfo, NULL, &drawFence);
VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo submit_info[1] = {};
submit_info[0].pNext = NULL;
submit_info[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info[0].waitSemaphoreCount = 1;
submit_info[0].pWaitSemaphores = &imageAcquiredSemaphore;
submit_info[0].pWaitDstStageMask = &pipe_stage_flags;
submit_info[0].commandBufferCount = 1;
submit_info[0].pCommandBuffers = cmd_bufs;
submit_info[0].signalSemaphoreCount = 0;
submit_info[0].pSignalSemaphores = NULL;
/* Queue the command buffer for execution */
res = vkQueueSubmit(info.graphics_queue, 1, submit_info, drawFence);
assert(res == VK_SUCCESS);
/* Now present the image in the window */
VkPresentInfoKHR present;
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present.pNext = NULL;
present.swapchainCount = 1;
present.pSwapchains = &info.swap_chain;
present.pImageIndices = &info.current_buffer;
present.pWaitSemaphores = NULL;
present.waitSemaphoreCount = 0;
present.pResults = NULL;
/* 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.present_queue, &present);
assert(res == VK_SUCCESS);
wait_seconds(1);
/* VULKAN_KEY_END */
if (info.save_images) write_ppm(info, "draw_textured_cube");
vkDestroyFence(info.device, drawFence, NULL);
vkDestroySemaphore(info.device, imageAcquiredSemaphore, 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;
fail:
fprintf(logfile, "Fail. Res: %d. Line: %u\n", res, line);
return 1;
}
Run Code Online (Sandbox Code Playgroud)
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.11)
project (STUPID_CUBE)
# set (CMAKE_VERBOSE_MAKEFILE 1)
set(API_NAME "Vulkan" CACHE STRING "API name to use when building")
string(TOLOWER ${API_NAME} API_LOWERCASE)
include(GNUInstallDirs)
file(TO_CMAKE_PATH $ENV{VULKAN_SDK} VULKAN)
add_definitions("-DVULKAN_SAMPLES_BASE_DIR=\"${CMAKE_SOURCE_DIR}\"")
# The MAJOR number of the version we're building, used in naming
# vulkan-<major>.dll (and other files).
set(MAJOR "1")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
set (CMAKE_INSTALL_PREFIX "")
set (UTILS_NAME vsamputils)
if(NOT WIN32)
include(FindPkgConfig)
option(BUILD_WSI_XCB_SUPPORT "Build XCB WSI support" ON)
option(BUILD_WSI_WAYLAND_SUPPORT "Build Wayland WSI support" OFF)
set(DEMOS_WSI_SELECTION "XCB" CACHE STRING "Select WSI target for demos (XCB, XLIB, WAYLAND, DISPLAY)")
set(SAMPLES_WSI_SELECTION "XCB" CACHE STRING "Select WSI target for api-samples (XCB, WAYLAND, DISPLAY)")
if (BUILD_WSI_XCB_SUPPORT)
find_package(XCB REQUIRED)
endif()
if (BUILD_WSI_WAYLAND_SUPPORT)
find_package(Wayland REQUIRED)
endif()
set (BUILDTGT_DIR build)
set (BINDATA_DIR x86_64/bin)
set (LIBSOURCE_DIR Lib)
else()
# For Windows, since 32-bit and 64-bit items can co-exist, we build each in its own build directory.
# 32-bit target data goes in build32, and 64-bit target data goes into build. So, include/link the
# appropriate data at build time.
if (CMAKE_CL_64)
set (BUILDTGT_DIR build)
set (BINDATA_DIR Bin)
set (LIBSOURCE_DIR Lib)
else()
set (BUILDTGT_DIR build32)
set (BINDATA_DIR Bin32)
set (LIBSOURCE_DIR Lib32)
endif()
endif()
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
set(COMMON_COMPILE_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
set(COMMON_COMPILE_FLAGS "${COMMON_COMPILE_FLAGS} -fno-strict-aliasing -fno-builtin-memcmp")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 ${COMMON_COMPILE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_COMPILE_FLAGS} -std=c++11")
if (UNIX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
endif()
endif()
find_program(GLSLANG_VALIDATOR NAMES glslangValidator
HINTS "${VULKAN}/glslang/${BUILDTGT_DIR}/install/bin"
"${VULKAN}/${BINDATA_DIR}" )
find_path(GLSLANG_SPIRV_INCLUDE_DIR SPIRV/spirv.hpp HINTS "${VULKAN}/source/glslang/"
"${VULKAN}/glslang"
DOC "Path to SPIRV/spirv.hpp")
find_path(SPIRV_TOOLS_INCLUDE_DIR spirv-tools/libspirv.h HINTS "${VULKAN}/spirv-tools/include"
"${VULKAN}/source/spirv-tools/include"
"${VULKAN}/spirv-tools/external/include"
"${VULKAN}/source/spirv-tools/external/include"
DOC "Path to spirv-tools/libspirv.h")
find_path(Vulkan_INCLUDE_DIR vulkan/vulkan.h HINTS "${VULKAN}"
"${VULKAN}/Include" )
if (WIN32)
set (GLSLANG_SEARCH_PATH "${VULKAN}/glslang/${BUILDTGT_DIR}/glslang/Release"
"${VULKAN}/glslang/${BUILDTGT_DIR}/glslang/OSDependent/Windows/Release"
"${VULKAN}/glslang/${BUILDTGT_DIR}/hlsl/Release"
"${VULKAN}/glslang/${BUILDTGT_DIR}/OGLCompilersDLL/Release"
"${VULKAN}/glslang/${BUILDTGT_DIR}/SPIRV/Release" )
set (SPIRV_TOOLS_SEARCH_PATH "${VULKAN}/spirv-tools/${BUILDTGT_DIR}/source/Release")
set (SPIRV_TOOLS_OPT_SEARCH_PATH "${VULKAN}/spirv-tools/${BUILDTGT_DIR}/source/opt/Release")
else()
set (GLSLANG_SEARCH_PATH "${VULKAN}/glslang/build/install/lib" "${VULKAN}/x86_64/lib/glslang" )
set (SPIRV_TOOLS_SEARCH_PATH "${VULKAN}/spirv-tools/build" "${VULKAN}/x86_64/lib/spirv-tools" )
set (SPIRV_TOOLS_OPT_SEARCH_PATH "${SPIRV_TOOLS_SEARCH_PATH}")
endif()
find_library(GLSLANG_LIB NAMES glslang
HINTS ${GLSLANG_SEARCH_PATH} )
find_library(OGLCompiler_LIB NAMES OGLCompiler
HINTS ${GLSLANG_SEARCH_PATH} )
find_library(OSDependent_LIB NAMES OSDependent
HINTS ${GLSLANG_SEARCH_PATH} )
find_library(HLSL_LIB NAMES HLSL
HINTS ${GLSLANG_SEARCH_PATH} )
find_library(SPIRV_LIB NAMES SPIRV
HINTS ${GLSLANG_SEARCH_PATH} )
find_library(SPIRV_TOOLS_LIB NAMES SPIRV-Tools
HINTS ${SPIRV_TOOLS_SEARCH_PATH} )
find_library(SPIRV_TOOLS_OPT_LIB NAMES SPIRV-Tools-opt
HINTS ${SPIRV_TOOLS_OPT_SEARCH_PATH} )
find_library(SPIRV_REMAPPER_LIB NAMES SPVRemapper
HINTS ${GLSLANG_SEARCH_PATH} )
# On Windows, we must pair Debug and Release appropriately
if (WIN32)
set (GLSLANG_DEBUG_SEARCH_PATH "${VULKAN}/glslang/${BUILDTGT_DIR}/glslang/Debug"
"${VULKAN}/glslang/${BUILDTGT_DIR}/glslang/OSDependent/Windows/Debug"
"${VULKAN}/glslang/${BUILDTGT_DIR}/hlsl/Debug"
"${VULKAN}/glslang/${BUILDTGT_DIR}/OGLCompilersDLL/Debug"
"${VULKAN}/glslang/${BUILDTGT_DIR}/SPIRV/Debug")
set (SPIRV_TOOLS_DEBUG_SEARCH_PATH "${VULKAN}/spirv-tools/${BUILDTGT_DIR}/source/Debug")
set (SPIRV_TOOLS_OPT_DEBUG_SEARCH_PATH "${VULKAN}/spirv-tools/${BUILDTGT_DIR}/source/opt/Debug")
add_library(glslang STATIC IMPORTED)
add_library(OGLCompiler STATIC IMPORTED)
add_library(OSDependent STATIC IMPORTED)
add_library(HLSL STATIC IMPORTED)
add_library(SPIRV STATIC IMPORTED)
add_library(Loader STATIC IMPORTED)
add_library(SPIRV-Tools STATIC IMPORTED)
add_library(SPIRV-Tools-opt STATIC IMPORTED)
add_library(SPVRemapper STATIC IMPORTED)
find_library(GLSLANG_DLIB NAMES glslangd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
find_library(OGLCompiler_DLIB NAMES OGLCompilerd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
find_library(OSDependent_DLIB NAMES OSDependentd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
find_library(HLSL_DLIB NAMES HLSLd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
find_library(SPIRV_DLIB NAMES SPIRVd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
find_library(SPIRV_TOOLS_DLIB NAMES SPIRV-Tools
HINTS ${SPIRV_TOOLS_DEBUG_SEARCH_PATH} )
find_library(SPIRV_TOOLS_OPT_DLIB NAMES SPIRV-Tools-opt
HINTS ${SPIRV_TOOLS_OPT_DEBUG_SEARCH_PATH} )
find_library(SPIRV_REMAPPER_DLIB NAMES SPVRemapperd
HINTS ${GLSLANG_DEBUG_SEARCH_PATH} )
set_target_properties(glslang PROPERTIES
IMPORTED_LOCATION "${GLSLANG_LIB}"
IMPORTED_LOCATION_DEBUG "${GLSLANG_DLIB}")
set_target_properties(OGLCompiler PROPERTIES
IMPORTED_LOCATION "${OGLCompiler_LIB}"
IMPORTED_LOCATION_DEBUG "${OGLCompiler_DLIB}")
set_target_properties(OSDependent PROPERTIES
IMPORTED_LOCATION "${OSDependent_LIB}"
IMPORTED_LOCATION_DEBUG "${OSDependent_DLIB}")
set_target_properties(HLSL PROPERTIES
IMPORTED_LOCATION "${HLSL_LIB}"
IMPORTED_LOCATION_DEBUG "${HLSL_DLIB}")
set_target_properties(SPIRV PROPERTIES
IMPORTED_LOCATION "${SPIRV_LIB}"
IMPORTED_LOCATION_DEBUG "${SPIRV_DLIB}")
set_target_properties(SPIRV-Tools PROPERTIES
IMPORTED_LOCATION "${SPIRV_TOOLS_LIB}"
IMPORTED_LOCATION_DEBUG "${SPIRV_TOOLS_DLIB}")
set_target_properties(SPIRV-Tools-opt PROPERTIES
IMPORTED_LOCATION "${SPIRV_TOOLS_OPT_LIB}"
IMPORTED_LOCATION_DEBUG "${SPIRV_TOOLS_OPT_DLIB}")
set_target_properties(SPVRemapper PROPERTIES
IMPORTED_LOCATION "${SPIRV_REMAPPER_LIB}"
IMPORTED_LOCATION_DEBUG "${SPIRV_REMAPPER_DLIB}")
set (SPIRV_TOOLS_LIBRARIES SPIRV-Tools-opt SPIRV-Tools)
set (GLSLANG_LIBRARIES glslang OGLCompiler OSDependent HLSL SPIRV SPVRemapper ${SPIRV_TOOLS_LIBRARIES})
else ()
set (SPIRV_TOOLS_LIBRARIES ${SPIRV_TOOLS_OPT_LIB} ${SPIRV_TOOLS_LIB})
set (GLSLANG_LIBRARIES ${GLSLANG_LIB} ${OGLCompiler_LIB} ${OSDependent_LIB} ${HLSL_LIB} ${SPIRV_LIB} ${SPIRV_REMAPPER_LIB} ${SPIRV_TOOLS_LIBRARIES})
endif()
set (GLMINCLUDES "${CMAKE_SOURCE_DIR}/utils")
# to run with source glslang libs/headers
if(UNIX)
add_definitions(-DVK_USE_PLATFORM_XCB_KHR)
if (EXIS
在 Windows 上,您需要通过将fopen模式标志指定为“rb”以二进制模式打开二进制 SPIR-V 文件。SPIR-V 代码是一个 32 位无符号整数序列,在 Windows 上,您需要使用“二进制”模式标志来抑制任何行尾转换。“b”标志在符合 POSIX 的系统(如 Linux)上被忽略,因此如果要在多个平台上编译,您可以将其保留在代码中。
| 归档时间: |
|
| 查看次数: |
1891 次 |
| 最近记录: |