diff --git a/presubmit.sh b/presubmit.sh index b63a4373..6c3a293e 100755 --- a/presubmit.sh +++ b/presubmit.sh @@ -40,6 +40,9 @@ if [[ ( ${JOB_ARCHITECTURE} == "" && ${JOB_ENABLE_GL} == "1" ) ]]; then BUILD_OPENGL_TEST="ON" fi +#Vulkan Headers +git clone https://github.com/KhronosGroup/Vulkan-Headers.git + # Get and build loader git clone https://github.com/KhronosGroup/OpenCL-ICD-Loader.git cd ${TOP}/OpenCL-ICD-Loader @@ -48,6 +51,16 @@ cd build cmake .. -G Ninja -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} -DOPENCL_ICD_LOADER_HEADERS_DIR=${TOP}/OpenCL-Headers/ cmake --build . -j2 --config Release +#Vulkan Loader +cd ${TOP} +git clone https://github.com/KhronosGroup/Vulkan-Loader.git +cd Vulkan-Loader +mkdir build +cd build +python3 ../scripts/update_deps.py +cmake .. -G Ninja -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} -DBUILD_WSI_XLIB_SUPPORT=OFF -DBUILD_WSI_XCB_SUPPORT=OFF -DBUILD_WSI_WAYLAND_SUPPORT=OFF -DUSE_GAS=OFF -C helper.cmake .. +cmake --build . -j2 --config Release + # Build CTS cd ${TOP} ls -l @@ -68,6 +81,9 @@ cmake .. -G Ninja \ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=./bin \ -DOPENCL_LIBRARIES="${CMAKE_OPENCL_LIBRARIES_OPTION}" \ -DUSE_CL_EXPERIMENTAL=ON \ - -DGL_IS_SUPPORTED=${BUILD_OPENGL_TEST} + -DGL_IS_SUPPORTED=${BUILD_OPENGL_TEST} \ + -DVULKAN_INCLUDE_DIR=${TOP}/Vulkan-Headers/include/ \ + -DVULKAN_LIB_DIR=${TOP}/Vulkan-Loader/build/loader/ cmake --build . -j3 --config Release + diff --git a/test_common/harness/kernelHelpers.cpp b/test_common/harness/kernelHelpers.cpp index 1d1f8d8c..13ebcbc9 100644 --- a/test_common/harness/kernelHelpers.cpp +++ b/test_common/harness/kernelHelpers.cpp @@ -1661,8 +1661,10 @@ Version get_device_latest_cl_c_version(cl_device_id device) Version max_supported_cl_c_version{}; for (const auto &name_version : name_versions) { - Version current_version{ CL_VERSION_MAJOR(name_version.version), - CL_VERSION_MINOR(name_version.version) }; + Version current_version{ + static_cast(CL_VERSION_MAJOR(name_version.version)), + static_cast(CL_VERSION_MINOR(name_version.version)) + }; max_supported_cl_c_version = (current_version > max_supported_cl_c_version) ? current_version @@ -1745,8 +1747,10 @@ bool device_supports_cl_c_version(cl_device_id device, Version version) for (const auto &name_version : name_versions) { - Version current_version{ CL_VERSION_MAJOR(name_version.version), - CL_VERSION_MINOR(name_version.version) }; + Version current_version{ + static_cast(CL_VERSION_MAJOR(name_version.version)), + static_cast(CL_VERSION_MINOR(name_version.version)) + }; if (current_version == version) { return true; diff --git a/test_conformance/CMakeLists.txt b/test_conformance/CMakeLists.txt index 363ece86..f9514f1e 100644 --- a/test_conformance/CMakeLists.txt +++ b/test_conformance/CMakeLists.txt @@ -52,6 +52,7 @@ add_subdirectory( pipes ) add_subdirectory( device_timer ) add_subdirectory( spirv_new ) add_subdirectory( spir ) +add_subdirectory( vulkan ) file(GLOB CSV_FILES "opencl_conformance_tests_*.csv") diff --git a/test_conformance/subgroups/subhelpers.h b/test_conformance/subgroups/subhelpers.h index c73027dc..12704db8 100644 --- a/test_conformance/subgroups/subhelpers.h +++ b/test_conformance/subgroups/subhelpers.h @@ -55,6 +55,7 @@ static cl_uint4 bs128_to_cl_uint4(bs128 v) struct WorkGroupParams { + WorkGroupParams(size_t gws, size_t lws, int dm_arg = -1, int cs_arg = -1) : global_workgroup_size(gws), local_workgroup_size(lws), divergence_mask_arg(dm_arg), cluster_size_arg(cs_arg) diff --git a/test_conformance/vulkan/CMakeLists.txt b/test_conformance/vulkan/CMakeLists.txt new file mode 100644 index 00000000..4f43172a --- /dev/null +++ b/test_conformance/vulkan/CMakeLists.txt @@ -0,0 +1,50 @@ +set (MODULE_NAME VULKAN) + +if(WIN32) + list(APPEND CLConform_LIBRARIES vulkan-1) +else(WIN32) + list(APPEND CLConform_LIBRARIES vulkan dl) +endif(WIN32) +set(CMAKE_CXX_FLAGS "-fpermissive") +if(WIN32) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_USE_PLATFORM_WIN32_KHR") +endif(WIN32) + +set (CLConform_VULKAN_LIBRARIES_DIR "${VULKAN_LIB_DIR}") + +link_directories(${CLConform_VULKAN_LIBRARIES_DIR}) + +list(APPEND CLConform_INCLUDE_DIR ${VULKAN_INCLUDE_DIR}) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +include_directories (${CLConform_INCLUDE_DIR}) + +set (${MODULE_NAME}_SOURCES + main.cpp + test_vulkan_interop_buffer.cpp + test_vulkan_interop_image.cpp + test_vulkan_api_consistency.cpp + test_vulkan_platform_device_info.cpp + vulkan_interop_common/vulkan_wrapper.cpp + vulkan_interop_common/vulkan_interop_common.cpp + vulkan_interop_common/opencl_vulkan_wrapper.cpp + vulkan_interop_common/vulkan_utility.cpp + vulkan_interop_common/vulkan_list_map.cpp + ../../test_common/harness/genericThread.cpp + ../../test_common/harness/errorHelpers.cpp + ../../test_common/harness/testHarness.cpp + ../../test_common/harness/kernelHelpers.cpp + ../../test_common/harness/mt19937.cpp + ../../test_common/harness/msvc9.c + ../../test_common/harness/parseParameters.cpp + ../../test_common/harness/deviceInfo.cpp + ../../test_common/harness/crc32.cpp + ) + +set_source_files_properties( + ${${MODULE_NAME}_SOURCES} + PROPERTIES LANGUAGE CXX) +include_directories("./vulkan_interop_common/") + +include(../CMakeCommon.txt) diff --git a/test_conformance/vulkan/main.cpp b/test_conformance/vulkan/main.cpp new file mode 100644 index 00000000..6cbde5cc --- /dev/null +++ b/test_conformance/vulkan/main.cpp @@ -0,0 +1,344 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include +#include + +#if !defined(__APPLE__) +#include +#else +#include +#endif + + +#include "procs.h" +#include "harness/testHarness.h" +#include "harness/parseParameters.h" +#include "harness/deviceInfo.h" + +#if !defined(_WIN32) +#include +#endif +#include +#include + +#define BUFFERSIZE 3000 + +static void params_reset() +{ + numCQ = 1; + multiImport = false; + multiCtx = false; +} + +extern int test_buffer_common(cl_device_id device_, cl_context context_, + cl_command_queue queue_, int numElements_); +extern int test_image_common(cl_device_id device_, cl_context context_, + cl_command_queue queue_, int numElements_); + +int test_buffer_single_queue(cl_device_id device_, cl_context context_, + cl_command_queue queue_, int numElements_) +{ + params_reset(); + log_info("RUNNING TEST WITH ONE QUEUE...... \n\n"); + return test_buffer_common(device_, context_, queue_, numElements_); +} +int test_buffer_multiple_queue(cl_device_id device_, cl_context context_, + cl_command_queue queue_, int numElements_) +{ + params_reset(); + numCQ = 2; + log_info("RUNNING TEST WITH TWO QUEUE...... \n\n"); + return test_buffer_common(device_, context_, queue_, numElements_); +} +int test_buffer_multiImport_sameCtx(cl_device_id device_, cl_context context_, + cl_command_queue queue_, int numElements_) +{ + params_reset(); + multiImport = true; + log_info("RUNNING TEST WITH MULTIPLE DEVICE MEMORY IMPORT " + "IN SAME CONTEXT...... \n\n"); + return test_buffer_common(device_, context_, queue_, numElements_); +} +int test_buffer_multiImport_diffCtx(cl_device_id device_, cl_context context_, + cl_command_queue queue_, int numElements_) +{ + params_reset(); + multiImport = true; + multiCtx = true; + log_info("RUNNING TEST WITH MULTIPLE DEVICE MEMORY IMPORT " + "IN DIFFERENT CONTEXT...... \n\n"); + return test_buffer_common(device_, context_, queue_, numElements_); +} +int test_image_single_queue(cl_device_id device_, cl_context context_, + cl_command_queue queue_, int numElements_) +{ + params_reset(); + log_info("RUNNING TEST WITH ONE QUEUE...... \n\n"); + return test_image_common(device_, context_, queue_, numElements_); +} +int test_image_multiple_queue(cl_device_id device_, cl_context context_, + cl_command_queue queue_, int numElements_) +{ + params_reset(); + numCQ = 2; + log_info("RUNNING TEST WITH TWO QUEUE...... \n\n"); + return test_image_common(device_, context_, queue_, numElements_); +} + +test_definition test_list[] = { ADD_TEST(buffer_single_queue), + ADD_TEST(buffer_multiple_queue), + ADD_TEST(buffer_multiImport_sameCtx), + ADD_TEST(buffer_multiImport_diffCtx), + ADD_TEST(image_single_queue), + ADD_TEST(image_multiple_queue), + ADD_TEST(consistency_external_buffer), + ADD_TEST(consistency_external_image), + ADD_TEST(consistency_external_semaphore), + ADD_TEST(platform_info), + ADD_TEST(device_info) }; + +const int test_num = ARRAY_SIZE(test_list); + +cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT; +char *choosen_platform_name = NULL; +cl_platform_id platform = NULL; +cl_int choosen_platform_index = -1; +char platform_name[1024] = ""; +cl_platform_id select_platform = NULL; +char *extensions = NULL; +size_t extensionSize = 0; +cl_uint num_devices = 0; +cl_uint device_no = 0; +cl_device_id *devices; +const size_t bufsize = BUFFERSIZE; +char buf[BUFFERSIZE]; +cl_uchar uuid[CL_UUID_SIZE_KHR]; +VulkanDevice vkDevice; +unsigned int numCQ; +bool multiImport; +bool multiCtx; +bool debug_trace = false; +bool useSingleImageKernel = false; +bool useDeviceLocal = false; +bool disableNTHandleType = false; +bool enableOffset = false; +bool non_dedicated = false; + +static void printUsage(const char *execName) +{ + const char *p = strrchr(execName, '/'); + if (p != NULL) execName = p + 1; + + log_info("Usage: %s [test_names] [options]\n", execName); + log_info("Test names:\n"); + for (int i = 0; i < test_num; i++) + { + log_info("\t%s\n", test_list[i].name); + } + log_info("\n"); + log_info("Options:\n"); + log_info("\t--debug_trace - Enables additional debug info logging\n"); + log_info("\t--non_dedicated - Choose dedicated Vs. non_dedicated \n"); +} + +size_t parseParams(int argc, const char *argv[], const char **argList) +{ + size_t argCount = 1; + for (int i = 1; i < argc; i++) + { + if (argv[i] == NULL) break; + if (argv[i][0] == '-') + { + if (!strcmp(argv[i], "--debug_trace")) + { + debug_trace = true; + } + if (!strcmp(argv[i], "--useSingleImageKernel")) + { + useSingleImageKernel = true; + } + if (!strcmp(argv[i], "--useDeviceLocal")) + { + useDeviceLocal = true; + } + if (!strcmp(argv[i], "--disableNTHandleType")) + { + disableNTHandleType = true; + } + if (!strcmp(argv[i], "--enableOffset")) + { + enableOffset = true; + } + if (!strcmp(argv[i], "--non_dedicated")) + { + non_dedicated = true; + } + if (strcmp(argv[i], "-h") == 0) + { + printUsage(argv[0]); + argCount = 0; // Returning argCount=0 to assert error in main() + break; + } + } + else + { + argList[argCount] = argv[i]; + argCount++; + } + } + return argCount; +} + +int main(int argc, const char *argv[]) +{ + int errNum = 0; + + test_start(); + params_reset(); + + if (!checkVkSupport()) + { + log_info("Vulkan supported GPU not found \n"); + return 0; + } + + cl_device_type requestedDeviceType = CL_DEVICE_TYPE_GPU; + char *force_cpu = getenv("CL_DEVICE_TYPE"); + if (force_cpu != NULL) + { + if (strcmp(force_cpu, "gpu") == 0 + || strcmp(force_cpu, "CL_DEVICE_TYPE_GPU") == 0) + requestedDeviceType = CL_DEVICE_TYPE_GPU; + else if (strcmp(force_cpu, "cpu") == 0 + || strcmp(force_cpu, "CL_DEVICE_TYPE_CPU") == 0) + requestedDeviceType = CL_DEVICE_TYPE_CPU; + else if (strcmp(force_cpu, "accelerator") == 0 + || strcmp(force_cpu, "CL_DEVICE_TYPE_ACCELERATOR") == 0) + requestedDeviceType = CL_DEVICE_TYPE_ACCELERATOR; + else if (strcmp(force_cpu, "CL_DEVICE_TYPE_DEFAULT") == 0) + requestedDeviceType = CL_DEVICE_TYPE_DEFAULT; + } + + if (requestedDeviceType != CL_DEVICE_TYPE_GPU) + { + log_info("Vulkan tests can only run on a GPU device.\n"); + return 0; + } + gDeviceType = CL_DEVICE_TYPE_GPU; + + const char **argList = (const char **)calloc(argc, sizeof(char *)); + size_t argCount = parseParams(argc, argv, argList); + if (argCount == 0) return 0; + // get the platform ID + errNum = clGetPlatformIDs(1, &platform, NULL); + if (errNum != CL_SUCCESS) + { + print_error(errNum, "Error: Failed to get platform\n"); + return errNum; + } + + errNum = + clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &num_devices); + if (CL_SUCCESS != errNum) + { + print_error(errNum, "clGetDeviceIDs failed in returning of devices\n"); + return errNum; + } + devices = (cl_device_id *)malloc(num_devices * sizeof(cl_device_id)); + if (NULL == devices) + { + print_error(errNum, "Unable to allocate memory for devices\n"); + return CL_OUT_OF_HOST_MEMORY; + } + errNum = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, num_devices, devices, + NULL); + if (CL_SUCCESS != errNum) + { + print_error(errNum, "Failed to get deviceID.\n"); + return errNum; + } + for (device_no = 0; device_no < num_devices; device_no++) + { + errNum = clGetDeviceInfo(devices[device_no], CL_DEVICE_EXTENSIONS, 0, + NULL, &extensionSize); + if (CL_SUCCESS != errNum) + { + log_error("Error in clGetDeviceInfo for getting " + "device_extension size....\n"); + return errNum; + } + extensions = (char *)malloc(extensionSize); + if (NULL == extensions) + { + log_error("Unable to allocate memory for extensions\n"); + return CL_OUT_OF_HOST_MEMORY; + } + errNum = + clGetDeviceInfo(devices[device_no], CL_DEVICE_EXTENSIONS, + extensionSize, extensions, NULL /*&extensionSize*/); + if (CL_SUCCESS != errNum) + { + print_error(errNum, + "Error in clGetDeviceInfo for getting " + "device_extension\n"); + return errNum; + } + errNum = clGetDeviceInfo(devices[device_no], CL_DEVICE_UUID_KHR, + CL_UUID_SIZE_KHR, uuid, &extensionSize); + if (CL_SUCCESS != errNum) + { + print_error(errNum, "clGetDeviceInfo failed with error\n "); + return errNum; + } + errNum = + memcmp(uuid, vkDevice.getPhysicalDevice().getUUID(), VK_UUID_SIZE); + if (errNum == 0) + { + break; + } + } + if (device_no >= num_devices) + { + fprintf(stderr, + "OpenCL error: " + "No Vulkan-OpenCL Interop capable GPU found.\n"); + } + if (!(is_extension_available(devices[device_no], "cl_khr_external_memory") + && is_extension_available(devices[device_no], + "cl_khr_external_semaphore"))) + { + log_info("Device does not support cl_khr_external_memory " + "or cl_khr_external_semaphore\n"); + log_info(" TEST SKIPPED\n"); + return CL_SUCCESS; + } + init_cl_vk_ext(platform); + + // Execute tests. + // Note: don't use the entire harness, because we have a different way of + // obtaining the device (via the context) + errNum = parseAndCallCommandLineTests(argCount, argList, devices[device_no], + test_num, test_list, true, 0, 1024); + return errNum; +} diff --git a/test_conformance/vulkan/procs.h b/test_conformance/vulkan/procs.h new file mode 100644 index 00000000..37bf7869 --- /dev/null +++ b/test_conformance/vulkan/procs.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#include "harness/mt19937.h" + +extern int test_vulkan_interop_buffer(cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements); +extern int test_vulkan_interop_image(cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements); +extern int test_consistency_external_buffer(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements); +extern int test_consistency_external_image(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements); +extern int test_consistency_external_semaphore(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements); +extern int test_platform_info(cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements); +extern int test_device_info(cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements); diff --git a/test_conformance/vulkan/test_vulkan_api_consistency.cpp b/test_conformance/vulkan/test_vulkan_api_consistency.cpp new file mode 100644 index 00000000..2987418f --- /dev/null +++ b/test_conformance/vulkan/test_vulkan_api_consistency.cpp @@ -0,0 +1,568 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#include +#include +#include +#if !defined(__APPLE__) +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include "harness/testHarness.h" +#include "harness/typeWrappers.h" +#include "harness/deviceInfo.h" + +int test_consistency_external_buffer(cl_device_id deviceID, cl_context _context, + cl_command_queue _queue, int num_elements) +{ + cl_int errNum; + VulkanDevice vkDevice; + // Context and command queue creation + cl_platform_id platform = NULL; + cl_context context = NULL; + cl_command_queue cmd_queue = NULL; + + cl_context_properties contextProperties[] = { CL_CONTEXT_PLATFORM, 0, 0 }; + errNum = clGetPlatformIDs(1, &platform, NULL); + test_error(errNum, "Failed to get platform Id"); + + contextProperties[1] = (cl_context_properties)platform; + + context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU, + NULL, NULL, &errNum); + test_error(errNum, "Unable to create context with properties"); + + cmd_queue = clCreateCommandQueue(context, deviceID, 0, &errNum); + test_error(errNum, "Unable to create command queue"); + + uint32_t bufferSize = 32; + cl_device_id devList[] = { deviceID, NULL }; + +#ifdef _WIN32 + if (!is_extension_available(devList[0], "cl_khr_external_memory_win32")) + { + throw std::runtime_error("Device does not support " + "cl_khr_external_memory_win32 extension \n"); + } +#else + if (!is_extension_available(devList[0], "cl_khr_external_memory_opaque_fd")) + { + throw std::runtime_error( + "Device does not support " + "cl_khr_external_memory_opaque_fd extension \n"); + } +#endif + + VulkanExternalMemoryHandleType vkExternalMemoryHandleType = + getSupportedVulkanExternalMemoryHandleTypeList()[0]; + + VulkanBuffer vkDummyBuffer(vkDevice, 4 * 1024, vkExternalMemoryHandleType); + const VulkanMemoryTypeList& memoryTypeList = + vkDummyBuffer.getMemoryTypeList(); + + VulkanDeviceMemory* vkDeviceMem = new VulkanDeviceMemory( + vkDevice, bufferSize, memoryTypeList[0], vkExternalMemoryHandleType); + VulkanBufferList vkBufferList(1, vkDevice, bufferSize, + vkExternalMemoryHandleType); + + vkDeviceMem->bindBuffer(vkBufferList[0], 0); + + void* handle = NULL; + int fd; + + std::vector extMemProperties{ + (cl_mem_properties)CL_DEVICE_HANDLE_LIST_KHR, + (cl_mem_properties)devList[0], + (cl_mem_properties)CL_DEVICE_HANDLE_LIST_END_KHR, + }; + cl_external_memory_handle_type_khr type; + switch (vkExternalMemoryHandleType) + { +#ifdef _WIN32 + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT: + handle = vkDeviceMem->getHandle(vkExternalMemoryHandleType); + type = CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR; + errNum = check_external_memory_handle_type(devList[0], type); + extMemProperties.push_back((cl_mem_properties)type); + extMemProperties.push_back((cl_mem_properties)handle); + break; + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT: + handle = vkDeviceMem->getHandle(vkExternalMemoryHandleType); + type = CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR; + errNum = check_external_memory_handle_type(devList[0], type); + extMemProperties.push_back((cl_mem_properties)type); + extMemProperties.push_back((cl_mem_properties)handle); + break; +#else + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD: + fd = (int)vkDeviceMem->getHandle(vkExternalMemoryHandleType); + type = CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR; + errNum = check_external_memory_handle_type(devList[0], type); + extMemProperties.push_back((cl_mem_properties)type); + extMemProperties.push_back((cl_mem_properties)fd); + break; +#endif + default: + errNum = TEST_FAIL; + log_error("Unsupported external memory handle type \n"); + break; + } + if (errNum != CL_SUCCESS) + { + log_error("Checks failed for " + "CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR\n"); + return TEST_FAIL; + } + extMemProperties.push_back(0); + + clMemWrapper buffer; + + // Passing NULL properties and a valid extMem_desc size + buffer = clCreateBufferWithProperties(context, NULL, 1, bufferSize, NULL, + &errNum); + test_error(errNum, "Unable to create buffer with NULL properties"); + + buffer.reset(); + + // Passing valid extMemProperties and buffersize + buffer = clCreateBufferWithProperties(context, extMemProperties.data(), 1, + bufferSize, NULL, &errNum); + test_error(errNum, "Unable to create buffer with Properties"); + + buffer.reset(); + + // Not passing external memory handle + std::vector extMemProperties2{ +#ifdef _WIN32 + (cl_mem_properties)type, + NULL, // Passing NULL handle +#else + (cl_mem_properties)type, + (cl_mem_properties)-64, // Passing random invalid fd +#endif + (cl_mem_properties)CL_DEVICE_HANDLE_LIST_KHR, + (cl_mem_properties)devList[0], + (cl_mem_properties)CL_DEVICE_HANDLE_LIST_END_KHR, + 0 + }; + buffer = clCreateBufferWithProperties(context, extMemProperties2.data(), 1, + bufferSize, NULL, &errNum); + test_failure_error(errNum, CL_INVALID_VALUE, + "Should return CL_INVALID_VALUE "); + + buffer.reset(); + + // Passing extMem_desc size = 0 but valid memProperties, CL_INVALID_SIZE + // should be returned. + buffer = clCreateBufferWithProperties(context, extMemProperties.data(), 1, + 0, NULL, &errNum); + test_failure_error(errNum, CL_INVALID_BUFFER_SIZE, + "Should return CL_INVALID_BUFFER_SIZE"); + + return TEST_PASS; +} + +int test_consistency_external_image(cl_device_id deviceID, cl_context _context, + cl_command_queue _queue, int num_elements) +{ + cl_int errNum; + VulkanDevice vkDevice; + + // Context and command queue creation + cl_platform_id platform = NULL; + cl_context context = NULL; + cl_command_queue cmd_queue = NULL; + + cl_context_properties contextProperties[] = { CL_CONTEXT_PLATFORM, 0, 0 }; + errNum = clGetPlatformIDs(1, &platform, NULL); + test_error(errNum, "Failed to get platform id"); + + contextProperties[1] = (cl_context_properties)platform; + + context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU, + NULL, NULL, &errNum); + test_error(errNum, "Unable to create context with properties"); + + cmd_queue = clCreateCommandQueue(context, deviceID, 0, &errNum); + test_error(errNum, "Unable to create command queue"); + + cl_device_id devList[] = { deviceID, NULL }; + +#ifdef _WIN32 + if (!is_extension_available(devList[0], "cl_khr_external_memory_win32")) + { + throw std::runtime_error("Device does not support" + "cl_khr_external_memory_win32 extension \n"); + } +#else + if (!is_extension_available(devList[0], "cl_khr_external_memory_opaque_fd")) + { + throw std::runtime_error( + "Device does not support cl_khr_external_memory_opaque_fd " + "extension \n"); + } +#endif + uint32_t width = 256; + uint32_t height = 16; + cl_image_desc image_desc; + memset(&image_desc, 0x0, sizeof(cl_image_desc)); + cl_image_format img_format = { 0 }; + + VulkanExternalMemoryHandleType vkExternalMemoryHandleType = + getSupportedVulkanExternalMemoryHandleTypeList()[0]; + VulkanImage2D* vkImage2D = + new VulkanImage2D(vkDevice, VULKAN_FORMAT_R8G8B8A8_UNORM, width, height, + 1, vkExternalMemoryHandleType); + + const VulkanMemoryTypeList& memoryTypeList = vkImage2D->getMemoryTypeList(); + uint64_t totalImageMemSize = vkImage2D->getSize(); + + log_info("Memory type index: %d\n", (uint32_t)memoryTypeList[0]); + log_info("Memory type property: %d\n", + memoryTypeList[0].getMemoryTypeProperty()); + log_info("Image size : %d\n", totalImageMemSize); + + VulkanDeviceMemory* vkDeviceMem = + new VulkanDeviceMemory(vkDevice, totalImageMemSize, memoryTypeList[0], + vkExternalMemoryHandleType); + vkDeviceMem->bindImage(*vkImage2D, 0); + + void* handle = NULL; + int fd; + std::vector extMemProperties{ + (cl_mem_properties)CL_DEVICE_HANDLE_LIST_KHR, + (cl_mem_properties)devList[0], + (cl_mem_properties)CL_DEVICE_HANDLE_LIST_END_KHR, + }; + switch (vkExternalMemoryHandleType) + { +#ifdef _WIN32 + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT: + handle = vkDeviceMem->getHandle(vkExternalMemoryHandleType); + errNum = check_external_memory_handle_type( + devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR); + extMemProperties.push_back( + (cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR); + extMemProperties.push_back((cl_mem_properties)handle); + break; + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT: + handle = vkDeviceMem->getHandle(vkExternalMemoryHandleType); + errNum = check_external_memory_handle_type( + devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR); + extMemProperties.push_back( + (cl_mem_properties) + CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR); + extMemProperties.push_back((cl_mem_properties)handle); + break; +#else + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD: + fd = (int)vkDeviceMem->getHandle(vkExternalMemoryHandleType); + errNum = check_external_memory_handle_type( + devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR); + extMemProperties.push_back( + (cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR); + extMemProperties.push_back((cl_mem_properties)fd); + break; +#endif + default: + errNum = TEST_FAIL; + log_error("Unsupported external memory handle type \n"); + break; + } + if (errNum != CL_SUCCESS) + { + log_error("Checks failed for " + "CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR\n"); + return TEST_FAIL; + } + extMemProperties.push_back(0); + + const VkImageCreateInfo VulkanImageCreateInfo = + vkImage2D->getVkImageCreateInfo(); + + errNum = getCLImageInfoFromVkImageInfo( + &VulkanImageCreateInfo, totalImageMemSize, &img_format, &image_desc); + if (errNum != CL_SUCCESS) + { + log_error("getCLImageInfoFromVkImageInfo failed!!!"); + return TEST_FAIL; + } + + clMemWrapper image; + + // Pass valid properties, image_desc and image_format + image = clCreateImageWithProperties( + context, extMemProperties.data(), CL_MEM_READ_WRITE, &img_format, + &image_desc, NULL /* host_ptr */, &errNum); + test_error(errNum, "Unable to create Image with Properties"); + image.reset(); + + // Passing properties, image_desc and image_format all as NULL + image = clCreateImageWithProperties(context, NULL, CL_MEM_READ_WRITE, NULL, + NULL, NULL, &errNum); + test_failure_error( + errNum, CL_INVALID_IMAGE_DESCRIPTOR, + "Image creation must fail with CL_INVALID_IMAGE_DESCRIPTOR " + "when all are passed as NULL"); + + image.reset(); + + // Passing NULL properties and a valid image_format and image_desc + image = + clCreateImageWithProperties(context, NULL, CL_MEM_READ_WRITE, + &img_format, &image_desc, NULL, &errNum); + test_error(errNum, + "Unable to create image with NULL properties " + "with valid image format and image desc"); + + image.reset(); + + // Passing image_format as NULL + image = clCreateImageWithProperties(context, extMemProperties.data(), + CL_MEM_READ_WRITE, NULL, &image_desc, + NULL, &errNum); + test_failure_error(errNum, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, + "Image creation must fail with " + "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" + "when image desc passed as NULL"); + + image.reset(); + + // Passing image_desc as NULL + image = clCreateImageWithProperties(context, extMemProperties.data(), + CL_MEM_READ_WRITE, &img_format, NULL, + NULL, &errNum); + test_failure_error(errNum, CL_INVALID_IMAGE_DESCRIPTOR, + "Image creation must fail with " + "CL_INVALID_IMAGE_DESCRIPTOR " + "when image desc passed as NULL"); + image.reset(); + + return TEST_PASS; +} + +int test_consistency_external_semaphore(cl_device_id deviceID, + cl_context _context, + cl_command_queue _queue, + int num_elements) +{ + cl_int errNum; + VulkanDevice vkDevice; + // Context and command queue creation + cl_platform_id platform = NULL; + cl_context context = NULL; + cl_command_queue cmd_queue = NULL; + + errNum = clGetPlatformIDs(1, &platform, NULL); + test_error(errNum, "Failed to get platform Id"); + + cl_context_properties contextProperties[] = { CL_CONTEXT_PLATFORM, 0, 0 }; + + contextProperties[1] = (cl_context_properties)platform; + + context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU, + NULL, NULL, &errNum); + test_error(errNum, "Unable to create context with properties"); + + cmd_queue = clCreateCommandQueue(context, deviceID, 0, &errNum); + test_error(errNum, "Unable to create command queue"); + + cl_device_id devList[] = { deviceID, NULL }; + +#ifdef _WIN32 + if (!is_extension_available(devList[0], "cl_khr_external_semaphore_win32")) + { + throw std::runtime_error( + "Device does not support cl_khr_external_semaphore_win32 " + "extension \n"); + } +#else + if (!is_extension_available(devList[0], + "cl_khr_external_semaphore_opaque_fd")) + { + throw std::runtime_error( + "Device does not support " + "cl_khr_external_semaphore_opaque_fd extension \n"); + } +#endif + VulkanExternalSemaphoreHandleType vkExternalSemaphoreHandleType = + getSupportedVulkanExternalSemaphoreHandleTypeList()[0]; + VulkanSemaphore vkVk2Clsemaphore(vkDevice, vkExternalSemaphoreHandleType); + VulkanSemaphore vkCl2Vksemaphore(vkDevice, vkExternalSemaphoreHandleType); + cl_semaphore_khr clCl2Vksemaphore; + cl_semaphore_khr clVk2Clsemaphore; + + void* handle1 = NULL; + void* handle2 = NULL; + int fd1, fd2; + std::vector sema_props1{ + (cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_KHR, + (cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_BINARY_KHR, + }; + std::vector sema_props2{ + (cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_KHR, + (cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_BINARY_KHR, + }; + switch (vkExternalSemaphoreHandleType) + { +#ifdef _WIN32 + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT: + log_info(" Opaque NT handles are only supported on Windows\n"); + handle1 = vkVk2Clsemaphore.getHandle(vkExternalSemaphoreHandleType); + handle2 = vkCl2Vksemaphore.getHandle(vkExternalSemaphoreHandleType); + errNum = check_external_semaphore_handle_type( + devList[0], CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KHR); + sema_props1.push_back((cl_semaphore_properties_khr) + CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KHR); + sema_props1.push_back((cl_semaphore_properties_khr)handle1); + sema_props2.push_back((cl_semaphore_properties_khr) + CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KHR); + sema_props2.push_back((cl_semaphore_properties_khr)handle2); + break; + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT: + log_info(" Opaque D3DKMT handles are only supported on Windows\n"); + handle1 = vkVk2Clsemaphore.getHandle(vkExternalSemaphoreHandleType); + handle2 = vkCl2Vksemaphore.getHandle(vkExternalSemaphoreHandleType); + errNum = check_external_semaphore_handle_type( + devList[0], CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KMT_KHR); + sema_props1.push_back((cl_semaphore_properties_khr) + CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KMT_KHR); + sema_props1.push_back((cl_semaphore_properties_khr)handle1); + sema_props2.push_back((cl_semaphore_properties_khr) + CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KMT_KHR); + sema_props2.push_back((cl_semaphore_properties_khr)handle2); + break; +#else + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD: + log_info(" Opaque file descriptors are not supported on Windows\n"); + fd1 = + (int)vkVk2Clsemaphore.getHandle(vkExternalSemaphoreHandleType); + fd2 = + (int)vkCl2Vksemaphore.getHandle(vkExternalSemaphoreHandleType); + errNum = check_external_semaphore_handle_type( + devList[0], CL_SEMAPHORE_HANDLE_OPAQUE_FD_KHR); + sema_props1.push_back( + (cl_semaphore_properties_khr)CL_SEMAPHORE_HANDLE_OPAQUE_FD_KHR); + sema_props1.push_back((cl_semaphore_properties_khr)fd1); + sema_props2.push_back( + (cl_semaphore_properties_khr)CL_SEMAPHORE_HANDLE_OPAQUE_FD_KHR); + sema_props2.push_back((cl_semaphore_properties_khr)fd2); + break; +#endif + default: log_error("Unsupported external memory handle type\n"); break; + } + if (CL_SUCCESS != errNum) + { + throw std::runtime_error( + "Unsupported external sempahore handle type\n "); + } + sema_props1.push_back( + (cl_semaphore_properties_khr)CL_DEVICE_HANDLE_LIST_KHR); + sema_props1.push_back((cl_semaphore_properties_khr)devList[0]); + sema_props1.push_back( + (cl_semaphore_properties_khr)CL_DEVICE_HANDLE_LIST_END_KHR); + sema_props2.push_back( + (cl_semaphore_properties_khr)CL_DEVICE_HANDLE_LIST_KHR); + sema_props2.push_back((cl_semaphore_properties_khr)devList[0]); + sema_props2.push_back( + (cl_semaphore_properties_khr)CL_DEVICE_HANDLE_LIST_END_KHR); + sema_props1.push_back(0); + sema_props2.push_back(0); + + // Pass NULL properties + cl_semaphore_khr cl_ext_semaphore = + clCreateSemaphoreWithPropertiesKHRptr(context, NULL, &errNum); + test_failure_error(errNum, CL_INVALID_VALUE, + "Semaphore creation must fail with CL_INVALID_VALUE " + " when properties are passed as NULL"); + + + // Pass invalid semaphore object to wait + errNum = + clEnqueueWaitSemaphoresKHRptr(cmd_queue, 1, NULL, NULL, 0, NULL, NULL); + test_failure_error(errNum, CL_INVALID_VALUE, + "clEnqueueWaitSemaphoresKHR fails with CL_INVALID_VALUE " + "when invalid semaphore object is passed"); + + + // Pass invalid semaphore object to signal + errNum = clEnqueueSignalSemaphoresKHRptr(cmd_queue, 1, NULL, NULL, 0, NULL, + NULL); + test_failure_error( + errNum, CL_INVALID_VALUE, + "clEnqueueSignalSemaphoresKHR fails with CL_INVALID_VALUE" + "when invalid semaphore object is passed"); + + + // Create two semaphore objects + clVk2Clsemaphore = clCreateSemaphoreWithPropertiesKHRptr( + context, sema_props1.data(), &errNum); + test_error(errNum, + "Unable to create semaphore with valid semaphore properties"); + + clCl2Vksemaphore = clCreateSemaphoreWithPropertiesKHRptr( + context, sema_props2.data(), &errNum); + test_error(errNum, + "Unable to create semaphore with valid semaphore properties"); + + + // Call Signal twice consecutively + errNum = clEnqueueSignalSemaphoresKHRptr(cmd_queue, 1, &clVk2Clsemaphore, + NULL, 0, NULL, NULL); + test_error(errNum, "clEnqueueSignalSemaphoresKHRptr failed"); + + errNum = clEnqueueSignalSemaphoresKHRptr(cmd_queue, 1, &clCl2Vksemaphore, + NULL, 0, NULL, NULL); + test_error(errNum, + "clEnqueueSignalSemaphoresKHRptr failed for two " + "consecutive wait events"); + + + // Call Wait twice consecutively + errNum = clEnqueueWaitSemaphoresKHRptr(cmd_queue, 1, &clVk2Clsemaphore, + NULL, 0, NULL, NULL); + test_error(errNum, "clEnqueueWaitSemaphoresKHRptr failed"); + + errNum = clEnqueueWaitSemaphoresKHRptr(cmd_queue, 1, &clCl2Vksemaphore, + NULL, 0, NULL, NULL); + test_error(errNum, + "clEnqueueWaitSemaphoresKHRptr failed for two " + " consecutive wait events"); + + + // Pass invalid object to release call + errNum = clReleaseSemaphoreObjectKHRptr(NULL); + test_failure_error(errNum, CL_INVALID_VALUE, + "clReleaseSemaphoreObjectKHRptr fails with " + "CL_INVALID_VALUE when NULL semaphore object is passed"); + + // Release both semaphore objects + errNum = clReleaseSemaphoreObjectKHRptr(clVk2Clsemaphore); + test_error(errNum, "clReleaseSemaphoreObjectKHRptr failed"); + + errNum = clReleaseSemaphoreObjectKHRptr(clCl2Vksemaphore); + test_error(errNum, "clReleaseSemaphoreObjectKHRptr failed"); + + return TEST_PASS; +} diff --git a/test_conformance/vulkan/test_vulkan_interop_buffer.cpp b/test_conformance/vulkan/test_vulkan_interop_buffer.cpp new file mode 100644 index 00000000..7daf96de --- /dev/null +++ b/test_conformance/vulkan/test_vulkan_interop_buffer.cpp @@ -0,0 +1,1808 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include "harness/errorHelpers.h" + +#define MAX_BUFFERS 5 +#define MAX_IMPORTS 5 +#define BUFFERSIZE 3000 +static cl_uchar uuid[CL_UUID_SIZE_KHR]; +static cl_device_id deviceId = NULL; + +namespace { +struct Params +{ + uint32_t numBuffers; + uint32_t bufferSize; + uint32_t interBufferOffset; +}; +} + +static const char *vkBufferShader = + "#version 450\n" + "#extension GL_ARB_separate_shader_objects : enable\n" + "#extension GL_NV_gpu_shader5 : enable\n" + "layout(binding = 0) buffer Params\n" + "{\n" + " uint32_t numBuffers;\n" + " uint32_t bufferSize;\n" + " uint32_t interBufferOffset;\n" + "};\n" + "layout(binding = 1) buffer Buffer\n" + "{\n" + " uint8_t ptr[];\n" + "} bufferPtrList[" STRING( + MAX_BUFFERS) "];\n" + "layout(local_size_x = 512) in;\n" + "void main() {\n" + " for (uint32_t bufIdx = 0; bufIdx < numBuffers;" + " bufIdx++) {\n" + " uint32_t ptrIdx = gl_GlobalInvocationID.x;\n" + " uint32_t limit = bufferSize;\n" + " while (ptrIdx < limit) {\n" + " bufferPtrList[bufIdx].ptr[ptrIdx]++;\n" + " ptrIdx += (gl_NumWorkGroups.x * " + "gl_WorkGroupSize.x);\n" + " }\n" + " }\n" + "}\n"; + +const char *kernel_text_numbuffer_1 = " \ +__kernel void clUpdateBuffer(int bufferSize, __global unsigned char *a) { \n\ + int gid = get_global_id(0); \n\ + if (gid < bufferSize) { \n\ + a[gid]++; \n\ + } \n\ +}"; + +const char *kernel_text_numbuffer_2 = " \ +__kernel void clUpdateBuffer(int bufferSize, __global unsigned char *a, __global unsigned char *b) { \n\ + int gid = get_global_id(0); \n\ + if (gid < bufferSize) { \n\ + a[gid]++; \n\ + b[gid]++;\n\ + } \n\ +}"; + +const char *kernel_text_numbuffer_4 = " \ +__kernel void clUpdateBuffer(int bufferSize, __global unsigned char *a, __global unsigned char *b, __global unsigned char *c, __global unsigned char *d) { \n\ + int gid = get_global_id(0); \n\ + if (gid < bufferSize) { \n\ + a[gid]++;\n\ + b[gid]++; \n\ + c[gid]++; \n\ + d[gid]++; \n\ + } \n\ +}"; + + +const char *kernel_text_verify = " \ +__kernel void checkKernel(__global unsigned char *ptr, int size, int expVal, __global unsigned char *err) \n\ +{ \n\ + int idx = get_global_id(0); \n\ + if ((idx < size) && (*err == 0)) { \n\ + if (ptr[idx] != expVal){ \n\ + *err = 1; \n\ + } \n\ + } \n\ +}"; + +int run_test_with_two_queue(cl_context &context, cl_command_queue &cmd_queue1, + cl_command_queue &cmd_queue2, cl_kernel *kernel, + cl_kernel &verify_kernel, VulkanDevice &vkDevice, + uint32_t numBuffers, uint32_t bufferSize) +{ + int err = CL_SUCCESS; + size_t global_work_size[1]; + uint8_t *error_2; + cl_mem error_1; + cl_kernel update_buffer_kernel; + cl_kernel kernel_cq; + clExternalSemaphore *clVk2CLExternalSemaphore = NULL; + clExternalSemaphore *clCl2VkExternalSemaphore = NULL; + const char *program_source_const = kernel_text_numbuffer_2; + size_t program_source_length = strlen(program_source_const); + cl_program program = clCreateProgramWithSource( + context, 1, &program_source_const, &program_source_length, &err); + err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL); + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed to build program \n"); + return err; + } + // create the kernel + kernel_cq = clCreateKernel(program, "clUpdateBuffer", &err); + if (err != CL_SUCCESS) + { + print_error(err, "clCreateKernel failed \n"); + return err; + } + + const std::vector + vkExternalMemoryHandleTypeList = + getSupportedVulkanExternalMemoryHandleTypeList(); + VulkanExternalSemaphoreHandleType vkExternalSemaphoreHandleType = + getSupportedVulkanExternalSemaphoreHandleTypeList()[0]; + VulkanSemaphore vkVk2CLSemaphore(vkDevice, vkExternalSemaphoreHandleType); + VulkanSemaphore vkCl2VkSemaphore(vkDevice, vkExternalSemaphoreHandleType); + + VulkanQueue &vkQueue = vkDevice.getQueue(); + + VulkanShaderModule vkBufferShaderModule(vkDevice, vkBufferShader); + VulkanDescriptorSetLayoutBindingList vkDescriptorSetLayoutBindingList( + MAX_BUFFERS + 1, VULKAN_DESCRIPTOR_TYPE_STORAGE_BUFFER); + VulkanDescriptorSetLayout vkDescriptorSetLayout( + vkDevice, vkDescriptorSetLayoutBindingList); + VulkanPipelineLayout vkPipelineLayout(vkDevice, vkDescriptorSetLayout); + VulkanComputePipeline vkComputePipeline(vkDevice, vkPipelineLayout, + vkBufferShaderModule); + + VulkanDescriptorPool vkDescriptorPool(vkDevice, + vkDescriptorSetLayoutBindingList); + VulkanDescriptorSet vkDescriptorSet(vkDevice, vkDescriptorPool, + vkDescriptorSetLayout); + + clVk2CLExternalSemaphore = new clExternalSemaphore( + vkVk2CLSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + clCl2VkExternalSemaphore = new clExternalSemaphore( + vkCl2VkSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + + const uint32_t maxIter = innerIterations; + VulkanCommandPool vkCommandPool(vkDevice); + VulkanCommandBuffer vkCommandBuffer(vkDevice, vkCommandPool); + + VulkanBuffer vkParamsBuffer(vkDevice, sizeof(Params)); + VulkanDeviceMemory vkParamsDeviceMemory( + vkDevice, vkParamsBuffer.getSize(), + getVulkanMemoryType(vkDevice, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_COHERENT)); + vkParamsDeviceMemory.bindBuffer(vkParamsBuffer); + std::vector vkBufferListDeviceMemory; + std::vector externalMemory; + for (size_t emhtIdx = 0; emhtIdx < vkExternalMemoryHandleTypeList.size(); + emhtIdx++) + { + VulkanExternalMemoryHandleType vkExternalMemoryHandleType = + vkExternalMemoryHandleTypeList[emhtIdx]; + log_info("External memory handle type: %d\n", + vkExternalMemoryHandleType); + + VulkanBuffer vkDummyBuffer(vkDevice, 4 * 1024, + vkExternalMemoryHandleType); + const VulkanMemoryTypeList &memoryTypeList = + vkDummyBuffer.getMemoryTypeList(); + + for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++) + { + const VulkanMemoryType &memoryType = memoryTypeList[mtIdx]; + + log_info("Memory type index: %d\n", (uint32_t)memoryType); + log_info("Memory type property: %d\n", + memoryType.getMemoryTypeProperty()); + + VulkanBufferList vkBufferList(numBuffers, vkDevice, bufferSize, + vkExternalMemoryHandleType); + + for (size_t bIdx = 0; bIdx < numBuffers; bIdx++) + { + vkBufferListDeviceMemory.push_back( + new VulkanDeviceMemory(vkDevice, bufferSize, memoryType, + vkExternalMemoryHandleType)); + externalMemory.push_back(new clExternalMemory( + vkBufferListDeviceMemory[bIdx], vkExternalMemoryHandleType, + 0, bufferSize, context, deviceId)); + } + cl_mem buffers[MAX_BUFFERS]; + clFinish(cmd_queue1); + Params *params = (Params *)vkParamsDeviceMemory.map(); + params->numBuffers = numBuffers; + params->bufferSize = bufferSize; + params->interBufferOffset = 0; + vkParamsDeviceMemory.unmap(); + vkDescriptorSet.update(0, vkParamsBuffer); + for (size_t bIdx = 0; bIdx < vkBufferList.size(); bIdx++) + { + size_t buffer_size = vkBufferList[bIdx].getSize(); + vkBufferListDeviceMemory[bIdx]->bindBuffer(vkBufferList[bIdx], + 0); + buffers[bIdx] = externalMemory[bIdx]->getExternalMemoryBuffer(); + vkDescriptorSet.update((uint32_t)bIdx + 1, vkBufferList[bIdx]); + } + vkCommandBuffer.begin(); + vkCommandBuffer.bindPipeline(vkComputePipeline); + vkCommandBuffer.bindDescriptorSets( + vkComputePipeline, vkPipelineLayout, vkDescriptorSet); + vkCommandBuffer.dispatch(512, 1, 1); + vkCommandBuffer.end(); + + if (vkBufferList.size() == 2) + { + update_buffer_kernel = kernel[0]; + } + else if (vkBufferList.size() == 3) + { + update_buffer_kernel = kernel[1]; + } + else if (vkBufferList.size() == 5) + { + update_buffer_kernel = kernel[2]; + } + // global work size should be less than or equal to + // bufferSizeList[i] + global_work_size[0] = bufferSize; + for (uint32_t iter = 0; iter < maxIter; iter++) + { + + if (iter == 0) + { + vkQueue.submit(vkCommandBuffer, vkVk2CLSemaphore); + } + else + { + vkQueue.submit(vkCl2VkSemaphore, vkCommandBuffer, + vkVk2CLSemaphore); + } + clVk2CLExternalSemaphore->wait(cmd_queue1); + + err = clSetKernelArg(update_buffer_kernel, 0, sizeof(uint32_t), + (void *)&bufferSize); + err |= clSetKernelArg(kernel_cq, 0, sizeof(uint32_t), + (void *)&bufferSize); + err |= clSetKernelArg(kernel_cq, 1, sizeof(cl_mem), + (void *)&(buffers[0])); + + for (int i = 0; i < vkBufferList.size() - 1; i++) + { + err |= + clSetKernelArg(update_buffer_kernel, i + 1, + sizeof(cl_mem), (void *)&(buffers[i])); + } + + err |= + clSetKernelArg(kernel_cq, 2, sizeof(cl_mem), + (void *)&(buffers[vkBufferList.size() - 1])); + + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to set arg values for kernel\n"); + goto CLEANUP; + } + cl_event first_launch; + + err = clEnqueueNDRangeKernel(cmd_queue1, update_buffer_kernel, + 1, NULL, global_work_size, NULL, 0, + NULL, &first_launch); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to launch update_buffer_kernel," + "error\n"); + goto CLEANUP; + } + + err = clEnqueueNDRangeKernel(cmd_queue2, kernel_cq, 1, NULL, + global_work_size, NULL, 1, + &first_launch, NULL); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to launch update_buffer_kernel," + "error\n"); + goto CLEANUP; + } + + if (iter != (maxIter - 1)) + { + clCl2VkExternalSemaphore->signal(cmd_queue2); + } + } + error_2 = (uint8_t *)malloc(sizeof(uint8_t)); + if (NULL == error_2) + { + log_error("Not able to allocate memory\n"); + goto CLEANUP; + } + clFinish(cmd_queue2); + error_1 = clCreateBuffer(context, CL_MEM_WRITE_ONLY, + sizeof(uint8_t), NULL, &err); + if (CL_SUCCESS != err) + { + print_error(err, "Error: clCreateBuffer \n"); + goto CLEANUP; + } + uint8_t val = 0; + err = clEnqueueWriteBuffer(cmd_queue1, error_1, CL_TRUE, 0, + sizeof(uint8_t), &val, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed read output, error\n"); + goto CLEANUP; + } + + int calc_max_iter; + for (int i = 0; i < vkBufferList.size(); i++) + { + if (i == 0) + calc_max_iter = (maxIter * 3); + else + calc_max_iter = (maxIter * 2); + err = clSetKernelArg(verify_kernel, 0, sizeof(cl_mem), + (void *)&(buffers[i])); + err |= + clSetKernelArg(verify_kernel, 1, sizeof(int), &bufferSize); + err |= clSetKernelArg(verify_kernel, 2, sizeof(int), + &calc_max_iter); + err |= clSetKernelArg(verify_kernel, 3, sizeof(cl_mem), + (void *)&error_1); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to set arg values for " + "verify_kernel \n"); + goto CLEANUP; + } + err = clEnqueueNDRangeKernel(cmd_queue1, verify_kernel, 1, NULL, + global_work_size, NULL, 0, NULL, + NULL); + + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to launch verify_kernel," + "error \n"); + goto CLEANUP; + } + err = clEnqueueReadBuffer(cmd_queue1, error_1, CL_TRUE, 0, + sizeof(uint8_t), error_2, 0, NULL, + NULL); + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed read output, error \n "); + goto CLEANUP; + } + if (*error_2 == 1) + { + log_error("&&&& vulkan_opencl_buffer test FAILED\n"); + goto CLEANUP; + } + } + for (size_t i = 0; i < vkBufferList.size(); i++) + { + delete vkBufferListDeviceMemory[i]; + delete externalMemory[i]; + } + vkBufferListDeviceMemory.erase(vkBufferListDeviceMemory.begin(), + vkBufferListDeviceMemory.begin() + + numBuffers); + externalMemory.erase(externalMemory.begin(), + externalMemory.begin() + numBuffers); + } + } +CLEANUP: + for (size_t i = 0; i < vkBufferListDeviceMemory.size(); i++) + { + if (vkBufferListDeviceMemory[i]) + { + delete vkBufferListDeviceMemory[i]; + } + if (externalMemory[i]) + { + delete externalMemory[i]; + } + } + if (program) clReleaseProgram(program); + if (kernel_cq) clReleaseKernel(kernel_cq); + if (clVk2CLExternalSemaphore) delete clVk2CLExternalSemaphore; + if (clCl2VkExternalSemaphore) delete clCl2VkExternalSemaphore; + if (error_2) free(error_2); + if (error_1) clReleaseMemObject(error_1); + + return err; +} + +int run_test_with_one_queue(cl_context &context, cl_command_queue &cmd_queue1, + cl_kernel *kernel, cl_kernel &verify_kernel, + VulkanDevice &vkDevice, uint32_t numBuffers, + uint32_t bufferSize) +{ + log_info("RUNNING TEST WITH ONE QUEUE...... \n\n"); + size_t global_work_size[1]; + uint8_t *error_2; + cl_mem error_1; + cl_kernel update_buffer_kernel; + clExternalSemaphore *clVk2CLExternalSemaphore = NULL; + clExternalSemaphore *clCl2VkExternalSemaphore = NULL; + int err = CL_SUCCESS; + + const std::vector + vkExternalMemoryHandleTypeList = + getSupportedVulkanExternalMemoryHandleTypeList(); + VulkanExternalSemaphoreHandleType vkExternalSemaphoreHandleType = + getSupportedVulkanExternalSemaphoreHandleTypeList()[0]; + VulkanSemaphore vkVk2CLSemaphore(vkDevice, vkExternalSemaphoreHandleType); + VulkanSemaphore vkCl2VkSemaphore(vkDevice, vkExternalSemaphoreHandleType); + + VulkanQueue &vkQueue = vkDevice.getQueue(); + + VulkanShaderModule vkBufferShaderModule(vkDevice, vkBufferShader); + VulkanDescriptorSetLayoutBindingList vkDescriptorSetLayoutBindingList( + MAX_BUFFERS + 1, VULKAN_DESCRIPTOR_TYPE_STORAGE_BUFFER); + VulkanDescriptorSetLayout vkDescriptorSetLayout( + vkDevice, vkDescriptorSetLayoutBindingList); + VulkanPipelineLayout vkPipelineLayout(vkDevice, vkDescriptorSetLayout); + VulkanComputePipeline vkComputePipeline(vkDevice, vkPipelineLayout, + vkBufferShaderModule); + + VulkanDescriptorPool vkDescriptorPool(vkDevice, + vkDescriptorSetLayoutBindingList); + VulkanDescriptorSet vkDescriptorSet(vkDevice, vkDescriptorPool, + vkDescriptorSetLayout); + + clVk2CLExternalSemaphore = new clExternalSemaphore( + vkVk2CLSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + clCl2VkExternalSemaphore = new clExternalSemaphore( + vkCl2VkSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + const uint32_t maxIter = innerIterations; + VulkanCommandPool vkCommandPool(vkDevice); + VulkanCommandBuffer vkCommandBuffer(vkDevice, vkCommandPool); + + VulkanBuffer vkParamsBuffer(vkDevice, sizeof(Params)); + VulkanDeviceMemory vkParamsDeviceMemory( + vkDevice, vkParamsBuffer.getSize(), + getVulkanMemoryType(vkDevice, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_COHERENT)); + vkParamsDeviceMemory.bindBuffer(vkParamsBuffer); + std::vector vkBufferListDeviceMemory; + std::vector externalMemory; + + for (size_t emhtIdx = 0; emhtIdx < vkExternalMemoryHandleTypeList.size(); + emhtIdx++) + { + VulkanExternalMemoryHandleType vkExternalMemoryHandleType = + vkExternalMemoryHandleTypeList[emhtIdx]; + log_info("External memory handle type: %d\n", + vkExternalMemoryHandleType); + + VulkanBuffer vkDummyBuffer(vkDevice, 4 * 1024, + vkExternalMemoryHandleType); + const VulkanMemoryTypeList &memoryTypeList = + vkDummyBuffer.getMemoryTypeList(); + + for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++) + { + const VulkanMemoryType &memoryType = memoryTypeList[mtIdx]; + + log_info("Memory type index: %d\n", (uint32_t)memoryType); + log_info("Memory type property: %d\n", + memoryType.getMemoryTypeProperty()); + + VulkanBufferList vkBufferList(numBuffers, vkDevice, bufferSize, + vkExternalMemoryHandleType); + + for (size_t bIdx = 0; bIdx < numBuffers; bIdx++) + { + vkBufferListDeviceMemory.push_back( + new VulkanDeviceMemory(vkDevice, bufferSize, memoryType, + vkExternalMemoryHandleType)); + externalMemory.push_back(new clExternalMemory( + vkBufferListDeviceMemory[bIdx], vkExternalMemoryHandleType, + 0, bufferSize, context, deviceId)); + } + cl_mem buffers[4]; + clFinish(cmd_queue1); + Params *params = (Params *)vkParamsDeviceMemory.map(); + params->numBuffers = numBuffers; + params->bufferSize = bufferSize; + params->interBufferOffset = 0; + vkParamsDeviceMemory.unmap(); + vkDescriptorSet.update(0, vkParamsBuffer); + for (size_t bIdx = 0; bIdx < vkBufferList.size(); bIdx++) + { + size_t buffer_size = vkBufferList[bIdx].getSize(); + vkBufferListDeviceMemory[bIdx]->bindBuffer(vkBufferList[bIdx], + 0); + buffers[bIdx] = externalMemory[bIdx]->getExternalMemoryBuffer(); + vkDescriptorSet.update((uint32_t)bIdx + 1, vkBufferList[bIdx]); + } + vkCommandBuffer.begin(); + vkCommandBuffer.bindPipeline(vkComputePipeline); + vkCommandBuffer.bindDescriptorSets( + vkComputePipeline, vkPipelineLayout, vkDescriptorSet); + vkCommandBuffer.dispatch(512, 1, 1); + vkCommandBuffer.end(); + + if (vkBufferList.size() == 1) + { + update_buffer_kernel = kernel[0]; + } + else if (vkBufferList.size() == 2) + { + update_buffer_kernel = kernel[1]; + } + else if (vkBufferList.size() == 4) + { + update_buffer_kernel = kernel[2]; + } + + // global work size should be less than or equal to + // bufferSizeList[i] + global_work_size[0] = bufferSize; + + for (uint32_t iter = 0; iter < maxIter; iter++) + { + if (iter == 0) + { + vkQueue.submit(vkCommandBuffer, vkVk2CLSemaphore); + } + else + { + vkQueue.submit(vkCl2VkSemaphore, vkCommandBuffer, + vkVk2CLSemaphore); + } + clVk2CLExternalSemaphore->wait(cmd_queue1); + + err = clSetKernelArg(update_buffer_kernel, 0, sizeof(uint32_t), + (void *)&bufferSize); + for (int i = 0; i < vkBufferList.size(); i++) + { + err |= + clSetKernelArg(update_buffer_kernel, i + 1, + sizeof(cl_mem), (void *)&(buffers[i])); + } + + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to set arg values for kernel\n"); + goto CLEANUP; + } + err = clEnqueueNDRangeKernel(cmd_queue1, update_buffer_kernel, + 1, NULL, global_work_size, NULL, 0, + NULL, NULL); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to launch update_buffer_kernel," + " error\n"); + goto CLEANUP; + } + if (iter != (maxIter - 1)) + { + clCl2VkExternalSemaphore->signal(cmd_queue1); + } + } + error_2 = (uint8_t *)malloc(sizeof(uint8_t)); + if (NULL == error_2) + { + log_error("Not able to allocate memory\n"); + goto CLEANUP; + } + + error_1 = clCreateBuffer(context, CL_MEM_WRITE_ONLY, + sizeof(uint8_t), NULL, &err); + if (CL_SUCCESS != err) + { + print_error(err, "Error: clCreateBuffer \n"); + goto CLEANUP; + } + uint8_t val = 0; + err = clEnqueueWriteBuffer(cmd_queue1, error_1, CL_TRUE, 0, + sizeof(uint8_t), &val, 0, NULL, NULL); + if (CL_SUCCESS != err) + { + print_error(err, "Error: clEnqueueWriteBuffer \n"); + goto CLEANUP; + } + + int calc_max_iter = (maxIter * 2); + for (int i = 0; i < vkBufferList.size(); i++) + { + err = clSetKernelArg(verify_kernel, 0, sizeof(cl_mem), + (void *)&(buffers[i])); + err |= + clSetKernelArg(verify_kernel, 1, sizeof(int), &bufferSize); + err |= clSetKernelArg(verify_kernel, 2, sizeof(int), + &calc_max_iter); + err |= clSetKernelArg(verify_kernel, 3, sizeof(cl_mem), + (void *)&error_1); + if (err != CL_SUCCESS) + { + print_error( + err, + "Error: Failed to set arg values for verify_kernel \n"); + goto CLEANUP; + } + err = clEnqueueNDRangeKernel(cmd_queue1, verify_kernel, 1, NULL, + global_work_size, NULL, 0, NULL, + NULL); + if (err != CL_SUCCESS) + { + print_error( + err, "Error: Failed to launch verify_kernel, error\n"); + goto CLEANUP; + } + + err = clEnqueueReadBuffer(cmd_queue1, error_1, CL_TRUE, 0, + sizeof(uint8_t), error_2, 0, NULL, + NULL); + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed read output, error \n"); + goto CLEANUP; + } + if (*error_2 == 1) + { + log_error("&&&& vulkan_opencl_buffer test FAILED\n"); + goto CLEANUP; + } + } + for (size_t i = 0; i < vkBufferList.size(); i++) + { + delete vkBufferListDeviceMemory[i]; + delete externalMemory[i]; + } + vkBufferListDeviceMemory.erase(vkBufferListDeviceMemory.begin(), + vkBufferListDeviceMemory.begin() + + numBuffers); + externalMemory.erase(externalMemory.begin(), + externalMemory.begin() + numBuffers); + } + } +CLEANUP: + for (size_t i = 0; i < vkBufferListDeviceMemory.size(); i++) + { + if (vkBufferListDeviceMemory[i]) + { + delete vkBufferListDeviceMemory[i]; + } + if (externalMemory[i]) + { + delete externalMemory[i]; + } + } + if (clVk2CLExternalSemaphore) delete clVk2CLExternalSemaphore; + if (clCl2VkExternalSemaphore) delete clCl2VkExternalSemaphore; + if (error_2) free(error_2); + if (error_1) clReleaseMemObject(error_1); + return err; +} + +int run_test_with_multi_import_same_ctx( + cl_context &context, cl_command_queue &cmd_queue1, cl_kernel *kernel, + cl_kernel &verify_kernel, VulkanDevice &vkDevice, uint32_t numBuffers, + uint32_t bufferSize, uint32_t bufferSizeForOffset) +{ + size_t global_work_size[1]; + uint8_t *error_2; + cl_mem error_1; + int numImports = numBuffers; + cl_kernel update_buffer_kernel[MAX_IMPORTS]; + clExternalSemaphore *clVk2CLExternalSemaphore = NULL; + clExternalSemaphore *clCl2VkExternalSemaphore = NULL; + int err = CL_SUCCESS; + int calc_max_iter; + bool withOffset; + uint32_t pBufferSize; + + const std::vector + vkExternalMemoryHandleTypeList = + getSupportedVulkanExternalMemoryHandleTypeList(); + VulkanExternalSemaphoreHandleType vkExternalSemaphoreHandleType = + getSupportedVulkanExternalSemaphoreHandleTypeList()[0]; + VulkanSemaphore vkVk2CLSemaphore(vkDevice, vkExternalSemaphoreHandleType); + VulkanSemaphore vkCl2VkSemaphore(vkDevice, vkExternalSemaphoreHandleType); + + VulkanQueue &vkQueue = vkDevice.getQueue(); + + VulkanShaderModule vkBufferShaderModule(vkDevice, vkBufferShader); + VulkanDescriptorSetLayoutBindingList vkDescriptorSetLayoutBindingList( + MAX_BUFFERS + 1, VULKAN_DESCRIPTOR_TYPE_STORAGE_BUFFER); + VulkanDescriptorSetLayout vkDescriptorSetLayout( + vkDevice, vkDescriptorSetLayoutBindingList); + VulkanPipelineLayout vkPipelineLayout(vkDevice, vkDescriptorSetLayout); + VulkanComputePipeline vkComputePipeline(vkDevice, vkPipelineLayout, + vkBufferShaderModule); + + VulkanDescriptorPool vkDescriptorPool(vkDevice, + vkDescriptorSetLayoutBindingList); + VulkanDescriptorSet vkDescriptorSet(vkDevice, vkDescriptorPool, + vkDescriptorSetLayout); + + clVk2CLExternalSemaphore = new clExternalSemaphore( + vkVk2CLSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + clCl2VkExternalSemaphore = new clExternalSemaphore( + vkCl2VkSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + const uint32_t maxIter = innerIterations; + VulkanCommandPool vkCommandPool(vkDevice); + VulkanCommandBuffer vkCommandBuffer(vkDevice, vkCommandPool); + + VulkanBuffer vkParamsBuffer(vkDevice, sizeof(Params)); + VulkanDeviceMemory vkParamsDeviceMemory( + vkDevice, vkParamsBuffer.getSize(), + getVulkanMemoryType(vkDevice, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_COHERENT)); + vkParamsDeviceMemory.bindBuffer(vkParamsBuffer); + std::vector vkBufferListDeviceMemory; + std::vector> externalMemory; + + + for (size_t emhtIdx = 0; emhtIdx < vkExternalMemoryHandleTypeList.size(); + emhtIdx++) + { + VulkanExternalMemoryHandleType vkExternalMemoryHandleType = + vkExternalMemoryHandleTypeList[emhtIdx]; + log_info("External memory handle type: %d\n", + vkExternalMemoryHandleType); + + VulkanBuffer vkDummyBuffer(vkDevice, 4 * 1024, + vkExternalMemoryHandleType); + const VulkanMemoryTypeList &memoryTypeList = + vkDummyBuffer.getMemoryTypeList(); + + for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++) + { + const VulkanMemoryType &memoryType = memoryTypeList[mtIdx]; + + log_info("Memory type index: %d\n", (uint32_t)memoryType); + log_info("Memory type property: %d\n", + memoryType.getMemoryTypeProperty()); + for (unsigned int withOffset = 0; + withOffset <= (unsigned int)enableOffset; withOffset++) + { + log_info("Running withOffset case %d\n", (uint32_t)withOffset); + if (withOffset) + { + pBufferSize = bufferSizeForOffset; + } + else + { + pBufferSize = bufferSize; + } + cl_mem buffers[MAX_BUFFERS][MAX_IMPORTS]; + VulkanBufferList vkBufferList(numBuffers, vkDevice, pBufferSize, + vkExternalMemoryHandleType); + uint32_t interBufferOffset = + (uint32_t)(vkBufferList[0].getSize()); + + for (size_t bIdx = 0; bIdx < numBuffers; bIdx++) + { + if (withOffset == 0) + { + vkBufferListDeviceMemory.push_back( + new VulkanDeviceMemory(vkDevice, pBufferSize, + memoryType, + vkExternalMemoryHandleType)); + } + if (withOffset == 1) + { + uint32_t totalSize = + (uint32_t)(vkBufferList.size() * interBufferOffset); + vkBufferListDeviceMemory.push_back( + new VulkanDeviceMemory(vkDevice, totalSize, + memoryType, + vkExternalMemoryHandleType)); + } + std::vector pExternalMemory; + for (size_t cl_bIdx = 0; cl_bIdx < numImports; cl_bIdx++) + { + pExternalMemory.push_back(new clExternalMemory( + vkBufferListDeviceMemory[bIdx], + vkExternalMemoryHandleType, + withOffset * bIdx * interBufferOffset, pBufferSize, + context, deviceId)); + } + externalMemory.push_back(pExternalMemory); + } + + clFinish(cmd_queue1); + Params *params = (Params *)vkParamsDeviceMemory.map(); + params->numBuffers = numBuffers; + params->bufferSize = pBufferSize; + params->interBufferOffset = interBufferOffset * withOffset; + vkParamsDeviceMemory.unmap(); + vkDescriptorSet.update(0, vkParamsBuffer); + for (size_t bIdx = 0; bIdx < vkBufferList.size(); bIdx++) + { + size_t buffer_size = vkBufferList[bIdx].getSize(); + vkBufferListDeviceMemory[bIdx]->bindBuffer( + vkBufferList[bIdx], + bIdx * interBufferOffset * withOffset); + for (size_t cl_bIdx = 0; cl_bIdx < numImports; cl_bIdx++) + { + buffers[bIdx][cl_bIdx] = + externalMemory[bIdx][cl_bIdx] + ->getExternalMemoryBuffer(); + } + vkDescriptorSet.update((uint32_t)bIdx + 1, + vkBufferList[bIdx]); + } + vkCommandBuffer.begin(); + vkCommandBuffer.bindPipeline(vkComputePipeline); + vkCommandBuffer.bindDescriptorSets( + vkComputePipeline, vkPipelineLayout, vkDescriptorSet); + vkCommandBuffer.dispatch(512, 1, 1); + vkCommandBuffer.end(); + for (int i = 0; i < numImports; i++) + { + update_buffer_kernel[i] = (numBuffers == 1) + ? kernel[0] + : ((numBuffers == 2) ? kernel[1] : kernel[2]); + } + // global work size should be less than or equal to + // bufferSizeList[i] + global_work_size[0] = pBufferSize; + + for (uint32_t iter = 0; iter < maxIter; iter++) + { + if (iter == 0) + { + vkQueue.submit(vkCommandBuffer, vkVk2CLSemaphore); + } + else + { + vkQueue.submit(vkCl2VkSemaphore, vkCommandBuffer, + vkVk2CLSemaphore); + } + clVk2CLExternalSemaphore->wait(cmd_queue1); + for (uint8_t launchIter = 0; launchIter < numImports; + launchIter++) + { + err = clSetKernelArg(update_buffer_kernel[launchIter], + 0, sizeof(uint32_t), + (void *)&pBufferSize); + for (int i = 0; i < numBuffers; i++) + { + err |= clSetKernelArg( + update_buffer_kernel[launchIter], i + 1, + sizeof(cl_mem), + (void *)&(buffers[i][launchIter])); + } + + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to set arg values for " + "kernel\n "); + goto CLEANUP; + } + err = clEnqueueNDRangeKernel( + cmd_queue1, update_buffer_kernel[launchIter], 1, + NULL, global_work_size, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to launch " + "update_buffer_kernel, error\n "); + goto CLEANUP; + } + } + if (iter != (maxIter - 1)) + { + clCl2VkExternalSemaphore->signal(cmd_queue1); + } + } + error_2 = (uint8_t *)malloc(sizeof(uint8_t)); + if (NULL == error_2) + { + log_error("Not able to allocate memory\n"); + goto CLEANUP; + } + + error_1 = clCreateBuffer(context, CL_MEM_WRITE_ONLY, + sizeof(uint8_t), NULL, &err); + if (CL_SUCCESS != err) + { + print_error(err, "Error: clCreateBuffer \n"); + goto CLEANUP; + } + uint8_t val = 0; + err = + clEnqueueWriteBuffer(cmd_queue1, error_1, CL_TRUE, 0, + sizeof(uint8_t), &val, 0, NULL, NULL); + if (CL_SUCCESS != err) + { + print_error(err, "Error: clEnqueueWriteBuffer \n"); + goto CLEANUP; + } + calc_max_iter = maxIter * (numBuffers + 1); + + for (int i = 0; i < vkBufferList.size(); i++) + { + err = clSetKernelArg(verify_kernel, 0, sizeof(cl_mem), + (void *)&(buffers[i][0])); + err |= clSetKernelArg(verify_kernel, 1, sizeof(int), + &pBufferSize); + err |= clSetKernelArg(verify_kernel, 2, sizeof(int), + &calc_max_iter); + err |= clSetKernelArg(verify_kernel, 3, sizeof(cl_mem), + (void *)&error_1); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to set arg values for " + "verify_kernel \n"); + goto CLEANUP; + } + err = clEnqueueNDRangeKernel(cmd_queue1, verify_kernel, 1, + NULL, global_work_size, NULL, + 0, NULL, NULL); + if (err != CL_SUCCESS) + { + print_error( + err, + "Error: Failed to launch verify_kernel, error\n"); + goto CLEANUP; + } + + err = clEnqueueReadBuffer(cmd_queue1, error_1, CL_TRUE, 0, + sizeof(uint8_t), error_2, 0, NULL, + NULL); + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed read output, error \n"); + goto CLEANUP; + } + if (*error_2 == 1) + { + log_error("&&&& vulkan_opencl_buffer test FAILED\n"); + goto CLEANUP; + } + } + for (size_t i = 0; i < vkBufferList.size(); i++) + { + for (size_t j = 0; j < numImports; j++) + { + delete externalMemory[i][j]; + } + } + for (size_t i = 0; i < vkBufferListDeviceMemory.size(); i++) + { + delete vkBufferListDeviceMemory[i]; + } + vkBufferListDeviceMemory.erase(vkBufferListDeviceMemory.begin(), + vkBufferListDeviceMemory.end()); + for (size_t i = 0; i < externalMemory.size(); i++) + { + externalMemory[i].erase(externalMemory[i].begin(), + externalMemory[i].begin() + + numBuffers); + } + externalMemory.clear(); + } + } + } +CLEANUP: + for (size_t i = 0; i < vkBufferListDeviceMemory.size(); i++) + { + if (vkBufferListDeviceMemory[i]) + { + delete vkBufferListDeviceMemory[i]; + } + } + for (size_t i = 0; i < externalMemory.size(); i++) + { + for (size_t j = 0; j < externalMemory[i].size(); j++) + { + if (externalMemory[i][j]) + { + delete externalMemory[i][j]; + } + } + } + if (clVk2CLExternalSemaphore) delete clVk2CLExternalSemaphore; + if (clCl2VkExternalSemaphore) delete clCl2VkExternalSemaphore; + if (error_2) free(error_2); + if (error_1) clReleaseMemObject(error_1); + return err; +} + +int run_test_with_multi_import_diff_ctx( + cl_context &context, cl_context &context2, cl_command_queue &cmd_queue1, + cl_command_queue &cmd_queue2, cl_kernel *kernel1, cl_kernel *kernel2, + cl_kernel &verify_kernel, cl_kernel verify_kernel2, VulkanDevice &vkDevice, + uint32_t numBuffers, uint32_t bufferSize, uint32_t bufferSizeForOffset) +{ + size_t global_work_size[1]; + uint8_t *error_3; + cl_mem error_1; + cl_mem error_2; + int numImports = numBuffers; + cl_kernel update_buffer_kernel1[MAX_IMPORTS]; + cl_kernel update_buffer_kernel2[MAX_IMPORTS]; + clExternalSemaphore *clVk2CLExternalSemaphore = NULL; + clExternalSemaphore *clCl2VkExternalSemaphore = NULL; + clExternalSemaphore *clVk2CLExternalSemaphore2 = NULL; + clExternalSemaphore *clCl2VkExternalSemaphore2 = NULL; + int err = CL_SUCCESS; + int calc_max_iter; + bool withOffset; + uint32_t pBufferSize; + + const std::vector + vkExternalMemoryHandleTypeList = + getSupportedVulkanExternalMemoryHandleTypeList(); + VulkanExternalSemaphoreHandleType vkExternalSemaphoreHandleType = + getSupportedVulkanExternalSemaphoreHandleTypeList()[0]; + VulkanSemaphore vkVk2CLSemaphore(vkDevice, vkExternalSemaphoreHandleType); + VulkanSemaphore vkCl2VkSemaphore(vkDevice, vkExternalSemaphoreHandleType); + + VulkanQueue &vkQueue = vkDevice.getQueue(); + + VulkanShaderModule vkBufferShaderModule(vkDevice, vkBufferShader); + VulkanDescriptorSetLayoutBindingList vkDescriptorSetLayoutBindingList( + MAX_BUFFERS + 1, VULKAN_DESCRIPTOR_TYPE_STORAGE_BUFFER); + VulkanDescriptorSetLayout vkDescriptorSetLayout( + vkDevice, vkDescriptorSetLayoutBindingList); + VulkanPipelineLayout vkPipelineLayout(vkDevice, vkDescriptorSetLayout); + VulkanComputePipeline vkComputePipeline(vkDevice, vkPipelineLayout, + vkBufferShaderModule); + + VulkanDescriptorPool vkDescriptorPool(vkDevice, + vkDescriptorSetLayoutBindingList); + VulkanDescriptorSet vkDescriptorSet(vkDevice, vkDescriptorPool, + vkDescriptorSetLayout); + + clVk2CLExternalSemaphore = new clExternalSemaphore( + vkVk2CLSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + clCl2VkExternalSemaphore = new clExternalSemaphore( + vkCl2VkSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + + clVk2CLExternalSemaphore2 = new clExternalSemaphore( + vkVk2CLSemaphore, context2, vkExternalSemaphoreHandleType, deviceId); + clCl2VkExternalSemaphore2 = new clExternalSemaphore( + vkCl2VkSemaphore, context2, vkExternalSemaphoreHandleType, deviceId); + + const uint32_t maxIter = innerIterations; + VulkanCommandPool vkCommandPool(vkDevice); + VulkanCommandBuffer vkCommandBuffer(vkDevice, vkCommandPool); + + VulkanBuffer vkParamsBuffer(vkDevice, sizeof(Params)); + VulkanDeviceMemory vkParamsDeviceMemory( + vkDevice, vkParamsBuffer.getSize(), + getVulkanMemoryType(vkDevice, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_COHERENT)); + vkParamsDeviceMemory.bindBuffer(vkParamsBuffer); + std::vector vkBufferListDeviceMemory; + std::vector> externalMemory1; + std::vector> externalMemory2; + + for (size_t emhtIdx = 0; emhtIdx < vkExternalMemoryHandleTypeList.size(); + emhtIdx++) + { + VulkanExternalMemoryHandleType vkExternalMemoryHandleType = + vkExternalMemoryHandleTypeList[emhtIdx]; + log_info("External memory handle type:%d\n", + vkExternalMemoryHandleType); + + VulkanBuffer vkDummyBuffer(vkDevice, 4 * 1024, + vkExternalMemoryHandleType); + const VulkanMemoryTypeList &memoryTypeList = + vkDummyBuffer.getMemoryTypeList(); + + for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++) + { + const VulkanMemoryType &memoryType = memoryTypeList[mtIdx]; + + log_info("Memory type index: %d\n", (uint32_t)memoryType); + log_info("Memory type property: %d\n", + memoryType.getMemoryTypeProperty()); + + for (unsigned int withOffset = 0; + withOffset <= (unsigned int)enableOffset; withOffset++) + { + log_info("Running withOffset case %d\n", (uint32_t)withOffset); + cl_mem buffers1[MAX_BUFFERS][MAX_IMPORTS]; + cl_mem buffers2[MAX_BUFFERS][MAX_IMPORTS]; + if (withOffset) + { + pBufferSize = bufferSizeForOffset; + } + else + { + pBufferSize = bufferSize; + } + VulkanBufferList vkBufferList(numBuffers, vkDevice, pBufferSize, + vkExternalMemoryHandleType); + uint32_t interBufferOffset = + (uint32_t)(vkBufferList[0].getSize()); + + for (size_t bIdx = 0; bIdx < numBuffers; bIdx++) + { + if (withOffset == 0) + { + vkBufferListDeviceMemory.push_back( + new VulkanDeviceMemory(vkDevice, pBufferSize, + memoryType, + vkExternalMemoryHandleType)); + } + if (withOffset == 1) + { + uint32_t totalSize = + (uint32_t)(vkBufferList.size() * interBufferOffset); + vkBufferListDeviceMemory.push_back( + new VulkanDeviceMemory(vkDevice, totalSize, + memoryType, + vkExternalMemoryHandleType)); + } + std::vector pExternalMemory1; + std::vector pExternalMemory2; + for (size_t cl_bIdx = 0; cl_bIdx < numImports; cl_bIdx++) + { + pExternalMemory1.push_back(new clExternalMemory( + vkBufferListDeviceMemory[bIdx], + vkExternalMemoryHandleType, + withOffset * bIdx * interBufferOffset, pBufferSize, + context, deviceId)); + pExternalMemory2.push_back(new clExternalMemory( + vkBufferListDeviceMemory[bIdx], + vkExternalMemoryHandleType, + withOffset * bIdx * interBufferOffset, pBufferSize, + context2, deviceId)); + } + externalMemory1.push_back(pExternalMemory1); + externalMemory2.push_back(pExternalMemory2); + } + + clFinish(cmd_queue1); + Params *params = (Params *)vkParamsDeviceMemory.map(); + params->numBuffers = numBuffers; + params->bufferSize = pBufferSize; + params->interBufferOffset = interBufferOffset * withOffset; + vkParamsDeviceMemory.unmap(); + vkDescriptorSet.update(0, vkParamsBuffer); + for (size_t bIdx = 0; bIdx < vkBufferList.size(); bIdx++) + { + size_t buffer_size = vkBufferList[bIdx].getSize(); + vkBufferListDeviceMemory[bIdx]->bindBuffer( + vkBufferList[bIdx], + bIdx * interBufferOffset * withOffset); + for (size_t cl_bIdx = 0; cl_bIdx < numImports; cl_bIdx++) + { + buffers1[bIdx][cl_bIdx] = + externalMemory1[bIdx][cl_bIdx] + ->getExternalMemoryBuffer(); + buffers2[bIdx][cl_bIdx] = + externalMemory2[bIdx][cl_bIdx] + ->getExternalMemoryBuffer(); + } + vkDescriptorSet.update((uint32_t)bIdx + 1, + vkBufferList[bIdx]); + } + + vkCommandBuffer.begin(); + vkCommandBuffer.bindPipeline(vkComputePipeline); + vkCommandBuffer.bindDescriptorSets( + vkComputePipeline, vkPipelineLayout, vkDescriptorSet); + vkCommandBuffer.dispatch(512, 1, 1); + vkCommandBuffer.end(); + + for (int i = 0; i < numImports; i++) + { + update_buffer_kernel1[i] = (numBuffers == 1) + ? kernel1[0] + : ((numBuffers == 2) ? kernel1[1] : kernel1[2]); + update_buffer_kernel2[i] = (numBuffers == 1) + ? kernel2[0] + : ((numBuffers == 2) ? kernel2[1] : kernel2[2]); + } + + // global work size should be less than or equal + // to bufferSizeList[i] + global_work_size[0] = pBufferSize; + + for (uint32_t iter = 0; iter < maxIter; iter++) + { + if (iter == 0) + { + vkQueue.submit(vkCommandBuffer, vkVk2CLSemaphore); + } + else + { + vkQueue.submit(vkCl2VkSemaphore, vkCommandBuffer, + vkVk2CLSemaphore); + } + clVk2CLExternalSemaphore->wait(cmd_queue1); + + for (uint8_t launchIter = 0; launchIter < numImports; + launchIter++) + { + err = clSetKernelArg(update_buffer_kernel1[launchIter], + 0, sizeof(uint32_t), + (void *)&pBufferSize); + for (int i = 0; i < numBuffers; i++) + { + err |= clSetKernelArg( + update_buffer_kernel1[launchIter], i + 1, + sizeof(cl_mem), + (void *)&(buffers1[i][launchIter])); + } + + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to set arg values for " + "kernel\n "); + goto CLEANUP; + } + err = clEnqueueNDRangeKernel( + cmd_queue1, update_buffer_kernel1[launchIter], 1, + NULL, global_work_size, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to launch " + "update_buffer_kernel, error\n"); + goto CLEANUP; + } + } + if (iter != (maxIter - 1)) + { + clCl2VkExternalSemaphore->signal(cmd_queue1); + } + } + clFinish(cmd_queue1); + for (uint32_t iter = 0; iter < maxIter; iter++) + { + if (iter == 0) + { + vkQueue.submit(vkCommandBuffer, vkVk2CLSemaphore); + } + else + { + vkQueue.submit(vkCl2VkSemaphore, vkCommandBuffer, + vkVk2CLSemaphore); + } + clVk2CLExternalSemaphore2->wait(cmd_queue2); + + for (uint8_t launchIter = 0; launchIter < numImports; + launchIter++) + { + err = clSetKernelArg(update_buffer_kernel2[launchIter], + 0, sizeof(uint32_t), + (void *)&bufferSize); + for (int i = 0; i < numBuffers; i++) + { + err |= clSetKernelArg( + update_buffer_kernel2[launchIter], i + 1, + sizeof(cl_mem), + (void *)&(buffers2[i][launchIter])); + } + + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to set arg values for " + "kernel\n "); + goto CLEANUP; + } + err = clEnqueueNDRangeKernel( + cmd_queue2, update_buffer_kernel2[launchIter], 1, + NULL, global_work_size, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to launch " + "update_buffer_kernel, error\n "); + goto CLEANUP; + } + } + if (iter != (maxIter - 1)) + { + clCl2VkExternalSemaphore2->signal(cmd_queue2); + } + } + clFinish(cmd_queue2); + error_3 = (uint8_t *)malloc(sizeof(uint8_t)); + if (NULL == error_3) + { + log_error("Not able to allocate memory\n"); + goto CLEANUP; + } + + error_1 = clCreateBuffer(context, CL_MEM_WRITE_ONLY, + sizeof(uint8_t), NULL, &err); + if (CL_SUCCESS != err) + { + print_error(err, "Error: clCreateBuffer \n"); + goto CLEANUP; + } + error_2 = clCreateBuffer(context2, CL_MEM_WRITE_ONLY, + sizeof(uint8_t), NULL, &err); + if (CL_SUCCESS != err) + { + print_error(err, "Error: clCreateBuffer \n"); + goto CLEANUP; + } + uint8_t val = 0; + err = + clEnqueueWriteBuffer(cmd_queue1, error_1, CL_TRUE, 0, + sizeof(uint8_t), &val, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed read output, error \n"); + goto CLEANUP; + } + + err = + clEnqueueWriteBuffer(cmd_queue2, error_2, CL_TRUE, 0, + sizeof(uint8_t), &val, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed read output, error \n"); + goto CLEANUP; + } + + calc_max_iter = maxIter * 2 * (numBuffers + 1); + for (int i = 0; i < numBuffers; i++) + { + err = clSetKernelArg(verify_kernel, 0, sizeof(cl_mem), + (void *)&(buffers1[i][0])); + err |= clSetKernelArg(verify_kernel, 1, sizeof(int), + &pBufferSize); + err |= clSetKernelArg(verify_kernel, 2, sizeof(int), + &calc_max_iter); + err |= clSetKernelArg(verify_kernel, 3, sizeof(cl_mem), + (void *)&error_1); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to set arg values for " + "verify_kernel \n"); + goto CLEANUP; + } + err = clEnqueueNDRangeKernel(cmd_queue1, verify_kernel, 1, + NULL, global_work_size, NULL, + 0, NULL, NULL); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to launch verify_kernel," + "error\n"); + goto CLEANUP; + } + + err = clEnqueueReadBuffer(cmd_queue1, error_1, CL_TRUE, 0, + sizeof(uint8_t), error_3, 0, NULL, + NULL); + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed read output, error\n"); + goto CLEANUP; + } + if (*error_3 == 1) + { + log_error("&&&& vulkan_opencl_buffer test FAILED\n"); + goto CLEANUP; + } + } + *error_3 = 0; + for (int i = 0; i < vkBufferList.size(); i++) + { + err = clSetKernelArg(verify_kernel2, 0, sizeof(cl_mem), + (void *)&(buffers2[i][0])); + err |= clSetKernelArg(verify_kernel2, 1, sizeof(int), + &pBufferSize); + err |= clSetKernelArg(verify_kernel2, 2, sizeof(int), + &calc_max_iter); + err |= clSetKernelArg(verify_kernel2, 3, sizeof(cl_mem), + (void *)&error_2); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to set arg values for " + "verify_kernel \n"); + goto CLEANUP; + } + err = clEnqueueNDRangeKernel(cmd_queue2, verify_kernel2, 1, + NULL, global_work_size, NULL, + 0, NULL, NULL); + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to launch verify_kernel," + "error\n"); + goto CLEANUP; + } + + err = clEnqueueReadBuffer(cmd_queue2, error_2, CL_TRUE, 0, + sizeof(uint8_t), error_3, 0, NULL, + NULL); + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed read output, error\n"); + goto CLEANUP; + } + if (*error_3 == 1) + { + log_error("&&&& vulkan_opencl_buffer test FAILED\n"); + goto CLEANUP; + } + } + for (size_t i = 0; i < vkBufferList.size(); i++) + { + for (size_t j = 0; j < numImports; j++) + { + delete externalMemory1[i][j]; + delete externalMemory2[i][j]; + } + } + for (size_t i = 0; i < vkBufferListDeviceMemory.size(); i++) + { + delete vkBufferListDeviceMemory[i]; + } + vkBufferListDeviceMemory.erase(vkBufferListDeviceMemory.begin(), + vkBufferListDeviceMemory.end()); + for (size_t i = 0; i < externalMemory1.size(); i++) + { + externalMemory1[i].erase(externalMemory1[i].begin(), + externalMemory1[i].begin() + + numBuffers); + externalMemory2[i].erase(externalMemory2[i].begin(), + externalMemory2[i].begin() + + numBuffers); + } + externalMemory1.clear(); + externalMemory2.clear(); + } + } + } +CLEANUP: + for (size_t i = 0; i < vkBufferListDeviceMemory.size(); i++) + { + if (vkBufferListDeviceMemory[i]) + { + delete vkBufferListDeviceMemory[i]; + } + } + for (size_t i = 0; i < externalMemory1.size(); i++) + { + for (size_t j = 0; j < externalMemory1[i].size(); j++) + { + if (externalMemory1[i][j]) + { + delete externalMemory1[i][j]; + } + } + } + for (size_t i = 0; i < externalMemory2.size(); i++) + { + for (size_t j = 0; j < externalMemory2[i].size(); j++) + { + if (externalMemory2[i][j]) + { + delete externalMemory2[i][j]; + } + } + } + if (clVk2CLExternalSemaphore) delete clVk2CLExternalSemaphore; + if (clCl2VkExternalSemaphore) delete clCl2VkExternalSemaphore; + if (clVk2CLExternalSemaphore2) delete clVk2CLExternalSemaphore2; + if (clCl2VkExternalSemaphore2) delete clCl2VkExternalSemaphore2; + if (error_3) free(error_3); + if (error_1) clReleaseMemObject(error_1); + if (error_2) clReleaseMemObject(error_2); + return err; +} + +int test_buffer_common(cl_device_id device_, cl_context context_, + cl_command_queue queue_, int numElements_) +{ + + int current_device = 0; + int device_count = 0; + int devices_prohibited = 0; + cl_int errNum = CL_SUCCESS; + cl_platform_id platform = NULL; + size_t extensionSize = 0; + cl_uint num_devices = 0; + cl_uint device_no = 0; + const size_t bufsize = BUFFERSIZE; + char buf[BUFFERSIZE]; + cl_device_id *devices; + char *extensions = NULL; + cl_kernel verify_kernel; + cl_kernel verify_kernel2; + cl_kernel kernel[3] = { NULL, NULL, NULL }; + cl_kernel kernel2[3] = { NULL, NULL, NULL }; + const char *program_source_const[3] = { kernel_text_numbuffer_1, + kernel_text_numbuffer_2, + kernel_text_numbuffer_4 }; + const char *program_source_const_verify; + size_t program_source_length; + cl_command_queue cmd_queue1 = NULL; + cl_command_queue cmd_queue2 = NULL; + cl_command_queue cmd_queue3 = NULL; + cl_context context = NULL; + cl_program program[3] = { NULL, NULL, NULL }; + cl_program program_verify, program_verify2; + cl_context context2 = NULL; + + + VulkanDevice vkDevice; + uint32_t numBuffersList[] = { 1, 2, 4 }; + uint32_t bufferSizeList[] = { 4 * 1024, 64 * 1024, 2 * 1024 * 1024 }; + uint32_t bufferSizeListforOffset[] = { 256, 512, 1024 }; + + cl_context_properties contextProperties[] = { CL_CONTEXT_PLATFORM, 0, 0 }; + errNum = clGetPlatformIDs(1, &platform, NULL); + if (errNum != CL_SUCCESS) + { + print_error(errNum, "Error: Failed to get platform\n"); + goto CLEANUP; + } + + errNum = + clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &num_devices); + if (CL_SUCCESS != errNum) + { + print_error(errNum, "clGetDeviceIDs failed in returning of devices\n"); + goto CLEANUP; + } + devices = (cl_device_id *)malloc(num_devices * sizeof(cl_device_id)); + if (NULL == devices) + { + errNum = CL_OUT_OF_HOST_MEMORY; + print_error(errNum, "Unable to allocate memory for devices\n"); + goto CLEANUP; + } + errNum = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, num_devices, devices, + NULL); + if (CL_SUCCESS != errNum) + { + print_error(errNum, "Failed to get deviceID.\n"); + goto CLEANUP; + } + contextProperties[1] = (cl_context_properties)platform; + log_info("Assigned contextproperties for platform\n"); + for (device_no = 0; device_no < num_devices; device_no++) + { + errNum = clGetDeviceInfo(devices[device_no], CL_DEVICE_EXTENSIONS, 0, + NULL, &extensionSize); + if (CL_SUCCESS != errNum) + { + print_error(errNum, + "Error in clGetDeviceInfo for getting device_extension " + "size....\n"); + goto CLEANUP; + } + extensions = (char *)malloc(extensionSize); + if (NULL == extensions) + { + print_error(errNum, "Unable to allocate memory for extensions\n"); + errNum = CL_OUT_OF_HOST_MEMORY; + goto CLEANUP; + } + errNum = clGetDeviceInfo(devices[device_no], CL_DEVICE_EXTENSIONS, + extensionSize, extensions, NULL); + if (CL_SUCCESS != errNum) + { + print_error(errNum, + "Error in clGetDeviceInfo for device_extension\n"); + goto CLEANUP; + } + errNum = clGetDeviceInfo(devices[device_no], CL_DEVICE_UUID_KHR, + CL_UUID_SIZE_KHR, uuid, &extensionSize); + if (CL_SUCCESS != errNum) + { + print_error(errNum, "clGetDeviceInfo failed\n"); + goto CLEANUP; + } + errNum = + memcmp(uuid, vkDevice.getPhysicalDevice().getUUID(), VK_UUID_SIZE); + if (errNum == 0) + { + break; + } + } + if (device_no >= num_devices) + { + errNum = EXIT_FAILURE; + print_error(errNum, + "OpenCL error: " + "No Vulkan-OpenCL Interop capable GPU found.\n"); + goto CLEANUP; + } + deviceId = devices[device_no]; + context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU, + NULL, NULL, &errNum); + if (CL_SUCCESS != errNum) + { + print_error(errNum, "error creating context\n"); + goto CLEANUP; + } + log_info("Successfully created context !!!\n"); + + cmd_queue1 = clCreateCommandQueue(context, devices[device_no], 0, &errNum); + if (CL_SUCCESS != errNum) + { + errNum = CL_INVALID_COMMAND_QUEUE; + print_error(errNum, "Error: Failed to create command queue!\n"); + goto CLEANUP; + } + cmd_queue2 = clCreateCommandQueue(context, devices[device_no], 0, &errNum); + if (CL_SUCCESS != errNum) + { + errNum = CL_INVALID_COMMAND_QUEUE; + print_error(errNum, "Error: Failed to create command queue!\n"); + goto CLEANUP; + } + log_info("clCreateCommandQueue successful\n"); + for (int i = 0; i < 3; i++) + { + program_source_length = strlen(program_source_const[i]); + program[i] = + clCreateProgramWithSource(context, 1, &program_source_const[i], + &program_source_length, &errNum); + errNum = clBuildProgram(program[i], 0, NULL, NULL, NULL, NULL); + if (errNum != CL_SUCCESS) + { + print_error(errNum, "Error: Failed to build program \n"); + return errNum; + } + // create the kernel + kernel[i] = clCreateKernel(program[i], "clUpdateBuffer", &errNum); + if (errNum != CL_SUCCESS) + { + print_error(errNum, "clCreateKernel failed \n"); + return errNum; + } + } + + program_source_const_verify = kernel_text_verify; + program_source_length = strlen(program_source_const_verify); + program_verify = + clCreateProgramWithSource(context, 1, &program_source_const_verify, + &program_source_length, &errNum); + errNum = clBuildProgram(program_verify, 0, NULL, NULL, NULL, NULL); + if (errNum != CL_SUCCESS) + { + log_error("Error: Failed to build program2\n"); + return errNum; + } + verify_kernel = clCreateKernel(program_verify, "checkKernel", &errNum); + if (errNum != CL_SUCCESS) + { + print_error(errNum, "clCreateKernel failed \n"); + return errNum; + } + + if (multiCtx) // different context guard + { + context2 = clCreateContextFromType( + contextProperties, CL_DEVICE_TYPE_GPU, NULL, NULL, &errNum); + if (CL_SUCCESS != errNum) + { + print_error(errNum, "error creating context\n"); + goto CLEANUP; + } + cmd_queue3 = + clCreateCommandQueue(context2, devices[device_no], 0, &errNum); + if (CL_SUCCESS != errNum) + { + errNum = CL_INVALID_COMMAND_QUEUE; + print_error(errNum, "Error: Failed to create command queue!\n"); + goto CLEANUP; + } + for (int i = 0; i < 3; i++) + { + program_source_length = strlen(program_source_const[i]); + program[i] = + clCreateProgramWithSource(context2, 1, &program_source_const[i], + &program_source_length, &errNum); + errNum = clBuildProgram(program[i], 0, NULL, NULL, NULL, NULL); + if (errNum != CL_SUCCESS) + { + print_error(errNum, "Error: Failed to build program \n"); + return errNum; + } + // create the kernel + kernel2[i] = clCreateKernel(program[i], "clUpdateBuffer", &errNum); + if (errNum != CL_SUCCESS) + { + print_error(errNum, "clCreateKernel failed \n"); + return errNum; + } + } + program_source_length = strlen(program_source_const_verify); + program_verify = + clCreateProgramWithSource(context2, 1, &program_source_const_verify, + &program_source_length, &errNum); + errNum = clBuildProgram(program_verify, 0, NULL, NULL, NULL, NULL); + if (errNum != CL_SUCCESS) + { + log_error("Error: Failed to build program2\n"); + return errNum; + } + verify_kernel2 = clCreateKernel(program_verify, "checkKernel", &errNum); + if (errNum != CL_SUCCESS) + { + print_error(errNum, "clCreateKernel failed \n"); + return errNum; + } + } + + for (size_t numBuffersIdx = 0; numBuffersIdx < ARRAY_SIZE(numBuffersList); + numBuffersIdx++) + { + uint32_t numBuffers = numBuffersList[numBuffersIdx]; + log_info("Number of buffers: %d\n", numBuffers); + for (size_t sizeIdx = 0; sizeIdx < ARRAY_SIZE(bufferSizeList); + sizeIdx++) + { + uint32_t bufferSize = bufferSizeList[sizeIdx]; + uint32_t bufferSizeForOffset = bufferSizeListforOffset[sizeIdx]; + log_info("&&&& RUNNING vulkan_opencl_buffer test for Buffer size: " + "%d\n", + bufferSize); + if (multiImport && !multiCtx) + { + errNum = run_test_with_multi_import_same_ctx( + context, cmd_queue1, kernel, verify_kernel, vkDevice, + numBuffers, bufferSize, bufferSizeForOffset); + } + else if (multiImport && multiCtx) + { + errNum = run_test_with_multi_import_diff_ctx( + context, context2, cmd_queue1, cmd_queue3, kernel, kernel2, + verify_kernel, verify_kernel2, vkDevice, numBuffers, + bufferSize, bufferSizeForOffset); + } + else if (numCQ == 2) + { + errNum = run_test_with_two_queue( + context, cmd_queue1, cmd_queue2, kernel, verify_kernel, + vkDevice, numBuffers + 1, bufferSize); + } + else + { + errNum = run_test_with_one_queue(context, cmd_queue1, kernel, + verify_kernel, vkDevice, + numBuffers, bufferSize); + } + if (errNum != CL_SUCCESS) + { + print_error(errNum, "func_name failed \n"); + goto CLEANUP; + } + } + } + +CLEANUP: + for (int i = 0; i < 3; i++) + { + if (program[i]) clReleaseProgram(program[i]); + if (kernel[i]) clReleaseKernel(kernel[i]); + } + if (cmd_queue1) clReleaseCommandQueue(cmd_queue1); + if (cmd_queue2) clReleaseCommandQueue(cmd_queue2); + if (cmd_queue3) clReleaseCommandQueue(cmd_queue3); + if (context) clReleaseContext(context); + if (context2) clReleaseContext(context2); + + if (devices) free(devices); + if (extensions) free(extensions); + + return errNum; +} diff --git a/test_conformance/vulkan/test_vulkan_interop_image.cpp b/test_conformance/vulkan/test_vulkan_interop_image.cpp new file mode 100644 index 00000000..f1d0af1f --- /dev/null +++ b/test_conformance/vulkan/test_vulkan_interop_image.cpp @@ -0,0 +1,1648 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#define NOMINMAX +#include +#include +#include "harness/errorHelpers.h" + +#define MAX_2D_IMAGES 5 +#define MAX_2D_IMAGE_WIDTH 1024 +#define MAX_2D_IMAGE_HEIGHT 1024 +#define MAX_2D_IMAGE_ELEMENT_SIZE 16 +#define MAX_2D_IMAGE_MIP_LEVELS 11 +#define MAX_2D_IMAGE_DESCRIPTORS MAX_2D_IMAGES *MAX_2D_IMAGE_MIP_LEVELS +#define GLSL_FORMAT_STRING "" +#define GLSL_TYPE_PREFIX_STRING "" +#define NUM_THREADS_PER_GROUP_X 32 +#define NUM_THREADS_PER_GROUP_Y 32 +#define NUM_BLOCKS(size, blockSize) \ + (ROUND_UP((size), (blockSize)) / (blockSize)) + +#define ASSERT(x) \ + if (!(x)) \ + { \ + fprintf(stderr, "Assertion \"%s\" failed at %s:%d\n", #x, __FILE__, \ + __LINE__); \ + exit(1); \ + } + +#define ASSERT_LEQ(x, y) \ + if (x > y) \ + { \ + ASSERT(0); \ + } + +namespace { +struct Params +{ + uint32_t numImage2DDescriptors; +}; +} +static cl_uchar uuid[CL_UUID_SIZE_KHR]; +static cl_device_id deviceId = NULL; + +static const char *vkImage2DShader = + "#version 450\n" + "#extension GL_ARB_separate_shader_objects : enable\n" + "#extension GL_NV_gpu_shader5 : enable\n" + "layout(binding = 0) buffer Params\n" + "{\n" + " uint32_t numImage2DDescriptors;\n" + "};\n" + "layout(binding = 1, " GLSL_FORMAT_STRING + ") uniform " GLSL_TYPE_PREFIX_STRING "image2D image2DList[" STRING( + MAX_2D_IMAGE_DESCRIPTORS) "];\n" + "layout(local_size_x = 32, local_size_y = " + "32) in;\n" + "void main() {\n" + " uvec3 numThreads = gl_NumWorkGroups * " + "gl_WorkGroupSize;\n" + " for (uint32_t image2DIdx = 0; " + "image2DIdx < numImage2DDescriptors; " + "image2DIdx++)" + " {\n" + " ivec2 imageDim = " + "imageSize(image2DList[image2DIdx]);\n" + " uint32_t heightBy2 = imageDim.y / " + "2;\n" + " for (uint32_t row = " + "gl_GlobalInvocationID.y; row < heightBy2; " + "row += numThreads.y)" + " {\n" + " for (uint32_t col = " + "gl_GlobalInvocationID.x; col < imageDim.x; " + "col += numThreads.x)" + " {\n" + " ivec2 coordsA = ivec2(col, " + "row);\n" + " ivec2 coordsB = ivec2(col, " + "imageDim.y - row - 1);\n" + " " GLSL_TYPE_PREFIX_STRING + "vec4 dataA = " + "imageLoad(image2DList[image2DIdx], " + "coordsA);\n" + " " GLSL_TYPE_PREFIX_STRING + "vec4 dataB = " + "imageLoad(image2DList[image2DIdx], " + "coordsB);\n" + " " + "imageStore(image2DList[image2DIdx], " + "coordsA, dataB);\n" + " " + "imageStore(image2DList[image2DIdx], " + "coordsB, dataA);\n" + " }\n" + " }\n" + " }\n" + "}\n"; + +const char *kernel_text_numImage_1 = " \ +__constant sampler_t smpImg = CLK_NORMALIZED_COORDS_FALSE|CLK_ADDRESS_NONE|CLK_FILTER_NEAREST;\n\ +__kernel void image2DKernel(read_only image2d_t InputImage, write_only image2d_t OutImage, int num2DImages, int baseWidth, int baseHeight, int numMipLevels)\n\ +{\n\ + int threadIdxX = get_global_id(0);\n\ + int threadIdxY = get_global_id(1);\n\ + int numThreadsX = get_global_size(0); \n\ + int numThreadsY = get_global_size(1);\n\ + if (threadIdxX >= baseWidth || threadIdxY >= baseHeight)\n\ + {\n\ + return;\n\ + }\n\ + %s dataA = read_image%s(InputImage, smpImg, (int2)(threadIdxX, threadIdxY)); \n\ + %s dataB = read_image%s(InputImage, smpImg, (int2)(threadIdxX, baseHeight-threadIdxY-1)); \n\ + write_image%s(OutImage, (int2)(threadIdxX, baseHeight-threadIdxY-1), dataA);\n\ + write_image%s(OutImage, (int2)( threadIdxX, threadIdxY), dataB);\n\ +\n\ +}"; + +const char *kernel_text_numImage_2 = " \ +__constant sampler_t smpImg = CLK_NORMALIZED_COORDS_FALSE|CLK_ADDRESS_NONE|CLK_FILTER_NEAREST;\n\ +__kernel void image2DKernel(read_only image2d_t InputImage_1, write_only image2d_t OutImage_1, read_only image2d_t InputImage_2,write_only image2d_t OutImage_2,int num2DImages, int baseWidth, int baseHeight, int numMipLevels) \n\ +{\n\ + int threadIdxX = get_global_id(0);\n\ + int threadIdxY = get_global_id(1);\n\ + int numThreadsX = get_global_size(0);\n\ + int numThreadsY = get_global_size(1);\n\ + if (threadIdxX >= baseWidth || threadIdxY >= baseHeight) \n\ + {\n\ + return;\n\ + }\n\ + %s dataA = read_image%s(InputImage_1, smpImg, (int2)(threadIdxX, threadIdxY)); \n\ + %s dataB = read_image%s(InputImage_1, smpImg, (int2)(threadIdxX, baseHeight-threadIdxY-1)); \n\ + %s dataC = read_image%s(InputImage_2, smpImg, (int2)(threadIdxX, threadIdxY)); \n\ + %s dataD = read_image%s(InputImage_2, smpImg, (int2)(threadIdxX, baseHeight-threadIdxY-1)); \n\ + write_image%s(OutImage_1, (int2)(threadIdxX, baseHeight-threadIdxY-1), dataA);\n\ + write_image%s(OutImage_1, (int2)(threadIdxX, threadIdxY), dataB);\n\ + write_image%s(OutImage_2, (int2)(threadIdxX, baseHeight-threadIdxY-1), dataC);\n\ + write_image%s(OutImage_2, (int2)(threadIdxX, threadIdxY), dataD);\n\ +\n\ +}"; + +const char *kernel_text_numImage_4 = " \ +__constant sampler_t smpImg = CLK_NORMALIZED_COORDS_FALSE|CLK_ADDRESS_NONE|CLK_FILTER_NEAREST;\n\ +__kernel void image2DKernel(read_only image2d_t InputImage_1, write_only image2d_t OutImage_1, read_only image2d_t InputImage_2, write_only image2d_t OutImage_2, read_only image2d_t InputImage_3, write_only image2d_t OutImage_3, read_only image2d_t InputImage_4, write_only image2d_t OutImage_4, int num2DImages, int baseWidth, int baseHeight, int numMipLevels) \n\ +{\n\ + int threadIdxX = get_global_id(0);\n\ + int threadIdxY = get_global_id(1);\n\ + int numThreadsX = get_global_size(0);\n\ + int numThreadsY = get_global_size(1);\n\ + if (threadIdxX >= baseWidth || threadIdxY >= baseHeight) \n\ + {\n\ + return;\n\ + }\n\ + %s dataA = read_image%s(InputImage_1, smpImg, (int2)(threadIdxX, threadIdxY)); \n\ + %s dataB = read_image%s(InputImage_1, smpImg, (int2)(threadIdxX, baseHeight-threadIdxY-1)); \n\ + %s dataC = read_image%s(InputImage_2, smpImg, (int2)(threadIdxX, threadIdxY)); \n\ + %s dataD = read_image%s(InputImage_2, smpImg, (int2)(threadIdxX, baseHeight-threadIdxY-1)); \n\ + %s dataE = read_image%s(InputImage_3, smpImg, (int2)(threadIdxX, threadIdxY)); \n\ + %s dataF = read_image%s(InputImage_3, smpImg, (int2)(threadIdxX, baseHeight-threadIdxY-1)); \n\ + %s dataG = read_image%s(InputImage_4, smpImg, (int2)(threadIdxX, threadIdxY)); \n\ + %s dataH = read_image%s(InputImage_4, smpImg, (int2)(threadIdxX, baseHeight-threadIdxY-1)); \n\ + write_image%s(OutImage_1, (int2)(threadIdxX, baseHeight-threadIdxY-1), dataA);\n\ + write_image%s(OutImage_1, (int2)(threadIdxX, threadIdxY), dataB);\n\ + write_image%s(OutImage_2, (int2)(threadIdxX, baseHeight-threadIdxY-1), dataC);\n\ + write_image%s(OutImage_2, (int2)(threadIdxX, threadIdxY), dataD);\n\ + write_image%s(OutImage_3, (int2)(threadIdxX, baseHeight-threadIdxY-1), dataE);\n\ + write_image%s(OutImage_3, (int2)(threadIdxX, threadIdxY), dataF);\n\ + write_image%s(OutImage_4, (int2)(threadIdxX, baseHeight-threadIdxY-1), dataG);\n\ + write_image%s(OutImage_4, (int2)(threadIdxX, threadIdxY), dataH);\n\ +\n\ +}"; + +const uint32_t num2DImagesList[] = { 1, 2, 4 }; +const uint32_t widthList[] = { 4, 64, 183, 1024 }; +const uint32_t heightList[] = { 4, 64, 365 }; + +const cl_kernel getKernelType(VulkanFormat format, cl_kernel kernel_float, + cl_kernel kernel_signed, + cl_kernel kernel_unsigned) +{ + cl_kernel kernel; + switch (format) + { + case VULKAN_FORMAT_R32G32B32A32_SFLOAT: kernel = kernel_float; break; + + case VULKAN_FORMAT_R32G32B32A32_UINT: kernel = kernel_unsigned; break; + + case VULKAN_FORMAT_R32G32B32A32_SINT: kernel = kernel_signed; break; + + case VULKAN_FORMAT_R16G16B16A16_UINT: kernel = kernel_unsigned; break; + + case VULKAN_FORMAT_R16G16B16A16_SINT: kernel = kernel_signed; break; + + case VULKAN_FORMAT_R8G8B8A8_UINT: kernel = kernel_unsigned; break; + + case VULKAN_FORMAT_R8G8B8A8_SINT: kernel = kernel_signed; break; + + case VULKAN_FORMAT_R32G32_SFLOAT: kernel = kernel_float; break; + + case VULKAN_FORMAT_R32G32_UINT: kernel = kernel_unsigned; break; + + case VULKAN_FORMAT_R32G32_SINT: kernel = kernel_signed; break; + + case VULKAN_FORMAT_R16G16_UINT: kernel = kernel_unsigned; break; + + case VULKAN_FORMAT_R16G16_SINT: kernel = kernel_signed; break; + + case VULKAN_FORMAT_R8G8_UINT: kernel = kernel_unsigned; break; + + case VULKAN_FORMAT_R8G8_SINT: kernel = kernel_signed; break; + + case VULKAN_FORMAT_R32_SFLOAT: kernel = kernel_float; break; + + case VULKAN_FORMAT_R32_UINT: kernel = kernel_unsigned; break; + + case VULKAN_FORMAT_R32_SINT: kernel = kernel_signed; break; + + case VULKAN_FORMAT_R16_UINT: kernel = kernel_unsigned; break; + + case VULKAN_FORMAT_R16_SINT: kernel = kernel_signed; break; + + case VULKAN_FORMAT_R8_UINT: kernel = kernel_unsigned; break; + + case VULKAN_FORMAT_R8_SINT: kernel = kernel_signed; break; + + default: + log_error(" Unsupported format"); + ASSERT(0); + break; + } + return kernel; +} + +int run_test_with_two_queue(cl_context &context, cl_command_queue &cmd_queue1, + cl_command_queue &cmd_queue2, + cl_kernel *kernel_unsigned, + cl_kernel *kernel_signed, cl_kernel *kernel_float, + VulkanDevice &vkDevice) +{ + cl_int err = CL_SUCCESS; + size_t origin[3] = { 0, 0, 0 }; + size_t region[3] = { 1, 1, 1 }; + + cl_kernel updateKernelCQ1, updateKernelCQ2; + std::vector vkFormatList = getSupportedVulkanFormatList(); + const std::vector + vkExternalMemoryHandleTypeList = + getSupportedVulkanExternalMemoryHandleTypeList(); + char magicValue = 0; + + VulkanBuffer vkParamsBuffer(vkDevice, sizeof(Params)); + VulkanDeviceMemory vkParamsDeviceMemory( + vkDevice, vkParamsBuffer.getSize(), + getVulkanMemoryType(vkDevice, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_COHERENT)); + vkParamsDeviceMemory.bindBuffer(vkParamsBuffer); + + uint64_t maxImage2DSize = MAX_2D_IMAGE_WIDTH * MAX_2D_IMAGE_HEIGHT + * MAX_2D_IMAGE_ELEMENT_SIZE * 2; + VulkanBuffer vkSrcBuffer(vkDevice, maxImage2DSize); + VulkanDeviceMemory vkSrcBufferDeviceMemory( + vkDevice, vkSrcBuffer.getSize(), + getVulkanMemoryType(vkDevice, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_COHERENT)); + vkSrcBufferDeviceMemory.bindBuffer(vkSrcBuffer); + + char *srcBufferPtr, *dstBufferPtr; + srcBufferPtr = (char *)malloc(maxImage2DSize); + dstBufferPtr = (char *)malloc(maxImage2DSize); + + VulkanDescriptorSetLayoutBindingList vkDescriptorSetLayoutBindingList( + VULKAN_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VULKAN_DESCRIPTOR_TYPE_STORAGE_IMAGE, MAX_2D_IMAGE_DESCRIPTORS); + VulkanDescriptorSetLayout vkDescriptorSetLayout( + vkDevice, vkDescriptorSetLayoutBindingList); + VulkanPipelineLayout vkPipelineLayout(vkDevice, vkDescriptorSetLayout); + + VulkanDescriptorPool vkDescriptorPool(vkDevice, + vkDescriptorSetLayoutBindingList); + VulkanDescriptorSet vkDescriptorSet(vkDevice, vkDescriptorPool, + vkDescriptorSetLayout); + + VulkanCommandPool vkCommandPool(vkDevice); + VulkanCommandBuffer vkCopyCommandBuffer(vkDevice, vkCommandPool); + VulkanCommandBuffer vkShaderCommandBuffer(vkDevice, vkCommandPool); + VulkanQueue &vkQueue = vkDevice.getQueue(); + + VulkanExternalSemaphoreHandleType vkExternalSemaphoreHandleType = + getSupportedVulkanExternalSemaphoreHandleTypeList()[0]; + VulkanSemaphore vkVk2CLSemaphore(vkDevice, vkExternalSemaphoreHandleType); + VulkanSemaphore vkCl2VkSemaphore(vkDevice, vkExternalSemaphoreHandleType); + clExternalSemaphore *clVk2CLExternalSemaphore = NULL; + clExternalSemaphore *clCl2VkExternalSemaphore = NULL; + + clVk2CLExternalSemaphore = new clExternalSemaphore( + vkVk2CLSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + clCl2VkExternalSemaphore = new clExternalSemaphore( + vkCl2VkSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + + for (size_t fIdx = 0; fIdx < vkFormatList.size(); fIdx++) + { + VulkanFormat vkFormat = vkFormatList[fIdx]; + log_info("Format: %d\n", vkFormat); + uint32_t elementSize = getVulkanFormatElementSize(vkFormat); + ASSERT_LEQ(elementSize, (uint32_t)MAX_2D_IMAGE_ELEMENT_SIZE); + log_info("elementSize= %d\n", elementSize); + std::map patternToSubstituteMap; + patternToSubstituteMap[GLSL_FORMAT_STRING] = + getVulkanFormatGLSLFormat(vkFormat); + patternToSubstituteMap[GLSL_TYPE_PREFIX_STRING] = + getVulkanFormatGLSLTypePrefix(vkFormat); + + VulkanShaderModule vkImage2DShaderModule( + vkDevice, + prepareVulkanShader(vkImage2DShader, patternToSubstituteMap)); + VulkanComputePipeline vkComputePipeline(vkDevice, vkPipelineLayout, + vkImage2DShaderModule); + + for (size_t wIdx = 0; wIdx < ARRAY_SIZE(widthList); wIdx++) + { + uint32_t width = widthList[wIdx]; + log_info("Width: %d\n", width); + ASSERT_LEQ(width, (uint32_t)MAX_2D_IMAGE_WIDTH); + region[0] = width; + for (size_t hIdx = 0; hIdx < ARRAY_SIZE(heightList); hIdx++) + { + uint32_t height = heightList[hIdx]; + log_info("Height: %d", height); + ASSERT_LEQ(height, (uint32_t)MAX_2D_IMAGE_HEIGHT); + region[1] = height; + + uint32_t numMipLevels = 1; + log_info("Number of mipmap levels: %d\n", numMipLevels); + + magicValue++; + char *vkSrcBufferDeviceMemoryPtr = + (char *)vkSrcBufferDeviceMemory.map(); + uint64_t srcBufSize = 0; + memset(vkSrcBufferDeviceMemoryPtr, 0, maxImage2DSize); + memset(srcBufferPtr, 0, maxImage2DSize); + uint32_t mipLevel = 0; + for (uint32_t row = 0; + row < std::max(height >> mipLevel, uint32_t(1)); row++) + { + for (uint32_t col = 0; + col < std::max(width >> mipLevel, uint32_t(1)); col++) + { + for (uint32_t elementByte = 0; + elementByte < elementSize; elementByte++) + { + vkSrcBufferDeviceMemoryPtr[srcBufSize] = + (char)(magicValue + mipLevel + row + col); + srcBufferPtr[srcBufSize] = + (char)(magicValue + mipLevel + row + col); + srcBufSize++; + } + } + } + srcBufSize = ROUND_UP( + srcBufSize, + std::max( + elementSize, + (uint32_t)VULKAN_MIN_BUFFER_OFFSET_COPY_ALIGNMENT)); + vkSrcBufferDeviceMemory.unmap(); + + for (size_t niIdx = 0; niIdx < ARRAY_SIZE(num2DImagesList); + niIdx++) + { + uint32_t num2DImages = num2DImagesList[niIdx] + 1; + // added one image for cross-cq case for updateKernelCQ2 + log_info("Number of images: %d\n", num2DImages); + ASSERT_LEQ(num2DImages, (uint32_t)MAX_2D_IMAGES); + uint32_t num_2D_image; + if (useSingleImageKernel) + { + num_2D_image = 1; + } + else + { + num_2D_image = num2DImages; + } + Params *params = (Params *)vkParamsDeviceMemory.map(); + params->numImage2DDescriptors = num_2D_image * numMipLevels; + vkParamsDeviceMemory.unmap(); + vkDescriptorSet.update(0, vkParamsBuffer); + for (size_t emhtIdx = 0; + emhtIdx < vkExternalMemoryHandleTypeList.size(); + emhtIdx++) + { + VulkanExternalMemoryHandleType + vkExternalMemoryHandleType = + vkExternalMemoryHandleTypeList[emhtIdx]; + log_info("External memory handle type: %d \n", + vkExternalMemoryHandleType); + if ((true == disableNTHandleType) + && (VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT + == vkExternalMemoryHandleType)) + { + // Skip running for WIN32 NT handle. + continue; + } + VulkanImage2D vkDummyImage2D( + vkDevice, vkFormatList[0], widthList[0], + heightList[0], 1, vkExternalMemoryHandleType); + const VulkanMemoryTypeList &memoryTypeList = + vkDummyImage2D.getMemoryTypeList(); + + std::vector + vkNonDedicatedImage2DListDeviceMemory1; + std::vector + vkNonDedicatedImage2DListDeviceMemory2; + std::vector + nonDedicatedExternalMemory1; + std::vector + nonDedicatedExternalMemory2; + for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); + mtIdx++) + { + const VulkanMemoryType &memoryType = + memoryTypeList[mtIdx]; + log_info("Memory type index: %d\n", + (uint32_t)memoryType); + log_info("Memory type property: %d\n", + memoryType.getMemoryTypeProperty()); + if (!useDeviceLocal) + { + if (VULKAN_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL + == memoryType.getMemoryTypeProperty()) + { + continue; + } + } + + size_t totalImageMemSize = 0; + uint64_t interImageOffset = 0; + { + VulkanImage2D vkImage2D( + vkDevice, vkFormat, width, height, + numMipLevels, vkExternalMemoryHandleType); + ASSERT_LEQ(vkImage2D.getSize(), maxImage2DSize); + totalImageMemSize = + ROUND_UP(vkImage2D.getSize(), + vkImage2D.getAlignment()); + } + VulkanImage2DList vkNonDedicatedImage2DList( + num2DImages, vkDevice, vkFormat, width, height, + numMipLevels, vkExternalMemoryHandleType); + for (size_t bIdx = 0; bIdx < num2DImages; bIdx++) + { + if (non_dedicated) + { + vkNonDedicatedImage2DListDeviceMemory1 + .push_back(new VulkanDeviceMemory( + vkDevice, totalImageMemSize, + memoryType, + vkExternalMemoryHandleType)); + } + else + { + vkNonDedicatedImage2DListDeviceMemory1 + .push_back(new VulkanDeviceMemory( + vkDevice, + vkNonDedicatedImage2DList[bIdx], + memoryType, + vkExternalMemoryHandleType)); + } + vkNonDedicatedImage2DListDeviceMemory1[bIdx] + ->bindImage(vkNonDedicatedImage2DList[bIdx], + 0); + nonDedicatedExternalMemory1.push_back( + new clExternalMemoryImage( + *vkNonDedicatedImage2DListDeviceMemory1 + [bIdx], + vkExternalMemoryHandleType, context, + totalImageMemSize, width, height, 0, + vkNonDedicatedImage2DList[bIdx], + deviceId)); + } + VulkanImageViewList vkNonDedicatedImage2DViewList( + vkDevice, vkNonDedicatedImage2DList); + VulkanImage2DList vkNonDedicatedImage2DList2( + num2DImages, vkDevice, vkFormat, width, height, + numMipLevels, vkExternalMemoryHandleType); + for (size_t bIdx = 0; bIdx < num2DImages; bIdx++) + { + if (non_dedicated) + { + vkNonDedicatedImage2DListDeviceMemory2 + .push_back(new VulkanDeviceMemory( + vkDevice, totalImageMemSize, + memoryType, + vkExternalMemoryHandleType)); + } + else + { + vkNonDedicatedImage2DListDeviceMemory2 + .push_back(new VulkanDeviceMemory( + vkDevice, + vkNonDedicatedImage2DList2[bIdx], + memoryType, + vkExternalMemoryHandleType)); + } + vkNonDedicatedImage2DListDeviceMemory2[bIdx] + ->bindImage( + vkNonDedicatedImage2DList2[bIdx], 0); + nonDedicatedExternalMemory2.push_back( + new clExternalMemoryImage( + *vkNonDedicatedImage2DListDeviceMemory2 + [bIdx], + vkExternalMemoryHandleType, context, + totalImageMemSize, width, height, 0, + vkNonDedicatedImage2DList2[bIdx], + deviceId)); + } + VulkanImageViewList vkDedicatedImage2DViewList( + vkDevice, vkNonDedicatedImage2DList2); + + cl_mem external_mem_image1[5]; + cl_mem external_mem_image2[5]; + for (int i = 0; i < num2DImages; i++) + { + external_mem_image1[i] = + nonDedicatedExternalMemory1[i] + ->getExternalMemoryImage(); + external_mem_image2[i] = + nonDedicatedExternalMemory2[i] + ->getExternalMemoryImage(); + } + VulkanImage2DList &vkImage2DList = + vkNonDedicatedImage2DList; + VulkanImageViewList &vkImage2DViewList = + vkNonDedicatedImage2DViewList; + + clCl2VkExternalSemaphore->signal(cmd_queue1); + if (!useSingleImageKernel) + { + for (size_t i2DIdx = 0; + i2DIdx < vkImage2DList.size(); i2DIdx++) + { + for (uint32_t mipLevel = 0; + mipLevel < numMipLevels; mipLevel++) + { + uint32_t i2DvIdx = + (uint32_t)(i2DIdx * numMipLevels) + + mipLevel; + vkDescriptorSet.update( + 1 + i2DvIdx, + vkImage2DViewList[i2DvIdx]); + } + } + vkCopyCommandBuffer.begin(); + vkCopyCommandBuffer.pipelineBarrier( + vkImage2DList, + VULKAN_IMAGE_LAYOUT_UNDEFINED, + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + for (size_t i2DIdx = 0; + i2DIdx < vkImage2DList.size(); i2DIdx++) + { + vkCopyCommandBuffer.copyBufferToImage( + vkSrcBuffer, vkImage2DList[i2DIdx], + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + } + vkCopyCommandBuffer.pipelineBarrier( + vkImage2DList, + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VULKAN_IMAGE_LAYOUT_GENERAL); + vkCopyCommandBuffer.end(); + memset(dstBufferPtr, 0, srcBufSize); + vkQueue.submit(vkCopyCommandBuffer); + vkShaderCommandBuffer.begin(); + vkShaderCommandBuffer.bindPipeline( + vkComputePipeline); + vkShaderCommandBuffer.bindDescriptorSets( + vkComputePipeline, vkPipelineLayout, + vkDescriptorSet); + vkShaderCommandBuffer.dispatch( + NUM_BLOCKS(width, NUM_THREADS_PER_GROUP_X), + NUM_BLOCKS(height, + NUM_THREADS_PER_GROUP_Y / 2), + 1); + vkShaderCommandBuffer.end(); + } + for (uint32_t iter = 0; iter < innerIterations; + iter++) + { + if (useSingleImageKernel) + { + for (size_t i2DIdx = 0; + i2DIdx < vkImage2DList.size(); + i2DIdx++) + { + vkDescriptorSet.update( + 1, vkImage2DViewList[i2DIdx]); + vkCopyCommandBuffer.begin(); + vkCopyCommandBuffer.pipelineBarrier( + vkImage2DList, + VULKAN_IMAGE_LAYOUT_UNDEFINED, + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + vkCopyCommandBuffer.copyBufferToImage( + vkSrcBuffer, vkImage2DList[i2DIdx], + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + vkCopyCommandBuffer.pipelineBarrier( + vkImage2DList, + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VULKAN_IMAGE_LAYOUT_GENERAL); + vkCopyCommandBuffer.end(); + memset(dstBufferPtr, 0, srcBufSize); + vkQueue.submit(vkCopyCommandBuffer); + vkShaderCommandBuffer.begin(); + vkShaderCommandBuffer.bindPipeline( + vkComputePipeline); + vkShaderCommandBuffer + .bindDescriptorSets( + vkComputePipeline, + vkPipelineLayout, + vkDescriptorSet); + vkShaderCommandBuffer.dispatch( + NUM_BLOCKS(width, + NUM_THREADS_PER_GROUP_X), + NUM_BLOCKS(height, + NUM_THREADS_PER_GROUP_Y + / 2), + 1); + vkShaderCommandBuffer.end(); + if (i2DIdx < vkImage2DList.size() - 1) + { + vkQueue.submit( + vkShaderCommandBuffer); + } + } + } + vkQueue.submit(vkCl2VkSemaphore, + vkShaderCommandBuffer, + vkVk2CLSemaphore); + clVk2CLExternalSemaphore->wait(cmd_queue1); + switch (num2DImages) + { + case 2: + updateKernelCQ1 = getKernelType( + vkFormat, kernel_float[0], + kernel_signed[0], + kernel_unsigned[0]); + break; + case 3: + updateKernelCQ1 = getKernelType( + vkFormat, kernel_float[1], + kernel_signed[1], + kernel_unsigned[1]); + break; + case 5: + updateKernelCQ1 = getKernelType( + vkFormat, kernel_float[2], + kernel_signed[2], + kernel_unsigned[2]); + break; + } + updateKernelCQ2 = getKernelType( + vkFormat, kernel_float[3], kernel_signed[3], + kernel_unsigned[3]); + // similar kernel-type based on vkFormat + int j = 0; + // Setting arguments of updateKernelCQ2 + + err = clSetKernelArg(updateKernelCQ2, 0, + sizeof(cl_mem), + &external_mem_image1[0]); + err |= clSetKernelArg(updateKernelCQ2, 1, + sizeof(cl_mem), + &external_mem_image2[0]); + err |= clSetKernelArg( + updateKernelCQ2, 2, sizeof(cl_mem), + &external_mem_image1[num2DImages - 1]); + err |= clSetKernelArg( + updateKernelCQ2, 3, sizeof(cl_mem), + &external_mem_image2[num2DImages - 1]); + err |= clSetKernelArg(updateKernelCQ2, 4, + sizeof(unsigned int), + &num2DImages); + err |= clSetKernelArg(updateKernelCQ2, 5, + sizeof(unsigned int), + &width); + err |= clSetKernelArg(updateKernelCQ2, 6, + sizeof(unsigned int), + &height); + err |= clSetKernelArg(updateKernelCQ2, 7, + sizeof(unsigned int), + &numMipLevels); + for (int i = 0; i < num2DImages - 1; i++, ++j) + { + err = clSetKernelArg( + updateKernelCQ1, j, sizeof(cl_mem), + &external_mem_image1[i]); + err |= clSetKernelArg( + updateKernelCQ1, ++j, sizeof(cl_mem), + &external_mem_image2[i]); + } + err |= clSetKernelArg(updateKernelCQ1, j, + sizeof(unsigned int), + &num2DImages); + err |= clSetKernelArg(updateKernelCQ1, ++j, + sizeof(unsigned int), + &width); + err |= clSetKernelArg(updateKernelCQ1, ++j, + sizeof(unsigned int), + &height); + err |= clSetKernelArg(updateKernelCQ1, ++j, + sizeof(unsigned int), + &numMipLevels); + + if (err != CL_SUCCESS) + { + print_error( + err, + "Error: Failed to set arg values \n"); + goto CLEANUP; + } + // clVk2CLExternalSemaphore->wait(cmd_queue1); + size_t global_work_size[3] = { width, height, + 1 }; + cl_event first_launch; + err = clEnqueueNDRangeKernel( + cmd_queue1, updateKernelCQ1, 2, NULL, + global_work_size, NULL, 0, NULL, + &first_launch); + if (err != CL_SUCCESS) + { + goto CLEANUP; + } + err = clEnqueueNDRangeKernel( + cmd_queue2, updateKernelCQ2, 2, NULL, + global_work_size, NULL, 1, &first_launch, + NULL); + if (err != CL_SUCCESS) + { + goto CLEANUP; + } + + clFinish(cmd_queue2); + clCl2VkExternalSemaphore->signal(cmd_queue2); + } + + unsigned int flags = 0; + size_t mipmapLevelOffset = 0; + cl_event eventReadImage = NULL; + clFinish(cmd_queue2); + for (int i = 0; i < num2DImages; i++) + { + err = clEnqueueReadImage( + cmd_queue1, external_mem_image2[i], CL_TRUE, + origin, region, 0, 0, dstBufferPtr, 0, NULL, + &eventReadImage); + + if (err != CL_SUCCESS) + { + print_error(err, + "clEnqueueReadImage failed with" + "error\n"); + } + + if (memcmp(srcBufferPtr, dstBufferPtr, + srcBufSize)) + { + log_info("Source and destination buffers " + "don't match\n"); + if (debug_trace) + { + log_info("Source buffer contents: \n"); + for (uint64_t sIdx = 0; + sIdx < srcBufSize; sIdx++) + { + log_info( + "%d ", + (int)vkSrcBufferDeviceMemoryPtr + [sIdx]); + } + log_info("Destination buffer contents:" + "\n"); + for (uint64_t dIdx = 0; + dIdx < srcBufSize; dIdx++) + { + log_info("%d ", + (int)dstBufferPtr[dIdx]); + } + } + err = -1; + break; + } + } + for (int i = 0; i < num2DImages; i++) + { + delete vkNonDedicatedImage2DListDeviceMemory1 + [i]; + delete vkNonDedicatedImage2DListDeviceMemory2 + [i]; + delete nonDedicatedExternalMemory1[i]; + delete nonDedicatedExternalMemory2[i]; + } + vkNonDedicatedImage2DListDeviceMemory1.erase( + vkNonDedicatedImage2DListDeviceMemory1.begin(), + vkNonDedicatedImage2DListDeviceMemory1.begin() + + num2DImages); + vkNonDedicatedImage2DListDeviceMemory2.erase( + vkNonDedicatedImage2DListDeviceMemory2.begin(), + vkNonDedicatedImage2DListDeviceMemory2.begin() + + num2DImages); + nonDedicatedExternalMemory1.erase( + nonDedicatedExternalMemory1.begin(), + nonDedicatedExternalMemory1.begin() + + num2DImages); + nonDedicatedExternalMemory2.erase( + nonDedicatedExternalMemory2.begin(), + nonDedicatedExternalMemory2.begin() + + num2DImages); + if (CL_SUCCESS != err) + { + goto CLEANUP; + } + } + } + } + } + } + } +CLEANUP: + if (clVk2CLExternalSemaphore) delete clVk2CLExternalSemaphore; + if (clCl2VkExternalSemaphore) delete clCl2VkExternalSemaphore; + + if (srcBufferPtr) free(srcBufferPtr); + if (dstBufferPtr) free(dstBufferPtr); + return err; +} + +int run_test_with_one_queue(cl_context &context, cl_command_queue &cmd_queue1, + cl_kernel *kernel_unsigned, + cl_kernel *kernel_signed, cl_kernel *kernel_float, + VulkanDevice &vkDevice) +{ + cl_int err = CL_SUCCESS; + size_t origin[3] = { 0, 0, 0 }; + size_t region[3] = { 1, 1, 1 }; + cl_kernel updateKernelCQ1; + std::vector vkFormatList = getSupportedVulkanFormatList(); + const std::vector + vkExternalMemoryHandleTypeList = + getSupportedVulkanExternalMemoryHandleTypeList(); + char magicValue = 0; + + VulkanBuffer vkParamsBuffer(vkDevice, sizeof(Params)); + VulkanDeviceMemory vkParamsDeviceMemory( + vkDevice, vkParamsBuffer.getSize(), + getVulkanMemoryType(vkDevice, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_COHERENT)); + vkParamsDeviceMemory.bindBuffer(vkParamsBuffer); + + uint64_t maxImage2DSize = MAX_2D_IMAGE_WIDTH * MAX_2D_IMAGE_HEIGHT + * MAX_2D_IMAGE_ELEMENT_SIZE * 2; + VulkanBuffer vkSrcBuffer(vkDevice, maxImage2DSize); + VulkanDeviceMemory vkSrcBufferDeviceMemory( + vkDevice, vkSrcBuffer.getSize(), + getVulkanMemoryType(vkDevice, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_COHERENT)); + vkSrcBufferDeviceMemory.bindBuffer(vkSrcBuffer); + + char *srcBufferPtr, *dstBufferPtr; + srcBufferPtr = (char *)malloc(maxImage2DSize); + dstBufferPtr = (char *)malloc(maxImage2DSize); + + VulkanDescriptorSetLayoutBindingList vkDescriptorSetLayoutBindingList( + VULKAN_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VULKAN_DESCRIPTOR_TYPE_STORAGE_IMAGE, MAX_2D_IMAGE_DESCRIPTORS); + VulkanDescriptorSetLayout vkDescriptorSetLayout( + vkDevice, vkDescriptorSetLayoutBindingList); + VulkanPipelineLayout vkPipelineLayout(vkDevice, vkDescriptorSetLayout); + + VulkanDescriptorPool vkDescriptorPool(vkDevice, + vkDescriptorSetLayoutBindingList); + VulkanDescriptorSet vkDescriptorSet(vkDevice, vkDescriptorPool, + vkDescriptorSetLayout); + + VulkanCommandPool vkCommandPool(vkDevice); + VulkanCommandBuffer vkCopyCommandBuffer(vkDevice, vkCommandPool); + VulkanCommandBuffer vkShaderCommandBuffer(vkDevice, vkCommandPool); + VulkanQueue &vkQueue = vkDevice.getQueue(); + + VulkanExternalSemaphoreHandleType vkExternalSemaphoreHandleType = + getSupportedVulkanExternalSemaphoreHandleTypeList()[0]; + VulkanSemaphore vkVk2CLSemaphore(vkDevice, vkExternalSemaphoreHandleType); + VulkanSemaphore vkCl2VkSemaphore(vkDevice, vkExternalSemaphoreHandleType); + clExternalSemaphore *clVk2CLExternalSemaphore = NULL; + clExternalSemaphore *clCl2VkExternalSemaphore = NULL; + + clVk2CLExternalSemaphore = new clExternalSemaphore( + vkVk2CLSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + clCl2VkExternalSemaphore = new clExternalSemaphore( + vkCl2VkSemaphore, context, vkExternalSemaphoreHandleType, deviceId); + + for (size_t fIdx = 0; fIdx < vkFormatList.size(); fIdx++) + { + VulkanFormat vkFormat = vkFormatList[fIdx]; + log_info("Format: %d\n", vkFormat); + uint32_t elementSize = getVulkanFormatElementSize(vkFormat); + ASSERT_LEQ(elementSize, (uint32_t)MAX_2D_IMAGE_ELEMENT_SIZE); + log_info("elementSize= %d\n", elementSize); + std::map patternToSubstituteMap; + patternToSubstituteMap[GLSL_FORMAT_STRING] = + getVulkanFormatGLSLFormat(vkFormat); + patternToSubstituteMap[GLSL_TYPE_PREFIX_STRING] = + getVulkanFormatGLSLTypePrefix(vkFormat); + + VulkanShaderModule vkImage2DShaderModule( + vkDevice, + prepareVulkanShader(vkImage2DShader, patternToSubstituteMap)); + VulkanComputePipeline vkComputePipeline(vkDevice, vkPipelineLayout, + vkImage2DShaderModule); + + for (size_t wIdx = 0; wIdx < ARRAY_SIZE(widthList); wIdx++) + { + uint32_t width = widthList[wIdx]; + log_info("Width: %d\n", width); + ASSERT_LEQ(width, (uint32_t)MAX_2D_IMAGE_WIDTH); + region[0] = width; + for (size_t hIdx = 0; hIdx < ARRAY_SIZE(heightList); hIdx++) + { + uint32_t height = heightList[hIdx]; + log_info("Height: %d\n", height); + ASSERT_LEQ(height, (uint32_t)MAX_2D_IMAGE_HEIGHT); + region[1] = height; + + uint32_t numMipLevels = 1; + log_info("Number of mipmap levels: %d\n", numMipLevels); + + magicValue++; + char *vkSrcBufferDeviceMemoryPtr = + (char *)vkSrcBufferDeviceMemory.map(); + uint64_t srcBufSize = 0; + memset(vkSrcBufferDeviceMemoryPtr, 0, maxImage2DSize); + memset(srcBufferPtr, 0, maxImage2DSize); + uint32_t mipLevel = 0; + for (uint32_t row = 0; + row < std::max(height >> mipLevel, uint32_t(1)); row++) + { + for (uint32_t col = 0; + col < std::max(width >> mipLevel, uint32_t(1)); col++) + { + for (uint32_t elementByte = 0; + elementByte < elementSize; elementByte++) + { + vkSrcBufferDeviceMemoryPtr[srcBufSize] = + (char)(magicValue + mipLevel + row + col); + srcBufferPtr[srcBufSize] = + (char)(magicValue + mipLevel + row + col); + srcBufSize++; + } + } + } + srcBufSize = ROUND_UP( + srcBufSize, + std::max( + elementSize, + (uint32_t)VULKAN_MIN_BUFFER_OFFSET_COPY_ALIGNMENT)); + vkSrcBufferDeviceMemory.unmap(); + + for (size_t niIdx = 0; niIdx < ARRAY_SIZE(num2DImagesList); + niIdx++) + { + uint32_t num2DImages = num2DImagesList[niIdx]; + log_info("Number of images: %d\n", num2DImages); + ASSERT_LEQ(num2DImages, (uint32_t)MAX_2D_IMAGES); + + Params *params = (Params *)vkParamsDeviceMemory.map(); + uint32_t num_2D_image; + if (useSingleImageKernel) + { + num_2D_image = 1; + } + else + { + num_2D_image = num2DImages; + } + params->numImage2DDescriptors = num_2D_image * numMipLevels; + vkParamsDeviceMemory.unmap(); + vkDescriptorSet.update(0, vkParamsBuffer); + for (size_t emhtIdx = 0; + emhtIdx < vkExternalMemoryHandleTypeList.size(); + emhtIdx++) + { + VulkanExternalMemoryHandleType + vkExternalMemoryHandleType = + vkExternalMemoryHandleTypeList[emhtIdx]; + log_info("External memory handle type: %d \n", + vkExternalMemoryHandleType); + if ((true == disableNTHandleType) + && (VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT + == vkExternalMemoryHandleType)) + { + // Skip running for WIN32 NT handle. + continue; + } + VulkanImage2D vkDummyImage2D( + vkDevice, vkFormatList[0], widthList[0], + heightList[0], 1, vkExternalMemoryHandleType); + const VulkanMemoryTypeList &memoryTypeList = + vkDummyImage2D.getMemoryTypeList(); + + std::vector + vkNonDedicatedImage2DListDeviceMemory1; + std::vector + vkNonDedicatedImage2DListDeviceMemory2; + std::vector + nonDedicatedExternalMemory1; + std::vector + nonDedicatedExternalMemory2; + for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); + mtIdx++) + { + const VulkanMemoryType &memoryType = + memoryTypeList[mtIdx]; + log_info("Memory type index: %d\n", + (uint32_t)memoryType); + log_info("Memory type property: %d\n", + memoryType.getMemoryTypeProperty()); + if (!useDeviceLocal) + { + if (VULKAN_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL + == memoryType.getMemoryTypeProperty()) + { + continue; + } + } + size_t totalImageMemSize = 0; + uint64_t interImageOffset = 0; + { + VulkanImage2D vkImage2D( + vkDevice, vkFormat, width, height, + numMipLevels, vkExternalMemoryHandleType); + ASSERT_LEQ(vkImage2D.getSize(), maxImage2DSize); + totalImageMemSize = + ROUND_UP(vkImage2D.getSize(), + vkImage2D.getAlignment()); + } + VulkanImage2DList vkNonDedicatedImage2DList( + num2DImages, vkDevice, vkFormat, width, height, + numMipLevels, vkExternalMemoryHandleType); + for (size_t bIdx = 0; + bIdx < vkNonDedicatedImage2DList.size(); + bIdx++) + { + // Create list of Vulkan device memories and + // bind the list of Vulkan images. + vkNonDedicatedImage2DListDeviceMemory1 + .push_back(new VulkanDeviceMemory( + vkDevice, totalImageMemSize, memoryType, + vkExternalMemoryHandleType)); + vkNonDedicatedImage2DListDeviceMemory1[bIdx] + ->bindImage(vkNonDedicatedImage2DList[bIdx], + 0); + nonDedicatedExternalMemory1.push_back( + new clExternalMemoryImage( + *vkNonDedicatedImage2DListDeviceMemory1 + [bIdx], + vkExternalMemoryHandleType, context, + totalImageMemSize, width, height, 0, + vkNonDedicatedImage2DList[bIdx], + deviceId)); + } + VulkanImageViewList vkNonDedicatedImage2DViewList( + vkDevice, vkNonDedicatedImage2DList); + + VulkanImage2DList vkNonDedicatedImage2DList2( + num2DImages, vkDevice, vkFormat, width, height, + numMipLevels, vkExternalMemoryHandleType); + for (size_t bIdx = 0; + bIdx < vkNonDedicatedImage2DList2.size(); + bIdx++) + { + vkNonDedicatedImage2DListDeviceMemory2 + .push_back(new VulkanDeviceMemory( + vkDevice, totalImageMemSize, memoryType, + vkExternalMemoryHandleType)); + vkNonDedicatedImage2DListDeviceMemory2[bIdx] + ->bindImage( + vkNonDedicatedImage2DList2[bIdx], 0); + nonDedicatedExternalMemory2.push_back( + new clExternalMemoryImage( + *vkNonDedicatedImage2DListDeviceMemory2 + [bIdx], + vkExternalMemoryHandleType, context, + totalImageMemSize, width, height, 0, + vkNonDedicatedImage2DList2[bIdx], + deviceId)); + } + VulkanImageViewList vkDedicatedImage2DViewList( + vkDevice, vkNonDedicatedImage2DList2); + cl_mem external_mem_image1[4]; + cl_mem external_mem_image2[4]; + for (int i = 0; i < num2DImages; i++) + { + external_mem_image1[i] = + nonDedicatedExternalMemory1[i] + ->getExternalMemoryImage(); + external_mem_image2[i] = + nonDedicatedExternalMemory2[i] + ->getExternalMemoryImage(); + } + VulkanImage2DList &vkImage2DList = + vkNonDedicatedImage2DList; + VulkanImageViewList &vkImage2DViewList = + vkNonDedicatedImage2DViewList; + + clCl2VkExternalSemaphore->signal(cmd_queue1); + if (!useSingleImageKernel) + { + for (size_t i2DIdx = 0; + i2DIdx < vkImage2DList.size(); i2DIdx++) + { + for (uint32_t mipLevel = 0; + mipLevel < numMipLevels; mipLevel++) + { + uint32_t i2DvIdx = + (uint32_t)(i2DIdx * numMipLevels) + + mipLevel; + vkDescriptorSet.update( + 1 + i2DvIdx, + vkImage2DViewList[i2DvIdx]); + } + } + vkCopyCommandBuffer.begin(); + vkCopyCommandBuffer.pipelineBarrier( + vkImage2DList, + VULKAN_IMAGE_LAYOUT_UNDEFINED, + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + for (size_t i2DIdx = 0; + i2DIdx < vkImage2DList.size(); i2DIdx++) + { + vkCopyCommandBuffer.copyBufferToImage( + vkSrcBuffer, vkImage2DList[i2DIdx], + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + } + vkCopyCommandBuffer.pipelineBarrier( + vkImage2DList, + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VULKAN_IMAGE_LAYOUT_GENERAL); + vkCopyCommandBuffer.end(); + memset(dstBufferPtr, 0, srcBufSize); + vkQueue.submit(vkCopyCommandBuffer); + vkShaderCommandBuffer.begin(); + vkShaderCommandBuffer.bindPipeline( + vkComputePipeline); + vkShaderCommandBuffer.bindDescriptorSets( + vkComputePipeline, vkPipelineLayout, + vkDescriptorSet); + vkShaderCommandBuffer.dispatch( + NUM_BLOCKS(width, NUM_THREADS_PER_GROUP_X), + NUM_BLOCKS(height, + NUM_THREADS_PER_GROUP_Y / 2), + 1); + vkShaderCommandBuffer.end(); + } + for (uint32_t iter = 0; iter < innerIterations; + iter++) + { + if (useSingleImageKernel) + { + for (size_t i2DIdx = 0; + i2DIdx < vkImage2DList.size(); + i2DIdx++) + { + vkDescriptorSet.update( + 1, vkImage2DViewList[i2DIdx]); + vkCopyCommandBuffer.begin(); + vkCopyCommandBuffer.pipelineBarrier( + vkImage2DList, + VULKAN_IMAGE_LAYOUT_UNDEFINED, + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + vkCopyCommandBuffer.copyBufferToImage( + vkSrcBuffer, vkImage2DList[i2DIdx], + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + vkCopyCommandBuffer.pipelineBarrier( + vkImage2DList, + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VULKAN_IMAGE_LAYOUT_GENERAL); + vkCopyCommandBuffer.end(); + memset(dstBufferPtr, 0, srcBufSize); + vkQueue.submit(vkCopyCommandBuffer); + vkShaderCommandBuffer.begin(); + vkShaderCommandBuffer.bindPipeline( + vkComputePipeline); + vkShaderCommandBuffer + .bindDescriptorSets( + vkComputePipeline, + vkPipelineLayout, + vkDescriptorSet); + vkShaderCommandBuffer.dispatch( + NUM_BLOCKS(width, + NUM_THREADS_PER_GROUP_X), + NUM_BLOCKS(height, + NUM_THREADS_PER_GROUP_Y + / 2), + 1); + vkShaderCommandBuffer.end(); + if (i2DIdx < vkImage2DList.size() - 1) + { + vkQueue.submit( + vkShaderCommandBuffer); + } + } + } + vkQueue.submit(vkCl2VkSemaphore, + vkShaderCommandBuffer, + vkVk2CLSemaphore); + clVk2CLExternalSemaphore->wait(cmd_queue1); + switch (num2DImages) + { + case 1: + updateKernelCQ1 = getKernelType( + vkFormat, kernel_float[0], + kernel_signed[0], + kernel_unsigned[0]); + break; + case 2: + updateKernelCQ1 = getKernelType( + vkFormat, kernel_float[1], + kernel_signed[1], + kernel_unsigned[1]); + break; + case 4: + updateKernelCQ1 = getKernelType( + vkFormat, kernel_float[2], + kernel_signed[2], + kernel_unsigned[2]); + break; + } + int j = 0; + for (int i = 0; i < num2DImages; i++, ++j) + { + err = clSetKernelArg( + updateKernelCQ1, j, sizeof(cl_mem), + &external_mem_image1[i]); + err |= clSetKernelArg( + updateKernelCQ1, ++j, sizeof(cl_mem), + &external_mem_image2[i]); + } + err |= clSetKernelArg(updateKernelCQ1, j, + sizeof(unsigned int), + &num2DImages); + err |= clSetKernelArg(updateKernelCQ1, ++j, + sizeof(unsigned int), + &width); + err |= clSetKernelArg(updateKernelCQ1, ++j, + sizeof(unsigned int), + &height); + err |= clSetKernelArg(updateKernelCQ1, ++j, + sizeof(unsigned int), + &numMipLevels); + + if (err != CL_SUCCESS) + { + print_error(err, + "Error: Failed to set arg " + "values for kernel-1\n"); + goto CLEANUP; + } + + size_t global_work_size[3] = { width, height, + 1 }; + err = clEnqueueNDRangeKernel( + cmd_queue1, updateKernelCQ1, 2, NULL, + global_work_size, NULL, 0, NULL, NULL); + if (err != CL_SUCCESS) + { + goto CLEANUP; + } + clCl2VkExternalSemaphore->signal(cmd_queue1); + } + + unsigned int flags = 0; + size_t mipmapLevelOffset = 0; + cl_event eventReadImage = NULL; + for (int i = 0; i < num2DImages; i++) + { + err = clEnqueueReadImage( + cmd_queue1, external_mem_image2[i], CL_TRUE, + origin, region, 0, 0, dstBufferPtr, 0, NULL, + &eventReadImage); + + if (err != CL_SUCCESS) + { + print_error(err, + "clEnqueueReadImage failed with" + "error\n"); + } + + if (memcmp(srcBufferPtr, dstBufferPtr, + srcBufSize)) + { + log_info("Source and destination buffers " + "don't match\n"); + if (debug_trace) + { + log_info("Source buffer contents: \n"); + for (uint64_t sIdx = 0; + sIdx < srcBufSize; sIdx++) + { + log_info( + "%d", + (int)vkSrcBufferDeviceMemoryPtr + [sIdx]); + } + log_info( + "Destination buffer contents:"); + for (uint64_t dIdx = 0; + dIdx < srcBufSize; dIdx++) + { + log_info("%d", + (int)dstBufferPtr[dIdx]); + } + } + err = -1; + break; + } + } + for (int i = 0; i < num2DImages; i++) + { + delete vkNonDedicatedImage2DListDeviceMemory1 + [i]; + delete vkNonDedicatedImage2DListDeviceMemory2 + [i]; + delete nonDedicatedExternalMemory1[i]; + delete nonDedicatedExternalMemory2[i]; + } + vkNonDedicatedImage2DListDeviceMemory1.erase( + vkNonDedicatedImage2DListDeviceMemory1.begin(), + vkNonDedicatedImage2DListDeviceMemory1.begin() + + num2DImages); + vkNonDedicatedImage2DListDeviceMemory2.erase( + vkNonDedicatedImage2DListDeviceMemory2.begin(), + vkNonDedicatedImage2DListDeviceMemory2.begin() + + num2DImages); + nonDedicatedExternalMemory1.erase( + nonDedicatedExternalMemory1.begin(), + nonDedicatedExternalMemory1.begin() + + num2DImages); + nonDedicatedExternalMemory2.erase( + nonDedicatedExternalMemory2.begin(), + nonDedicatedExternalMemory2.begin() + + num2DImages); + if (CL_SUCCESS != err) + { + goto CLEANUP; + } + } + } + } + } + } + } +CLEANUP: + if (clVk2CLExternalSemaphore) delete clVk2CLExternalSemaphore; + if (clCl2VkExternalSemaphore) delete clCl2VkExternalSemaphore; + + if (srcBufferPtr) free(srcBufferPtr); + if (dstBufferPtr) free(dstBufferPtr); + return err; +} + +int test_image_common(cl_device_id device_, cl_context context_, + cl_command_queue queue_, int numElements_) +{ + int current_device = 0; + int device_count = 0; + int devices_prohibited = 0; + cl_int err = CL_SUCCESS; + cl_platform_id platform = NULL; + size_t extensionSize = 0; + cl_uint num_devices = 0; + cl_uint device_no = 0; + cl_device_id *devices; + char *extensions = NULL; + const char *program_source_const; + cl_command_queue cmd_queue1 = NULL; + cl_command_queue cmd_queue2 = NULL; + cl_context context = NULL; + const uint32_t num_kernels = ARRAY_SIZE(num2DImagesList) + 1; + // One kernel for Cross-CQ case + const uint32_t num_kernel_types = 3; + const char *kernel_source[num_kernels] = { kernel_text_numImage_1, + kernel_text_numImage_2, + kernel_text_numImage_4 }; + char source_1[4096]; + char source_2[4096]; + char source_3[4096]; + size_t program_source_length; + cl_program program[num_kernel_types]; + cl_kernel kernel_float[num_kernels] = { NULL, NULL, NULL, NULL }; + cl_kernel kernel_signed[num_kernels] = { NULL, NULL, NULL, NULL }; + cl_kernel kernel_unsigned[num_kernels] = { NULL, NULL, NULL, NULL }; + cl_mem external_mem_image1; + cl_mem external_mem_image2; + + VulkanDevice vkDevice; + + cl_context_properties contextProperties[] = { CL_CONTEXT_PLATFORM, 0, 0 }; + // get the platform ID + err = clGetPlatformIDs(1, &platform, NULL); + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed to get platform\n"); + goto CLEANUP; + } + + err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &num_devices); + if (CL_SUCCESS != err) + { + print_error(err, "clGetDeviceIDs failed in returning no. of devices\n"); + goto CLEANUP; + } + devices = (cl_device_id *)malloc(num_devices * sizeof(cl_device_id)); + if (NULL == devices) + { + err = CL_OUT_OF_HOST_MEMORY; + print_error(err, "Unable to allocate memory for devices\n"); + goto CLEANUP; + } + err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, num_devices, devices, + NULL); + if (CL_SUCCESS != err) + { + print_error(err, "Failed to get deviceID.\n"); + goto CLEANUP; + } + contextProperties[1] = (cl_context_properties)platform; + log_info("Assigned contextproperties for platform\n"); + for (device_no = 0; device_no < num_devices; device_no++) + { + err = clGetDeviceInfo(devices[device_no], CL_DEVICE_EXTENSIONS, 0, NULL, + &extensionSize); + if (CL_SUCCESS != err) + { + print_error( + err, + "Error in clGetDeviceInfo for getting device_extension size\n"); + goto CLEANUP; + } + extensions = (char *)malloc(extensionSize); + if (NULL == extensions) + { + err = CL_OUT_OF_HOST_MEMORY; + print_error(err, "Unable to allocate memory for extensions\n"); + goto CLEANUP; + } + err = clGetDeviceInfo(devices[device_no], CL_DEVICE_EXTENSIONS, + extensionSize, extensions, NULL); + if (CL_SUCCESS != err) + { + print_error( + err, "Error in clGetDeviceInfo for getting device_extension\n"); + goto CLEANUP; + } + err = clGetDeviceInfo(devices[device_no], CL_DEVICE_UUID_KHR, + CL_UUID_SIZE_KHR, uuid, &extensionSize); + if (CL_SUCCESS != err) + { + print_error(err, "clGetDeviceInfo failed with error"); + goto CLEANUP; + } + err = + memcmp(uuid, vkDevice.getPhysicalDevice().getUUID(), VK_UUID_SIZE); + if (err == 0) + { + break; + } + } + if (device_no >= num_devices) + { + err = EXIT_FAILURE; + print_error(err, + "OpenCL error:" + "No Vulkan-OpenCL Interop capable GPU found.\n"); + goto CLEANUP; + } + deviceId = devices[device_no]; + context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU, + NULL, NULL, &err); + if (CL_SUCCESS != err) + { + print_error(err, "error creating context"); + goto CLEANUP; + } + log_info("Successfully created context !!!\n"); + + cmd_queue1 = clCreateCommandQueue(context, devices[device_no], 0, &err); + if (CL_SUCCESS != err) + { + err = CL_INVALID_COMMAND_QUEUE; + print_error(err, "Error: Failed to create command queue!\n"); + goto CLEANUP; + } + log_info("clCreateCommandQueue successfull \n"); + + cmd_queue2 = clCreateCommandQueue(context, devices[device_no], 0, &err); + if (CL_SUCCESS != err) + { + err = CL_INVALID_COMMAND_QUEUE; + print_error(err, "Error: Failed to create command queue!\n"); + goto CLEANUP; + } + log_info("clCreateCommandQueue2 successful \n"); + + for (int i = 0; i < num_kernels; i++) + { + switch (i) + { + case 0: + sprintf(source_1, kernel_source[i], "float4", "f", "float4", + "f", "f", "f"); + sprintf(source_2, kernel_source[i], "int4", "i", "int4", "i", + "i", "i"); + sprintf(source_3, kernel_source[i], "uint4", "ui", "uint4", + "ui", "ui", "ui"); + break; + case 1: + sprintf(source_1, kernel_source[i], "float4", "f", "float4", + "f", "float4", "f", "float4", "f", "f", "f", "f", "f"); + sprintf(source_2, kernel_source[i], "int4", "i", "int4", "i", + "int4", "i", "int4", "i", "i", "i", "i", "i"); + sprintf(source_3, kernel_source[i], "uint4", "ui", "uint4", + "ui", "uint4", "ui", "uint4", "ui", "ui", "ui", "ui", + "ui"); + break; + case 2: + sprintf(source_1, kernel_source[i], "float4", "f", "float4", + "f", "float4", "f", "float4", "f", "float4", "f", + "float4", "f", "float4", "f", "float4", "f", "f", "f", + "f", "f", "f", "f", "f", "f"); + sprintf(source_2, kernel_source[i], "int4", "i", "int4", "i", + "int4", "i", "int4", "i", "int4", "i", "int4", "i", + "int4", "i", "int4", "i", "i", "i", "i", "i", "i", "i", + "i", "i"); + sprintf(source_3, kernel_source[i], "uint4", "ui", "uint4", + "ui", "uint4", "ui", "uint4", "ui", "uint4", "ui", + "uint4", "ui", "uint4", "ui", "uint4", "ui", "ui", "ui", + "ui", "ui", "ui", "ui", "ui", "ui"); + break; + case 3: + // Addtional case for creating updateKernelCQ2 which takes two + // images + sprintf(source_1, kernel_source[1], "float4", "f", "float4", + "f", "float4", "f", "float4", "f", "f", "f", "f", "f"); + sprintf(source_2, kernel_source[1], "int4", "i", "int4", "i", + "int4", "i", "int4", "i", "i", "i", "i", "i"); + sprintf(source_3, kernel_source[1], "uint4", "ui", "uint4", + "ui", "uint4", "ui", "uint4", "ui", "ui", "ui", "ui", + "ui"); + break; + } + const char *sourceTexts[num_kernel_types] = { source_1, source_2, + source_3 }; + for (int k = 0; k < num_kernel_types; k++) + { + program_source_length = strlen(sourceTexts[k]); + program[k] = clCreateProgramWithSource( + context, 1, &sourceTexts[k], &program_source_length, &err); + err |= clBuildProgram(program[k], 0, NULL, NULL, NULL, NULL); + } + + if (err != CL_SUCCESS) + { + print_error(err, "Error: Failed to build program"); + goto CLEANUP; + } + // create the kernel + kernel_float[i] = clCreateKernel(program[0], "image2DKernel", &err); + if (err != CL_SUCCESS) + { + print_error(err, "clCreateKernel failed"); + goto CLEANUP; + } + kernel_signed[i] = clCreateKernel(program[1], "image2DKernel", &err); + if (err != CL_SUCCESS) + { + print_error(err, "clCreateKernel failed"); + goto CLEANUP; + } + kernel_unsigned[i] = clCreateKernel(program[2], "image2DKernel", &err); + if (err != CL_SUCCESS) + { + print_error(err, "clCreateKernel failed "); + goto CLEANUP; + } + } + if (numCQ == 2) + { + err = run_test_with_two_queue(context, cmd_queue1, cmd_queue2, + kernel_unsigned, kernel_signed, + kernel_float, vkDevice); + } + else + { + err = run_test_with_one_queue(context, cmd_queue1, kernel_unsigned, + kernel_signed, kernel_float, vkDevice); + } +CLEANUP: + for (int i = 0; i < num_kernels; i++) + { + if (kernel_float[i]) + { + clReleaseKernel(kernel_float[i]); + } + if (kernel_unsigned[i]) + { + clReleaseKernel(kernel_unsigned[i]); + } + if (kernel_signed[i]) + { + clReleaseKernel(kernel_signed[i]); + } + } + for (int i = 0; i < num_kernel_types; i++) + { + if (program[i]) + { + clReleaseProgram(program[i]); + } + } + if (cmd_queue1) clReleaseCommandQueue(cmd_queue1); + if (cmd_queue2) clReleaseCommandQueue(cmd_queue2); + if (context) clReleaseContext(context); + + if (extensions) free(extensions); + if (devices) free(devices); + + return err; +} diff --git a/test_conformance/vulkan/test_vulkan_platform_device_info.cpp b/test_conformance/vulkan/test_vulkan_platform_device_info.cpp new file mode 100644 index 00000000..12f373b5 --- /dev/null +++ b/test_conformance/vulkan/test_vulkan_platform_device_info.cpp @@ -0,0 +1,146 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#include +#include +#include "harness/testHarness.h" +#include +#include + +typedef struct +{ + cl_uint info; + const char *name; +} _info; + +_info platform_info_table[] = { +#define STRING(x) \ + { \ + x, #x \ + } + STRING(CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR), + STRING(CL_PLATFORM_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR), + STRING(CL_PLATFORM_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR) +#undef STRING +}; + +_info device_info_table[] = { +#define STRING(x) \ + { \ + x, #x \ + } + STRING(CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR), + STRING(CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR), + STRING(CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR) +#undef STRING +}; + +int test_platform_info(cl_device_id deviceID, cl_context _context, + cl_command_queue _queue, int num_elements) +{ + cl_uint num_platforms; + cl_uint i, j; + cl_platform_id *platforms; + cl_int errNum; + cl_uint *handle_type; + size_t handle_type_size = 0; + cl_uint num_handles = 0; + + // get total # of platforms + errNum = clGetPlatformIDs(0, NULL, &num_platforms); + test_error(errNum, "clGetPlatformIDs (getting count) failed"); + + platforms = + (cl_platform_id *)malloc(num_platforms * sizeof(cl_platform_id)); + if (!platforms) + { + printf("error allocating memory\n"); + exit(1); + } + log_info("%d platforms available\n", num_platforms); + errNum = clGetPlatformIDs(num_platforms, platforms, NULL); + test_error(errNum, "clGetPlatformIDs (getting IDs) failed"); + + for (i = 0; i < num_platforms; i++) + { + log_info("Platform%d (id %lu) info:\n", i, (unsigned long)platforms[i]); + for (j = 0; + j < sizeof(platform_info_table) / sizeof(platform_info_table[0]); + j++) + { + errNum = + clGetPlatformInfo(platforms[i], platform_info_table[j].info, 0, + NULL, &handle_type_size); + test_error(errNum, "clGetPlatformInfo failed"); + num_handles = handle_type_size / sizeof(cl_uint); + handle_type = (cl_uint *)malloc(handle_type_size); + errNum = + clGetPlatformInfo(platforms[i], platform_info_table[j].info, + handle_type_size, handle_type, NULL); + test_error(errNum, "clGetPlatformInfo failed"); + + log_info("%s: \n", platform_info_table[j].name); + while (num_handles--) + { + log_info("%x \n", handle_type[num_handles]); + } + if (handle_type) + { + free(handle_type); + } + } + } + if (platforms) + { + free(platforms); + } + return TEST_PASS; +} + +int test_device_info(cl_device_id deviceID, cl_context _context, + cl_command_queue _queue, int num_elements) +{ + cl_uint j; + cl_uint *handle_type; + size_t handle_type_size = 0; + cl_uint num_handles = 0; + cl_int errNum = CL_SUCCESS; + for (j = 0; j < sizeof(device_info_table) / sizeof(device_info_table[0]); + j++) + { + errNum = clGetDeviceInfo(deviceID, device_info_table[j].info, 0, NULL, + &handle_type_size); + test_error(errNum, "clGetDeviceInfo failed"); + + num_handles = handle_type_size / sizeof(cl_uint); + handle_type = (cl_uint *)malloc(handle_type_size); + + errNum = clGetDeviceInfo(deviceID, device_info_table[j].info, + handle_type_size, handle_type, NULL); + test_error(errNum, "clGetDeviceInfo failed"); + + log_info("%s: \n", device_info_table[j].name); + while (num_handles--) + { + log_info("%x \n", handle_type[num_handles]); + } + if (handle_type) + { + free(handle_type); + } + } + return TEST_PASS; +} diff --git a/test_conformance/vulkan/vulkan_interop_common/opencl_vulkan_wrapper.cpp b/test_conformance/vulkan/vulkan_interop_common/opencl_vulkan_wrapper.cpp new file mode 100644 index 00000000..136818f6 --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/opencl_vulkan_wrapper.cpp @@ -0,0 +1,818 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// +#include +#include "opencl_vulkan_wrapper.hpp" +#include "vulkan_wrapper.hpp" +#include "harness/errorHelpers.h" +#include "harness/deviceInfo.h" +#include +#include +#include + +#define ASSERT(x) assert((x)) + +pfnclCreateSemaphoreWithPropertiesKHR clCreateSemaphoreWithPropertiesKHRptr; +pfnclEnqueueWaitSemaphoresKHR clEnqueueWaitSemaphoresKHRptr; +pfnclEnqueueSignalSemaphoresKHR clEnqueueSignalSemaphoresKHRptr; +pfnclEnqueueAcquireExternalMemObjectsKHR + clEnqueueAcquireExternalMemObjectsKHRptr; +pfnclEnqueueReleaseExternalMemObjectsKHR + clEnqueueReleaseExternalMemObjectsKHRptr; +pfnclReleaseSemaphoreObjectKHR clReleaseSemaphoreObjectKHRptr; + +void init_cl_vk_ext(cl_platform_id opencl_platform) +{ + clEnqueueWaitSemaphoresKHRptr = + (pfnclEnqueueWaitSemaphoresKHR)clGetExtensionFunctionAddressForPlatform( + opencl_platform, "clEnqueueWaitSemaphoresKHR"); + if (NULL == clEnqueueWaitSemaphoresKHRptr) + { + throw std::runtime_error("Failed to get the function pointer of " + "clEnqueueWaitSemaphoresKHRptr!"); + } + clEnqueueSignalSemaphoresKHRptr = (pfnclEnqueueSignalSemaphoresKHR) + clGetExtensionFunctionAddressForPlatform( + opencl_platform, "clEnqueueSignalSemaphoresKHR"); + if (NULL == clEnqueueSignalSemaphoresKHRptr) + { + throw std::runtime_error("Failed to get the function pointer of " + "clEnqueueSignalSemaphoresKHRptr!"); + } + clReleaseSemaphoreObjectKHRptr = (pfnclReleaseSemaphoreObjectKHR) + clGetExtensionFunctionAddressForPlatform(opencl_platform, + "clReleaseSemaphoreObjectKHR"); + if (NULL == clReleaseSemaphoreObjectKHRptr) + { + throw std::runtime_error("Failed to get the function pointer of " + "clReleaseSemaphoreObjectKHRptr!"); + } + clCreateSemaphoreWithPropertiesKHRptr = + (pfnclCreateSemaphoreWithPropertiesKHR) + clGetExtensionFunctionAddressForPlatform( + opencl_platform, "clCreateSemaphoreWithPropertiesKHR"); + if (NULL == clCreateSemaphoreWithPropertiesKHRptr) + { + throw std::runtime_error("Failed to get the function pointer of " + "clCreateSemaphoreWithPropertiesKHRptr!"); + } +} + +cl_int getCLFormatFromVkFormat(VkFormat vkFormat, + cl_image_format *clImageFormat) +{ + cl_int result = CL_SUCCESS; + switch (vkFormat) + { + case VK_FORMAT_R8G8B8A8_UNORM: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_UNORM_INT8; + break; + case VK_FORMAT_B8G8R8A8_UNORM: + clImageFormat->image_channel_order = CL_BGRA; + clImageFormat->image_channel_data_type = CL_UNORM_INT8; + break; + case VK_FORMAT_R16G16B16A16_UNORM: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_UNORM_INT16; + break; + case VK_FORMAT_R8G8B8A8_SINT: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_SIGNED_INT8; + break; + case VK_FORMAT_R16G16B16A16_SINT: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_SIGNED_INT16; + break; + case VK_FORMAT_R32G32B32A32_SINT: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_SIGNED_INT32; + break; + case VK_FORMAT_R8G8B8A8_UINT: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8; + break; + case VK_FORMAT_R16G16B16A16_UINT: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_UNSIGNED_INT16; + break; + case VK_FORMAT_R32G32B32A32_UINT: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_UNSIGNED_INT32; + break; + case VK_FORMAT_R16G16B16A16_SFLOAT: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_HALF_FLOAT; + break; + case VK_FORMAT_R32G32B32A32_SFLOAT: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_FLOAT; + break; + case VK_FORMAT_R8_SNORM: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_SNORM_INT8; + break; + case VK_FORMAT_R16_SNORM: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_SNORM_INT16; + break; + case VK_FORMAT_R8_UNORM: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_UNORM_INT8; + break; + case VK_FORMAT_R16_UNORM: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_UNORM_INT16; + break; + case VK_FORMAT_R8_SINT: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_SIGNED_INT8; + break; + case VK_FORMAT_R16_SINT: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_SIGNED_INT16; + break; + case VK_FORMAT_R32_SINT: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_SIGNED_INT32; + break; + case VK_FORMAT_R8_UINT: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8; + break; + case VK_FORMAT_R16_UINT: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_UNSIGNED_INT16; + break; + case VK_FORMAT_R32_UINT: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_UNSIGNED_INT32; + break; + case VK_FORMAT_R16_SFLOAT: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_HALF_FLOAT; + break; + case VK_FORMAT_R32_SFLOAT: + clImageFormat->image_channel_order = CL_R; + clImageFormat->image_channel_data_type = CL_FLOAT; + break; + case VK_FORMAT_R8G8_SNORM: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_SNORM_INT8; + break; + case VK_FORMAT_R16G16_SNORM: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_SNORM_INT16; + break; + case VK_FORMAT_R8G8_UNORM: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_UNORM_INT8; + break; + case VK_FORMAT_R16G16_UNORM: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_UNORM_INT16; + break; + case VK_FORMAT_R8G8_SINT: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_SIGNED_INT8; + break; + case VK_FORMAT_R16G16_SINT: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_SIGNED_INT16; + break; + case VK_FORMAT_R32G32_SINT: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_SIGNED_INT32; + break; + case VK_FORMAT_R8G8_UINT: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8; + break; + case VK_FORMAT_R16G16_UINT: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_UNSIGNED_INT16; + break; + case VK_FORMAT_R32G32_UINT: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_UNSIGNED_INT32; + break; + case VK_FORMAT_R16G16_SFLOAT: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_HALF_FLOAT; + break; + case VK_FORMAT_R32G32_SFLOAT: + clImageFormat->image_channel_order = CL_RG; + clImageFormat->image_channel_data_type = CL_FLOAT; + break; + case VK_FORMAT_R5G6B5_UNORM_PACK16: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_UNORM_SHORT_565; + break; + case VK_FORMAT_R5G5B5A1_UNORM_PACK16: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_UNORM_SHORT_555; + break; + case VK_FORMAT_R8G8B8A8_SNORM: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_SNORM_INT8; + break; + case VK_FORMAT_R16G16B16A16_SNORM: + clImageFormat->image_channel_order = CL_RGBA; + clImageFormat->image_channel_data_type = CL_SNORM_INT16; + break; + case VK_FORMAT_B8G8R8A8_SNORM: + clImageFormat->image_channel_order = CL_BGRA; + clImageFormat->image_channel_data_type = CL_SNORM_INT8; + break; + case VK_FORMAT_B5G6R5_UNORM_PACK16: + clImageFormat->image_channel_order = CL_BGRA; + clImageFormat->image_channel_data_type = CL_UNORM_SHORT_565; + break; + case VK_FORMAT_B5G5R5A1_UNORM_PACK16: + clImageFormat->image_channel_order = CL_BGRA; + clImageFormat->image_channel_data_type = CL_UNORM_SHORT_555; + break; + case VK_FORMAT_B8G8R8A8_SINT: + clImageFormat->image_channel_order = CL_BGRA; + clImageFormat->image_channel_data_type = CL_SIGNED_INT8; + break; + case VK_FORMAT_B8G8R8A8_UINT: + clImageFormat->image_channel_order = CL_BGRA; + clImageFormat->image_channel_data_type = CL_UNSIGNED_INT8; + break; + case VK_FORMAT_A8B8G8R8_SNORM_PACK32: result = CL_INVALID_VALUE; break; + case VK_FORMAT_A8B8G8R8_UNORM_PACK32: result = CL_INVALID_VALUE; break; + case VK_FORMAT_A8B8G8R8_SINT_PACK32: result = CL_INVALID_VALUE; break; + case VK_FORMAT_A8B8G8R8_UINT_PACK32: result = CL_INVALID_VALUE; break; + default: + log_error("Unsupported format\n"); + ASSERT(0); + break; + } + return result; +} + +cl_mem_object_type getImageTypeFromVk(VkImageType imageType) +{ + cl_mem_object_type cl_image_type = CL_INVALID_VALUE; + switch (imageType) + { + case VK_IMAGE_TYPE_1D: cl_image_type = CL_MEM_OBJECT_IMAGE1D; break; + case VK_IMAGE_TYPE_2D: cl_image_type = CL_MEM_OBJECT_IMAGE2D; break; + case VK_IMAGE_TYPE_3D: cl_image_type = CL_MEM_OBJECT_IMAGE3D; break; + default: break; + } + return cl_image_type; +} + +size_t GetElementNBytes(const cl_image_format *format) +{ + size_t result; + + switch (format->image_channel_order) + { + case CL_R: + case CL_A: + case CL_INTENSITY: + case CL_LUMINANCE: + case CL_DEPTH: result = 1; break; + case CL_RG: + case CL_RA: result = 2; break; + case CL_RGB: result = 3; break; + case CL_RGBA: + case CL_ARGB: + case CL_BGRA: + case CL_sRGBA: result = 4; break; + default: result = 0; break; + } + + switch (format->image_channel_data_type) + { + case CL_SNORM_INT8: + case CL_UNORM_INT8: + case CL_SIGNED_INT8: + case CL_UNSIGNED_INT8: + // result *= 1; + break; + + case CL_SNORM_INT16: + case CL_UNORM_INT16: + case CL_SIGNED_INT16: + case CL_UNSIGNED_INT16: + case CL_HALF_FLOAT: result *= 2; break; + + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT32: + case CL_FLOAT: result *= 4; break; + + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: + if (result == 3) + { + result = 2; + } + else + { + result = 0; + } + break; + + case CL_UNORM_INT_101010: + if (result == 3) + { + result = 4; + } + else + { + result = 0; + } + break; + + default: result = 0; break; + } + + return result; +} + +cl_int get2DImageDimensions(const VkImageCreateInfo *VulkanImageCreateInfo, + cl_image_format *img_fmt, size_t totalImageSize, + size_t &width, size_t &height) +{ + cl_int result = CL_SUCCESS; + if (totalImageSize == 0) + { + result = CL_INVALID_VALUE; + } + size_t element_size = GetElementNBytes(img_fmt); + size_t row_pitch = element_size * VulkanImageCreateInfo->extent.width; + row_pitch = row_pitch % 64 == 0 ? row_pitch : ((row_pitch / 64) + 1) * 64; + + width = row_pitch / element_size; + height = totalImageSize / row_pitch; + + return result; +} + +cl_int +getCLImageInfoFromVkImageInfo(const VkImageCreateInfo *VulkanImageCreateInfo, + size_t totalImageSize, cl_image_format *img_fmt, + cl_image_desc *img_desc) +{ + cl_int result = CL_SUCCESS; + + cl_image_format clImgFormat = { 0 }; + result = + getCLFormatFromVkFormat(VulkanImageCreateInfo->format, &clImgFormat); + if (CL_SUCCESS != result) + { + return result; + } + memcpy(img_fmt, &clImgFormat, sizeof(cl_image_format)); + + img_desc->image_type = getImageTypeFromVk(VulkanImageCreateInfo->imageType); + if (CL_INVALID_VALUE == img_desc->image_type) + { + return CL_INVALID_VALUE; + } + + result = + get2DImageDimensions(VulkanImageCreateInfo, img_fmt, totalImageSize, + img_desc->image_width, img_desc->image_height); + if (CL_SUCCESS != result) + { + throw std::runtime_error("get2DImageDimensions failed!!!"); + } + + img_desc->image_depth = 0; // VulkanImageCreateInfo->extent.depth; + img_desc->image_array_size = 0; + img_desc->image_row_pitch = 0; // Row pitch set to zero as host_ptr is NULL + img_desc->image_slice_pitch = + img_desc->image_row_pitch * img_desc->image_height; + img_desc->num_mip_levels = 1; + img_desc->num_samples = 0; + img_desc->buffer = NULL; + + return result; +} + +cl_int check_external_memory_handle_type( + cl_device_id deviceID, + cl_external_memory_handle_type_khr requiredHandleType) +{ + unsigned int i; + cl_external_memory_handle_type_khr *handle_type; + size_t handle_type_size = 0; + + cl_int errNum = CL_SUCCESS; + + errNum = clGetDeviceInfo(deviceID, + CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR, + 0, NULL, &handle_type_size); + handle_type = + (cl_external_memory_handle_type_khr *)malloc(handle_type_size); + + errNum = clGetDeviceInfo(deviceID, + CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR, + handle_type_size, handle_type, NULL); + + test_error( + errNum, + "Unable to query CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR \n"); + + for (i = 0; i < handle_type_size; i++) + { + if (requiredHandleType == handle_type[i]) + { + return CL_SUCCESS; + } + } + log_error("cl_khr_external_memory extension is missing support for %d\n", + requiredHandleType); + + return CL_INVALID_VALUE; +} + +cl_int check_external_semaphore_handle_type( + cl_device_id deviceID, + cl_external_semaphore_handle_type_khr requiredHandleType) +{ + unsigned int i; + cl_external_semaphore_handle_type_khr *handle_type; + size_t handle_type_size = 0; + cl_int errNum = CL_SUCCESS; + + errNum = + clGetDeviceInfo(deviceID, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR, + 0, NULL, &handle_type_size); + handle_type = + (cl_external_semaphore_handle_type_khr *)malloc(handle_type_size); + + errNum = + clGetDeviceInfo(deviceID, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR, + handle_type_size, handle_type, NULL); + + test_error( + errNum, + "Unable to query CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR \n"); + + for (i = 0; i < handle_type_size; i++) + { + if (requiredHandleType == handle_type[i]) + { + return CL_SUCCESS; + } + } + log_error("cl_khr_external_semaphore extension is missing support for %d\n", + requiredHandleType); + + return CL_INVALID_VALUE; +} +clExternalMemory::clExternalMemory() {} + +clExternalMemory::clExternalMemory(const clExternalMemory &externalMemory) + : m_externalMemory(externalMemory.m_externalMemory) +{} + +clExternalMemory::clExternalMemory( + const VulkanDeviceMemory *deviceMemory, + VulkanExternalMemoryHandleType externalMemoryHandleType, uint64_t offset, + uint64_t size, cl_context context, cl_device_id deviceId) +{ + int err = 0; + m_externalMemory = NULL; + cl_device_id devList[] = { deviceId, NULL }; + std::vector extMemProperties; +#ifdef _WIN32 + if (!is_extension_available(devList[0], "cl_khr_external_memory_win32")) + { + throw std::runtime_error( + "Device does not support cl_khr_external_memory_win32 extension\n"); + } +#else + if (!is_extension_available(devList[0], "cl_khr_external_memory_opaque_fd")) + { + throw std::runtime_error( + "Device does not support cl_khr_external_memory_opaque_fd " + "extension \n"); + } +#endif + + switch (externalMemoryHandleType) + { + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD: +#ifdef _WIN32 + ASSERT(0); +#endif + log_info("Opaque file descriptors are not supported on Windows\n"); + fd = (int)deviceMemory->getHandle(externalMemoryHandleType); + err = check_external_memory_handle_type( + devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR); + extMemProperties.push_back( + (cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR); + extMemProperties.push_back((cl_mem_properties)fd); + break; + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT: +#ifndef _WIN32 + ASSERT(0); +#else + log_info(" Opaque NT handles are only supported on Windows\n"); + handle = deviceMemory->getHandle(externalMemoryHandleType); + err = check_external_memory_handle_type( + devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR); + extMemProperties.push_back( + (cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR); + extMemProperties.push_back((cl_mem_properties)handle); +#endif + break; + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT: +#ifndef _WIN32 + ASSERT(0); +#else + log_info("Opaque D3DKMT handles are only supported on Windows\n"); + handle = deviceMemory->getHandle(externalMemoryHandleType); + err = check_external_memory_handle_type( + devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR); + extMemProperties.push_back( + (cl_mem_properties) + CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR); + extMemProperties.push_back((cl_mem_properties)handle); +#endif + break; + default: + ASSERT(0); + log_error("Unsupported external memory handle type\n"); + break; + } + if (CL_SUCCESS != err) + { + throw std::runtime_error("Unsupported external memory type\n "); + } + + extMemProperties.push_back((cl_mem_properties)CL_DEVICE_HANDLE_LIST_KHR); + extMemProperties.push_back((cl_mem_properties)devList[0]); + extMemProperties.push_back( + (cl_mem_properties)CL_DEVICE_HANDLE_LIST_END_KHR); + extMemProperties.push_back(0); + + m_externalMemory = clCreateBufferWithProperties( + context, extMemProperties.data(), 1, size, NULL, &err); + if (CL_SUCCESS != err) + { + log_error("clCreateBufferWithProperties failed with %d\n", err); + throw std::runtime_error("clCreateBufferWithProperties failed "); + } +} +clExternalMemoryImage::clExternalMemoryImage( + const VulkanDeviceMemory &deviceMemory, + VulkanExternalMemoryHandleType externalMemoryHandleType, cl_context context, + size_t totalImageMemSize, size_t imageWidth, size_t imageHeight, + size_t totalSize, const VulkanImage2D &image2D, cl_device_id deviceId) +{ + cl_int errcode_ret = 0; + std::vector extMemProperties1; + cl_device_id devList[] = { deviceId, NULL }; + +#ifdef _WIN32 + if (!is_extension_available(devList[0], "cl_khr_external_memory_win32")) + { + throw std::runtime_error("Device does not support " + "cl_khr_external_memory_win32 extension \n"); + } +#elif !defined(__APPLE__) + if (!is_extension_available(devList[0], "cl_khr_external_memory_opaque_fd")) + { + throw std::runtime_error( + "Device does not support cl_khr_external_memory_opaque_fd " + "extension\n"); + } +#endif + + switch (externalMemoryHandleType) + { +#ifdef _WIN32 + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT: + log_info("Opaque NT handles are only supported on Windows\n"); + handle = deviceMemory.getHandle(externalMemoryHandleType); + errcode_ret = check_external_memory_handle_type( + devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR); + extMemProperties1.push_back( + (cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KHR); + extMemProperties1.push_back((cl_mem_properties)handle); + break; + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT: + log_info("Opaque D3DKMT handles are only supported on Windows\n"); + handle = deviceMemory.getHandle(externalMemoryHandleType); + errcode_ret = check_external_memory_handle_type( + devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR); + extMemProperties1.push_back( + (cl_mem_properties) + CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR); + extMemProperties1.push_back((cl_mem_properties)handle); + break; +#elif !defined(__APPLE__) + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD: + log_info(" Opaque file descriptors are not supported on Windows\n"); + fd = (int)deviceMemory.getHandle(externalMemoryHandleType); + errcode_ret = check_external_memory_handle_type( + devList[0], CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR); + extMemProperties1.push_back( + (cl_mem_properties)CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR); + extMemProperties1.push_back((cl_mem_properties)fd); + break; +#endif + default: + ASSERT(0); + log_error("Unsupported external memory handle type\n"); + break; + } + if (CL_SUCCESS != errcode_ret) + { + throw std::runtime_error("Unsupported external memory type\n "); + } + // Set cl_image_desc + size_t clImageFormatSize; + cl_image_desc image_desc; + memset(&image_desc, 0x0, sizeof(cl_image_desc)); + cl_image_format img_format = { 0 }; + const VkImageCreateInfo VulkanImageCreateInfo = + image2D.getVkImageCreateInfo(); + + errcode_ret = getCLImageInfoFromVkImageInfo( + &VulkanImageCreateInfo, image2D.getSize(), &img_format, &image_desc); + if (CL_SUCCESS != errcode_ret) + { + throw std::runtime_error("getCLImageInfoFromVkImageInfo failed!!!"); + } + + extMemProperties1.push_back((cl_mem_properties)CL_DEVICE_HANDLE_LIST_KHR); + extMemProperties1.push_back((cl_mem_properties)devList[0]); + extMemProperties1.push_back( + (cl_mem_properties)CL_DEVICE_HANDLE_LIST_END_KHR); + extMemProperties1.push_back(0); + m_externalMemory = clCreateImageWithProperties( + context, extMemProperties1.data(), CL_MEM_READ_WRITE, &img_format, + &image_desc, NULL, &errcode_ret); + if (CL_SUCCESS != errcode_ret) + { + throw std::runtime_error("clCreateImageWithProperties failed!!!"); + } +} + +cl_mem clExternalMemory::getExternalMemoryBuffer() { return m_externalMemory; } + +cl_mem clExternalMemoryImage::getExternalMemoryImage() +{ + return m_externalMemory; +} + +clExternalMemoryImage::~clExternalMemoryImage() +{ + clReleaseMemObject(m_externalMemory); +} + +clExternalMemory::~clExternalMemory() { clReleaseMemObject(m_externalMemory); } + +clExternalMemoryImage::clExternalMemoryImage() {} + + +////////////////////////////////////////// +// clExternalSemaphore implementation // +////////////////////////////////////////// + +clExternalSemaphore::clExternalSemaphore( + const clExternalSemaphore &externalSemaphore) + : m_externalSemaphore(externalSemaphore.m_externalSemaphore) +{} + +clExternalSemaphore::clExternalSemaphore( + const VulkanSemaphore &semaphore, cl_context context, + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType, + cl_device_id deviceId) +{ + + cl_int err = 0; + cl_device_id devList[] = { deviceId, NULL }; + +#ifdef _WIN32 + if (!is_extension_available(devList[0], "cl_khr_external_semaphore_win32")) + { + throw std::runtime_error("Device does not support " + "cl_khr_external_semaphore_win32 extension\n"); + } +#elif !defined(__APPLE__) + if (!is_extension_available(devList[0], + "cl_khr_external_semaphore_opaque_fd")) + { + throw std::runtime_error( + "Device does not support cl_khr_external_semaphore_opaque_fd " + "extension \n"); + } +#endif + + std::vector sema_props{ + (cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_KHR, + (cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_BINARY_KHR, + }; + switch (externalSemaphoreHandleType) + { + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD: +#ifdef _WIN32 + ASSERT(0); +#else + log_info(" Opaque file descriptors are not supported on Windows\n"); + fd = (int)semaphore.getHandle(externalSemaphoreHandleType); + err = check_external_semaphore_handle_type( + devList[0], CL_SEMAPHORE_HANDLE_OPAQUE_FD_KHR); + sema_props.push_back( + (cl_semaphore_properties_khr)CL_SEMAPHORE_HANDLE_OPAQUE_FD_KHR); + sema_props.push_back((cl_semaphore_properties_khr)fd); +#endif + break; + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT: +#ifndef _WIN32 + ASSERT(0); +#else + log_info(" Opaque NT handles are only supported on Windows\n"); + handle = semaphore.getName().size() + ? NULL + : semaphore.getHandle(externalSemaphoreHandleType); + err = check_external_semaphore_handle_type( + devList[0], CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KHR); + sema_props.push_back((cl_semaphore_properties_khr) + CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KHR); + sema_props.push_back((cl_semaphore_properties_khr)handle); +#endif + break; + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT: +#ifndef _WIN32 + ASSERT(0); +#else + log_info(" Opaque D3DKMT handles are only supported on Windows\n"); + handle = semaphore.getHandle(externalSemaphoreHandleType); + err = check_external_semaphore_handle_type( + devList[0], CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KMT_KHR); + sema_props.push_back((cl_semaphore_properties_khr) + CL_SEMAPHORE_HANDLE_OPAQUE_WIN32_KMT_KHR); + sema_props.push_back((cl_semaphore_properties_khr)handle); +#endif + break; + default: + ASSERT(0); + log_error("Unsupported external memory handle type\n"); + break; + } + if (CL_SUCCESS != err) + { + throw std::runtime_error( + "Unsupported external sempahore handle type\n "); + } + + sema_props.push_back( + (cl_semaphore_properties_khr)CL_DEVICE_HANDLE_LIST_KHR); + sema_props.push_back((cl_semaphore_properties_khr)devList[0]); + sema_props.push_back( + (cl_semaphore_properties_khr)CL_DEVICE_HANDLE_LIST_END_KHR); + sema_props.push_back(0); + m_externalSemaphore = + clCreateSemaphoreWithPropertiesKHRptr(context, sema_props.data(), &err); + if (CL_SUCCESS != err) + { + log_error("clCreateSemaphoreWithPropertiesKHRptr failed with %d\n", + err); + throw std::runtime_error( + "clCreateSemaphoreWithPropertiesKHRptr failed! "); + } +} + +clExternalSemaphore::~clExternalSemaphore() +{ + cl_int err = clReleaseSemaphoreObjectKHRptr(m_externalSemaphore); + if (err != CL_SUCCESS) + { + throw std::runtime_error("clReleaseSemaphoreObjectKHR failed!"); + } +} + +void clExternalSemaphore::signal(cl_command_queue cmd_queue) +{ + clEnqueueSignalSemaphoresKHRptr(cmd_queue, 1, &m_externalSemaphore, NULL, 0, + NULL, NULL); +} + +void clExternalSemaphore::wait(cl_command_queue cmd_queue) +{ + clEnqueueWaitSemaphoresKHRptr(cmd_queue, 1, &m_externalSemaphore, NULL, 0, + NULL, NULL); +} diff --git a/test_conformance/vulkan/vulkan_interop_common/opencl_vulkan_wrapper.hpp b/test_conformance/vulkan/vulkan_interop_common/opencl_vulkan_wrapper.hpp new file mode 100644 index 00000000..c1d2a766 --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/opencl_vulkan_wrapper.hpp @@ -0,0 +1,129 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// +#ifndef _opencl_vulkan_wrapper_hpp_ +#define _opencl_vulkan_wrapper_hpp_ + +#include "vulkan_wrapper.hpp" + +#if !defined(__APPLE__) +#include +#include +#else +#include +#include +#endif + +typedef cl_semaphore_khr (*pfnclCreateSemaphoreWithPropertiesKHR)( + cl_context context, cl_semaphore_properties_khr *sema_props, + cl_int *errcode_ret); +typedef cl_int (*pfnclEnqueueWaitSemaphoresKHR)( + cl_command_queue command_queue, cl_uint num_semaphores, + const cl_semaphore_khr *sema_list, + const cl_semaphore_payload_khr *sema_payload_list, + cl_uint num_events_in_wait_list, const cl_event *event_wait_list, + cl_event *event); +typedef cl_int (*pfnclEnqueueSignalSemaphoresKHR)( + cl_command_queue command_queue, cl_uint num_semaphores, + const cl_semaphore_khr *sema_list, + const cl_semaphore_payload_khr *sema_payload_list, + cl_uint num_events_in_wait_list, const cl_event *event_wait_list, + cl_event *event); +typedef cl_int (*pfnclEnqueueAcquireExternalMemObjectsKHR)( + cl_command_queue command_queue, cl_uint num_mem_objects, + const cl_mem *mem_objects, cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, cl_event *event); +typedef cl_int (*pfnclEnqueueReleaseExternalMemObjectsKHR)( + cl_command_queue command_queue, cl_uint num_mem_objects, + const cl_mem *mem_objects, cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, cl_event *event); +typedef cl_int (*pfnclReleaseSemaphoreObjectKHR)(cl_semaphore_khr sema_object); + +extern pfnclCreateSemaphoreWithPropertiesKHR + clCreateSemaphoreWithPropertiesKHRptr; +extern pfnclEnqueueWaitSemaphoresKHR clEnqueueWaitSemaphoresKHRptr; +extern pfnclEnqueueSignalSemaphoresKHR clEnqueueSignalSemaphoresKHRptr; +extern pfnclEnqueueAcquireExternalMemObjectsKHR + clEnqueueAcquireExternalMemObjectsKHRptr; +extern pfnclEnqueueReleaseExternalMemObjectsKHR + clEnqueueReleaseExternalMemObjectsKHRptr; +extern pfnclReleaseSemaphoreObjectKHR clReleaseSemaphoreObjectKHRptr; + +cl_int getCLImageInfoFromVkImageInfo(const VkImageCreateInfo *, size_t, + cl_image_format *, cl_image_desc *); +cl_int check_external_memory_handle_type( + cl_device_id deviceID, + cl_external_memory_handle_type_khr requiredHandleType); +cl_int check_external_semaphore_handle_type( + cl_device_id deviceID, + cl_external_semaphore_handle_type_khr requiredHandleType); + +class clExternalMemory { +protected: + cl_mem m_externalMemory; + int fd; + void *handle; + clExternalMemory(const clExternalMemory &externalMemory); + +public: + clExternalMemory(); + clExternalMemory(const VulkanDeviceMemory *deviceMemory, + VulkanExternalMemoryHandleType externalMemoryHandleType, + uint64_t offset, uint64_t size, cl_context context, + cl_device_id deviceId); + + virtual ~clExternalMemory(); + cl_mem getExternalMemoryBuffer(); +}; +class clExternalMemoryImage { +protected: + cl_mem m_externalMemory; + int fd; + void *handle; + cl_command_queue cmd_queue; + clExternalMemoryImage(); + +public: + clExternalMemoryImage( + const VulkanDeviceMemory &deviceMemory, + VulkanExternalMemoryHandleType externalMemoryHandleType, + cl_context context, size_t totalImageMemSize, size_t imageWidth, + size_t imageHeight, size_t totalSize, const VulkanImage2D &image2D, + cl_device_id deviceId); + virtual ~clExternalMemoryImage(); + cl_mem getExternalMemoryImage(); +}; + +class clExternalSemaphore { +protected: + cl_semaphore_khr m_externalSemaphore; + int fd; + void *handle; + clExternalSemaphore(const clExternalSemaphore &externalSemaphore); + +public: + clExternalSemaphore( + const VulkanSemaphore &deviceSemaphore, cl_context context, + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType, + cl_device_id deviceId); + virtual ~clExternalSemaphore(); + void signal(cl_command_queue command_queue); + void wait(cl_command_queue command_queue); + // operator openclExternalSemaphore_t() const; +}; + +extern void init_cl_vk_ext(cl_platform_id); + +#endif // _opencl_vulkan_wrapper_hpp_ diff --git a/test_conformance/vulkan/vulkan_interop_common/vulkan_api_list.hpp b/test_conformance/vulkan/vulkan_interop_common/vulkan_api_list.hpp new file mode 100644 index 00000000..017aefd2 --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/vulkan_api_list.hpp @@ -0,0 +1,195 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#ifndef _vulkan_api_list_hpp_ +#define _vulkan_api_list_hpp_ + +#define VK_FUNC_LIST \ + VK_FUNC_DECL(vkEnumerateInstanceVersion) \ + VK_FUNC_DECL(vkEnumerateInstanceExtensionProperties) \ + VK_FUNC_DECL(vkEnumerateInstanceLayerProperties) \ + VK_FUNC_DECL(vkCreateInstance) \ + VK_FUNC_DECL(vkGetInstanceProcAddr) \ + VK_FUNC_DECL(vkGetDeviceProcAddr) \ + VK_FUNC_DECL(vkEnumeratePhysicalDevices) \ + VK_FUNC_DECL(vkGetPhysicalDeviceProperties) \ + VK_FUNC_DECL(vkCreateDevice) \ + VK_FUNC_DECL(vkDestroyDevice) \ + VK_FUNC_DECL(vkGetDeviceQueue) \ + VK_FUNC_DECL(vkQueueWaitIdle) \ + VK_FUNC_DECL(vkCreateDescriptorSetLayout) \ + VK_FUNC_DECL(vkCreatePipelineLayout) \ + VK_FUNC_DECL(vkCreateShaderModule) \ + VK_FUNC_DECL(vkCreateComputePipelines) \ + VK_FUNC_DECL(vkCreateDescriptorPool) \ + VK_FUNC_DECL(vkAllocateDescriptorSets) \ + VK_FUNC_DECL(vkFreeDescriptorSets) \ + VK_FUNC_DECL(vkAllocateCommandBuffers) \ + VK_FUNC_DECL(vkBeginCommandBuffer) \ + VK_FUNC_DECL(vkCmdBindPipeline) \ + VK_FUNC_DECL(vkCmdBindDescriptorSets) \ + VK_FUNC_DECL(vkCmdPipelineBarrier) \ + VK_FUNC_DECL(vkCmdDispatch) \ + VK_FUNC_DECL(vkCmdFillBuffer) \ + VK_FUNC_DECL(vkCmdCopyBuffer) \ + VK_FUNC_DECL(vkCmdUpdateBuffer) \ + VK_FUNC_DECL(vkCmdCopyBufferToImage) \ + VK_FUNC_DECL(vkCmdCopyImageToBuffer) \ + VK_FUNC_DECL(vkEndCommandBuffer) \ + VK_FUNC_DECL(vkCreateBuffer) \ + VK_FUNC_DECL(vkCreateImageView) \ + VK_FUNC_DECL(vkAllocateMemory) \ + VK_FUNC_DECL(vkMapMemory) \ + VK_FUNC_DECL(vkBindBufferMemory) \ + VK_FUNC_DECL(vkBindImageMemory) \ + VK_FUNC_DECL(vkUnmapMemory) \ + VK_FUNC_DECL(vkFreeMemory) \ + VK_FUNC_DECL(vkCreateCommandPool) \ + VK_FUNC_DECL(vkResetCommandPool) \ + VK_FUNC_DECL(vkDestroyCommandPool) \ + VK_FUNC_DECL(vkResetCommandBuffer) \ + VK_FUNC_DECL(vkFreeCommandBuffers) \ + VK_FUNC_DECL(vkQueueSubmit) \ + VK_FUNC_DECL(vkCmdExecuteCommands) \ + VK_FUNC_DECL(vkCreateFence) \ + VK_FUNC_DECL(vkDestroyFence) \ + VK_FUNC_DECL(vkGetFenceStatus) \ + VK_FUNC_DECL(vkResetFences) \ + VK_FUNC_DECL(vkWaitForFences) \ + VK_FUNC_DECL(vkCreateSemaphore) \ + VK_FUNC_DECL(vkDestroySemaphore) \ + VK_FUNC_DECL(vkCreateEvent) \ + VK_FUNC_DECL(vkDestroyImageView) \ + VK_FUNC_DECL(vkCreateImage) \ + VK_FUNC_DECL(vkGetImageMemoryRequirements) \ + VK_FUNC_DECL(vkDestroyImage) \ + VK_FUNC_DECL(vkDestroyBuffer) \ + VK_FUNC_DECL(vkDestroyPipeline) \ + VK_FUNC_DECL(vkDestroyShaderModule) \ + VK_FUNC_DECL(vkGetPhysicalDeviceMemoryProperties) \ + VK_FUNC_DECL(vkDestroyInstance) \ + VK_FUNC_DECL(vkUpdateDescriptorSets) \ + VK_FUNC_DECL(vkDestroyDescriptorPool) \ + VK_FUNC_DECL(vkDestroyPipelineLayout) \ + VK_FUNC_DECL(vkDestroyDescriptorSetLayout) \ + VK_FUNC_DECL(vkGetPhysicalDeviceQueueFamilyProperties) \ + VK_FUNC_DECL(vkGetPhysicalDeviceFeatures) \ + VK_FUNC_DECL(vkGetPhysicalDeviceProperties2KHR) \ + VK_FUNC_DECL(vkGetBufferMemoryRequirements) \ + VK_FUNC_DECL(vkGetMemoryFdKHR) \ + VK_FUNC_DECL(vkGetSemaphoreFdKHR) \ + VK_FUNC_DECL(vkEnumeratePhysicalDeviceGroups) \ + VK_FUNC_DECL(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \ + VK_FUNC_DECL(vkGetPhysicalDeviceSurfaceFormatsKHR) \ + VK_FUNC_DECL(vkGetPhysicalDeviceSurfacePresentModesKHR) \ + VK_FUNC_DECL(vkEnumerateDeviceExtensionProperties) \ + VK_FUNC_DECL(vkGetPhysicalDeviceSurfaceSupportKHR) + +#define VK_WINDOWS_FUNC_LIST \ + VK_FUNC_DECL(vkGetMemoryWin32HandleKHR) \ + VK_FUNC_DECL(vkGetSemaphoreWin32HandleKHR) + +#define vkEnumerateInstanceVersion _vkEnumerateInstanceVersion +#define vkEnumerateInstanceExtensionProperties \ + _vkEnumerateInstanceExtensionProperties +#define vkEnumerateInstanceLayerProperties _vkEnumerateInstanceLayerProperties +#define vkCreateInstance _vkCreateInstance +#define vkGetInstanceProcAddr _vkGetInstanceProcAddr +#define vkGetDeviceProcAddr _vkGetDeviceProcAddr +#define vkEnumeratePhysicalDevices _vkEnumeratePhysicalDevices +#define vkGetPhysicalDeviceProperties _vkGetPhysicalDeviceProperties +#define vkCreateDevice _vkCreateDevice +#define vkDestroyDevice _vkDestroyDevice +#define vkGetDeviceQueue _vkGetDeviceQueue +#define vkQueueWaitIdle _vkQueueWaitIdle +#define vkCreateDescriptorSetLayout _vkCreateDescriptorSetLayout +#define vkCreatePipelineLayout _vkCreatePipelineLayout +#define vkCreateShaderModule _vkCreateShaderModule +#define vkCreateComputePipelines _vkCreateComputePipelines +#define vkCreateDescriptorPool _vkCreateDescriptorPool +#define vkAllocateDescriptorSets _vkAllocateDescriptorSets +#define vkFreeDescriptorSets _vkFreeDescriptorSets +#define vkAllocateCommandBuffers _vkAllocateCommandBuffers +#define vkBeginCommandBuffer _vkBeginCommandBuffer +#define vkCmdBindPipeline _vkCmdBindPipeline +#define vkCmdBindDescriptorSets _vkCmdBindDescriptorSets +#define vkCmdPipelineBarrier _vkCmdPipelineBarrier +#define vkCmdDispatch _vkCmdDispatch +#define vkCmdFillBuffer _vkCmdFillBuffer +#define vkCmdCopyBuffer _vkCmdCopyBuffer +#define vkCmdUpdateBuffer _vkCmdUpdateBuffer +#define vkCmdCopyBufferToImage _vkCmdCopyBufferToImage +#define vkCmdCopyImageToBuffer _vkCmdCopyImageToBuffer +#define vkEndCommandBuffer _vkEndCommandBuffer +#define vkCreateBuffer _vkCreateBuffer +#define vkCreateImageView _vkCreateImageView +#define vkAllocateMemory _vkAllocateMemory +#define vkMapMemory _vkMapMemory +#define vkBindBufferMemory _vkBindBufferMemory +#define vkBindImageMemory _vkBindImageMemory +#define vkUnmapMemory _vkUnmapMemory +#define vkFreeMemory _vkFreeMemory +#define vkCreateCommandPool _vkCreateCommandPool +#define vkResetCommandPool _vkResetCommandPool +#define vkDestroyCommandPool _vkDestroyCommandPool +#define vkResetCommandBuffer _vkResetCommandBuffer +#define vkFreeCommandBuffers _vkFreeCommandBuffers +#define vkQueueSubmit _vkQueueSubmit +#define vkCmdExecuteCommands _vkCmdExecuteCommands +#define vkCreateFence _vkCreateFence +#define vkDestroyFence _vkDestroyFence +#define vkGetFenceStatus _vkGetFenceStatus +#define vkResetFences _vkResetFences +#define vkWaitForFences _vkWaitForFences +#define vkCreateSemaphore _vkCreateSemaphore +#define vkDestroySemaphore _vkDestroySemaphore +#define vkCreateEvent _vkCreateEvent +#define vkDestroyImageView _vkDestroyImageView +#define vkCreateImage _vkCreateImage +#define vkGetImageMemoryRequirements _vkGetImageMemoryRequirements +#define vkDestroyImage _vkDestroyImage +#define vkDestroyBuffe _vkDestroyBuffer +#define vkDestroyPipeline _vkDestroyPipeline +#define vkDestroyShaderModule _vkDestroyShaderModule +#define vkGetPhysicalDeviceMemoryProperties _vkGetPhysicalDeviceMemoryProperties +#define vkDestroyInstance _vkDestroyInstance +#define vkUpdateDescriptorSets _vkUpdateDescriptorSets +#define vkDestroyDescriptorPool _vkDestroyDescriptorPool +#define vkDestroyPipelineLayout _vkDestroyPipelineLayout +#define vkDestroyDescriptorSetLayout _vkDestroyDescriptorSetLayout +#define vkGetPhysicalDeviceQueueFamilyProperties \ + _vkGetPhysicalDeviceQueueFamilyProperties +#define vkGetPhysicalDeviceFeatures _vkGetPhysicalDeviceFeatures +#define vkGetPhysicalDeviceProperties2KHR _vkGetPhysicalDeviceProperties2KHR +#define vkGetBufferMemoryRequirements _vkGetBufferMemoryRequirements +#define vkGetMemoryFdKHR _vkGetMemoryFdKHR +#define vkGetSemaphoreFdKHR _vkGetSemaphoreFdKHR +#define vkEnumeratePhysicalDeviceGroups _vkEnumeratePhysicalDeviceGroups +#define vkGetPhysicalDeviceSurfaceCapabilitiesKHR \ + _vkGetPhysicalDeviceSurfaceCapabilitiesKHR +#define vkGetPhysicalDeviceSurfaceFormatsKHR \ + _vkGetPhysicalDeviceSurfaceFormatsKHR +#define vkGetPhysicalDeviceSurfacePresentModesKHR \ + _vkGetPhysicalDeviceSurfacePresentModesKHR +#define vkEnumerateDeviceExtensionProperties \ + _vkEnumerateDeviceExtensionProperties +#define vkGetPhysicalDeviceSurfaceSupportKHR \ + _vkGetPhysicalDeviceSurfaceSupportKHR + +#define vkGetMemoryWin32HandleKHR _vkGetMemoryWin32HandleKHR +#define vkGetSemaphoreWin32HandleKHR _vkGetSemaphoreWin32HandleKHR + +#endif //_vulkan_api_list_hpp_ diff --git a/test_conformance/vulkan/vulkan_interop_common/vulkan_interop_common.cpp b/test_conformance/vulkan/vulkan_interop_common/vulkan_interop_common.cpp new file mode 100644 index 00000000..db9d168f --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/vulkan_interop_common.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#include "vulkan_interop_common.hpp" + +uint32_t innerIterations(5); +uint32_t perfIterations(100); +uint32_t stressIterations(1000); +size_t cpuThreadsPerGpu(3); diff --git a/test_conformance/vulkan/vulkan_interop_common/vulkan_interop_common.hpp b/test_conformance/vulkan/vulkan_interop_common/vulkan_interop_common.hpp new file mode 100644 index 00000000..18d84f09 --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/vulkan_interop_common.hpp @@ -0,0 +1,50 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#ifndef _vulkan_interop_common_hpp_ +#define _vulkan_interop_common_hpp_ + +#include "vulkan_wrapper_types.hpp" +#include "vulkan_wrapper.hpp" +#include "vulkan_list_map.hpp" +#include "vulkan_utility.hpp" +#include "opencl_vulkan_wrapper.hpp" + +// Number of iterations for loops within tests (default value 5) +extern unsigned int innerIterations; +// Number of iterations for loops within perf tests (default value 100) +extern unsigned int perfIterations; +// Number of iterations for loops within stress tests (default value 1000) +extern unsigned int stressIterations; +// Number of CPU threads per GPU (default value 3) +extern size_t cpuThreadsPerGpu; +// Number of command queues (default value 1) +extern unsigned int numCQ; +// Enable Multi-import of vulkan device memory +extern bool multiImport; +// Enable Multi-import of vulkan device memory under different context +extern bool multiCtx; +// Enable additional debug info logging +extern bool debug_trace; + +extern bool useSingleImageKernel; +extern bool useDeviceLocal; +extern bool disableNTHandleType; +// Enable offset for multiImport of vulkan device memory +extern bool enableOffset; +extern bool non_dedicated; + +#endif // _vulkan_interop_common_hpp_ diff --git a/test_conformance/vulkan/vulkan_interop_common/vulkan_list_map.cpp b/test_conformance/vulkan/vulkan_interop_common/vulkan_list_map.cpp new file mode 100644 index 00000000..bdae5d22 --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/vulkan_list_map.cpp @@ -0,0 +1,424 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#ifdef _WIN32 +#define NOMINMAX +#endif +#include "vulkan_list_map.hpp" +#include "vulkan_utility.hpp" +#include "vulkan_wrapper.hpp" + +///////////////////////////////////////////// +// VulkanPhysicalDeviceList implementation // +///////////////////////////////////////////// + +VulkanPhysicalDeviceList::VulkanPhysicalDeviceList( + const VulkanPhysicalDeviceList &physicalDeviceList) +{} + +VulkanPhysicalDeviceList::VulkanPhysicalDeviceList() {} + +VulkanPhysicalDeviceList::~VulkanPhysicalDeviceList() {} + +///////////////////////////////////////// +// VulkanMemoryHeapList implementation // +///////////////////////////////////////// + +VulkanMemoryHeapList::VulkanMemoryHeapList( + const VulkanMemoryHeapList &memoryHeapList) +{} + +VulkanMemoryHeapList::VulkanMemoryHeapList() {} + +VulkanMemoryHeapList::~VulkanMemoryHeapList() {} + +///////////////////////////////////////// +// VulkanMemoryTypeList implementation // +///////////////////////////////////////// + +VulkanMemoryTypeList::VulkanMemoryTypeList( + const VulkanMemoryTypeList &memoryTypeList) +{} + +VulkanMemoryTypeList::VulkanMemoryTypeList() {} + +VulkanMemoryTypeList::~VulkanMemoryTypeList() {} + +////////////////////////////////////////// +// VulkanQueueFamilyList implementation // +////////////////////////////////////////// + +VulkanQueueFamilyList::VulkanQueueFamilyList( + const VulkanQueueFamilyList &queueFamilyList) +{} + +VulkanQueueFamilyList::VulkanQueueFamilyList() {} + +VulkanQueueFamilyList::~VulkanQueueFamilyList() {} + +///////////////////////////////////////////////////// +// VulkanQueueFamilyToQueueCountMap implementation // +///////////////////////////////////////////////////// + +VulkanQueueFamilyToQueueCountMap::VulkanQueueFamilyToQueueCountMap( + const VulkanQueueFamilyToQueueCountMap &queueFamilyToQueueCountMap) +{} + +VulkanQueueFamilyToQueueCountMap::VulkanQueueFamilyToQueueCountMap( + uint32_t numQueuesPerFamily) +{ + uint32_t maxQueueFamilyCount = 0; + const VulkanPhysicalDeviceList &physicalDeviceList = + getVulkanInstance().getPhysicalDeviceList(); + for (size_t pdIdx = 0; pdIdx < physicalDeviceList.size(); pdIdx++) + { + maxQueueFamilyCount = std::max( + maxQueueFamilyCount, + (uint32_t)physicalDeviceList[pdIdx].getQueueFamilyList().size()); + } + + for (uint32_t qfIdx = 0; qfIdx < maxQueueFamilyCount; qfIdx++) + { + insert(qfIdx, numQueuesPerFamily); + } +} + +VulkanQueueFamilyToQueueCountMap::~VulkanQueueFamilyToQueueCountMap() {} + +//////////////////////////////////////////////////// +// VulkanQueueFamilyToQueueListMap implementation // +//////////////////////////////////////////////////// + +VulkanQueueFamilyToQueueListMap::VulkanQueueFamilyToQueueListMap( + const VulkanQueueFamilyToQueueListMap &queueFamilyToQueueMap) +{} + +VulkanQueueFamilyToQueueListMap::VulkanQueueFamilyToQueueListMap() {} + +VulkanQueueFamilyToQueueListMap::~VulkanQueueFamilyToQueueListMap() {} + +void VulkanQueueFamilyToQueueListMap::insert(uint32_t key, + VulkanQueueList &queueList) +{ + m_map.insert(std::pair>( + key, std::reference_wrapper(queueList))); +} + +VulkanQueueList &VulkanQueueFamilyToQueueListMap::operator[](uint32_t key) +{ + return m_map.at(key).get(); +} + +//////////////////////////////////// +// VulkanQueueList implementation // +//////////////////////////////////// + +VulkanQueueList::VulkanQueueList(const VulkanQueueList &queueList) {} + +VulkanQueueList::VulkanQueueList() {} + +VulkanQueueList::~VulkanQueueList() {} + +///////////////////////////////////////////////////////// +// VulkanDescriptorSetLayoutBindingList implementation // +///////////////////////////////////////////////////////// + +VulkanDescriptorSetLayoutBindingList::VulkanDescriptorSetLayoutBindingList( + const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList) +{} + +VulkanDescriptorSetLayoutBindingList::VulkanDescriptorSetLayoutBindingList() {} + +VulkanDescriptorSetLayoutBindingList::VulkanDescriptorSetLayoutBindingList( + size_t numDescriptorSetLayoutBindings, VulkanDescriptorType descriptorType, + uint32_t descriptorCount, VulkanShaderStage shaderStage) +{ + for (size_t idx = 0; idx < numDescriptorSetLayoutBindings; idx++) + { + VulkanDescriptorSetLayoutBinding *descriptorSetLayoutBinding = + new VulkanDescriptorSetLayoutBinding((uint32_t)idx, descriptorType, + descriptorCount, shaderStage); + add(*descriptorSetLayoutBinding); + } +} + +VulkanDescriptorSetLayoutBindingList::VulkanDescriptorSetLayoutBindingList( + VulkanDescriptorType descriptorType0, uint32_t descriptorCount0, + VulkanDescriptorType descriptorType1, uint32_t descriptorCount1, + VulkanShaderStage shaderStage) +{ + for (uint32_t idx = 0; idx < descriptorCount0; idx++) + { + VulkanDescriptorSetLayoutBinding *descriptorSetLayoutBinding0 = + new VulkanDescriptorSetLayoutBinding(idx, descriptorType0, 1, + shaderStage); + add(*descriptorSetLayoutBinding0); + } + for (uint32_t idx = 0; idx < descriptorCount1; idx++) + { + VulkanDescriptorSetLayoutBinding *descriptorSetLayoutBinding1 = + new VulkanDescriptorSetLayoutBinding( + descriptorCount0 + idx, descriptorType1, 1, shaderStage); + add(*descriptorSetLayoutBinding1); + } +} + +VulkanDescriptorSetLayoutBindingList::~VulkanDescriptorSetLayoutBindingList() +{ + for (size_t idx = 0; idx < m_wrapperList.size(); idx++) + { + VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding = + m_wrapperList[idx]; + delete &descriptorSetLayoutBinding; + } +} + +////////////////////////////////////////////////// +// VulkanDescriptorSetLayoutList implementation // +////////////////////////////////////////////////// + +VulkanDescriptorSetLayoutList::VulkanDescriptorSetLayoutList( + const VulkanDescriptorSetLayoutList &descriptorSetLayoutList) +{} + +VulkanDescriptorSetLayoutList::VulkanDescriptorSetLayoutList() {} + +VulkanDescriptorSetLayoutList::~VulkanDescriptorSetLayoutList() {} + +//////////////////////////////////////////// +// VulkanCommandBufferList implementation // +//////////////////////////////////////////// + +VulkanCommandBufferList::VulkanCommandBufferList( + const VulkanCommandBufferList &commandBufferList) +{} + +VulkanCommandBufferList::VulkanCommandBufferList() {} + +VulkanCommandBufferList::VulkanCommandBufferList( + size_t numCommandBuffers, const VulkanDevice &device, + const VulkanCommandPool &commandPool) +{ + for (size_t idx = 0; idx < numCommandBuffers; idx++) + { + VulkanCommandBuffer *commandBuffer = + new VulkanCommandBuffer(device, commandPool); + add(*commandBuffer); + } +} + +VulkanCommandBufferList::~VulkanCommandBufferList() +{ + for (size_t idx = 0; idx < m_wrapperList.size(); idx++) + { + VulkanCommandBuffer &commandBuffer = m_wrapperList[idx]; + delete &commandBuffer; + } +} + +///////////////////////////////////// +// VulkanBufferList implementation // +///////////////////////////////////// + +VulkanBufferList::VulkanBufferList(const VulkanBufferList &bufferList) {} + +VulkanBufferList::VulkanBufferList( + size_t numBuffers, const VulkanDevice &device, uint64_t size, + VulkanExternalMemoryHandleType externalMemoryHandleType, + VulkanBufferUsage bufferUsage, VulkanSharingMode sharingMode, + const VulkanQueueFamilyList &queueFamilyList) +{ + for (size_t bIdx = 0; bIdx < numBuffers; bIdx++) + { + VulkanBuffer *buffer = + new VulkanBuffer(device, size, externalMemoryHandleType, + bufferUsage, sharingMode, queueFamilyList); + add(*buffer); + } +} + +VulkanBufferList::~VulkanBufferList() +{ + for (size_t bIdx = 0; bIdx < m_wrapperList.size(); bIdx++) + { + VulkanBuffer &buffer = m_wrapperList[bIdx]; + delete &buffer; + } +} + +////////////////////////////////////// +// VulkanImage2DList implementation // +////////////////////////////////////// + +VulkanImage2DList::VulkanImage2DList(const VulkanImage2DList &image2DList) {} + +VulkanImage2DList::VulkanImage2DList( + size_t numImages, std::vector &deviceMemory, + uint64_t baseOffset, uint64_t interImageOffset, const VulkanDevice &device, + VulkanFormat format, uint32_t width, uint32_t height, uint32_t mipLevels, + VulkanExternalMemoryHandleType externalMemoryHandleType, + VulkanImageCreateFlag imageCreateFlag, VulkanImageUsage imageUsage, + VulkanSharingMode sharingMode) +{ + for (size_t i2DIdx = 0; i2DIdx < numImages; i2DIdx++) + { + VulkanImage2D *image2D = new VulkanImage2D( + device, format, width, height, mipLevels, externalMemoryHandleType, + imageCreateFlag, imageUsage, sharingMode); + add(*image2D); + deviceMemory[i2DIdx]->bindImage( + *image2D, baseOffset + (i2DIdx * interImageOffset)); + } +} + +VulkanImage2DList::VulkanImage2DList( + size_t numImages, const VulkanDevice &device, VulkanFormat format, + uint32_t width, uint32_t height, uint32_t mipLevels, + VulkanExternalMemoryHandleType externalMemoryHandleType, + VulkanImageCreateFlag imageCreateFlag, VulkanImageUsage imageUsage, + VulkanSharingMode sharingMode) +{ + for (size_t bIdx = 0; bIdx < numImages; bIdx++) + { + VulkanImage2D *image2D = new VulkanImage2D( + device, format, width, height, mipLevels, externalMemoryHandleType, + imageCreateFlag, imageUsage, sharingMode); + add(*image2D); + } +} + +VulkanImage2DList::~VulkanImage2DList() +{ + for (size_t i2DIdx = 0; i2DIdx < m_wrapperList.size(); i2DIdx++) + { + VulkanImage2D &image2D = m_wrapperList[i2DIdx]; + delete &image2D; + } +} + +//////////////////////////////////////// +// VulkanImageViewList implementation // +//////////////////////////////////////// + +VulkanImageViewList::VulkanImageViewList(const VulkanImageViewList &image2DList) +{} + +VulkanImageViewList::VulkanImageViewList(const VulkanDevice &device, + const VulkanImage2DList &image2DList, + bool createImageViewPerMipLevel) +{ + for (size_t i2DIdx = 0; i2DIdx < image2DList.size(); i2DIdx++) + { + if (createImageViewPerMipLevel) + { + for (uint32_t mipLevel = 0; + mipLevel < image2DList[i2DIdx].getNumMipLevels(); mipLevel++) + { + VulkanImageView *image2DView = + new VulkanImageView(device, image2DList[i2DIdx], + VULKAN_IMAGE_VIEW_TYPE_2D, mipLevel, 1); + add(*image2DView); + } + } + else + { + VulkanImageView *image2DView = new VulkanImageView( + device, image2DList[i2DIdx], VULKAN_IMAGE_VIEW_TYPE_2D); + add(*image2DView); + } + } +} + +VulkanImageViewList::~VulkanImageViewList() +{ + for (size_t ivIdx = 0; ivIdx < m_wrapperList.size(); ivIdx++) + { + VulkanImageView &imageView = m_wrapperList[ivIdx]; + delete &imageView; + } +} + +/////////////////////////////////////////// +// VulkanDeviceMemoryList implementation // +/////////////////////////////////////////// + +VulkanDeviceMemoryList::VulkanDeviceMemoryList( + const VulkanDeviceMemoryList &deviceMemoryList) +{} + +VulkanDeviceMemoryList::VulkanDeviceMemoryList( + size_t numImages, const VulkanImage2DList &image2DList, + const VulkanDevice &device, const VulkanMemoryType &memoryType, + VulkanExternalMemoryHandleType externalMemoryHandleType) +{ + for (size_t i2DIdx = 0; i2DIdx < image2DList.size(); i2DIdx++) + { + VulkanDeviceMemory *deviceMemory = new VulkanDeviceMemory( + device, image2DList[i2DIdx], memoryType, externalMemoryHandleType); + add(*deviceMemory); + deviceMemory->bindImage(image2DList[i2DIdx]); + } +} + +VulkanDeviceMemoryList::~VulkanDeviceMemoryList() +{ + for (size_t dmIdx = 0; dmIdx < m_wrapperList.size(); dmIdx++) + { + VulkanDeviceMemory &deviceMemory = m_wrapperList[dmIdx]; + delete &deviceMemory; + } +} + +//////////////////////////////////////// +// VulkanSemaphoreList implementation // +//////////////////////////////////////// + +VulkanSemaphoreList::VulkanSemaphoreList( + const VulkanSemaphoreList &semaphoreList) +{} + +VulkanSemaphoreList::VulkanSemaphoreList() {} + +VulkanSemaphoreList::VulkanSemaphoreList( + size_t numSemaphores, const VulkanDevice &device, + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType, + const std::wstring namePrefix) +{ + std::wstring name = L""; + for (size_t idx = 0; idx < numSemaphores; idx++) + { + if (namePrefix.size()) + { + const size_t maxNameSize = 256; + wchar_t tempName[maxNameSize]; + swprintf(tempName, maxNameSize, L"%s%d", namePrefix.c_str(), + (int)idx); + name = tempName; + } + VulkanSemaphore *semaphore = + new VulkanSemaphore(device, externalSemaphoreHandleType, name); + add(*semaphore); + } +} + +VulkanSemaphoreList::~VulkanSemaphoreList() +{ + for (size_t idx = 0; idx < m_wrapperList.size(); idx++) + { + VulkanSemaphore &Semaphore = m_wrapperList[idx]; + delete &Semaphore; + } +} diff --git a/test_conformance/vulkan/vulkan_interop_common/vulkan_list_map.hpp b/test_conformance/vulkan/vulkan_interop_common/vulkan_list_map.hpp new file mode 100644 index 00000000..831403e1 --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/vulkan_list_map.hpp @@ -0,0 +1,389 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#ifndef _vulkan_list_map_hpp_ +#define _vulkan_list_map_hpp_ + +#include +#include "vulkan_wrapper_types.hpp" +#include "vulkan_utility.hpp" +#include +template class VulkanList { +protected: + std::vector> m_wrapperList; + std::vector> m_constWrapperList; + std::vector m_nativeList; + + VulkanList(const VulkanList &list); + VulkanList(); + virtual ~VulkanList(); + virtual void add(VulkanWrapper &wrapper); + +public: + virtual void add(const VulkanWrapper &wrapper); + virtual size_t size() const; + virtual const VulkanWrapper &operator[](size_t idx) const; + virtual VulkanWrapper &operator[](size_t idx); + virtual operator const VulkanNative *() const; +}; + +template class VulkanMap { +protected: + std::map m_map; + + VulkanMap(const VulkanMap &map); + VulkanMap(); + virtual ~VulkanMap(); + +public: + void insert(const VulkanKey &key, VulkanValue &value); + const VulkanValue &operator[](const VulkanKey &key) const; + VulkanValue &operator[](const VulkanKey &key); +}; + +class VulkanPhysicalDeviceList + : public VulkanList { + friend class VulkanInstance; + +protected: + VulkanPhysicalDeviceList( + const VulkanPhysicalDeviceList &physicalDeviceList); + +public: + VulkanPhysicalDeviceList(); + virtual ~VulkanPhysicalDeviceList(); +}; + +class VulkanQueueFamilyList : public VulkanList { + friend class VulkanPhysicalDevice; + +protected: + VulkanQueueFamilyList(const VulkanQueueFamilyList &queueFamilyList); + +public: + VulkanQueueFamilyList(); + virtual ~VulkanQueueFamilyList(); +}; + +class VulkanMemoryHeapList : public VulkanList { + friend class VulkanPhysicalDevice; + +protected: + VulkanMemoryHeapList(const VulkanMemoryHeapList &memoryHeapList); + +public: + VulkanMemoryHeapList(); + virtual ~VulkanMemoryHeapList(); +}; + +class VulkanMemoryTypeList : public VulkanList { + friend class VulkanPhysicalDevice; + friend class VulkanBuffer; + friend class VulkanImage; + +protected: + VulkanMemoryTypeList(const VulkanMemoryTypeList &memoryTypeList); + +public: + VulkanMemoryTypeList(); + virtual ~VulkanMemoryTypeList(); +}; + +class VulkanQueueFamilyToQueueCountMap : public VulkanMap { +protected: + VulkanQueueFamilyToQueueCountMap( + const VulkanQueueFamilyToQueueCountMap &queueFamilyToQueueCountMap); + +public: + VulkanQueueFamilyToQueueCountMap(uint32_t numQueuesPerFamily = 0); + virtual ~VulkanQueueFamilyToQueueCountMap(); +}; + +class VulkanQueueList : public VulkanList { + friend class VulkanDevice; + +protected: + VulkanQueueList(const VulkanQueueList &queueList); + +public: + VulkanQueueList(); + virtual ~VulkanQueueList(); +}; + +class VulkanQueueFamilyToQueueListMap + : public VulkanMap> { +protected: + VulkanQueueFamilyToQueueListMap( + const VulkanQueueFamilyToQueueListMap &queueFamilyToQueueMap); + +public: + VulkanQueueFamilyToQueueListMap(); + virtual ~VulkanQueueFamilyToQueueListMap(); + void insert(uint32_t key, VulkanQueueList &queueList); + VulkanQueueList &operator[](uint32_t key); +}; + +class VulkanDescriptorSetLayoutBindingList + : public VulkanList { +protected: + VulkanDescriptorSetLayoutBindingList( + const VulkanDescriptorSetLayoutBindingList + &descriptorSetLayoutBindingList); + +public: + VulkanDescriptorSetLayoutBindingList(); + VulkanDescriptorSetLayoutBindingList( + size_t numDescriptorSetLayoutBindings, + VulkanDescriptorType descriptorType, uint32_t descriptorCount = 1, + VulkanShaderStage shaderStage = VULKAN_SHADER_STAGE_COMPUTE); + VulkanDescriptorSetLayoutBindingList( + VulkanDescriptorType descriptorType0, uint32_t descriptorCount0, + VulkanDescriptorType descriptorType1, uint32_t descriptorCount1, + VulkanShaderStage shaderStage = VULKAN_SHADER_STAGE_COMPUTE); + virtual ~VulkanDescriptorSetLayoutBindingList(); +}; + +class VulkanDescriptorSetLayoutList + : public VulkanList { +protected: + VulkanDescriptorSetLayoutList( + const VulkanDescriptorSetLayoutList &descriptorSetLayoutList); + +public: + VulkanDescriptorSetLayoutList(); + virtual ~VulkanDescriptorSetLayoutList(); +}; + +class VulkanCommandBufferList + : public VulkanList { +protected: + VulkanCommandBufferList(const VulkanCommandBufferList &commandBufferList); + +public: + VulkanCommandBufferList(); + VulkanCommandBufferList(size_t numCommandBuffers, + const VulkanDevice &device, + const VulkanCommandPool &commandPool); + virtual ~VulkanCommandBufferList(); +}; + +class VulkanBufferList : public VulkanList { +protected: + VulkanBufferList(const VulkanBufferList &bufferList); + +public: + VulkanBufferList( + size_t numBuffers, const VulkanDevice &device, uint64_t size, + VulkanExternalMemoryHandleType externalMemoryHandleType = + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE, + VulkanBufferUsage bufferUsage = + VULKAN_BUFFER_USAGE_STORAGE_BUFFER_TRANSFER_SRC_DST, + VulkanSharingMode sharingMode = VULKAN_SHARING_MODE_EXCLUSIVE, + const VulkanQueueFamilyList &queueFamilyList = + getEmptyVulkanQueueFamilyList()); + virtual ~VulkanBufferList(); +}; + +class VulkanImage2DList : public VulkanList { +protected: + VulkanImage2DList(const VulkanImage2DList &image2DList); + +public: + VulkanImage2DList( + size_t numImages, std::vector &deviceMemory, + uint64_t baseOffset, uint64_t interImageOffset, + const VulkanDevice &device, VulkanFormat format, uint32_t width, + uint32_t height, uint32_t mipLevels, + VulkanExternalMemoryHandleType externalMemoryHandleType = + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE, + VulkanImageCreateFlag imageCreateFlag = VULKAN_IMAGE_CREATE_FLAG_NONE, + VulkanImageUsage imageUsage = + VULKAN_IMAGE_USAGE_SAMPLED_STORAGE_TRANSFER_SRC_DST, + VulkanSharingMode sharingMode = VULKAN_SHARING_MODE_EXCLUSIVE); + VulkanImage2DList( + size_t numImages, const VulkanDevice &device, VulkanFormat format, + uint32_t width, uint32_t height, uint32_t mipLevels = 1, + VulkanExternalMemoryHandleType externalMemoryHandleType = + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE, + VulkanImageCreateFlag imageCreateFlag = VULKAN_IMAGE_CREATE_FLAG_NONE, + VulkanImageUsage imageUsage = + VULKAN_IMAGE_USAGE_SAMPLED_STORAGE_TRANSFER_SRC_DST, + VulkanSharingMode sharingMode = VULKAN_SHARING_MODE_EXCLUSIVE); + virtual ~VulkanImage2DList(); +}; + +class VulkanImageViewList : public VulkanList { +protected: + VulkanImageViewList(const VulkanImageViewList &imageViewList); + +public: + VulkanImageViewList(const VulkanDevice &device, + const VulkanImage2DList &image2DList, + bool createImageViewPerMipLevel = true); + virtual ~VulkanImageViewList(); +}; + +class VulkanDeviceMemoryList + : public VulkanList { +protected: + VulkanDeviceMemoryList(const VulkanDeviceMemoryList &deviceMemoryList); + +public: + VulkanDeviceMemoryList( + size_t numImages, const VulkanImage2DList &image2DList, + const VulkanDevice &device, const VulkanMemoryType &memoryType, + VulkanExternalMemoryHandleType externalMemoryHandleType = + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE); + virtual ~VulkanDeviceMemoryList(); +}; + +class VulkanSemaphoreList : public VulkanList { +protected: + VulkanSemaphoreList(const VulkanSemaphoreList &semaphoreList); + +public: + VulkanSemaphoreList(); + VulkanSemaphoreList( + size_t numSemaphores, const VulkanDevice &device, + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType = + VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE, + const std::wstring namePrefix = L""); + virtual ~VulkanSemaphoreList(); +}; + +/////////////////////////////// +// VulkanList implementation // +/////////////////////////////// + +template +VulkanList::VulkanList(const VulkanList &list) + : m_wrapperList(list.m_wrapperList), + m_constWrapperList(list.m_constWrapperList), + m_nativeList(list.m_nativeList) +{} + +template +VulkanList::VulkanList() +{} + +template +VulkanList::~VulkanList() +{} + +template +void VulkanList::add(VulkanWrapper &wrapper) +{ + + if (m_constWrapperList.size() != size_t(0)) + { + std::cout << "This list can only contain externally allocated objects" + << std::endl; + return; + } + m_wrapperList.push_back(std::reference_wrapper(wrapper)); + m_nativeList.push_back((VulkanNative)wrapper); +} + +template +void VulkanList::add(const VulkanWrapper &wrapper) +{ + if (m_wrapperList.size() != size_t(0)) + { + std::cout << "This list cannot contain externally allocated objects" + << std::endl; + return; + } + + m_constWrapperList.push_back( + std::reference_wrapper(wrapper)); + m_nativeList.push_back((VulkanNative)wrapper); +} + +template +size_t VulkanList::size() const +{ + return (m_wrapperList.size() > 0) ? m_wrapperList.size() + : m_constWrapperList.size(); +} + +template +const VulkanWrapper & + VulkanList::operator[](size_t idx) const +{ + if (idx < size()) + { + // CHECK_LT(idx, size()); + return (m_wrapperList.size() > 0) ? m_wrapperList[idx].get() + : m_constWrapperList[idx].get(); + } +} + +template +VulkanWrapper &VulkanList::operator[](size_t idx) +{ + if (idx < m_wrapperList.size()) + { + // CHECK_LT(idx, m_wrapperList.size()); + return m_wrapperList[idx].get(); + } +} + +template +VulkanList::operator const VulkanNative *() const +{ + return m_nativeList.data(); +} + +////////////////////////////// +// VulkanMap implementation // +////////////////////////////// + +template +VulkanMap::VulkanMap(const VulkanMap &map) + : m_map(map.m_map) +{} + +template +VulkanMap::VulkanMap() +{} + +template +VulkanMap::~VulkanMap() +{} + +template +void VulkanMap::insert(const VulkanKey &key, + VulkanValue &value) +{ + m_map.insert(std::pair>( + key, std::reference_wrapper(value))); +} + +template +const VulkanValue & + VulkanMap::operator[](const VulkanKey &key) const +{ + return m_map.at(key); +} + +template +VulkanValue &VulkanMap::operator[](const VulkanKey &key) +{ + return m_map.at(key); +} + +#endif // _vulkan_list_map_hpp_ diff --git a/test_conformance/vulkan/vulkan_interop_common/vulkan_utility.cpp b/test_conformance/vulkan/vulkan_interop_common/vulkan_utility.cpp new file mode 100644 index 00000000..81e12621 --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/vulkan_utility.cpp @@ -0,0 +1,693 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#include "vulkan_utility.hpp" +#include "vulkan_wrapper.hpp" +#include +#include +#include +#include +#include +#include +#if defined(_WIN32) || defined(_WIN64) +#include +#endif +#define ASSERT(x) assert((x)) +#define BUFFERSIZE 3000 + + +const VulkanInstance &getVulkanInstance() +{ + static VulkanInstance instance; + return instance; +} + +const VulkanPhysicalDevice &getVulkanPhysicalDevice() +{ + size_t pdIdx; + cl_int errNum = 0; + cl_platform_id platform = NULL; + cl_uchar uuid[CL_UUID_SIZE_KHR]; + cl_device_id *devices; + char *extensions = NULL; + size_t extensionSize = 0; + cl_uint num_devices = 0; + cl_uint device_no = 0; + const size_t bufsize = BUFFERSIZE; + char buf[BUFFERSIZE]; + const VulkanInstance &instance = getVulkanInstance(); + const VulkanPhysicalDeviceList &physicalDeviceList = + instance.getPhysicalDeviceList(); + + // get the platform ID + errNum = clGetPlatformIDs(1, &platform, NULL); + if (errNum != CL_SUCCESS) + { + printf("Error: Failed to get platform\n"); + throw std::runtime_error("Error: Failed to get number of platform\n"); + } + + errNum = + clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &num_devices); + if (CL_SUCCESS != errNum) + { + throw std::runtime_error( + "Error: clGetDeviceIDs failed in returning of devices\n"); + } + devices = (cl_device_id *)malloc(num_devices * sizeof(cl_device_id)); + if (NULL == devices) + { + throw std::runtime_error( + "Error: Unable to allocate memory for devices\n"); + } + errNum = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, num_devices, devices, + NULL); + if (CL_SUCCESS != errNum) + { + throw std::runtime_error("Error: Failed to get deviceID.\n"); + } + bool is_selected = false; + for (device_no = 0; device_no < num_devices; device_no++) + { + errNum = clGetDeviceInfo(devices[device_no], CL_DEVICE_EXTENSIONS, 0, + NULL, &extensionSize); + if (CL_SUCCESS != errNum) + { + throw std::runtime_error("Error in clGetDeviceInfo for getting " + "device_extension size....\n"); + } + extensions = (char *)malloc(extensionSize); + if (NULL == extensions) + { + throw std::runtime_error( + "Unable to allocate memory for extensions\n"); + } + errNum = clGetDeviceInfo(devices[device_no], CL_DEVICE_EXTENSIONS, + extensionSize, extensions, NULL); + if (CL_SUCCESS != errNum) + { + throw std::runtime_error("Error: Error in clGetDeviceInfo for " + "getting device_extension\n"); + } + errNum = clGetDeviceInfo(devices[device_no], CL_DEVICE_UUID_KHR, + CL_UUID_SIZE_KHR, uuid, &extensionSize); + if (CL_SUCCESS != errNum) + { + throw std::runtime_error( + "Error: clGetDeviceInfo failed with error\n"); + } + free(extensions); + for (pdIdx = 0; pdIdx < physicalDeviceList.size(); pdIdx++) + { + if (!memcmp(&uuid, physicalDeviceList[pdIdx].getUUID(), + VK_UUID_SIZE)) + { + std::cout << "Selected physical device = " + << physicalDeviceList[pdIdx] << std::endl; + is_selected = true; + break; + } + } + if (is_selected) + { + break; + } + } + + if ((pdIdx >= physicalDeviceList.size()) + || (physicalDeviceList[pdIdx] == (VkPhysicalDevice)VK_NULL_HANDLE)) + { + throw std::runtime_error("failed to find a suitable GPU!"); + } + std::cout << "Selected physical device is: " << physicalDeviceList[pdIdx] + << std::endl; + return physicalDeviceList[pdIdx]; +} + +const VulkanQueueFamily &getVulkanQueueFamily(uint32_t queueFlags) +{ + size_t qfIdx; + const VulkanPhysicalDevice &physicalDevice = getVulkanPhysicalDevice(); + const VulkanQueueFamilyList &queueFamilyList = + physicalDevice.getQueueFamilyList(); + + for (qfIdx = 0; qfIdx < queueFamilyList.size(); qfIdx++) + { + if ((queueFamilyList[qfIdx].getQueueFlags() & queueFlags) == queueFlags) + { + break; + } + } + + return queueFamilyList[qfIdx]; +} + +const VulkanMemoryType & +getVulkanMemoryType(const VulkanDevice &device, + VulkanMemoryTypeProperty memoryTypeProperty) +{ + size_t mtIdx; + const VulkanMemoryTypeList &memoryTypeList = + device.getPhysicalDevice().getMemoryTypeList(); + + for (mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++) + { + if ((memoryTypeList[mtIdx].getMemoryTypeProperty() & memoryTypeProperty) + == memoryTypeProperty) + { + break; + } + } + + // CHECK_LT(mtIdx, memoryTypeList.size()); + return memoryTypeList[mtIdx]; +} + +bool checkVkSupport() +{ + bool result = true; + const VulkanInstance &instance = getVulkanInstance(); + const VulkanPhysicalDeviceList &physicalDeviceList = + instance.getPhysicalDeviceList(); + if (physicalDeviceList == NULL) + { + std::cout << "physicalDeviceList is null, No GPUs found with " + "Vulkan support !!!\n"; + result = false; + } + return result; +} + +const VulkanQueueFamilyList &getEmptyVulkanQueueFamilyList() +{ + static VulkanQueueFamilyList queueFamilyList; + return queueFamilyList; +} + +const VulkanDescriptorSetLayoutList &getEmptyVulkanDescriptorSetLayoutList() +{ + static VulkanDescriptorSetLayoutList descriptorSetLayoutList; + + return descriptorSetLayoutList; +} + +const VulkanQueueFamilyToQueueCountMap & +getDefaultVulkanQueueFamilyToQueueCountMap() +{ + static VulkanQueueFamilyToQueueCountMap queueFamilyToQueueCountMap(1); + + return queueFamilyToQueueCountMap; +} + +const std::vector +getSupportedVulkanExternalMemoryHandleTypeList() +{ + std::vector externalMemoryHandleTypeList; + +#if _WIN32 + if (IsWindows8OrGreater()) + { + externalMemoryHandleTypeList.push_back( + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT); + } + externalMemoryHandleTypeList.push_back( + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT); +#else + externalMemoryHandleTypeList.push_back( + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD); +#endif + + return externalMemoryHandleTypeList; +} + +const std::vector +getSupportedVulkanExternalSemaphoreHandleTypeList() +{ + std::vector + externalSemaphoreHandleTypeList; + +#if _WIN32 + if (IsWindows8OrGreater()) + { + externalSemaphoreHandleTypeList.push_back( + VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT); + } + externalSemaphoreHandleTypeList.push_back( + VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT); +#else + externalSemaphoreHandleTypeList.push_back( + VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD); +#endif + + return externalSemaphoreHandleTypeList; +} + +const std::vector getSupportedVulkanFormatList() +{ + std::vector formatList; + + formatList.push_back(VULKAN_FORMAT_R8_UINT); + formatList.push_back(VULKAN_FORMAT_R8_SINT); + formatList.push_back(VULKAN_FORMAT_R8G8_UINT); + formatList.push_back(VULKAN_FORMAT_R8G8_SINT); + formatList.push_back(VULKAN_FORMAT_R8G8B8A8_UINT); + formatList.push_back(VULKAN_FORMAT_R8G8B8A8_SINT); + formatList.push_back(VULKAN_FORMAT_R16_UINT); + formatList.push_back(VULKAN_FORMAT_R16_SINT); + formatList.push_back(VULKAN_FORMAT_R16G16_UINT); + formatList.push_back(VULKAN_FORMAT_R16G16_SINT); + formatList.push_back(VULKAN_FORMAT_R16G16B16A16_UINT); + formatList.push_back(VULKAN_FORMAT_R16G16B16A16_SINT); + formatList.push_back(VULKAN_FORMAT_R32_UINT); + formatList.push_back(VULKAN_FORMAT_R32_SINT); + formatList.push_back(VULKAN_FORMAT_R32_SFLOAT); + formatList.push_back(VULKAN_FORMAT_R32G32_UINT); + formatList.push_back(VULKAN_FORMAT_R32G32_SINT); + formatList.push_back(VULKAN_FORMAT_R32G32_SFLOAT); + formatList.push_back(VULKAN_FORMAT_R32G32B32A32_UINT); + formatList.push_back(VULKAN_FORMAT_R32G32B32A32_SINT); + formatList.push_back(VULKAN_FORMAT_R32G32B32A32_SFLOAT); + + for (size_t fIdx = 0; fIdx < formatList.size(); fIdx++) + { + switch (formatList[fIdx]) + { + case VULKAN_FORMAT_R8_UINT: + case VULKAN_FORMAT_R8_SINT: + case VULKAN_FORMAT_R8G8_UINT: + case VULKAN_FORMAT_R8G8_SINT: + case VULKAN_FORMAT_R8G8B8A8_UINT: + case VULKAN_FORMAT_R8G8B8A8_SINT: + case VULKAN_FORMAT_R16_UINT: + case VULKAN_FORMAT_R16_SINT: + case VULKAN_FORMAT_R16G16_UINT: + case VULKAN_FORMAT_R16G16_SINT: + case VULKAN_FORMAT_R16G16B16A16_UINT: + case VULKAN_FORMAT_R16G16B16A16_SINT: + case VULKAN_FORMAT_R32_UINT: + case VULKAN_FORMAT_R32_SINT: + case VULKAN_FORMAT_R32_SFLOAT: + case VULKAN_FORMAT_R32G32_UINT: + case VULKAN_FORMAT_R32G32_SINT: + case VULKAN_FORMAT_R32G32_SFLOAT: + case VULKAN_FORMAT_R32G32B32A32_UINT: + case VULKAN_FORMAT_R32G32B32A32_SINT: + case VULKAN_FORMAT_R32G32B32A32_SFLOAT: break; + + case VULKAN_FORMAT_UNDEFINED: + case VULKAN_FORMAT_R4G4_UNORM_PACK8: + case VULKAN_FORMAT_R4G4B4A4_UNORM_PACK16: + case VULKAN_FORMAT_B4G4R4A4_UNORM_PACK16: + case VULKAN_FORMAT_R5G6B5_UNORM_PACK16: + case VULKAN_FORMAT_B5G6R5_UNORM_PACK16: + case VULKAN_FORMAT_R5G5B5A1_UNORM_PACK16: + case VULKAN_FORMAT_B5G5R5A1_UNORM_PACK16: + case VULKAN_FORMAT_A1R5G5B5_UNORM_PACK16: + case VULKAN_FORMAT_R8_UNORM: + case VULKAN_FORMAT_R8_SNORM: + case VULKAN_FORMAT_R8_USCALED: + case VULKAN_FORMAT_R8_SSCALED: + case VULKAN_FORMAT_R8_SRGB: + case VULKAN_FORMAT_R8G8_SNORM: + case VULKAN_FORMAT_R8G8_UNORM: + case VULKAN_FORMAT_R8G8_USCALED: + case VULKAN_FORMAT_R8G8_SSCALED: + case VULKAN_FORMAT_R8G8_SRGB: + case VULKAN_FORMAT_R8G8B8_UNORM: + case VULKAN_FORMAT_R8G8B8_SNORM: + case VULKAN_FORMAT_R8G8B8_USCALED: + case VULKAN_FORMAT_R8G8B8_SSCALED: + case VULKAN_FORMAT_R8G8B8_UINT: + case VULKAN_FORMAT_R8G8B8_SINT: + case VULKAN_FORMAT_R8G8B8_SRGB: + case VULKAN_FORMAT_B8G8R8_UNORM: + case VULKAN_FORMAT_B8G8R8_SNORM: + case VULKAN_FORMAT_B8G8R8_USCALED: + case VULKAN_FORMAT_B8G8R8_SSCALED: + case VULKAN_FORMAT_B8G8R8_UINT: + case VULKAN_FORMAT_B8G8R8_SINT: + case VULKAN_FORMAT_B8G8R8_SRGB: + case VULKAN_FORMAT_R8G8B8A8_UNORM: + case VULKAN_FORMAT_R8G8B8A8_SNORM: + case VULKAN_FORMAT_R8G8B8A8_USCALED: + case VULKAN_FORMAT_R8G8B8A8_SSCALED: + case VULKAN_FORMAT_R8G8B8A8_SRGB: + case VULKAN_FORMAT_B8G8R8A8_UNORM: + case VULKAN_FORMAT_B8G8R8A8_SNORM: + case VULKAN_FORMAT_B8G8R8A8_USCALED: + case VULKAN_FORMAT_B8G8R8A8_SSCALED: + case VULKAN_FORMAT_B8G8R8A8_UINT: + case VULKAN_FORMAT_B8G8R8A8_SINT: + case VULKAN_FORMAT_B8G8R8A8_SRGB: + case VULKAN_FORMAT_A8B8G8R8_UNORM_PACK32: + case VULKAN_FORMAT_A8B8G8R8_SNORM_PACK32: + case VULKAN_FORMAT_A8B8G8R8_USCALED_PACK32: + case VULKAN_FORMAT_A8B8G8R8_SSCALED_PACK32: + case VULKAN_FORMAT_A8B8G8R8_UINT_PACK32: + case VULKAN_FORMAT_A8B8G8R8_SINT_PACK32: + case VULKAN_FORMAT_A8B8G8R8_SRGB_PACK32: + case VULKAN_FORMAT_A2R10G10B10_UNORM_PACK32: + case VULKAN_FORMAT_A2R10G10B10_SNORM_PACK32: + case VULKAN_FORMAT_A2R10G10B10_USCALED_PACK32: + case VULKAN_FORMAT_A2R10G10B10_SSCALED_PACK32: + case VULKAN_FORMAT_A2R10G10B10_UINT_PACK32: + case VULKAN_FORMAT_A2R10G10B10_SINT_PACK32: + case VULKAN_FORMAT_A2B10G10R10_UNORM_PACK32: + case VULKAN_FORMAT_A2B10G10R10_SNORM_PACK32: + case VULKAN_FORMAT_A2B10G10R10_USCALED_PACK32: + case VULKAN_FORMAT_A2B10G10R10_SSCALED_PACK32: + case VULKAN_FORMAT_A2B10G10R10_UINT_PACK32: + case VULKAN_FORMAT_A2B10G10R10_SINT_PACK32: + case VULKAN_FORMAT_R16_UNORM: + case VULKAN_FORMAT_R16_SNORM: + case VULKAN_FORMAT_R16_USCALED: + case VULKAN_FORMAT_R16_SSCALED: + case VULKAN_FORMAT_R16_SFLOAT: + case VULKAN_FORMAT_R16G16_UNORM: + case VULKAN_FORMAT_R16G16_SNORM: + case VULKAN_FORMAT_R16G16_USCALED: + case VULKAN_FORMAT_R16G16_SSCALED: + case VULKAN_FORMAT_R16G16_SFLOAT: + case VULKAN_FORMAT_R16G16B16_UNORM: + case VULKAN_FORMAT_R16G16B16_SNORM: + case VULKAN_FORMAT_R16G16B16_USCALED: + case VULKAN_FORMAT_R16G16B16_SSCALED: + case VULKAN_FORMAT_R16G16B16_UINT: + case VULKAN_FORMAT_R16G16B16_SINT: + case VULKAN_FORMAT_R16G16B16_SFLOAT: + case VULKAN_FORMAT_R16G16B16A16_UNORM: + case VULKAN_FORMAT_R16G16B16A16_SNORM: + case VULKAN_FORMAT_R16G16B16A16_USCALED: + case VULKAN_FORMAT_R16G16B16A16_SSCALED: + case VULKAN_FORMAT_R16G16B16A16_SFLOAT: + case VULKAN_FORMAT_R32G32B32_UINT: + case VULKAN_FORMAT_R32G32B32_SINT: + case VULKAN_FORMAT_R32G32B32_SFLOAT: + case VULKAN_FORMAT_R64_UINT: + case VULKAN_FORMAT_R64_SINT: + case VULKAN_FORMAT_R64_SFLOAT: + case VULKAN_FORMAT_R64G64_UINT: + case VULKAN_FORMAT_R64G64_SINT: + case VULKAN_FORMAT_R64G64_SFLOAT: + case VULKAN_FORMAT_R64G64B64_UINT: + case VULKAN_FORMAT_R64G64B64_SINT: + case VULKAN_FORMAT_R64G64B64_SFLOAT: + case VULKAN_FORMAT_R64G64B64A64_UINT: + case VULKAN_FORMAT_R64G64B64A64_SINT: + case VULKAN_FORMAT_R64G64B64A64_SFLOAT: + case VULKAN_FORMAT_B10G11R11_UFLOAT_PACK32: + case VULKAN_FORMAT_E5B9G9R9_UFLOAT_PACK32: + case VULKAN_FORMAT_D16_UNORM: + case VULKAN_FORMAT_X8_D24_UNORM_PACK32: + case VULKAN_FORMAT_D32_SFLOAT: + case VULKAN_FORMAT_S8_UINT: + case VULKAN_FORMAT_D16_UNORM_S8_UINT: + case VULKAN_FORMAT_D24_UNORM_S8_UINT: + case VULKAN_FORMAT_D32_SFLOAT_S8_UINT: + case VULKAN_FORMAT_BC1_RGB_UNORM_BLOCK: + case VULKAN_FORMAT_BC1_RGB_SRGB_BLOCK: + case VULKAN_FORMAT_BC1_RGBA_UNORM_BLOCK: + case VULKAN_FORMAT_BC1_RGBA_SRGB_BLOCK: + case VULKAN_FORMAT_BC2_UNORM_BLOCK: + case VULKAN_FORMAT_BC2_SRGB_BLOCK: + case VULKAN_FORMAT_BC3_UNORM_BLOCK: + case VULKAN_FORMAT_BC3_SRGB_BLOCK: + case VULKAN_FORMAT_BC4_UNORM_BLOCK: + case VULKAN_FORMAT_BC4_SNORM_BLOCK: + case VULKAN_FORMAT_BC5_UNORM_BLOCK: + case VULKAN_FORMAT_BC5_SNORM_BLOCK: + case VULKAN_FORMAT_BC6H_UFLOAT_BLOCK: + case VULKAN_FORMAT_BC6H_SFLOAT_BLOCK: + case VULKAN_FORMAT_BC7_UNORM_BLOCK: + case VULKAN_FORMAT_BC7_SRGB_BLOCK: + case VULKAN_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + case VULKAN_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + case VULKAN_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + case VULKAN_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + case VULKAN_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + case VULKAN_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + case VULKAN_FORMAT_EAC_R11_UNORM_BLOCK: + case VULKAN_FORMAT_EAC_R11_SNORM_BLOCK: + case VULKAN_FORMAT_EAC_R11G11_UNORM_BLOCK: + case VULKAN_FORMAT_EAC_R11G11_SNORM_BLOCK: + case VULKAN_FORMAT_ASTC_4x4_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_4x4_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_5x4_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_5x4_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_5x5_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_5x5_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_6x5_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_6x5_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_6x6_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_6x6_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_8x5_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_8x5_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_8x6_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_8x6_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_8x8_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_8x8_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_10x5_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_10x5_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_10x6_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_10x6_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_10x8_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_10x8_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_10x10_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_10x10_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_12x10_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_12x10_SRGB_BLOCK: + case VULKAN_FORMAT_ASTC_12x12_UNORM_BLOCK: + case VULKAN_FORMAT_ASTC_12x12_SRGB_BLOCK: + ASSERT(0); + std::cout << "Unsupport texture format"; + } + } + + return formatList; +} + +uint32_t getVulkanFormatElementSize(VulkanFormat format) +{ + switch (format) + { + case VULKAN_FORMAT_R8_UINT: return uint32_t(1); + case VULKAN_FORMAT_R8_SINT: return uint32_t(1); + case VULKAN_FORMAT_R8G8_UINT: return uint32_t(2); + case VULKAN_FORMAT_R8G8_SINT: return uint32_t(2); + case VULKAN_FORMAT_R8G8B8A8_UINT: return uint32_t(4); + case VULKAN_FORMAT_R8G8B8A8_SINT: return uint32_t(4); + case VULKAN_FORMAT_R16_UINT: return uint32_t(2); + case VULKAN_FORMAT_R16_SINT: return uint32_t(2); + case VULKAN_FORMAT_R16G16_UINT: return uint32_t(4); + case VULKAN_FORMAT_R16G16_SINT: return uint32_t(4); + case VULKAN_FORMAT_R16G16B16A16_UINT: return uint32_t(8); + case VULKAN_FORMAT_R16G16B16A16_SINT: return uint32_t(8); + case VULKAN_FORMAT_R32_UINT: return uint32_t(4); + case VULKAN_FORMAT_R32_SINT: return uint32_t(4); + case VULKAN_FORMAT_R32_SFLOAT: return uint32_t(4); + case VULKAN_FORMAT_R32G32_UINT: return uint32_t(8); + case VULKAN_FORMAT_R32G32_SINT: return uint32_t(8); + case VULKAN_FORMAT_R32G32_SFLOAT: return uint32_t(8); + case VULKAN_FORMAT_R32G32B32A32_UINT: return uint32_t(16); + case VULKAN_FORMAT_R32G32B32A32_SINT: return uint32_t(16); + case VULKAN_FORMAT_R32G32B32A32_SFLOAT: return uint32_t(16); + default: ASSERT(0); std::cout << "Unknown format"; + } + + return uint32_t(0); +} + +const char *getVulkanFormatGLSLFormat(VulkanFormat format) +{ + switch (format) + { + case VULKAN_FORMAT_R8_UINT: return "r8ui"; + case VULKAN_FORMAT_R8_SINT: return "r8i"; + case VULKAN_FORMAT_R8G8_UINT: return "rg8ui"; + case VULKAN_FORMAT_R8G8_SINT: return "rg8i"; + case VULKAN_FORMAT_R8G8B8A8_UINT: return "rgba8ui"; + case VULKAN_FORMAT_R8G8B8A8_SINT: return "rgba8i"; + case VULKAN_FORMAT_R16_UINT: return "r16ui"; + case VULKAN_FORMAT_R16_SINT: return "r16i"; + case VULKAN_FORMAT_R16G16_UINT: return "rg16ui"; + case VULKAN_FORMAT_R16G16_SINT: return "rg16i"; + case VULKAN_FORMAT_R16G16B16A16_UINT: return "rgba16ui"; + case VULKAN_FORMAT_R16G16B16A16_SINT: return "rgba16i"; + case VULKAN_FORMAT_R32_UINT: return "r32ui"; + case VULKAN_FORMAT_R32_SINT: return "r32i"; + case VULKAN_FORMAT_R32_SFLOAT: return "r32f"; + case VULKAN_FORMAT_R32G32_UINT: return "rg32ui"; + case VULKAN_FORMAT_R32G32_SINT: return "rg32i"; + case VULKAN_FORMAT_R32G32_SFLOAT: return "rg32f"; + case VULKAN_FORMAT_R32G32B32A32_UINT: return "rgba32ui"; + case VULKAN_FORMAT_R32G32B32A32_SINT: return "rgba32i"; + case VULKAN_FORMAT_R32G32B32A32_SFLOAT: return "rgba32f"; + default: ASSERT(0); std::cout << "Unknown format"; + } + + return (const char *)size_t(0); +} + +const char *getVulkanFormatGLSLTypePrefix(VulkanFormat format) +{ + switch (format) + { + case VULKAN_FORMAT_R8_UINT: + case VULKAN_FORMAT_R8G8_UINT: + case VULKAN_FORMAT_R8G8B8A8_UINT: + case VULKAN_FORMAT_R16_UINT: + case VULKAN_FORMAT_R16G16_UINT: + case VULKAN_FORMAT_R16G16B16A16_UINT: + case VULKAN_FORMAT_R32_UINT: + case VULKAN_FORMAT_R32G32_UINT: + case VULKAN_FORMAT_R32G32B32A32_UINT: return "u"; + + case VULKAN_FORMAT_R8_SINT: + case VULKAN_FORMAT_R8G8_SINT: + case VULKAN_FORMAT_R8G8B8A8_SINT: + case VULKAN_FORMAT_R16_SINT: + case VULKAN_FORMAT_R16G16_SINT: + case VULKAN_FORMAT_R16G16B16A16_SINT: + case VULKAN_FORMAT_R32_SINT: + case VULKAN_FORMAT_R32G32_SINT: + case VULKAN_FORMAT_R32G32B32A32_SINT: return "i"; + + case VULKAN_FORMAT_R32_SFLOAT: + case VULKAN_FORMAT_R32G32_SFLOAT: + case VULKAN_FORMAT_R32G32B32A32_SFLOAT: return ""; + + default: ASSERT(0); std::cout << "Unknown format"; + } + + return ""; +} + +std::string prepareVulkanShader( + std::string shaderCode, + const std::map &patternToSubstituteMap) +{ + for (std::map::const_iterator psIt = + patternToSubstituteMap.begin(); + psIt != patternToSubstituteMap.end(); ++psIt) + { + std::string::size_type pos = 0u; + while ((pos = shaderCode.find(psIt->first, pos)) != std::string::npos) + { + shaderCode.replace(pos, psIt->first.length(), psIt->second); + pos += psIt->second.length(); + } + } + + return shaderCode; +} + +std::ostream &operator<<(std::ostream &os, + VulkanMemoryTypeProperty memoryTypeProperty) +{ + switch (memoryTypeProperty) + { + case VULKAN_MEMORY_TYPE_PROPERTY_NONE: return os << "None"; + case VULKAN_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL: + return os << "Device local"; + case VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_COHERENT: + return os << "Host visible and coherent"; + case VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_CACHED: + return os << "Host visible and cached"; + case VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_CACHED_COHERENT: + return os << "Host visible, cached and coherent"; + case VULKAN_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL_HOST_VISIBLE_COHERENT: + return os << "Device local, Host visible and coherent"; + case VULKAN_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL_HOST_VISIBLE_CACHED: + return os << "Device local, Host visible and cached"; + case VULKAN_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL_HOST_VISIBLE_CACHED_COHERENT: + return os << "Device local, Host visible, cached and coherent"; + } + + return os; +} + +std::ostream & +operator<<(std::ostream &os, + VulkanExternalMemoryHandleType externalMemoryHandleType) +{ + switch (externalMemoryHandleType) + { + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE: return os << "None"; + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD: + return os << "Opaque file descriptor"; + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT: + return os << "Opaque NT handle"; + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT: + return os << "Opaque D3DKMT handle"; + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_KMT: + return os << "Opaque NT and D3DKMT handle"; + } + + return os; +} + +std::ostream & +operator<<(std::ostream &os, + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) +{ + switch (externalSemaphoreHandleType) + { + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE: return os << "None"; + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD: + return os << "Opaque file descriptor"; + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT: + return os << "Opaque NT handle"; + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT: + return os << "Opaque D3DKMT handle"; + case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT_KMT: + return os << "Opaque NT and D3DKMT handle"; + } + + return os; +} + +std::ostream &operator<<(std::ostream &os, VulkanFormat format) +{ + switch (format) + { + case VULKAN_FORMAT_R8_UINT: return os << "R8_UINT"; + case VULKAN_FORMAT_R8_SINT: return os << "R8_SINT"; + case VULKAN_FORMAT_R8G8_UINT: return os << "R8G8_UINT"; + case VULKAN_FORMAT_R8G8_SINT: return os << "R8G8_SINT"; + case VULKAN_FORMAT_R8G8B8A8_UINT: return os << "R8G8B8A8_UINT"; + case VULKAN_FORMAT_R8G8B8A8_SINT: return os << "R8G8B8A8_SINT"; + case VULKAN_FORMAT_R16_UINT: return os << "R16_UINT"; + case VULKAN_FORMAT_R16_SINT: return os << "R16_SINT"; + case VULKAN_FORMAT_R16G16_UINT: return os << "R16G16_UINT"; + case VULKAN_FORMAT_R16G16_SINT: return os << "R16G16_SINT"; + case VULKAN_FORMAT_R16G16B16A16_UINT: return os << "R16G16B16A16_UINT"; + case VULKAN_FORMAT_R16G16B16A16_SINT: return os << "R16G16B16A16_SINT"; + case VULKAN_FORMAT_R32_UINT: return os << "R32_UINT"; + case VULKAN_FORMAT_R32_SINT: return os << "R32_SINT"; + case VULKAN_FORMAT_R32_SFLOAT: return os << "R32_SFLOAT"; + case VULKAN_FORMAT_R32G32_UINT: return os << "R32G32_UINT"; + case VULKAN_FORMAT_R32G32_SINT: return os << "R32G32_SINT"; + case VULKAN_FORMAT_R32G32_SFLOAT: return os << "R32G32_SFLOAT"; + case VULKAN_FORMAT_R32G32B32A32_UINT: return os << "R32G32B32A32_UINT"; + case VULKAN_FORMAT_R32G32B32A32_SINT: return os << "R32G32B32A32_SINT"; + case VULKAN_FORMAT_R32G32B32A32_SFLOAT: + return os << "R32G32B32A32_SFLOAT"; + break; + default: ASSERT(0); std::cout << "Unknown format"; + } + + return os; +} diff --git a/test_conformance/vulkan/vulkan_interop_common/vulkan_utility.hpp b/test_conformance/vulkan/vulkan_interop_common/vulkan_utility.hpp new file mode 100644 index 00000000..7022fd5a --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/vulkan_utility.hpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#ifndef _vulkan_utility_hpp_ +#define _vulkan_utility_hpp_ + +#include "vulkan_wrapper_types.hpp" +#include +#include +#include +#include +#include "../../../test_common/harness/testHarness.h" + +#define STRING_(str) #str +#define STRING(str) STRING_(str) + +#define ROUND_UP(n, multiple) \ + (((n) + (multiple)-1) - ((((n) + (multiple)-1)) % (multiple))) + +const VulkanInstance& getVulkanInstance(); +const VulkanPhysicalDevice& getVulkanPhysicalDevice(); +const VulkanQueueFamily& +getVulkanQueueFamily(uint32_t queueFlags = VULKAN_QUEUE_FLAG_MASK_ALL); +const VulkanMemoryType& +getVulkanMemoryType(const VulkanDevice& device, + VulkanMemoryTypeProperty memoryTypeProperty); +bool checkVkSupport(); +const VulkanQueueFamilyList& getEmptyVulkanQueueFamilyList(); +const VulkanDescriptorSetLayoutList& getEmptyVulkanDescriptorSetLayoutList(); +const VulkanQueueFamilyToQueueCountMap& +getDefaultVulkanQueueFamilyToQueueCountMap(); +const std::vector +getSupportedVulkanExternalMemoryHandleTypeList(); +const std::vector +getSupportedVulkanExternalSemaphoreHandleTypeList(); +const std::vector getSupportedVulkanFormatList(); + +uint32_t getVulkanFormatElementSize(VulkanFormat format); +const char* getVulkanFormatGLSLFormat(VulkanFormat format); +const char* getVulkanFormatGLSLTypePrefix(VulkanFormat format); + +std::string prepareVulkanShader( + std::string shaderCode, + const std::map& patternToSubstituteMap); + +std::ostream& operator<<(std::ostream& os, + VulkanMemoryTypeProperty memoryTypeProperty); +std::ostream& +operator<<(std::ostream& os, + VulkanExternalMemoryHandleType externalMemoryHandleType); +std::ostream& +operator<<(std::ostream& os, + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType); +std::ostream& operator<<(std::ostream& os, VulkanFormat format); + +#endif // _vulkan_utility_hpp_ diff --git a/test_conformance/vulkan/vulkan_interop_common/vulkan_wrapper.cpp b/test_conformance/vulkan/vulkan_interop_common/vulkan_wrapper.cpp new file mode 100644 index 00000000..c044e009 --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/vulkan_wrapper.cpp @@ -0,0 +1,2075 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#ifdef _WIN32 +#define NOMINMAX +#include +#include +#include +#endif +#include +#include "vulkan_wrapper.hpp" +#if defined(__linux__) && !defined(__ANDROID__) +#include +#include +#elif defined(__ANDROID__) +#include +#endif +#if defined _WIN32 +#define LoadFunction GetProcAddress +#elif defined __linux +#define LoadFunction dlsym +#endif + +extern "C" { +#define VK_FUNC_DECL(name) PFN_##name _##name = NULL; +VK_FUNC_LIST +#if defined(_WIN32) || defined(_WIN64) +VK_WINDOWS_FUNC_LIST +#endif +#undef VK_FUNC_DECL +} + +#define WAIVED 2 +#define HANDLE_ERROR -1 + +#define CHECK_VK(call) \ + if (call != VK_SUCCESS) return call; +/////////////////////////////////// +// VulkanInstance implementation // +/////////////////////////////////// + +VulkanInstance::VulkanInstance(const VulkanInstance &instance) + : m_vkInstance(instance.m_vkInstance), + m_physicalDeviceList(instance.m_physicalDeviceList) +{} + +VulkanInstance::VulkanInstance(): m_vkInstance(VK_NULL_HANDLE) +{ +#if defined(__linux__) && !defined(__ANDROID__) + char *glibcVersion = strdup(gnu_get_libc_version()); + int majNum = (int)atoi(strtok(glibcVersion, ".")); + int minNum = (int)atoi(strtok(NULL, ".")); + free(glibcVersion); + if ((majNum < 2) || (majNum == 2 && minNum < 17)) + { + // WAIVE_TEST() << "Insufficient GLIBC version. Test waived!"; + } +#endif + +#if defined(_WIN32) || defined(_WIN64) + const char *vulkanLoaderLibraryName = "vulkan-1.dll"; +#elif defined(__linux__) + const char *vulkanLoaderLibraryName = "libvulkan.so.1"; +#endif +#ifdef _WIN32 + HINSTANCE hDLL; + hDLL = LoadLibrary(vulkanLoaderLibraryName); + if (hDLL == NULL) + { + throw std::runtime_error("LoadLibrary failed!"); + } + vkGetInstanceProcAddr = + (PFN_vkGetInstanceProcAddr)LoadFunction(hDLL, "vkGetInstanceProcAddr"); +#else +#if !defined(__APPLE__) + void *handle; + handle = dlopen(vulkanLoaderLibraryName, RTLD_LAZY); + if (!handle) + { + fputs(dlerror(), stderr); + throw std::runtime_error("dlopen failed !!!"); + } + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)LoadFunction( + handle, "vkGetInstanceProcAddr"); +#endif +#endif + if ((unsigned long long)vkGetInstanceProcAddr == (unsigned long long)NULL) + { + throw std::runtime_error("vkGetInstanceProcAddr() not found!"); + } +#define VK_GET_NULL_INSTANCE_PROC_ADDR(name) \ + _##name = (PFN_##name)vkGetInstanceProcAddr(NULL, #name); + + if ((unsigned long long)vkGetInstanceProcAddr == (unsigned long long)NULL) + { + throw std::runtime_error("Couldn't obtain address for function"); + } + VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceExtensionProperties); + uint32_t instanceExtensionPropertiesCount; + VkResult vkStatus = VK_SUCCESS; + vkStatus = vkEnumerateInstanceExtensionProperties( + NULL, &instanceExtensionPropertiesCount, NULL); + // Something went wrong in vulkan initialization (most likely incompatible + // device/driver combination) + if (vkStatus == VK_ERROR_INCOMPATIBLE_DRIVER) + { + throw std::runtime_error( + "Waiving vulkan test because " + "vkEnumerateInstanceExtensionProperties failed."); + // return WAIVED; + } + + VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceVersion); + VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceLayerProperties); + VK_GET_NULL_INSTANCE_PROC_ADDR(vkCreateInstance); +#undef VK_GET_NULL_INSTANCE_PROC_ADDR + + VkApplicationInfo vkApplicationInfo = {}; + vkApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + vkApplicationInfo.pNext = NULL; + vkApplicationInfo.pApplicationName = "Default app"; + vkApplicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + vkApplicationInfo.pEngineName = "No engine"; + vkApplicationInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + vkApplicationInfo.apiVersion = VK_API_VERSION_1_0; + + std::vector enabledExtensionNameList; + enabledExtensionNameList.push_back( + VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + enabledExtensionNameList.push_back( + VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME); + enabledExtensionNameList.push_back( + VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME); + + std::vector vkExtensionPropertiesList( + instanceExtensionPropertiesCount); + vkEnumerateInstanceExtensionProperties(NULL, + &instanceExtensionPropertiesCount, + vkExtensionPropertiesList.data()); + + for (size_t eenIdx = 0; eenIdx < enabledExtensionNameList.size(); eenIdx++) + { + bool isSupported = false; + for (size_t epIdx = 0; epIdx < vkExtensionPropertiesList.size(); + epIdx++) + { + if (!strcmp(enabledExtensionNameList[eenIdx], + vkExtensionPropertiesList[epIdx].extensionName)) + { + isSupported = true; + break; + } + } + if (!isSupported) + { + return; + } + } + + VkInstanceCreateInfo vkInstanceCreateInfo = {}; + vkInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + vkInstanceCreateInfo.pNext = NULL; + vkInstanceCreateInfo.flags = 0; + vkInstanceCreateInfo.pApplicationInfo = &vkApplicationInfo; + vkInstanceCreateInfo.enabledLayerCount = 0; + vkInstanceCreateInfo.ppEnabledLayerNames = NULL; + vkInstanceCreateInfo.enabledExtensionCount = + (uint32_t)enabledExtensionNameList.size(); + vkInstanceCreateInfo.ppEnabledExtensionNames = + enabledExtensionNameList.data(); + + vkCreateInstance(&vkInstanceCreateInfo, NULL, &m_vkInstance); + +#define VK_FUNC_DECL(name) \ + _##name = (PFN_##name)vkGetInstanceProcAddr(m_vkInstance, #name); \ + // ASSERT_NEQ((unsigned long long)name, 0ULL) << "Couldn't obtain address + // for function" << #name; + + VK_FUNC_LIST +#if defined(_WIN32) || defined(_WIN64) + VK_WINDOWS_FUNC_LIST +#endif +#undef VK_FUNC_DECL + + uint32_t physicalDeviceCount = 0; + vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount, NULL); + // CHECK_NEQ(physicalDeviceCount, uint32_t(0)); + + if (physicalDeviceCount == uint32_t(0)) + { + throw std::runtime_error("failed to find GPUs with Vulkan support!"); + } + + std::vector vkPhysicalDeviceList(physicalDeviceCount, + VK_NULL_HANDLE); + vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount, + vkPhysicalDeviceList.data()); + + for (size_t ppdIdx = 0; ppdIdx < vkPhysicalDeviceList.size(); ppdIdx++) + { + VulkanPhysicalDevice *physicalDevice = + new VulkanPhysicalDevice(vkPhysicalDeviceList[ppdIdx]); + m_physicalDeviceList.add(*physicalDevice); + } +} + +VulkanInstance::~VulkanInstance() +{ + for (size_t pdIdx = 0; pdIdx < m_physicalDeviceList.size(); pdIdx++) + { + const VulkanPhysicalDevice &physicalDevice = + m_physicalDeviceList[pdIdx]; + delete &physicalDevice; + } + if (m_vkInstance) + { + vkDestroyInstance(m_vkInstance, NULL); + } +} + +const VulkanPhysicalDeviceList &VulkanInstance::getPhysicalDeviceList() const +{ + return m_physicalDeviceList; +} + +VulkanInstance::operator VkInstance() const { return m_vkInstance; } + +///////////////////////////////////////// +// VulkanPhysicalDevice implementation // +///////////////////////////////////////// + +VulkanPhysicalDevice::VulkanPhysicalDevice( + const VulkanPhysicalDevice &physicalDevice) + : m_vkPhysicalDevice(physicalDevice.m_vkPhysicalDevice), + m_vkPhysicalDeviceProperties(physicalDevice.m_vkPhysicalDeviceProperties), + m_vkDeviceNodeMask(physicalDevice.m_vkDeviceNodeMask), + m_vkPhysicalDeviceFeatures(physicalDevice.m_vkPhysicalDeviceFeatures), + m_vkPhysicalDeviceMemoryProperties( + physicalDevice.m_vkPhysicalDeviceMemoryProperties), + m_queueFamilyList(physicalDevice.m_queueFamilyList) +{ + memcpy(m_vkDeviceUUID, physicalDevice.m_vkDeviceUUID, VK_UUID_SIZE); +} + +VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkPhysicalDevice) + : m_vkPhysicalDevice(vkPhysicalDevice) +{ + if (m_vkPhysicalDevice == (VkPhysicalDevice)VK_NULL_HANDLE) + { + throw std::runtime_error("failed to find a suitable GPU!"); + } + + vkGetPhysicalDeviceProperties(m_vkPhysicalDevice, + &m_vkPhysicalDeviceProperties); + vkGetPhysicalDeviceFeatures(m_vkPhysicalDevice, + &m_vkPhysicalDeviceFeatures); + + VkPhysicalDeviceIDPropertiesKHR vkPhysicalDeviceIDPropertiesKHR = {}; + vkPhysicalDeviceIDPropertiesKHR.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR; + vkPhysicalDeviceIDPropertiesKHR.pNext = NULL; + + VkPhysicalDeviceProperties2KHR vkPhysicalDeviceProperties2KHR = {}; + vkPhysicalDeviceProperties2KHR.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; + vkPhysicalDeviceProperties2KHR.pNext = &vkPhysicalDeviceIDPropertiesKHR; + + vkGetPhysicalDeviceProperties2KHR(m_vkPhysicalDevice, + &vkPhysicalDeviceProperties2KHR); + + memcpy(m_vkDeviceUUID, vkPhysicalDeviceIDPropertiesKHR.deviceUUID, + sizeof(m_vkDeviceUUID)); + memcpy(m_vkDeviceLUID, vkPhysicalDeviceIDPropertiesKHR.deviceLUID, + sizeof(m_vkDeviceLUID)); + m_vkDeviceNodeMask = vkPhysicalDeviceIDPropertiesKHR.deviceNodeMask; + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(m_vkPhysicalDevice, + &queueFamilyCount, NULL); + + std::vector vkQueueFamilyPropertiesList( + queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties( + m_vkPhysicalDevice, &queueFamilyCount, + vkQueueFamilyPropertiesList.data()); + + for (size_t qfpIdx = 0; qfpIdx < vkQueueFamilyPropertiesList.size(); + qfpIdx++) + { + VulkanQueueFamily *queueFamily = new VulkanQueueFamily( + uint32_t(qfpIdx), vkQueueFamilyPropertiesList[qfpIdx]); + m_queueFamilyList.add(*queueFamily); + } + + vkGetPhysicalDeviceMemoryProperties(m_vkPhysicalDevice, + &m_vkPhysicalDeviceMemoryProperties); + + for (uint32_t mhIdx = 0; + mhIdx < m_vkPhysicalDeviceMemoryProperties.memoryHeapCount; mhIdx++) + { + VulkanMemoryHeap *memoryHeap = new VulkanMemoryHeap( + mhIdx, m_vkPhysicalDeviceMemoryProperties.memoryHeaps[mhIdx].size, + (VulkanMemoryHeapFlag)m_vkPhysicalDeviceMemoryProperties + .memoryHeaps[mhIdx] + .flags); + m_memoryHeapList.add(*memoryHeap); + } + + for (uint32_t mtIdx = 0; + mtIdx < m_vkPhysicalDeviceMemoryProperties.memoryTypeCount; mtIdx++) + { + const VulkanMemoryHeap &memoryHeap = m_memoryHeapList + [m_vkPhysicalDeviceMemoryProperties.memoryTypes[mtIdx].heapIndex]; + VulkanMemoryType *memoryType = new VulkanMemoryType( + mtIdx, + (VulkanMemoryTypeProperty)m_vkPhysicalDeviceMemoryProperties + .memoryTypes[mtIdx] + .propertyFlags, + memoryHeap); + m_memoryTypeList.add(*memoryType); + } +} + +VulkanPhysicalDevice::~VulkanPhysicalDevice() +{ + for (size_t mtIdx = 0; mtIdx < m_memoryTypeList.size(); mtIdx++) + { + const VulkanMemoryType &memoryType = m_memoryTypeList[mtIdx]; + delete &memoryType; + } + + for (size_t mhIdx = 0; mhIdx < m_memoryHeapList.size(); mhIdx++) + { + const VulkanMemoryHeap &memoryHeap = m_memoryHeapList[mhIdx]; + delete &memoryHeap; + } + + for (size_t qfIdx = 0; qfIdx < m_queueFamilyList.size(); qfIdx++) + { + const VulkanQueueFamily &queueFamily = m_queueFamilyList[qfIdx]; + delete &queueFamily; + } +} + + +const VulkanQueueFamilyList &VulkanPhysicalDevice::getQueueFamilyList() const +{ + return m_queueFamilyList; +} + +const VulkanMemoryHeapList &VulkanPhysicalDevice::getMemoryHeapList() const +{ + return m_memoryHeapList; +} + +const VulkanMemoryTypeList &VulkanPhysicalDevice::getMemoryTypeList() const +{ + return m_memoryTypeList; +} + +const uint8_t *VulkanPhysicalDevice::getUUID() const { return m_vkDeviceUUID; } + +const uint8_t *VulkanPhysicalDevice::getLUID() const { return m_vkDeviceLUID; } + +uint32_t VulkanPhysicalDevice::getNodeMask() const +{ + return m_vkDeviceNodeMask; +} + +VulkanPhysicalDevice::operator VkPhysicalDevice() const +{ + return m_vkPhysicalDevice; +} + +bool operator<(const VulkanQueueFamily &queueFamilyA, + const VulkanQueueFamily &queueFamilyB) +{ + return (uint32_t)queueFamilyA < (uint32_t)queueFamilyB; +} + +///////////////////////////////////// +// VulkanMemoryHeap implementation // +///////////////////////////////////// + +VulkanMemoryHeap::VulkanMemoryHeap(const VulkanMemoryHeap &memoryHeap) + : m_memoryHeapIndex(memoryHeap.m_memoryHeapIndex), + m_size(memoryHeap.m_size), m_memoryHeapFlag(memoryHeap.m_memoryHeapFlag) +{} + +VulkanMemoryHeap::VulkanMemoryHeap(uint32_t memoryHeapIndex, uint64_t size, + VulkanMemoryHeapFlag memoryHeapFlag) + : m_memoryHeapIndex(memoryHeapIndex), m_size(size), + m_memoryHeapFlag(memoryHeapFlag) +{} + +VulkanMemoryHeap::~VulkanMemoryHeap() {} + +uint64_t VulkanMemoryHeap::getSize() const { return m_size; } + + +VulkanMemoryHeapFlag VulkanMemoryHeap::getMemoryHeapFlag() const +{ + return m_memoryHeapFlag; +} + +VulkanMemoryHeap::operator uint32_t() const { return m_memoryHeapIndex; } + +///////////////////////////////////// +// VulkanMemoryType implementation // +///////////////////////////////////// + +VulkanMemoryType::VulkanMemoryType(const VulkanMemoryType &memoryType) + : m_memoryTypeIndex(memoryType.m_memoryTypeIndex), + m_memoryTypeProperty(memoryType.m_memoryTypeProperty), + m_memoryHeap(memoryType.m_memoryHeap) +{} + +VulkanMemoryType::VulkanMemoryType(uint32_t memoryTypeIndex, + VulkanMemoryTypeProperty memoryTypeProperty, + const VulkanMemoryHeap &memoryHeap) + : m_memoryTypeIndex(memoryTypeIndex), + m_memoryTypeProperty(memoryTypeProperty), m_memoryHeap(memoryHeap) +{} + +VulkanMemoryType::~VulkanMemoryType() {} + +VulkanMemoryTypeProperty VulkanMemoryType::getMemoryTypeProperty() const +{ + return m_memoryTypeProperty; +} + +const VulkanMemoryHeap &VulkanMemoryType::getMemoryHeap() const +{ + return m_memoryHeap; +} + +VulkanMemoryType::operator uint32_t() const { return m_memoryTypeIndex; } + +////////////////////////////////////// +// VulkanQueueFamily implementation // +////////////////////////////////////// + +VulkanQueueFamily::VulkanQueueFamily(const VulkanQueueFamily &queueFamily) + : m_queueFamilyIndex(queueFamily.m_queueFamilyIndex), + m_vkQueueFamilyProperties(queueFamily.m_vkQueueFamilyProperties) +{} + +VulkanQueueFamily::VulkanQueueFamily( + uint32_t queueFamilyIndex, VkQueueFamilyProperties vkQueueFamilyProperties) + : m_queueFamilyIndex(queueFamilyIndex), + m_vkQueueFamilyProperties(vkQueueFamilyProperties) +{} + +VulkanQueueFamily::~VulkanQueueFamily() {} + +uint32_t VulkanQueueFamily::getQueueFlags() const +{ + return m_vkQueueFamilyProperties.queueFlags + & (uint32_t)VULKAN_QUEUE_FLAG_MASK_ALL; +} + +uint32_t VulkanQueueFamily::getQueueCount() const +{ + return m_vkQueueFamilyProperties.queueCount; +} + +VulkanQueueFamily::operator uint32_t() const { return m_queueFamilyIndex; } + +///////////////////////////////// +// VulkanDevice implementation // +///////////////////////////////// + +VulkanDevice::VulkanDevice(const VulkanDevice &device) + : m_physicalDevice(device.m_physicalDevice), m_vkDevice(device.m_vkDevice) +{} + +VulkanDevice::VulkanDevice( + const VulkanPhysicalDevice &physicalDevice, + const VulkanQueueFamilyToQueueCountMap &queueFamilyToQueueCountMap) + : m_physicalDevice(physicalDevice), m_vkDevice(NULL) +{ + uint32_t maxQueueCount = 0; + for (uint32_t qfIdx = 0; + qfIdx < (uint32_t)physicalDevice.getQueueFamilyList().size(); qfIdx++) + { + maxQueueCount = + std::max(maxQueueCount, queueFamilyToQueueCountMap[qfIdx]); + } + + std::vector vkDeviceQueueCreateInfoList; + std::vector queuePriorities(maxQueueCount); + for (uint32_t qfIdx = 0; + qfIdx < (uint32_t)physicalDevice.getQueueFamilyList().size(); qfIdx++) + { + if (queueFamilyToQueueCountMap[qfIdx]) + { + VkDeviceQueueCreateInfo vkDeviceQueueCreateInfo = {}; + vkDeviceQueueCreateInfo.sType = + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + vkDeviceQueueCreateInfo.pNext = NULL; + vkDeviceQueueCreateInfo.flags = 0; + vkDeviceQueueCreateInfo.queueFamilyIndex = qfIdx; + vkDeviceQueueCreateInfo.queueCount = + queueFamilyToQueueCountMap[qfIdx]; + vkDeviceQueueCreateInfo.pQueuePriorities = queuePriorities.data(); + + vkDeviceQueueCreateInfoList.push_back(vkDeviceQueueCreateInfo); + } + } + + std::vector enabledExtensionNameList; + enabledExtensionNameList.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); + enabledExtensionNameList.push_back( + VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); +#if defined(_WIN32) || defined(_WIN64) + enabledExtensionNameList.push_back( + VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME); + enabledExtensionNameList.push_back( + VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME); +#else + enabledExtensionNameList.push_back( + VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); + enabledExtensionNameList.push_back( + VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME); +#endif + + + VkDeviceCreateInfo vkDeviceCreateInfo = {}; + vkDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + vkDeviceCreateInfo.pNext = NULL; + vkDeviceCreateInfo.flags = 0; + vkDeviceCreateInfo.queueCreateInfoCount = + (uint32_t)vkDeviceQueueCreateInfoList.size(); + vkDeviceCreateInfo.pQueueCreateInfos = vkDeviceQueueCreateInfoList.data(); + vkDeviceCreateInfo.enabledLayerCount = 0; + vkDeviceCreateInfo.ppEnabledLayerNames = NULL; + vkDeviceCreateInfo.enabledExtensionCount = + (uint32_t)enabledExtensionNameList.size(); + vkDeviceCreateInfo.ppEnabledExtensionNames = + enabledExtensionNameList.data(); + vkDeviceCreateInfo.pEnabledFeatures = NULL; + + vkCreateDevice(physicalDevice, &vkDeviceCreateInfo, NULL, &m_vkDevice); + + for (uint32_t qfIdx = 0; + qfIdx < (uint32_t)m_physicalDevice.getQueueFamilyList().size(); + qfIdx++) + { + VulkanQueueList *queueList = new VulkanQueueList(); + m_queueFamilyIndexToQueueListMap.insert(qfIdx, *queueList); + for (uint32_t qIdx = 0; qIdx < queueFamilyToQueueCountMap[qfIdx]; + qIdx++) + { + VkQueue vkQueue; + vkGetDeviceQueue(m_vkDevice, qfIdx, qIdx, &vkQueue); + VulkanQueue *queue = new VulkanQueue(vkQueue); + m_queueFamilyIndexToQueueListMap[qfIdx].add(*queue); + } + } +} + +VulkanDevice::~VulkanDevice() +{ + for (uint32_t qfIdx = 0; + qfIdx < (uint32_t)m_physicalDevice.getQueueFamilyList().size(); + qfIdx++) + { + for (size_t qIdx = 0; + qIdx < m_queueFamilyIndexToQueueListMap[qfIdx].size(); qIdx++) + { + VulkanQueue &queue = m_queueFamilyIndexToQueueListMap[qfIdx][qIdx]; + delete &queue; + } + VulkanQueueList &queueList = m_queueFamilyIndexToQueueListMap[qfIdx]; + delete &queueList; + } + vkDestroyDevice(m_vkDevice, NULL); +} + +const VulkanPhysicalDevice &VulkanDevice::getPhysicalDevice() const +{ + return m_physicalDevice; +} + +VulkanQueue &VulkanDevice::getQueue(const VulkanQueueFamily &queueFamily, + uint32_t queueIndex) +{ + return m_queueFamilyIndexToQueueListMap[queueFamily][queueIndex]; +} + +VulkanDevice::operator VkDevice() const { return m_vkDevice; } + +//////////////////////////////// +// VulkanQueue implementation // +//////////////////////////////// + +VulkanQueue::VulkanQueue(const VulkanQueue &queue): m_vkQueue(queue.m_vkQueue) +{} + +VulkanQueue::VulkanQueue(VkQueue vkQueue): m_vkQueue(vkQueue) {} + +VulkanQueue::~VulkanQueue() {} + +void VulkanQueue::submit(const VulkanSemaphoreList &waitSemaphoreList, + const VulkanCommandBufferList &commandBufferList, + const VulkanSemaphoreList &signalSemaphoreList) +{ + std::vector vkPipelineStageFlagsList( + waitSemaphoreList.size(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + + VkSubmitInfo vkSubmitInfo = {}; + vkSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + vkSubmitInfo.pNext = NULL; + vkSubmitInfo.waitSemaphoreCount = (uint32_t)waitSemaphoreList.size(); + vkSubmitInfo.pWaitSemaphores = waitSemaphoreList; + vkSubmitInfo.pWaitDstStageMask = vkPipelineStageFlagsList.data(); + vkSubmitInfo.commandBufferCount = (uint32_t)commandBufferList.size(); + vkSubmitInfo.pCommandBuffers = commandBufferList; + vkSubmitInfo.signalSemaphoreCount = (uint32_t)signalSemaphoreList.size(); + vkSubmitInfo.pSignalSemaphores = signalSemaphoreList; + + vkQueueSubmit(m_vkQueue, 1, &vkSubmitInfo, NULL); +} + +void VulkanQueue::submit(const VulkanSemaphore &waitSemaphore, + const VulkanCommandBuffer &commandBuffer, + const VulkanSemaphore &signalSemaphore) +{ + VulkanSemaphoreList waitSemaphoreList; + VulkanCommandBufferList commandBufferList; + VulkanSemaphoreList signalSemaphoreList; + + waitSemaphoreList.add(waitSemaphore); + commandBufferList.add(commandBuffer); + signalSemaphoreList.add(signalSemaphore); + + submit(waitSemaphoreList, commandBufferList, signalSemaphoreList); +} + +void VulkanQueue::submit(const VulkanCommandBuffer &commandBuffer, + const VulkanSemaphore &signalSemaphore) +{ + VulkanSemaphoreList waitSemaphoreList; + VulkanCommandBufferList commandBufferList; + VulkanSemaphoreList signalSemaphoreList; + + commandBufferList.add(commandBuffer); + signalSemaphoreList.add(signalSemaphore); + + submit(waitSemaphoreList, commandBufferList, signalSemaphoreList); +} + +void VulkanQueue::submit(const VulkanCommandBuffer &commandBuffer) +{ + VulkanSemaphoreList waitSemaphoreList; + VulkanCommandBufferList commandBufferList; + VulkanSemaphoreList signalSemaphoreList; + + commandBufferList.add(commandBuffer); + + submit(waitSemaphoreList, commandBufferList, signalSemaphoreList); +} + +void VulkanQueue::waitIdle() { vkQueueWaitIdle(m_vkQueue); } + +VulkanQueue::operator VkQueue() const { return m_vkQueue; } + +///////////////////////////////////////////////////// +// VulkanDescriptorSetLayoutBinding implementation // +///////////////////////////////////////////////////// + +VulkanDescriptorSetLayoutBinding::VulkanDescriptorSetLayoutBinding( + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding) + : m_vkDescriptorSetLayoutBinding( + descriptorSetLayoutBinding.m_vkDescriptorSetLayoutBinding) +{} + +VulkanDescriptorSetLayoutBinding::VulkanDescriptorSetLayoutBinding( + uint32_t binding, VulkanDescriptorType descriptorType, + uint32_t descriptorCount, VulkanShaderStage shaderStage) +{ + m_vkDescriptorSetLayoutBinding.binding = binding; + m_vkDescriptorSetLayoutBinding.descriptorType = + (VkDescriptorType)descriptorType; + m_vkDescriptorSetLayoutBinding.descriptorCount = descriptorCount; + m_vkDescriptorSetLayoutBinding.stageFlags = + (VkShaderStageFlags)(VkShaderStageFlagBits)shaderStage; + m_vkDescriptorSetLayoutBinding.pImmutableSamplers = NULL; +} + +VulkanDescriptorSetLayoutBinding::~VulkanDescriptorSetLayoutBinding() {} + +VulkanDescriptorSetLayoutBinding::operator VkDescriptorSetLayoutBinding() const +{ + return m_vkDescriptorSetLayoutBinding; +} + +////////////////////////////////////////////// +// VulkanDescriptorSetLayout implementation // +////////////////////////////////////////////// + +VulkanDescriptorSetLayout::VulkanDescriptorSetLayout( + const VulkanDescriptorSetLayout &descriptorSetLayout) + : m_device(descriptorSetLayout.m_device), + m_vkDescriptorSetLayout(descriptorSetLayout.m_vkDescriptorSetLayout) +{} + +void VulkanDescriptorSetLayout::VulkanDescriptorSetLayoutCommon( + const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList) +{ + VkDescriptorSetLayoutCreateInfo vkDescriptorSetLayoutCreateInfo = {}; + vkDescriptorSetLayoutCreateInfo.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + vkDescriptorSetLayoutCreateInfo.pNext = NULL; + vkDescriptorSetLayoutCreateInfo.flags = 0; + vkDescriptorSetLayoutCreateInfo.bindingCount = + (uint32_t)descriptorSetLayoutBindingList.size(); + vkDescriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindingList; + + vkCreateDescriptorSetLayout(m_device, &vkDescriptorSetLayoutCreateInfo, + NULL, &m_vkDescriptorSetLayout); +} + +VulkanDescriptorSetLayout::VulkanDescriptorSetLayout( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding) + : m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE) +{ + VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList; + descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding); + + VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList); +} + +VulkanDescriptorSetLayout::VulkanDescriptorSetLayout( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding0, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding1) + : m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE) +{ + VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList; + descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding0); + descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding1); + + VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList); +} + +VulkanDescriptorSetLayout::VulkanDescriptorSetLayout( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList) + : m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE) +{ + VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList); +} + +VulkanDescriptorSetLayout::~VulkanDescriptorSetLayout() +{ + if (m_vkDescriptorSetLayout != VK_NULL_HANDLE) + { + vkDestroyDescriptorSetLayout(m_device, m_vkDescriptorSetLayout, NULL); + } +} + +VulkanDescriptorSetLayout::operator VkDescriptorSetLayout() const +{ + return m_vkDescriptorSetLayout; +} + +///////////////////////////////////////// +// VulkanPipelineLayout implementation // +///////////////////////////////////////// + +VulkanPipelineLayout::VulkanPipelineLayout( + const VulkanPipelineLayout &pipelineLayout) + : m_device(pipelineLayout.m_device), + m_vkPipelineLayout(pipelineLayout.m_vkPipelineLayout) +{} + +void VulkanPipelineLayout::VulkanPipelineLayoutCommon( + const VulkanDescriptorSetLayoutList &descriptorSetLayoutList) +{ + VkPipelineLayoutCreateInfo vkPipelineLayoutCreateInfo = {}; + vkPipelineLayoutCreateInfo.sType = + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + vkPipelineLayoutCreateInfo.pNext = NULL; + vkPipelineLayoutCreateInfo.flags = 0; + vkPipelineLayoutCreateInfo.setLayoutCount = + (uint32_t)descriptorSetLayoutList.size(); + vkPipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayoutList; + vkPipelineLayoutCreateInfo.pushConstantRangeCount = 0; + vkPipelineLayoutCreateInfo.pPushConstantRanges = NULL; + + vkCreatePipelineLayout(m_device, &vkPipelineLayoutCreateInfo, NULL, + &m_vkPipelineLayout); +} + +VulkanPipelineLayout::VulkanPipelineLayout( + const VulkanDevice &device, + const VulkanDescriptorSetLayout &descriptorSetLayout) + : m_device(device), m_vkPipelineLayout(VK_NULL_HANDLE) +{ + VulkanDescriptorSetLayoutList descriptorSetLayoutList; + descriptorSetLayoutList.add(descriptorSetLayout); + + VulkanPipelineLayoutCommon(descriptorSetLayoutList); +} + +VulkanPipelineLayout::VulkanPipelineLayout( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutList &descriptorSetLayoutList) + : m_device(device), m_vkPipelineLayout(VK_NULL_HANDLE) +{ + VulkanPipelineLayoutCommon(descriptorSetLayoutList); +} + +VulkanPipelineLayout::~VulkanPipelineLayout() +{ + vkDestroyPipelineLayout(m_device, m_vkPipelineLayout, NULL); +} + +VulkanPipelineLayout::operator VkPipelineLayout() const +{ + return m_vkPipelineLayout; +} + +/////////////////////////////////////// +// VulkanShaderModule implementation // +/////////////////////////////////////// + +VulkanShaderModule::VulkanShaderModule(const VulkanShaderModule &shaderModule) + : m_device(shaderModule.m_device), + m_vkShaderModule(shaderModule.m_vkShaderModule) +{} + +VulkanShaderModule::VulkanShaderModule(const VulkanDevice &device, + const std::string &code) + : m_device(device) +{ + std::string paddedCode = code; + while (paddedCode.size() % 4) + { + paddedCode += " "; + } + + VkShaderModuleCreateInfo vkShaderModuleCreateInfo = {}; + vkShaderModuleCreateInfo.sType = + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + vkShaderModuleCreateInfo.pNext = NULL; + vkShaderModuleCreateInfo.flags = 0; + vkShaderModuleCreateInfo.codeSize = paddedCode.size(); + vkShaderModuleCreateInfo.pCode = + (const uint32_t *)(void *)paddedCode.c_str(); + + vkCreateShaderModule(m_device, &vkShaderModuleCreateInfo, NULL, + &m_vkShaderModule); +} + +VulkanShaderModule::~VulkanShaderModule() +{ + vkDestroyShaderModule(m_device, m_vkShaderModule, NULL); +} + +VulkanShaderModule::operator VkShaderModule() const { return m_vkShaderModule; } + +/////////////////////////////////// +// VulkanPipeline implementation // +/////////////////////////////////// + +VulkanPipeline::VulkanPipeline(const VulkanPipeline &pipeline) + : m_device(pipeline.m_device), m_vkPipeline(pipeline.m_vkPipeline) +{} + +VulkanPipeline::VulkanPipeline(const VulkanDevice &device) + : m_device(device), m_vkPipeline(VK_NULL_HANDLE) +{} + +VulkanPipeline::~VulkanPipeline() +{ + vkDestroyPipeline(m_device, m_vkPipeline, NULL); +} + +VulkanPipeline::operator VkPipeline() const { return m_vkPipeline; } + +////////////////////////////////////////// +// VulkanComputePipeline implementation // +////////////////////////////////////////// + +VulkanComputePipeline::VulkanComputePipeline( + const VulkanComputePipeline &computePipeline) + : VulkanPipeline(computePipeline) +{} + +VulkanComputePipeline::VulkanComputePipeline( + const VulkanDevice &device, const VulkanPipelineLayout &pipelineLayout, + const VulkanShaderModule &shaderModule, const std::string &entryFuncName) + : VulkanPipeline(device) +{ + VkPipelineShaderStageCreateInfo vkPipelineShaderStageCreateInfo = {}; + vkPipelineShaderStageCreateInfo.sType = + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vkPipelineShaderStageCreateInfo.pNext = NULL; + vkPipelineShaderStageCreateInfo.flags = 0; + vkPipelineShaderStageCreateInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; + vkPipelineShaderStageCreateInfo.module = shaderModule; + vkPipelineShaderStageCreateInfo.pName = entryFuncName.c_str(); + vkPipelineShaderStageCreateInfo.pSpecializationInfo = NULL; + + VkComputePipelineCreateInfo vkComputePipelineCreateInfo = {}; + vkComputePipelineCreateInfo.sType = + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + vkComputePipelineCreateInfo.pNext = NULL; + vkComputePipelineCreateInfo.flags = 0; + vkComputePipelineCreateInfo.stage = vkPipelineShaderStageCreateInfo; + vkComputePipelineCreateInfo.layout = pipelineLayout; + vkComputePipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE; + vkComputePipelineCreateInfo.basePipelineIndex = 0; + + vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, + &vkComputePipelineCreateInfo, NULL, &m_vkPipeline); +} + +VulkanComputePipeline::~VulkanComputePipeline() {} + +VulkanPipelineBindPoint VulkanComputePipeline::getPipelineBindPoint() const +{ + return VULKAN_PIPELINE_BIND_POINT_COMPUTE; +} + +///////////////////////////////////////// +// VulkanDescriptorPool implementation // +///////////////////////////////////////// + +VulkanDescriptorPool::VulkanDescriptorPool( + const VulkanDescriptorPool &descriptorPool) + : m_device(descriptorPool.m_device), + m_vkDescriptorPool(descriptorPool.m_vkDescriptorPool) +{} + +void VulkanDescriptorPool::VulkanDescriptorPoolCommon( + const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList) +{ + if (descriptorSetLayoutBindingList.size()) + { + std::map + vkDescriptorTypeToDescriptorCountMap; + + for (size_t dslbIdx = 0; + dslbIdx < descriptorSetLayoutBindingList.size(); dslbIdx++) + { + VkDescriptorSetLayoutBinding vkDescriptorSetLayoutBinding = + descriptorSetLayoutBindingList[dslbIdx]; + if (vkDescriptorTypeToDescriptorCountMap.find( + vkDescriptorSetLayoutBinding.descriptorType) + == vkDescriptorTypeToDescriptorCountMap.end()) + { + vkDescriptorTypeToDescriptorCountMap + [vkDescriptorSetLayoutBinding.descriptorType] = 1; + } + else + { + vkDescriptorTypeToDescriptorCountMap + [vkDescriptorSetLayoutBinding.descriptorType]++; + } + } + + std::vector vkDescriptorPoolSizeList; + std::map::iterator dtdcIt; + for (dtdcIt = vkDescriptorTypeToDescriptorCountMap.begin(); + dtdcIt != vkDescriptorTypeToDescriptorCountMap.end(); ++dtdcIt) + { + VkDescriptorPoolSize vkDescriptorPoolSize = {}; + vkDescriptorPoolSize.type = dtdcIt->first; + vkDescriptorPoolSize.descriptorCount = dtdcIt->second; + + vkDescriptorPoolSizeList.push_back(vkDescriptorPoolSize); + } + + VkDescriptorPoolCreateInfo vkDescriptorPoolCreateInfo = {}; + vkDescriptorPoolCreateInfo.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + vkDescriptorPoolCreateInfo.pNext = NULL; + vkDescriptorPoolCreateInfo.flags = + VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; + vkDescriptorPoolCreateInfo.maxSets = 1; + vkDescriptorPoolCreateInfo.poolSizeCount = + (uint32_t)vkDescriptorPoolSizeList.size(); + vkDescriptorPoolCreateInfo.pPoolSizes = vkDescriptorPoolSizeList.data(); + + vkCreateDescriptorPool(m_device, &vkDescriptorPoolCreateInfo, NULL, + &m_vkDescriptorPool); + } +} + +VulkanDescriptorPool::VulkanDescriptorPool( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding) + : m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE) +{ + VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList; + descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding); + + VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList); +} + +VulkanDescriptorPool::VulkanDescriptorPool( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding0, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding1) + : m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE) +{ + VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList; + descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding0); + descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding1); + + VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList); +} + +VulkanDescriptorPool::VulkanDescriptorPool( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList) + : m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE) +{ + VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList); +} + +VulkanDescriptorPool::~VulkanDescriptorPool() +{ + if (m_vkDescriptorPool != VK_NULL_HANDLE) + { + vkDestroyDescriptorPool(m_device, m_vkDescriptorPool, NULL); + } +} + +VulkanDescriptorPool::operator VkDescriptorPool() const +{ + return m_vkDescriptorPool; +} + +//////////////////////////////////////// +// VulkanDescriptorSet implementation // +//////////////////////////////////////// + +VulkanDescriptorSet::VulkanDescriptorSet( + const VulkanDescriptorSet &descriptorSet) + : m_device(descriptorSet.m_device), + m_descriptorPool(descriptorSet.m_descriptorPool), + m_vkDescriptorSet(descriptorSet.m_vkDescriptorSet) +{} + +VulkanDescriptorSet::VulkanDescriptorSet( + const VulkanDevice &device, const VulkanDescriptorPool &descriptorPool, + const VulkanDescriptorSetLayout &descriptorSetLayout) + : m_device(device), m_descriptorPool(descriptorPool), + m_vkDescriptorSet(VK_NULL_HANDLE) +{ + VkDescriptorSetLayout vkDescriptorSetLayout = descriptorSetLayout; + + if ((VkDescriptorPool)m_descriptorPool) + { + VkDescriptorSetAllocateInfo vkDescriptorSetAllocateInfo = {}; + vkDescriptorSetAllocateInfo.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + vkDescriptorSetAllocateInfo.pNext = NULL; + vkDescriptorSetAllocateInfo.descriptorPool = descriptorPool; + vkDescriptorSetAllocateInfo.descriptorSetCount = 1; + vkDescriptorSetAllocateInfo.pSetLayouts = &vkDescriptorSetLayout; + + vkAllocateDescriptorSets(m_device, &vkDescriptorSetAllocateInfo, + &m_vkDescriptorSet); + } +} + +VulkanDescriptorSet::~VulkanDescriptorSet() +{ + if ((VkDescriptorPool)m_descriptorPool) + { + vkFreeDescriptorSets(m_device, m_descriptorPool, 1, &m_vkDescriptorSet); + } +} + +void VulkanDescriptorSet::update(uint32_t binding, const VulkanBuffer &buffer) +{ + VkDescriptorBufferInfo vkDescriptorBufferInfo = {}; + vkDescriptorBufferInfo.buffer = buffer; + vkDescriptorBufferInfo.offset = 0; + vkDescriptorBufferInfo.range = VK_WHOLE_SIZE; + + VkWriteDescriptorSet vkWriteDescriptorSet = {}; + vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + vkWriteDescriptorSet.pNext = NULL; + vkWriteDescriptorSet.dstSet = m_vkDescriptorSet; + vkWriteDescriptorSet.dstBinding = binding; + vkWriteDescriptorSet.dstArrayElement = 0; + vkWriteDescriptorSet.descriptorCount = 1; + vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + vkWriteDescriptorSet.pImageInfo = NULL; + vkWriteDescriptorSet.pBufferInfo = &vkDescriptorBufferInfo; + vkWriteDescriptorSet.pTexelBufferView = NULL; + + vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL); +} + +void VulkanDescriptorSet::update(uint32_t binding, + const VulkanImageView &imageView) +{ + VkDescriptorImageInfo vkDescriptorImageInfo = {}; + vkDescriptorImageInfo.sampler = VK_NULL_HANDLE; + vkDescriptorImageInfo.imageView = imageView; + vkDescriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet vkWriteDescriptorSet = {}; + vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + vkWriteDescriptorSet.pNext = NULL; + vkWriteDescriptorSet.dstSet = m_vkDescriptorSet; + vkWriteDescriptorSet.dstBinding = binding; + vkWriteDescriptorSet.dstArrayElement = 0; + vkWriteDescriptorSet.descriptorCount = 1; + vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + vkWriteDescriptorSet.pImageInfo = &vkDescriptorImageInfo; + vkWriteDescriptorSet.pBufferInfo = NULL; + vkWriteDescriptorSet.pTexelBufferView = NULL; + + vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL); +} + +VulkanDescriptorSet::operator VkDescriptorSet() const +{ + return m_vkDescriptorSet; +} + +/////////////////////////////////// +// VulkanOffset3D implementation // +/////////////////////////////////// + +VulkanOffset3D::VulkanOffset3D(const VulkanOffset3D &offset3D) + : m_vkOffset3D(offset3D.m_vkOffset3D) +{} + +VulkanOffset3D::VulkanOffset3D(uint32_t x, uint32_t y, uint32_t z) +{ + m_vkOffset3D.x = x; + m_vkOffset3D.y = y; + m_vkOffset3D.z = z; +} + +VulkanOffset3D::~VulkanOffset3D() {} + +uint32_t VulkanOffset3D::getX() const { return m_vkOffset3D.x; } + +uint32_t VulkanOffset3D::getY() const { return m_vkOffset3D.y; } + +uint32_t VulkanOffset3D::getZ() const { return m_vkOffset3D.z; } + +VulkanOffset3D::operator VkOffset3D() const { return m_vkOffset3D; } + +/////////////////////////////////// +// VulkanExtent3D implementation // +/////////////////////////////////// + +VulkanExtent3D::VulkanExtent3D(const VulkanExtent3D &extent3D) + : m_vkExtent3D(extent3D.m_vkExtent3D) +{} + +VulkanExtent3D::VulkanExtent3D(uint32_t width, uint32_t height, uint32_t depth) +{ + m_vkExtent3D.width = width; + m_vkExtent3D.height = height; + m_vkExtent3D.depth = depth; +} + +VulkanExtent3D::~VulkanExtent3D() {} + +uint32_t VulkanExtent3D::getWidth() const { return m_vkExtent3D.width; } + +uint32_t VulkanExtent3D::getHeight() const { return m_vkExtent3D.height; } + +uint32_t VulkanExtent3D::getDepth() const { return m_vkExtent3D.depth; } + +VulkanExtent3D::operator VkExtent3D() const { return m_vkExtent3D; } + +////////////////////////////////////// +// VulkanCommandPool implementation // +////////////////////////////////////// + +VulkanCommandPool::VulkanCommandPool(const VulkanCommandPool &commandPool) + : m_device(commandPool.m_device), + m_vkCommandPool(commandPool.m_vkCommandPool) +{} + +VulkanCommandPool::VulkanCommandPool(const VulkanDevice &device, + const VulkanQueueFamily &queueFamily) + : m_device(device) +{ + VkCommandPoolCreateInfo vkCommandPoolCreateInfo = {}; + vkCommandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + vkCommandPoolCreateInfo.pNext = NULL; + vkCommandPoolCreateInfo.flags = + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + vkCommandPoolCreateInfo.queueFamilyIndex = queueFamily; + + vkCreateCommandPool(m_device, &vkCommandPoolCreateInfo, NULL, + &m_vkCommandPool); +} + +VulkanCommandPool::~VulkanCommandPool() +{ + vkDestroyCommandPool(m_device, m_vkCommandPool, NULL); +} + +VulkanCommandPool::operator VkCommandPool() const { return m_vkCommandPool; } + +//////////////////////////////////////// +// VulkanCommandBuffer implementation // +//////////////////////////////////////// + +VulkanCommandBuffer::VulkanCommandBuffer( + const VulkanCommandBuffer &commandBuffer) + : m_device(commandBuffer.m_device), + m_commandPool(commandBuffer.m_commandPool), + m_vkCommandBuffer(commandBuffer.m_vkCommandBuffer) +{} + +VulkanCommandBuffer::VulkanCommandBuffer(const VulkanDevice &device, + const VulkanCommandPool &commandPool) + : m_device(device), m_commandPool(commandPool) +{ + VkCommandBufferAllocateInfo vkCommandBufferAllocateInfo = {}; + vkCommandBufferAllocateInfo.sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + vkCommandBufferAllocateInfo.pNext = NULL; + vkCommandBufferAllocateInfo.commandPool = commandPool; + vkCommandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + vkCommandBufferAllocateInfo.commandBufferCount = 1; + + vkAllocateCommandBuffers(m_device, &vkCommandBufferAllocateInfo, + &m_vkCommandBuffer); +} + +VulkanCommandBuffer::~VulkanCommandBuffer() +{ + vkFreeCommandBuffers(m_device, m_commandPool, 1, &m_vkCommandBuffer); +} + +void VulkanCommandBuffer::begin() +{ + VkCommandBufferBeginInfo vkCommandBufferBeginInfo = {}; + vkCommandBufferBeginInfo.sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkCommandBufferBeginInfo.pNext = NULL; + vkCommandBufferBeginInfo.flags = + VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; + vkCommandBufferBeginInfo.pInheritanceInfo = NULL; + + vkBeginCommandBuffer(m_vkCommandBuffer, &vkCommandBufferBeginInfo); +} + +void VulkanCommandBuffer::bindPipeline(const VulkanPipeline &pipeline) +{ + VkPipelineBindPoint vkPipelineBindPoint = + (VkPipelineBindPoint)pipeline.getPipelineBindPoint(); + + vkCmdBindPipeline(m_vkCommandBuffer, vkPipelineBindPoint, pipeline); +} + +void VulkanCommandBuffer::bindDescriptorSets( + const VulkanPipeline &pipeline, const VulkanPipelineLayout &pipelineLayout, + const VulkanDescriptorSet &descriptorSet) +{ + VkPipelineBindPoint vkPipelineBindPoint = + (VkPipelineBindPoint)pipeline.getPipelineBindPoint(); + VkDescriptorSet vkDescriptorSet = descriptorSet; + + vkCmdBindDescriptorSets(m_vkCommandBuffer, vkPipelineBindPoint, + pipelineLayout, 0, 1, &vkDescriptorSet, 0, NULL); +} + +void VulkanCommandBuffer::pipelineBarrier(const VulkanImage2DList &image2DList, + VulkanImageLayout oldImageLayout, + VulkanImageLayout newImageLayout) +{ + std::vector vkImageMemoryBarrierList; + for (size_t i2DIdx = 0; i2DIdx < image2DList.size(); i2DIdx++) + { + VkImageSubresourceRange vkImageSubresourceRange = {}; + vkImageSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + vkImageSubresourceRange.baseMipLevel = 0; + vkImageSubresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + vkImageSubresourceRange.baseArrayLayer = 0; + vkImageSubresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + + VkImageMemoryBarrier vkImageMemoryBarrier = {}; + vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + vkImageMemoryBarrier.pNext = NULL; + vkImageMemoryBarrier.srcAccessMask = 0; + vkImageMemoryBarrier.dstAccessMask = 0; + vkImageMemoryBarrier.oldLayout = (VkImageLayout)oldImageLayout; + vkImageMemoryBarrier.newLayout = (VkImageLayout)newImageLayout; + vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkImageMemoryBarrier.image = image2DList[i2DIdx]; + vkImageMemoryBarrier.subresourceRange = vkImageSubresourceRange; + + vkImageMemoryBarrierList.push_back(vkImageMemoryBarrier); + } + + vkCmdPipelineBarrier(m_vkCommandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0, + NULL, (uint32_t)vkImageMemoryBarrierList.size(), + vkImageMemoryBarrierList.data()); +} + +void VulkanCommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, + uint32_t groupCountZ) +{ + vkCmdDispatch(m_vkCommandBuffer, groupCountX, groupCountY, groupCountZ); +} + +void VulkanCommandBuffer::fillBuffer(const VulkanBuffer &buffer, uint32_t data, + uint64_t offset, uint64_t size) +{ + vkCmdFillBuffer(m_vkCommandBuffer, buffer, offset, size, data); +} + +void VulkanCommandBuffer::updateBuffer(const VulkanBuffer &buffer, void *pdata, + uint64_t offset, uint64_t size) +{ + vkCmdUpdateBuffer(m_vkCommandBuffer, buffer, offset, size, pdata); +} + +void VulkanCommandBuffer::copyBufferToImage(const VulkanBuffer &buffer, + const VulkanImage &image, + VulkanImageLayout imageLayout) +{ + VkDeviceSize bufferOffset = 0; + + std::vector vkBufferImageCopyList; + for (uint32_t mipLevel = 0; mipLevel < image.getNumMipLevels(); mipLevel++) + { + VulkanExtent3D extent3D = image.getExtent3D(mipLevel); + size_t elementSize = getVulkanFormatElementSize(image.getFormat()); + + VkImageSubresourceLayers vkImageSubresourceLayers = {}; + vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + vkImageSubresourceLayers.mipLevel = mipLevel; + vkImageSubresourceLayers.baseArrayLayer = 0; + vkImageSubresourceLayers.layerCount = image.getNumLayers(); + + VkBufferImageCopy vkBufferImageCopy = {}; + vkBufferImageCopy.bufferOffset = bufferOffset; + vkBufferImageCopy.bufferRowLength = 0; + vkBufferImageCopy.bufferImageHeight = 0; + vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers; + vkBufferImageCopy.imageOffset = VulkanOffset3D(0, 0, 0); + vkBufferImageCopy.imageExtent = extent3D; + + vkBufferImageCopyList.push_back(vkBufferImageCopy); + + bufferOffset += extent3D.getWidth() * extent3D.getHeight() + * extent3D.getDepth() * elementSize; + bufferOffset = + ROUND_UP(bufferOffset, + std::max(elementSize, + (size_t)VULKAN_MIN_BUFFER_OFFSET_COPY_ALIGNMENT)); + } + + vkCmdCopyBufferToImage( + m_vkCommandBuffer, buffer, image, (VkImageLayout)imageLayout, + (uint32_t)vkBufferImageCopyList.size(), vkBufferImageCopyList.data()); +} + +void VulkanCommandBuffer::copyBufferToImage( + const VulkanBuffer &buffer, const VulkanImage &image, uint64_t bufferOffset, + uint32_t mipLevel, uint32_t baseArrayLayer, uint32_t layerCount, + VulkanOffset3D offset3D, VulkanExtent3D extent3D) +{ + VkImageSubresourceLayers vkImageSubresourceLayers = {}; + vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + vkImageSubresourceLayers.mipLevel = mipLevel; + vkImageSubresourceLayers.baseArrayLayer = baseArrayLayer; + vkImageSubresourceLayers.layerCount = layerCount; + + VkExtent3D vkExtent3D = extent3D; + if ((extent3D.getWidth() == 0) && (extent3D.getHeight() == 0) + && (extent3D.getDepth() == 0)) + { + vkExtent3D = image.getExtent3D(mipLevel); + } + + VkBufferImageCopy vkBufferImageCopy = {}; + vkBufferImageCopy.bufferOffset = bufferOffset; + vkBufferImageCopy.bufferRowLength = 0; + vkBufferImageCopy.bufferImageHeight = 0; + vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers; + vkBufferImageCopy.imageOffset = offset3D; + vkBufferImageCopy.imageExtent = vkExtent3D; + + vkCmdCopyBufferToImage(m_vkCommandBuffer, buffer, image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, + &vkBufferImageCopy); +} + +void VulkanCommandBuffer::copyImageToBuffer( + const VulkanImage &image, const VulkanBuffer &buffer, uint64_t bufferOffset, + uint32_t mipLevel, uint32_t baseArrayLayer, uint32_t layerCount, + VulkanOffset3D offset3D, VulkanExtent3D extent3D) +{ + VkImageSubresourceLayers vkImageSubresourceLayers = {}; + vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + vkImageSubresourceLayers.mipLevel = mipLevel; + vkImageSubresourceLayers.baseArrayLayer = baseArrayLayer; + vkImageSubresourceLayers.layerCount = layerCount; + + VkExtent3D vkExtent3D = extent3D; + if ((extent3D.getWidth() == 0) && (extent3D.getHeight() == 0) + && (extent3D.getDepth() == 0)) + { + vkExtent3D = image.getExtent3D(mipLevel); + } + + VkBufferImageCopy vkBufferImageCopy = {}; + vkBufferImageCopy.bufferOffset = bufferOffset; + vkBufferImageCopy.bufferRowLength = 0; + vkBufferImageCopy.bufferImageHeight = 0; + vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers; + vkBufferImageCopy.imageOffset = offset3D; + vkBufferImageCopy.imageExtent = vkExtent3D; + + vkCmdCopyImageToBuffer(m_vkCommandBuffer, image, VK_IMAGE_LAYOUT_GENERAL, + buffer, 1, &vkBufferImageCopy); +} + +void VulkanCommandBuffer::end() { vkEndCommandBuffer(m_vkCommandBuffer); } + +VulkanCommandBuffer::operator VkCommandBuffer() const +{ + return m_vkCommandBuffer; +} + +///////////////////////////////// +// VulkanBuffer implementation // +///////////////////////////////// + +VulkanBuffer::VulkanBuffer(const VulkanBuffer &buffer) + : m_device(buffer.m_device), m_vkBuffer(buffer.m_vkBuffer), + m_size(buffer.m_size), m_alignment(buffer.m_alignment), + m_memoryTypeList(buffer.m_memoryTypeList) +{} + +VulkanBuffer::VulkanBuffer( + const VulkanDevice &device, uint64_t size, + VulkanExternalMemoryHandleType externalMemoryHandleType, + VulkanBufferUsage bufferUsage, VulkanSharingMode sharingMode, + const VulkanQueueFamilyList &queueFamilyList) + : m_device(device), m_vkBuffer(VK_NULL_HANDLE) +{ + std::vector queueFamilyIndexList; + if (queueFamilyList.size() == 0) + { + for (size_t qfIdx = 0; + qfIdx < device.getPhysicalDevice().getQueueFamilyList().size(); + qfIdx++) + { + queueFamilyIndexList.push_back( + device.getPhysicalDevice().getQueueFamilyList()[qfIdx]); + } + } + else + { + for (size_t qfIdx = 0; qfIdx < queueFamilyList.size(); qfIdx++) + { + queueFamilyIndexList.push_back(queueFamilyList[qfIdx]); + } + } + + VkBufferCreateInfo vkBufferCreateInfo = {}; + vkBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + vkBufferCreateInfo.pNext = NULL; + vkBufferCreateInfo.flags = 0; + vkBufferCreateInfo.size = (VkDeviceSize)size; + vkBufferCreateInfo.usage = (VkBufferUsageFlags)bufferUsage; + vkBufferCreateInfo.sharingMode = (VkSharingMode)sharingMode; + vkBufferCreateInfo.queueFamilyIndexCount = + (uint32_t)queueFamilyIndexList.size(); + vkBufferCreateInfo.pQueueFamilyIndices = queueFamilyIndexList.data(); + + VkExternalMemoryBufferCreateInfo vkExternalMemoryBufferCreateInfo = {}; + if (externalMemoryHandleType != VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE) + { + vkExternalMemoryBufferCreateInfo.sType = + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR; + vkExternalMemoryBufferCreateInfo.pNext = NULL; + vkExternalMemoryBufferCreateInfo.handleTypes = + (VkExternalMemoryHandleTypeFlags)externalMemoryHandleType; + + vkBufferCreateInfo.pNext = &vkExternalMemoryBufferCreateInfo; + } + + vkCreateBuffer(m_device, &vkBufferCreateInfo, NULL, &m_vkBuffer); + + VkMemoryRequirements vkMemoryRequirements = {}; + vkGetBufferMemoryRequirements(m_device, m_vkBuffer, &vkMemoryRequirements); + m_size = vkMemoryRequirements.size; + m_alignment = vkMemoryRequirements.alignment; + const VulkanMemoryTypeList &memoryTypeList = + m_device.getPhysicalDevice().getMemoryTypeList(); + for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++) + { + uint32_t memoryTypeIndex = memoryTypeList[mtIdx]; + if ((1 << memoryTypeIndex) & vkMemoryRequirements.memoryTypeBits) + { + m_memoryTypeList.add(memoryTypeList[mtIdx]); + } + } +} + +VulkanBuffer::~VulkanBuffer() { vkDestroyBuffer(m_device, m_vkBuffer, NULL); } + +uint64_t VulkanBuffer::getSize() const { return m_size; } + +uint64_t VulkanBuffer::getAlignment() const { return m_alignment; } + +const VulkanMemoryTypeList &VulkanBuffer::getMemoryTypeList() const +{ + return m_memoryTypeList; +} + +VulkanBuffer::operator VkBuffer() const { return m_vkBuffer; } + +//////////////////////////////// +// VulkanImage implementation // +//////////////////////////////// + +VulkanImage::VulkanImage(const VulkanImage &image) + : m_device(image.m_device), m_imageType(image.m_imageType), + m_extent3D(image.m_extent3D), m_format(image.m_format), + m_numMipLevels(image.m_numMipLevels), m_numLayers(image.m_numLayers), + m_vkImage(image.m_vkImage), m_size(image.m_size), + m_alignment(image.m_alignment), m_memoryTypeList(image.m_memoryTypeList) +{} + +VulkanImage::VulkanImage( + const VulkanDevice &device, VulkanImageType imageType, VulkanFormat format, + const VulkanExtent3D &extent3D, uint32_t numMipLevels, uint32_t arrayLayers, + VulkanExternalMemoryHandleType externalMemoryHandleType, + VulkanImageCreateFlag imageCreateFlag, VulkanImageTiling imageTiling, + VulkanImageUsage imageUsage, VulkanSharingMode sharingMode) + : m_device(device), m_imageType(imageType), m_extent3D(extent3D), + m_format(format), m_numMipLevels(numMipLevels), m_numLayers(arrayLayers), + m_vkImage(VK_NULL_HANDLE) +{ + VkImageCreateInfo vkImageCreateInfo = {}; + vkImageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + vkImageCreateInfo.pNext = NULL; + vkImageCreateInfo.flags = (VkImageCreateFlags)imageCreateFlag; + vkImageCreateInfo.imageType = (VkImageType)imageType; + vkImageCreateInfo.format = (VkFormat)format; + vkImageCreateInfo.extent = extent3D; + vkImageCreateInfo.mipLevels = numMipLevels; + vkImageCreateInfo.arrayLayers = arrayLayers; + vkImageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + vkImageCreateInfo.tiling = (VkImageTiling)imageTiling; + vkImageCreateInfo.usage = (VkImageUsageFlags)imageUsage; + vkImageCreateInfo.sharingMode = (VkSharingMode)sharingMode; + vkImageCreateInfo.queueFamilyIndexCount = + (uint32_t)m_device.getPhysicalDevice().getQueueFamilyList().size(); + vkImageCreateInfo.pQueueFamilyIndices = + m_device.getPhysicalDevice().getQueueFamilyList(); + vkImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VkExternalMemoryImageCreateInfo vkExternalMemoryImageCreateInfo = {}; + if (externalMemoryHandleType != VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE) + { + vkExternalMemoryImageCreateInfo.sType = + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; + vkExternalMemoryImageCreateInfo.pNext = NULL; + vkExternalMemoryImageCreateInfo.handleTypes = + (VkExternalMemoryHandleTypeFlags)externalMemoryHandleType; + + vkImageCreateInfo.pNext = &vkExternalMemoryImageCreateInfo; + } + + vkCreateImage(m_device, &vkImageCreateInfo, NULL, &m_vkImage); + VulkanImageCreateInfo = vkImageCreateInfo; + VkMemoryRequirements vkMemoryRequirements = {}; + vkGetImageMemoryRequirements(m_device, m_vkImage, &vkMemoryRequirements); + m_size = vkMemoryRequirements.size; + m_alignment = vkMemoryRequirements.alignment; + const VulkanMemoryTypeList &memoryTypeList = + m_device.getPhysicalDevice().getMemoryTypeList(); + for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++) + { + uint32_t memoryTypeIndex = memoryTypeList[mtIdx]; + if ((1 << memoryTypeIndex) & vkMemoryRequirements.memoryTypeBits) + { + m_memoryTypeList.add(memoryTypeList[mtIdx]); + } + } +} + +VulkanImage::~VulkanImage() { vkDestroyImage(m_device, m_vkImage, NULL); } + +VulkanExtent3D VulkanImage::getExtent3D(uint32_t mipLevel) const +{ + return VulkanExtent3D(0, 0, 0); +} + +VulkanFormat VulkanImage::getFormat() const { return m_format; } + +VkImageCreateInfo VulkanImage::getVkImageCreateInfo() const +{ + return VulkanImageCreateInfo; +} + +uint32_t VulkanImage::getNumMipLevels() const { return m_numMipLevels; } + +uint32_t VulkanImage::getNumLayers() const { return m_numLayers; } + +uint64_t VulkanImage::getSize() const { return m_size; } + +uint64_t VulkanImage::getAlignment() const { return m_alignment; } + +const VulkanMemoryTypeList &VulkanImage::getMemoryTypeList() const +{ + return m_memoryTypeList; +} + +VulkanImage::operator VkImage() const { return m_vkImage; } + +////////////////////////////////// +// VulkanImage2D implementation // +////////////////////////////////// + +VulkanImage2D::VulkanImage2D(const VulkanImage2D &image2D): VulkanImage(image2D) +{} + +VulkanImage2D::VulkanImage2D( + const VulkanDevice &device, VulkanFormat format, uint32_t width, + uint32_t height, uint32_t numMipLevels, + VulkanExternalMemoryHandleType externalMemoryHandleType, + VulkanImageCreateFlag imageCreateFlag, VulkanImageUsage imageUsage, + VulkanSharingMode sharingMode) + : VulkanImage(device, VULKAN_IMAGE_TYPE_2D, format, + VulkanExtent3D(width, height, 1), numMipLevels, 1, + externalMemoryHandleType, imageCreateFlag, + VULKAN_IMAGE_TILING_OPTIMAL, imageUsage, sharingMode) +{} + +VulkanImage2D::~VulkanImage2D() {} + +VulkanExtent3D VulkanImage2D::getExtent3D(uint32_t mipLevel) const +{ + uint32_t width = std::max(m_extent3D.getWidth() >> mipLevel, uint32_t(1)); + uint32_t height = std::max(m_extent3D.getHeight() >> mipLevel, uint32_t(1)); + uint32_t depth = 1; + + return VulkanExtent3D(width, height, depth); +} + +//////////////////////////////////// +// VulkanImageView implementation // +//////////////////////////////////// + +VulkanImageView::VulkanImageView(const VulkanImageView &imageView) + : m_device(imageView.m_device), m_vkImageView(imageView.m_vkImageView) +{} + +VulkanImageView::VulkanImageView(const VulkanDevice &device, + const VulkanImage &image, + VulkanImageViewType imageViewType, + uint32_t baseMipLevel, uint32_t levelCount, + uint32_t baseArrayLayer, uint32_t layerCount) + : m_device(device), m_vkImageView(VK_NULL_HANDLE) +{ + VkComponentMapping vkComponentMapping = {}; + vkComponentMapping.r = VK_COMPONENT_SWIZZLE_IDENTITY; + vkComponentMapping.g = VK_COMPONENT_SWIZZLE_IDENTITY; + vkComponentMapping.b = VK_COMPONENT_SWIZZLE_IDENTITY; + vkComponentMapping.a = VK_COMPONENT_SWIZZLE_IDENTITY; + + VkImageSubresourceRange vkImageSubresourceRange = {}; + vkImageSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + vkImageSubresourceRange.baseMipLevel = baseMipLevel; + vkImageSubresourceRange.levelCount = levelCount; + vkImageSubresourceRange.baseArrayLayer = baseArrayLayer; + vkImageSubresourceRange.layerCount = layerCount; + + VkImageViewCreateInfo vkImageViewCreateInfo = {}; + vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + vkImageViewCreateInfo.pNext = NULL; + vkImageViewCreateInfo.flags = 0; + vkImageViewCreateInfo.image = image; + vkImageViewCreateInfo.viewType = (VkImageViewType)imageViewType; + vkImageViewCreateInfo.format = (VkFormat)image.getFormat(); + vkImageViewCreateInfo.components = vkComponentMapping; + vkImageViewCreateInfo.subresourceRange = vkImageSubresourceRange; + + vkCreateImageView(m_device, &vkImageViewCreateInfo, NULL, &m_vkImageView); +} + +VulkanImageView::~VulkanImageView() +{ + vkDestroyImageView(m_device, m_vkImageView, NULL); +} + +VulkanImageView::operator VkImageView() const { return m_vkImageView; } + +/////////////////////////////////////// +// VulkanDeviceMemory implementation // +/////////////////////////////////////// + +#if defined(_WIN32) || defined(_WIN64) + +class WindowsSecurityAttributes { +protected: + SECURITY_ATTRIBUTES m_winSecurityAttributes; + PSECURITY_DESCRIPTOR m_winPSecurityDescriptor; + +public: + WindowsSecurityAttributes(); + SECURITY_ATTRIBUTES *operator&(); + ~WindowsSecurityAttributes(); +}; + + +WindowsSecurityAttributes::WindowsSecurityAttributes() +{ + m_winPSecurityDescriptor = (PSECURITY_DESCRIPTOR)calloc( + 1, SECURITY_DESCRIPTOR_MIN_LENGTH + 2 * sizeof(void **)); + // CHECK_NEQ(m_winPSecurityDescriptor, (PSECURITY_DESCRIPTOR)NULL); + PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor + + SECURITY_DESCRIPTOR_MIN_LENGTH); + PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *)); + InitializeSecurityDescriptor(m_winPSecurityDescriptor, + SECURITY_DESCRIPTOR_REVISION); + SID_IDENTIFIER_AUTHORITY sidIdentifierAuthority = + SECURITY_WORLD_SID_AUTHORITY; + AllocateAndInitializeSid(&sidIdentifierAuthority, 1, SECURITY_WORLD_RID, 0, + 0, 0, 0, 0, 0, 0, ppSID); + EXPLICIT_ACCESS explicitAccess; + ZeroMemory(&explicitAccess, sizeof(EXPLICIT_ACCESS)); + explicitAccess.grfAccessPermissions = + STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; + explicitAccess.grfAccessMode = SET_ACCESS; + explicitAccess.grfInheritance = INHERIT_ONLY; + explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID; + explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + explicitAccess.Trustee.ptstrName = (LPTSTR)*ppSID; + SetEntriesInAcl(1, &explicitAccess, NULL, ppACL); + SetSecurityDescriptorDacl(m_winPSecurityDescriptor, TRUE, *ppACL, FALSE); + m_winSecurityAttributes.nLength = sizeof(m_winSecurityAttributes); + m_winSecurityAttributes.lpSecurityDescriptor = m_winPSecurityDescriptor; + m_winSecurityAttributes.bInheritHandle = TRUE; +} + +SECURITY_ATTRIBUTES *WindowsSecurityAttributes::operator&() +{ + return &m_winSecurityAttributes; +} + +WindowsSecurityAttributes::~WindowsSecurityAttributes() +{ + PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor + + SECURITY_DESCRIPTOR_MIN_LENGTH); + PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *)); + if (*ppSID) + { + FreeSid(*ppSID); + } + if (*ppACL) + { + LocalFree(*ppACL); + } + free(m_winPSecurityDescriptor); +} + +#endif + +VulkanDeviceMemory::VulkanDeviceMemory(const VulkanDeviceMemory &deviceMemory) + : m_device(deviceMemory.m_device), + m_vkDeviceMemory(deviceMemory.m_vkDeviceMemory), + m_size(deviceMemory.m_size), m_isDedicated(deviceMemory.m_isDedicated) +{} + +VulkanDeviceMemory::VulkanDeviceMemory( + const VulkanDevice &device, uint64_t size, + const VulkanMemoryType &memoryType, + VulkanExternalMemoryHandleType externalMemoryHandleType, const void *name) + : m_device(device), m_size(size), m_isDedicated(false) +{ +#if defined(_WIN32) || defined(_WIN64) + WindowsSecurityAttributes winSecurityAttributes; + + VkExportMemoryWin32HandleInfoKHR vkExportMemoryWin32HandleInfoKHR = {}; + vkExportMemoryWin32HandleInfoKHR.sType = + VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR; + vkExportMemoryWin32HandleInfoKHR.pNext = NULL; + vkExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes; + vkExportMemoryWin32HandleInfoKHR.dwAccess = + DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE; + vkExportMemoryWin32HandleInfoKHR.name = (LPCWSTR)name; + +#endif + + VkExportMemoryAllocateInfoKHR vkExportMemoryAllocateInfoKHR = {}; + vkExportMemoryAllocateInfoKHR.sType = + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR; +#if defined(_WIN32) || defined(_WIN64) + vkExportMemoryAllocateInfoKHR.pNext = externalMemoryHandleType + & VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT + ? &vkExportMemoryWin32HandleInfoKHR + : NULL; +#else + vkExportMemoryAllocateInfoKHR.pNext = NULL; +#endif + vkExportMemoryAllocateInfoKHR.handleTypes = + (VkExternalMemoryHandleTypeFlagsKHR)externalMemoryHandleType; + + VkMemoryAllocateInfo vkMemoryAllocateInfo = {}; + vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + vkMemoryAllocateInfo.pNext = + externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL; + vkMemoryAllocateInfo.allocationSize = m_size; + vkMemoryAllocateInfo.memoryTypeIndex = (uint32_t)memoryType; + + vkAllocateMemory(m_device, &vkMemoryAllocateInfo, NULL, &m_vkDeviceMemory); +} + +VulkanDeviceMemory::VulkanDeviceMemory( + const VulkanDevice &device, const VulkanImage &image, + const VulkanMemoryType &memoryType, + VulkanExternalMemoryHandleType externalMemoryHandleType, const void *name) + : m_device(device), m_size(image.getSize()), m_isDedicated(true) +{ +#if defined(_WIN32) || defined(_WIN64) + WindowsSecurityAttributes winSecurityAttributes; + + VkExportMemoryWin32HandleInfoKHR vkExportMemoryWin32HandleInfoKHR = {}; + vkExportMemoryWin32HandleInfoKHR.sType = + VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR; + vkExportMemoryWin32HandleInfoKHR.pNext = NULL; + vkExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes; + vkExportMemoryWin32HandleInfoKHR.dwAccess = + DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE; + vkExportMemoryWin32HandleInfoKHR.name = (LPCWSTR)name; + +#endif + + VkExportMemoryAllocateInfoKHR vkExportMemoryAllocateInfoKHR = {}; + vkExportMemoryAllocateInfoKHR.sType = + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR; +#if defined(_WIN32) || defined(_WIN64) + vkExportMemoryAllocateInfoKHR.pNext = externalMemoryHandleType + & VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT + ? &vkExportMemoryWin32HandleInfoKHR + : NULL; +#else + vkExportMemoryAllocateInfoKHR.pNext = NULL; +#endif + vkExportMemoryAllocateInfoKHR.handleTypes = + (VkExternalMemoryHandleTypeFlagsKHR)externalMemoryHandleType; + + VkMemoryDedicatedAllocateInfo vkMemoryDedicatedAllocateInfo = {}; + vkMemoryDedicatedAllocateInfo.sType = + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO; + vkMemoryDedicatedAllocateInfo.pNext = + externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL; + vkMemoryDedicatedAllocateInfo.image = image; + vkMemoryDedicatedAllocateInfo.buffer = VK_NULL_HANDLE; + + VkMemoryAllocateInfo vkMemoryAllocateInfo = {}; + vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + vkMemoryAllocateInfo.pNext = &vkMemoryDedicatedAllocateInfo; + vkMemoryAllocateInfo.allocationSize = m_size; + vkMemoryAllocateInfo.memoryTypeIndex = (uint32_t)memoryType; + + vkAllocateMemory(m_device, &vkMemoryAllocateInfo, NULL, &m_vkDeviceMemory); +} + +VulkanDeviceMemory::~VulkanDeviceMemory() +{ + vkFreeMemory(m_device, m_vkDeviceMemory, NULL); +} + +uint64_t VulkanDeviceMemory::getSize() const { return m_size; } + +#ifdef _WIN32 +HANDLE VulkanDeviceMemory::getHandle( + VulkanExternalMemoryHandleType externalMemoryHandleType) const +{ + HANDLE handle; + + VkMemoryGetWin32HandleInfoKHR vkMemoryGetWin32HandleInfoKHR = {}; + vkMemoryGetWin32HandleInfoKHR.sType = + VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR; + vkMemoryGetWin32HandleInfoKHR.pNext = NULL; + vkMemoryGetWin32HandleInfoKHR.memory = m_vkDeviceMemory; + vkMemoryGetWin32HandleInfoKHR.handleType = + (VkExternalMemoryHandleTypeFlagBitsKHR)externalMemoryHandleType; + + vkGetMemoryWin32HandleKHR(m_device, &vkMemoryGetWin32HandleInfoKHR, + &handle); + + return handle; +} +#else +int VulkanDeviceMemory::getHandle( + VulkanExternalMemoryHandleType externalMemoryHandleType) const +{ + if (externalMemoryHandleType + == VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD) + { + int fd; + + VkMemoryGetFdInfoKHR vkMemoryGetFdInfoKHR = {}; + vkMemoryGetFdInfoKHR.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR; + vkMemoryGetFdInfoKHR.pNext = NULL; + vkMemoryGetFdInfoKHR.memory = m_vkDeviceMemory; + vkMemoryGetFdInfoKHR.handleType = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; + + vkGetMemoryFdKHR(m_device, &vkMemoryGetFdInfoKHR, &fd); + + return fd; + } + return HANDLE_ERROR; +} +#endif + +bool VulkanDeviceMemory::isDedicated() const { return m_isDedicated; } + +void *VulkanDeviceMemory::map(size_t offset, size_t size) +{ + void *pData; + + vkMapMemory(m_device, m_vkDeviceMemory, (VkDeviceSize)offset, + (VkDeviceSize)size, 0, &pData); + + return pData; +} + +void VulkanDeviceMemory::unmap() { vkUnmapMemory(m_device, m_vkDeviceMemory); } + +void VulkanDeviceMemory::bindBuffer(const VulkanBuffer &buffer, uint64_t offset) +{ + vkBindBufferMemory(m_device, buffer, m_vkDeviceMemory, offset); +} + +void VulkanDeviceMemory::bindImage(const VulkanImage &image, uint64_t offset) +{ + vkBindImageMemory(m_device, image, m_vkDeviceMemory, offset); +} + +VulkanDeviceMemory::operator VkDeviceMemory() const { return m_vkDeviceMemory; } + +//////////////////////////////////// +// VulkanSemaphore implementation // +//////////////////////////////////// + +VulkanSemaphore::VulkanSemaphore(const VulkanSemaphore &semaphore) + : m_device(semaphore.m_device), m_vkSemaphore(semaphore.m_vkSemaphore) +{} + +VulkanSemaphore::VulkanSemaphore( + const VulkanDevice &device, + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType, + const std::wstring name) + : m_device(device), m_name(name) +{ +#if defined(_WIN32) || defined(_WIN64) + WindowsSecurityAttributes winSecurityAttributes; + + VkExportSemaphoreWin32HandleInfoKHR + vkExportSemaphoreWin32HandleInfoKHR = {}; + vkExportSemaphoreWin32HandleInfoKHR.sType = + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR; + vkExportSemaphoreWin32HandleInfoKHR.pNext = NULL; + vkExportSemaphoreWin32HandleInfoKHR.pAttributes = &winSecurityAttributes; + vkExportSemaphoreWin32HandleInfoKHR.dwAccess = + DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE; + vkExportSemaphoreWin32HandleInfoKHR.name = + m_name.size() ? (LPCWSTR)m_name.c_str() : NULL; +#endif + + VkExportSemaphoreCreateInfoKHR vkExportSemaphoreCreateInfoKHR = {}; + vkExportSemaphoreCreateInfoKHR.sType = + VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR; +#if defined(_WIN32) || defined(_WIN64) + vkExportSemaphoreCreateInfoKHR.pNext = + (externalSemaphoreHandleType + & VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT) + ? &vkExportSemaphoreWin32HandleInfoKHR + : NULL; +#else + vkExportSemaphoreCreateInfoKHR.pNext = NULL; +#endif + vkExportSemaphoreCreateInfoKHR.handleTypes = + (VkExternalSemaphoreHandleTypeFlagsKHR)externalSemaphoreHandleType; + + VkSemaphoreCreateInfo vkSemaphoreCreateInfo = {}; + vkSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + vkSemaphoreCreateInfo.pNext = + (externalSemaphoreHandleType + != VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE) + ? &vkExportSemaphoreCreateInfoKHR + : NULL; + vkSemaphoreCreateInfo.flags = 0; + + vkCreateSemaphore(m_device, &vkSemaphoreCreateInfo, NULL, &m_vkSemaphore); +} + +VulkanSemaphore::~VulkanSemaphore() +{ + vkDestroySemaphore(m_device, m_vkSemaphore, NULL); +} + +#if defined(_WIN32) || defined(_WIN64) +HANDLE VulkanSemaphore::getHandle( + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const +{ + HANDLE handle; + + VkSemaphoreGetWin32HandleInfoKHR vkSemaphoreGetWin32HandleInfoKHR = {}; + vkSemaphoreGetWin32HandleInfoKHR.sType = + VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR; + vkSemaphoreGetWin32HandleInfoKHR.pNext = NULL; + vkSemaphoreGetWin32HandleInfoKHR.semaphore = m_vkSemaphore; + vkSemaphoreGetWin32HandleInfoKHR.handleType = + (VkExternalSemaphoreHandleTypeFlagBitsKHR)externalSemaphoreHandleType; + + vkGetSemaphoreWin32HandleKHR(m_device, &vkSemaphoreGetWin32HandleInfoKHR, + &handle); + + return handle; +} +#else +int VulkanSemaphore::getHandle( + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const +{ + if (externalSemaphoreHandleType + == VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD) + { + int fd; + + VkSemaphoreGetFdInfoKHR vkSemaphoreGetFdInfoKHR = {}; + vkSemaphoreGetFdInfoKHR.sType = + VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR; + vkSemaphoreGetFdInfoKHR.pNext = NULL; + vkSemaphoreGetFdInfoKHR.semaphore = m_vkSemaphore; + vkSemaphoreGetFdInfoKHR.handleType = + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; + + vkGetSemaphoreFdKHR(m_device, &vkSemaphoreGetFdInfoKHR, &fd); + + return fd; + } + return HANDLE_ERROR; +} +#endif + +const std::wstring &VulkanSemaphore::getName() const { return m_name; } + +VulkanSemaphore::operator VkSemaphore() const { return m_vkSemaphore; } diff --git a/test_conformance/vulkan/vulkan_interop_common/vulkan_wrapper.hpp b/test_conformance/vulkan/vulkan_interop_common/vulkan_wrapper.hpp new file mode 100644 index 00000000..1f68a92b --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/vulkan_wrapper.hpp @@ -0,0 +1,579 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#ifndef _vulkan_wrapper_hpp_ +#define _vulkan_wrapper_hpp_ + +#include +#include "vulkan_wrapper_types.hpp" +#include "vulkan_list_map.hpp" +#include "vulkan_api_list.hpp" + +class VulkanInstance { + friend const VulkanInstance &getVulkanInstance(); + +protected: + VkInstance m_vkInstance; + VulkanPhysicalDeviceList m_physicalDeviceList; + + VulkanInstance(); + VulkanInstance(const VulkanInstance &); + virtual ~VulkanInstance(); + +public: + const VulkanPhysicalDeviceList &getPhysicalDeviceList() const; + operator VkInstance() const; +}; + +class VulkanPhysicalDevice { + friend class VulkanInstance; + +protected: + VkPhysicalDevice m_vkPhysicalDevice; + VkPhysicalDeviceProperties m_vkPhysicalDeviceProperties; + uint8_t m_vkDeviceUUID[VK_UUID_SIZE]; + uint8_t m_vkDeviceLUID[VK_LUID_SIZE]; + uint32_t m_vkDeviceNodeMask; + VkPhysicalDeviceFeatures m_vkPhysicalDeviceFeatures; + VkPhysicalDeviceMemoryProperties m_vkPhysicalDeviceMemoryProperties; + VulkanQueueFamilyList m_queueFamilyList; + VulkanMemoryHeapList m_memoryHeapList; + VulkanMemoryTypeList m_memoryTypeList; + + VulkanPhysicalDevice(const VulkanPhysicalDevice &physicalDevice); + VulkanPhysicalDevice(VkPhysicalDevice vkPhysicalDevice); + virtual ~VulkanPhysicalDevice(); + +public: + const VulkanQueueFamilyList &getQueueFamilyList() const; + const VulkanMemoryHeapList &getMemoryHeapList() const; + const VulkanMemoryTypeList &getMemoryTypeList() const; + const uint8_t *getUUID() const; + const uint8_t *getLUID() const; + uint32_t getNodeMask() const; + operator VkPhysicalDevice() const; +}; + +class VulkanMemoryHeap { + friend class VulkanPhysicalDevice; + +protected: + uint32_t m_memoryHeapIndex; + uint64_t m_size; + VulkanMemoryHeapFlag m_memoryHeapFlag; + + VulkanMemoryHeap(const VulkanMemoryHeap &memoryHeap); + VulkanMemoryHeap(uint32_t m_memoryHeapIndex, uint64_t m_size, + VulkanMemoryHeapFlag m_memoryHeapFlag); + virtual ~VulkanMemoryHeap(); + +public: + uint64_t getSize() const; + VulkanMemoryHeapFlag getMemoryHeapFlag() const; + operator uint32_t() const; +}; + +class VulkanMemoryType { + friend class VulkanPhysicalDevice; + +protected: + uint32_t m_memoryTypeIndex; + const VulkanMemoryTypeProperty m_memoryTypeProperty; + const VulkanMemoryHeap &m_memoryHeap; + + VulkanMemoryType(const VulkanMemoryType &memoryType); + VulkanMemoryType(uint32_t memoryTypeIndex, + VulkanMemoryTypeProperty memoryTypeProperty, + const VulkanMemoryHeap &memoryHeap); + virtual ~VulkanMemoryType(); + +public: + VulkanMemoryTypeProperty getMemoryTypeProperty() const; + const VulkanMemoryHeap &getMemoryHeap() const; + operator uint32_t() const; +}; + +class VulkanQueueFamily { + friend class VulkanPhysicalDevice; + +protected: + uint32_t m_queueFamilyIndex; + VkQueueFamilyProperties m_vkQueueFamilyProperties; + + VulkanQueueFamily(const VulkanQueueFamily &queueFamily); + VulkanQueueFamily(uint32_t queueFamilyIndex, + VkQueueFamilyProperties vkQueueFamilyProperties); + virtual ~VulkanQueueFamily(); + +public: + uint32_t getQueueFlags() const; + uint32_t getQueueCount() const; + operator uint32_t() const; +}; + +class VulkanDevice { +protected: + const VulkanPhysicalDevice &m_physicalDevice; + VkDevice m_vkDevice; + VulkanQueueFamilyToQueueListMap m_queueFamilyIndexToQueueListMap; + + VulkanDevice(const VulkanDevice &device); + +public: + VulkanDevice( + const VulkanPhysicalDevice &physicalDevice = getVulkanPhysicalDevice(), + const VulkanQueueFamilyToQueueCountMap &queueFamilyToQueueCountMap = + getDefaultVulkanQueueFamilyToQueueCountMap()); + virtual ~VulkanDevice(); + const VulkanPhysicalDevice &getPhysicalDevice() const; + VulkanQueue & + getQueue(const VulkanQueueFamily &queueFamily = getVulkanQueueFamily(), + uint32_t queueIndex = 0); + operator VkDevice() const; +}; + +class VulkanQueue { + friend class VulkanDevice; + +protected: + VkQueue m_vkQueue; + + VulkanQueue(VkQueue vkQueue); + VulkanQueue(const VulkanQueue &queue); + virtual ~VulkanQueue(); + +public: + const VulkanQueueFamily &getQueueFamily(); + void submit(const VulkanSemaphoreList &waitSemaphoreList, + const VulkanCommandBufferList &commandBufferList, + const VulkanSemaphoreList &signalSemaphoreList); + void submit(const VulkanSemaphore &waitSemaphore, + const VulkanCommandBuffer &commandBuffer, + const VulkanSemaphore &signalSemaphore); + void submit(const VulkanCommandBuffer &commandBuffer, + const VulkanSemaphore &signalSemaphore); + void submit(const VulkanCommandBuffer &commandBuffer); + void waitIdle(); + operator VkQueue() const; +}; + +class VulkanDescriptorSetLayoutBinding { +protected: + VkDescriptorSetLayoutBinding m_vkDescriptorSetLayoutBinding; + + VulkanDescriptorSetLayoutBinding( + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding); + +public: + VulkanDescriptorSetLayoutBinding( + uint32_t binding, VulkanDescriptorType descriptorType, + uint32_t descriptorCount = 1, + VulkanShaderStage shaderStage = VULKAN_SHADER_STAGE_COMPUTE); + virtual ~VulkanDescriptorSetLayoutBinding(); + operator VkDescriptorSetLayoutBinding() const; +}; + +class VulkanDescriptorSetLayout { +protected: + const VulkanDevice &m_device; + VkDescriptorSetLayout m_vkDescriptorSetLayout; + + VulkanDescriptorSetLayout( + const VulkanDescriptorSetLayout &descriptorSetLayout); + void + VulkanDescriptorSetLayoutCommon(const VulkanDescriptorSetLayoutBindingList + &descriptorSetLayoutBindingList); + +public: + VulkanDescriptorSetLayout( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding); + VulkanDescriptorSetLayout( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding0, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding1); + VulkanDescriptorSetLayout(const VulkanDevice &device, + const VulkanDescriptorSetLayoutBindingList + &descriptorSetLayoutBindingList); + virtual ~VulkanDescriptorSetLayout(); + operator VkDescriptorSetLayout() const; +}; + +class VulkanPipelineLayout { +protected: + const VulkanDevice &m_device; + VkPipelineLayout m_vkPipelineLayout; + + VulkanPipelineLayout(const VulkanPipelineLayout &pipelineLayout); + void VulkanPipelineLayoutCommon( + const VulkanDescriptorSetLayoutList &descriptorSetLayoutList); + +public: + VulkanPipelineLayout(const VulkanDevice &device, + const VulkanDescriptorSetLayout &descriptorSetLayout); + VulkanPipelineLayout( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutList &descriptorSetLayoutList = + getEmptyVulkanDescriptorSetLayoutList()); + virtual ~VulkanPipelineLayout(); + operator VkPipelineLayout() const; +}; + +class VulkanShaderModule { +protected: + const VulkanDevice &m_device; + VkShaderModule m_vkShaderModule; + + VulkanShaderModule(const VulkanShaderModule &shaderModule); + +public: + VulkanShaderModule(const VulkanDevice &device, const std::string &code); + virtual ~VulkanShaderModule(); + operator VkShaderModule() const; +}; + +class VulkanPipeline { +protected: + const VulkanDevice &m_device; + VkPipeline m_vkPipeline; + + VulkanPipeline(const VulkanPipeline &pipeline); + +public: + VulkanPipeline(const VulkanDevice &device); + virtual ~VulkanPipeline(); + virtual VulkanPipelineBindPoint getPipelineBindPoint() const = 0; + operator VkPipeline() const; +}; + +class VulkanComputePipeline : public VulkanPipeline { +protected: + VulkanComputePipeline(const VulkanComputePipeline &computePipeline); + +public: + VulkanComputePipeline(const VulkanDevice &device, + const VulkanPipelineLayout &pipelineLayout, + const VulkanShaderModule &shaderModule, + const std::string &entryFuncName = "main"); + virtual ~VulkanComputePipeline(); + VulkanPipelineBindPoint getPipelineBindPoint() const; +}; + +class VulkanDescriptorPool { +protected: + const VulkanDevice &m_device; + VkDescriptorPool m_vkDescriptorPool; + + VulkanDescriptorPool(const VulkanDescriptorPool &descriptorPool); + void VulkanDescriptorPoolCommon(const VulkanDescriptorSetLayoutBindingList + &descriptorSetLayoutBindingList); + +public: + VulkanDescriptorPool( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding); + VulkanDescriptorPool( + const VulkanDevice &device, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding0, + const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding1); + VulkanDescriptorPool(const VulkanDevice &device, + const VulkanDescriptorSetLayoutBindingList + &descriptorSetLayoutBindingList); + virtual ~VulkanDescriptorPool(); + operator VkDescriptorPool() const; +}; + +class VulkanDescriptorSet { +protected: + const VulkanDevice &m_device; + const VulkanDescriptorPool &m_descriptorPool; + VkDescriptorSet m_vkDescriptorSet; + + VulkanDescriptorSet(const VulkanDescriptorSet &descriptorSet); + +public: + VulkanDescriptorSet(const VulkanDevice &device, + const VulkanDescriptorPool &descriptorPool, + const VulkanDescriptorSetLayout &descriptorSetLayout); + virtual ~VulkanDescriptorSet(); + void update(uint32_t binding, const VulkanBuffer &buffer); + void update(uint32_t binding, const VulkanImageView &imageView); + operator VkDescriptorSet() const; +}; + +class VulkanOffset3D { +protected: + VkOffset3D m_vkOffset3D; + +public: + VulkanOffset3D(const VulkanOffset3D &extent3D); + VulkanOffset3D(uint32_t x = 0, uint32_t y = 0, uint32_t z = 0); + virtual ~VulkanOffset3D(); + uint32_t getX() const; + uint32_t getY() const; + uint32_t getZ() const; + operator VkOffset3D() const; +}; + +class VulkanExtent3D { +protected: + VkExtent3D m_vkExtent3D; + +public: + VulkanExtent3D(const VulkanExtent3D &extent3D); + VulkanExtent3D(uint32_t width, uint32_t height = 1, uint32_t depth = 1); + virtual ~VulkanExtent3D(); + uint32_t getWidth() const; + uint32_t getHeight() const; + uint32_t getDepth() const; + operator VkExtent3D() const; +}; + +class VulkanCommandPool { +protected: + const VulkanDevice &m_device; + VkCommandPool m_vkCommandPool; + + VulkanCommandPool(const VulkanCommandPool &commandPool); + +public: + VulkanCommandPool( + const VulkanDevice &device, + const VulkanQueueFamily &queueFamily = getVulkanQueueFamily()); + virtual ~VulkanCommandPool(); + operator VkCommandPool() const; +}; + +class VulkanCommandBuffer { +protected: + const VulkanDevice &m_device; + const VulkanCommandPool &m_commandPool; + VkCommandBuffer m_vkCommandBuffer; + + VulkanCommandBuffer(const VulkanCommandBuffer &commandBuffer); + +public: + VulkanCommandBuffer(const VulkanDevice &device, + const VulkanCommandPool &commandPool); + virtual ~VulkanCommandBuffer(); + void begin(); + void bindPipeline(const VulkanPipeline &pipeline); + void bindDescriptorSets(const VulkanPipeline &pipeline, + const VulkanPipelineLayout &pipelineLayout, + const VulkanDescriptorSet &descriptorSet); + void pipelineBarrier(const VulkanImage2DList &image2DList, + VulkanImageLayout oldImageLayout, + VulkanImageLayout newImageLayout); + void dispatch(uint32_t groupCountX, uint32_t groupCountY, + uint32_t groupCountZ); + void fillBuffer(const VulkanBuffer &buffer, uint32_t data, + uint64_t offset = 0, uint64_t size = VK_WHOLE_SIZE); + void updateBuffer(const VulkanBuffer &buffer, void *pdata, + uint64_t offset = 0, uint64_t size = VK_WHOLE_SIZE); + void copyBufferToImage(const VulkanBuffer &buffer, const VulkanImage &image, + VulkanImageLayout imageLayout = + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + void copyBufferToImage(const VulkanBuffer &buffer, const VulkanImage &image, + uint64_t bufferOffset = 0, uint32_t mipLevel = 0, + uint32_t baseArrayLayer = 0, uint32_t layerCount = 1, + VulkanOffset3D offset3D = VulkanOffset3D(0, 0, 0), + VulkanExtent3D extent3D = VulkanExtent3D(0, 0, 0)); + void copyImageToBuffer(const VulkanImage &image, const VulkanBuffer &buffer, + uint64_t bufferOffset = 0, uint32_t mipLevel = 0, + uint32_t baseArrayLayer = 0, uint32_t layerCount = 1, + VulkanOffset3D offset3D = VulkanOffset3D(0, 0, 0), + VulkanExtent3D extent3D = VulkanExtent3D(0, 0, 0)); + void end(); + operator VkCommandBuffer() const; +}; + +class VulkanBuffer { +protected: + const VulkanDevice &m_device; + VkBuffer m_vkBuffer; + uint64_t m_size; + uint64_t m_alignment; + VulkanMemoryTypeList m_memoryTypeList; + + VulkanBuffer(const VulkanBuffer &buffer); + +public: + VulkanBuffer(const VulkanDevice &device, uint64_t size, + VulkanExternalMemoryHandleType externalMemoryHandleType = + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE, + VulkanBufferUsage bufferUsage = + VULKAN_BUFFER_USAGE_STORAGE_BUFFER_TRANSFER_SRC_DST, + VulkanSharingMode sharingMode = VULKAN_SHARING_MODE_EXCLUSIVE, + const VulkanQueueFamilyList &queueFamilyList = + getEmptyVulkanQueueFamilyList()); + virtual ~VulkanBuffer(); + uint64_t getSize() const; + uint64_t getAlignment() const; + const VulkanMemoryTypeList &getMemoryTypeList() const; + operator VkBuffer() const; +}; + +class VulkanImage { +protected: + const VulkanDevice &m_device; + const VulkanImageType m_imageType; + const VulkanExtent3D m_extent3D; + const VulkanFormat m_format; + const uint32_t m_numMipLevels; + const uint32_t m_numLayers; + VkImage m_vkImage; + uint64_t m_size; + uint64_t m_alignment; + VulkanMemoryTypeList m_memoryTypeList; + VkImageCreateInfo VulkanImageCreateInfo; + VulkanImage(const VulkanImage &image); + +public: + VulkanImage( + const VulkanDevice &device, VulkanImageType imageType, + VulkanFormat format, const VulkanExtent3D &extent3D, + uint32_t numMipLevels = 1, uint32_t arrayLayers = 1, + VulkanExternalMemoryHandleType externalMemoryHandleType = + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE, + VulkanImageCreateFlag imageCreateFlags = VULKAN_IMAGE_CREATE_FLAG_NONE, + VulkanImageTiling imageTiling = VULKAN_IMAGE_TILING_OPTIMAL, + VulkanImageUsage imageUsage = + VULKAN_IMAGE_USAGE_SAMPLED_STORAGE_TRANSFER_SRC_DST, + VulkanSharingMode sharingMode = VULKAN_SHARING_MODE_EXCLUSIVE); + virtual ~VulkanImage(); + virtual VulkanExtent3D getExtent3D(uint32_t mipLevel = 0) const; + VulkanFormat getFormat() const; + uint32_t getNumMipLevels() const; + uint32_t getNumLayers() const; + uint64_t getSize() const; + uint64_t getAlignment() const; + const VulkanMemoryTypeList &getMemoryTypeList() const; + VkImageCreateInfo getVkImageCreateInfo() const; + operator VkImage() const; +}; + +class VulkanImage2D : public VulkanImage { +protected: + VkImageView m_vkImageView; + + VulkanImage2D(const VulkanImage2D &image2D); + +public: + VulkanImage2D( + const VulkanDevice &device, VulkanFormat format, uint32_t width, + uint32_t height, uint32_t numMipLevels = 1, + VulkanExternalMemoryHandleType externalMemoryHandleType = + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE, + VulkanImageCreateFlag imageCreateFlag = VULKAN_IMAGE_CREATE_FLAG_NONE, + VulkanImageUsage imageUsage = + VULKAN_IMAGE_USAGE_SAMPLED_STORAGE_TRANSFER_SRC_DST, + VulkanSharingMode sharingMode = VULKAN_SHARING_MODE_EXCLUSIVE); + virtual ~VulkanImage2D(); + virtual VulkanExtent3D getExtent3D(uint32_t mipLevel = 0) const; +}; + +class VulkanImageView { +protected: + const VulkanDevice &m_device; + VkImageView m_vkImageView; + + VulkanImageView(const VulkanImageView &imageView); + +public: + VulkanImageView(const VulkanDevice &device, const VulkanImage &image, + VulkanImageViewType imageViewType, + uint32_t baseMipLevel = 0, + uint32_t mipLevelCount = VULKAN_REMAINING_MIP_LEVELS, + uint32_t baseArrayLayer = 0, + uint32_t layerCount = VULKAN_REMAINING_ARRAY_LAYERS); + virtual ~VulkanImageView(); + operator VkImageView() const; +}; + +class VulkanDeviceMemory { +protected: + const VulkanDevice &m_device; + VkDeviceMemory m_vkDeviceMemory; + uint64_t m_size; + bool m_isDedicated; + + VulkanDeviceMemory(const VulkanDeviceMemory &deviceMemory); + +public: + VulkanDeviceMemory(const VulkanDevice &device, uint64_t size, + const VulkanMemoryType &memoryType, + VulkanExternalMemoryHandleType externalMemoryHandleType = + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE, + const void *name = NULL); + VulkanDeviceMemory(const VulkanDevice &device, const VulkanImage &image, + const VulkanMemoryType &memoryType, + VulkanExternalMemoryHandleType externalMemoryHandleType = + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE, + const void *name = NULL); + virtual ~VulkanDeviceMemory(); + uint64_t getSize() const; +#ifdef _WIN32 + HANDLE + getHandle(VulkanExternalMemoryHandleType externalMemoryHandleType) const; +#else + int + getHandle(VulkanExternalMemoryHandleType externalMemoryHandleType) const; +#endif + bool isDedicated() const; + void *map(size_t offset = 0, size_t size = VK_WHOLE_SIZE); + void unmap(); + void bindBuffer(const VulkanBuffer &buffer, uint64_t offset = 0); + void bindImage(const VulkanImage &image, uint64_t offset = 0); + operator VkDeviceMemory() const; +}; + +class VulkanSemaphore { + friend class VulkanQueue; + +protected: + const VulkanDevice &m_device; + VkSemaphore m_vkSemaphore; + const std::wstring m_name; + + VulkanSemaphore(const VulkanSemaphore &semaphore); + +public: + VulkanSemaphore( + const VulkanDevice &device, + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType = + VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE, + const std::wstring name = L""); + virtual ~VulkanSemaphore(); +#ifdef _WIN32 + HANDLE getHandle( + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const; +#else + int getHandle( + VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const; +#endif + const std::wstring &getName() const; + operator VkSemaphore() const; +}; + + +#define VK_FUNC_DECL(name) extern "C" PFN_##name _##name; +VK_FUNC_LIST +#if defined(_WIN32) || defined(_WIN64) +VK_WINDOWS_FUNC_LIST +#endif +#undef VK_FUNC_DECL + +#endif // _vulkan_wrapper_hpp_ diff --git a/test_conformance/vulkan/vulkan_interop_common/vulkan_wrapper_types.hpp b/test_conformance/vulkan/vulkan_interop_common/vulkan_wrapper_types.hpp new file mode 100644 index 00000000..359bcae4 --- /dev/null +++ b/test_conformance/vulkan/vulkan_interop_common/vulkan_wrapper_types.hpp @@ -0,0 +1,463 @@ +// +// Copyright (c) 2022 The Khronos Group 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. +// + +#ifndef _vulkan_wrapper_types_hpp_ +#define _vulkan_wrapper_types_hpp_ + +#include + +#define VULKAN_MIN_BUFFER_OFFSET_COPY_ALIGNMENT 4 +#define VULKAN_REMAINING_MIP_LEVELS VK_REMAINING_MIP_LEVELS +#define VULKAN_REMAINING_ARRAY_LAYERS VK_REMAINING_ARRAY_LAYERS + +class VulkanInstance; +class VulkanPhysicalDevice; +class VulkanMemoryHeap; +class VulkanMemoryType; +class VulkanQueueFamily; +class VulkanDevice; +class VulkanQueue; +class VulkanDescriptorSetLayoutBinding; +class VulkanDescriptorSetLayout; +class VulkanPipelineLayout; +class VulkanShaderModule; +class VulkanPipeline; +class VulkanComputePipeline; +class VulkanDescriptorPool; +class VulkanDescriptorSet; +class VulkanCommandPool; +class VulkanCommandBuffer; +class VulkanBuffer; +class VulkanOffset3D; +class VulkanExtent3D; +class VulkanImage; +class VulkanImage2D; +class VulkanImageView; +class VulkanDeviceMemory; +class VulkanSemaphore; + +class VulkanPhysicalDeviceList; +class VulkanMemoryHeapList; +class VulkanMemoryTypeList; +class VulkanQueueFamilyList; +class VulkanQueueFamilyToQueueCountMap; +class VulkanQueueFamilyToQueueListMap; +class VulkanQueueList; +class VulkanCommandBufferList; +class VulkanDescriptorSetLayoutList; +class VulkanBufferList; +class VulkanImage2DList; +class VulkanImageViewList; +class VulkanDeviceMemoryList; +class VulkanSemaphoreList; + +enum VulkanQueueFlag +{ + VULKAN_QUEUE_FLAG_GRAPHICS = VK_QUEUE_GRAPHICS_BIT, + VULKAN_QUEUE_FLAG_COMPUTE = VK_QUEUE_COMPUTE_BIT, + VULKAN_QUEUE_FLAG_TRANSFER = VK_QUEUE_TRANSFER_BIT, + VULKAN_QUEUE_FLAG_MASK_ALL = VULKAN_QUEUE_FLAG_GRAPHICS + | VULKAN_QUEUE_FLAG_COMPUTE | VULKAN_QUEUE_FLAG_TRANSFER +}; + +enum VulkanDescriptorType +{ + VULKAN_DESCRIPTOR_TYPE_SAMPLER = VK_DESCRIPTOR_TYPE_SAMPLER, + VULKAN_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + VULKAN_DESCRIPTOR_TYPE_SAMPLED_IMAGE = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + VULKAN_DESCRIPTOR_TYPE_STORAGE_IMAGE = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + VULKAN_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + VULKAN_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = + VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + VULKAN_DESCRIPTOR_TYPE_UNIFORM_BUFFER = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + VULKAN_DESCRIPTOR_TYPE_STORAGE_BUFFER = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + VULKAN_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + VULKAN_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, + VULKAN_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, +}; + +enum VulkanShaderStage +{ + VULKAN_SHADER_STAGE_VERTEX = VK_SHADER_STAGE_VERTEX_BIT, + VULKAN_SHADER_STAGE_FRAGMENT = VK_SHADER_STAGE_FRAGMENT_BIT, + VULKAN_SHADER_STAGE_COMPUTE = VK_SHADER_STAGE_COMPUTE_BIT, + VULKAN_SHADER_STAGE_ALL_GRAPHICS = VK_SHADER_STAGE_ALL_GRAPHICS, + VULKAN_SHADER_STAGE_ALL = VK_SHADER_STAGE_ALL +}; + +enum VulkanPipelineBindPoint +{ + VULKAN_PIPELINE_BIND_POINT_GRAPHICS = VK_PIPELINE_BIND_POINT_GRAPHICS, + VULKAN_PIPELINE_BIND_POINT_COMPUTE = VK_PIPELINE_BIND_POINT_COMPUTE +}; + +enum VulkanMemoryTypeProperty +{ + VULKAN_MEMORY_TYPE_PROPERTY_NONE = 0, + VULKAN_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL = + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_COHERENT = + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_CACHED = + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + VULKAN_MEMORY_TYPE_PROPERTY_HOST_VISIBLE_CACHED_COHERENT = + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + VULKAN_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL_HOST_VISIBLE_COHERENT = + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + VULKAN_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL_HOST_VISIBLE_CACHED = + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + VULKAN_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL_HOST_VISIBLE_CACHED_COHERENT = + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT +}; + +enum VulkanMemoryHeapFlag +{ + VULKAN_MEMORY_HEAP_FLAG_NONE = 0, + VULKAN_MEMORY_HEAP_FLAG_DEVICE_LOCAL = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT +}; + +enum VulkanExternalMemoryHandleType +{ + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE = 0, + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR, + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR, + VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_KMT = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR + | VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR +}; + +enum VulkanExternalSemaphoreHandleType +{ + VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE = 0, + VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD = + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, + VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT = + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR, + VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT = + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR, + VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT_KMT = + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR + | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR +}; + +enum VulkanBufferUsage +{ + VULKAN_BUFFER_USAGE_TRANSFER_SRC = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VULKAN_BUFFER_USAGE_TRANSFER_DST = VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VULKAN_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER = + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, + VULKAN_BUFFER_USAGE_STORAGE_TEXEL_BUFFER = + VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, + VULKAN_BUFFER_USAGE_UNIFORM_BUFFER = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VULKAN_BUFFER_USAGE_STORAGE_BUFFER = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VULKAN_BUFFER_USAGE_INDEX_BUFFER = VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + VULKAN_BUFFER_USAGE_VERTEX_BUFFER = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VULKAN_BUFFER_USAGE_INDIRECT_BUFFER = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, + VULKAN_BUFFER_USAGE_STORAGE_BUFFER_TRANSFER_SRC_DST = + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VULKAN_BUFFER_USAGE_UNIFORM_BUFFER_TRANSFER_SRC_DST = + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT, +}; + +enum VulkanSharingMode +{ + VULKAN_SHARING_MODE_EXCLUSIVE = VK_SHARING_MODE_EXCLUSIVE, + VULKAN_SHARING_MODE_CONCURRENT = VK_SHARING_MODE_CONCURRENT +}; + +enum VulkanImageType +{ + VULKAN_IMAGE_TYPE_1D = VK_IMAGE_TYPE_1D, + VULKAN_IMAGE_TYPE_2D = VK_IMAGE_TYPE_2D, + VULKAN_IMAGE_TYPE_3D = VK_IMAGE_TYPE_3D +}; + +enum VulkanFormat +{ + VULKAN_FORMAT_UNDEFINED = VK_FORMAT_UNDEFINED, + VULKAN_FORMAT_R4G4_UNORM_PACK8 = VK_FORMAT_R4G4_UNORM_PACK8, + VULKAN_FORMAT_R4G4B4A4_UNORM_PACK16 = VK_FORMAT_R4G4B4A4_UNORM_PACK16, + VULKAN_FORMAT_B4G4R4A4_UNORM_PACK16 = VK_FORMAT_B4G4R4A4_UNORM_PACK16, + VULKAN_FORMAT_R5G6B5_UNORM_PACK16 = VK_FORMAT_R5G6B5_UNORM_PACK16, + VULKAN_FORMAT_B5G6R5_UNORM_PACK16 = VK_FORMAT_B5G6R5_UNORM_PACK16, + VULKAN_FORMAT_R5G5B5A1_UNORM_PACK16 = VK_FORMAT_R5G5B5A1_UNORM_PACK16, + VULKAN_FORMAT_B5G5R5A1_UNORM_PACK16 = VK_FORMAT_B5G5R5A1_UNORM_PACK16, + VULKAN_FORMAT_A1R5G5B5_UNORM_PACK16 = VK_FORMAT_A1R5G5B5_UNORM_PACK16, + VULKAN_FORMAT_R8_UNORM = VK_FORMAT_R8_UNORM, + VULKAN_FORMAT_R8_SNORM = VK_FORMAT_R8_SNORM, + VULKAN_FORMAT_R8_USCALED = VK_FORMAT_R8_USCALED, + VULKAN_FORMAT_R8_SSCALED = VK_FORMAT_R8_SSCALED, + VULKAN_FORMAT_R8_UINT = VK_FORMAT_R8_UINT, + VULKAN_FORMAT_R8_SINT = VK_FORMAT_R8_SINT, + VULKAN_FORMAT_R8_SRGB = VK_FORMAT_R8_SRGB, + VULKAN_FORMAT_R8G8_SNORM = VK_FORMAT_R8G8_SNORM, + VULKAN_FORMAT_R8G8_UNORM = VK_FORMAT_R8G8_UNORM, + VULKAN_FORMAT_R8G8_USCALED = VK_FORMAT_R8G8_USCALED, + VULKAN_FORMAT_R8G8_SSCALED = VK_FORMAT_R8G8_SSCALED, + VULKAN_FORMAT_R8G8_UINT = VK_FORMAT_R8G8_UINT, + VULKAN_FORMAT_R8G8_SINT = VK_FORMAT_R8G8_SINT, + VULKAN_FORMAT_R8G8_SRGB = VK_FORMAT_R8G8_SRGB, + VULKAN_FORMAT_R8G8B8_UNORM = VK_FORMAT_R8G8B8_UNORM, + VULKAN_FORMAT_R8G8B8_SNORM = VK_FORMAT_R8G8B8_SNORM, + VULKAN_FORMAT_R8G8B8_USCALED = VK_FORMAT_R8G8B8_USCALED, + VULKAN_FORMAT_R8G8B8_SSCALED = VK_FORMAT_R8G8B8_SSCALED, + VULKAN_FORMAT_R8G8B8_UINT = VK_FORMAT_R8G8B8_UINT, + VULKAN_FORMAT_R8G8B8_SINT = VK_FORMAT_R8G8B8_SINT, + VULKAN_FORMAT_R8G8B8_SRGB = VK_FORMAT_R8G8B8_SRGB, + VULKAN_FORMAT_B8G8R8_UNORM = VK_FORMAT_B8G8R8_UNORM, + VULKAN_FORMAT_B8G8R8_SNORM = VK_FORMAT_B8G8R8_SNORM, + VULKAN_FORMAT_B8G8R8_USCALED = VK_FORMAT_B8G8R8_USCALED, + VULKAN_FORMAT_B8G8R8_SSCALED = VK_FORMAT_B8G8R8_SSCALED, + VULKAN_FORMAT_B8G8R8_UINT = VK_FORMAT_B8G8R8_UINT, + VULKAN_FORMAT_B8G8R8_SINT = VK_FORMAT_B8G8R8_SINT, + VULKAN_FORMAT_B8G8R8_SRGB = VK_FORMAT_B8G8R8_SRGB, + VULKAN_FORMAT_R8G8B8A8_UNORM = VK_FORMAT_R8G8B8A8_UNORM, + VULKAN_FORMAT_R8G8B8A8_SNORM = VK_FORMAT_R8G8B8A8_SNORM, + VULKAN_FORMAT_R8G8B8A8_USCALED = VK_FORMAT_R8G8B8A8_USCALED, + VULKAN_FORMAT_R8G8B8A8_SSCALED = VK_FORMAT_R8G8B8A8_SSCALED, + VULKAN_FORMAT_R8G8B8A8_UINT = VK_FORMAT_R8G8B8A8_UINT, + VULKAN_FORMAT_R8G8B8A8_SINT = VK_FORMAT_R8G8B8A8_SINT, + VULKAN_FORMAT_R8G8B8A8_SRGB = VK_FORMAT_R8G8B8A8_SRGB, + VULKAN_FORMAT_B8G8R8A8_UNORM = VK_FORMAT_B8G8R8A8_UNORM, + VULKAN_FORMAT_B8G8R8A8_SNORM = VK_FORMAT_B8G8R8A8_SNORM, + VULKAN_FORMAT_B8G8R8A8_USCALED = VK_FORMAT_B8G8R8A8_USCALED, + VULKAN_FORMAT_B8G8R8A8_SSCALED = VK_FORMAT_B8G8R8A8_SSCALED, + VULKAN_FORMAT_B8G8R8A8_UINT = VK_FORMAT_B8G8R8A8_UINT, + VULKAN_FORMAT_B8G8R8A8_SINT = VK_FORMAT_B8G8R8A8_SINT, + VULKAN_FORMAT_B8G8R8A8_SRGB = VK_FORMAT_B8G8R8A8_SRGB, + VULKAN_FORMAT_A8B8G8R8_UNORM_PACK32 = VK_FORMAT_A8B8G8R8_UNORM_PACK32, + VULKAN_FORMAT_A8B8G8R8_SNORM_PACK32 = VK_FORMAT_A8B8G8R8_SNORM_PACK32, + VULKAN_FORMAT_A8B8G8R8_USCALED_PACK32 = VK_FORMAT_A8B8G8R8_USCALED_PACK32, + VULKAN_FORMAT_A8B8G8R8_SSCALED_PACK32 = VK_FORMAT_A8B8G8R8_SSCALED_PACK32, + VULKAN_FORMAT_A8B8G8R8_UINT_PACK32 = VK_FORMAT_A8B8G8R8_UINT_PACK32, + VULKAN_FORMAT_A8B8G8R8_SINT_PACK32 = VK_FORMAT_A8B8G8R8_SINT_PACK32, + VULKAN_FORMAT_A8B8G8R8_SRGB_PACK32 = VK_FORMAT_A8B8G8R8_SRGB_PACK32, + VULKAN_FORMAT_A2R10G10B10_UNORM_PACK32 = VK_FORMAT_A2R10G10B10_UNORM_PACK32, + VULKAN_FORMAT_A2R10G10B10_SNORM_PACK32 = VK_FORMAT_A2R10G10B10_SNORM_PACK32, + VULKAN_FORMAT_A2R10G10B10_USCALED_PACK32 = + VK_FORMAT_A2R10G10B10_USCALED_PACK32, + VULKAN_FORMAT_A2R10G10B10_SSCALED_PACK32 = + VK_FORMAT_A2R10G10B10_SSCALED_PACK32, + VULKAN_FORMAT_A2R10G10B10_UINT_PACK32 = VK_FORMAT_A2R10G10B10_UINT_PACK32, + VULKAN_FORMAT_A2R10G10B10_SINT_PACK32 = VK_FORMAT_A2R10G10B10_SINT_PACK32, + VULKAN_FORMAT_A2B10G10R10_UNORM_PACK32 = VK_FORMAT_A2B10G10R10_UNORM_PACK32, + VULKAN_FORMAT_A2B10G10R10_SNORM_PACK32 = VK_FORMAT_A2B10G10R10_SNORM_PACK32, + VULKAN_FORMAT_A2B10G10R10_USCALED_PACK32 = + VK_FORMAT_A2B10G10R10_USCALED_PACK32, + VULKAN_FORMAT_A2B10G10R10_SSCALED_PACK32 = + VK_FORMAT_A2B10G10R10_SSCALED_PACK32, + VULKAN_FORMAT_A2B10G10R10_UINT_PACK32 = VK_FORMAT_A2B10G10R10_UINT_PACK32, + VULKAN_FORMAT_A2B10G10R10_SINT_PACK32 = VK_FORMAT_A2B10G10R10_SINT_PACK32, + VULKAN_FORMAT_R16_UNORM = VK_FORMAT_R16_UNORM, + VULKAN_FORMAT_R16_SNORM = VK_FORMAT_R16_SNORM, + VULKAN_FORMAT_R16_USCALED = VK_FORMAT_R16_USCALED, + VULKAN_FORMAT_R16_SSCALED = VK_FORMAT_R16_SSCALED, + VULKAN_FORMAT_R16_UINT = VK_FORMAT_R16_UINT, + VULKAN_FORMAT_R16_SINT = VK_FORMAT_R16_SINT, + VULKAN_FORMAT_R16_SFLOAT = VK_FORMAT_R16_SFLOAT, + VULKAN_FORMAT_R16G16_UNORM = VK_FORMAT_R16G16_UNORM, + VULKAN_FORMAT_R16G16_SNORM = VK_FORMAT_R16G16_SNORM, + VULKAN_FORMAT_R16G16_USCALED = VK_FORMAT_R16G16_USCALED, + VULKAN_FORMAT_R16G16_SSCALED = VK_FORMAT_R16G16_SSCALED, + VULKAN_FORMAT_R16G16_UINT = VK_FORMAT_R16G16_UINT, + VULKAN_FORMAT_R16G16_SINT = VK_FORMAT_R16G16_SINT, + VULKAN_FORMAT_R16G16_SFLOAT = VK_FORMAT_R16G16_SFLOAT, + VULKAN_FORMAT_R16G16B16_UNORM = VK_FORMAT_R16G16B16_UNORM, + VULKAN_FORMAT_R16G16B16_SNORM = VK_FORMAT_R16G16B16_SNORM, + VULKAN_FORMAT_R16G16B16_USCALED = VK_FORMAT_R16G16B16_USCALED, + VULKAN_FORMAT_R16G16B16_SSCALED = VK_FORMAT_R16G16B16_SSCALED, + VULKAN_FORMAT_R16G16B16_UINT = VK_FORMAT_R16G16B16_UINT, + VULKAN_FORMAT_R16G16B16_SINT = VK_FORMAT_R16G16B16_SINT, + VULKAN_FORMAT_R16G16B16_SFLOAT = VK_FORMAT_R16G16B16_SFLOAT, + VULKAN_FORMAT_R16G16B16A16_UNORM = VK_FORMAT_R16G16B16A16_UNORM, + VULKAN_FORMAT_R16G16B16A16_SNORM = VK_FORMAT_R16G16B16A16_SNORM, + VULKAN_FORMAT_R16G16B16A16_USCALED = VK_FORMAT_R16G16B16A16_USCALED, + VULKAN_FORMAT_R16G16B16A16_SSCALED = VK_FORMAT_R16G16B16A16_SSCALED, + VULKAN_FORMAT_R16G16B16A16_UINT = VK_FORMAT_R16G16B16A16_UINT, + VULKAN_FORMAT_R16G16B16A16_SINT = VK_FORMAT_R16G16B16A16_SINT, + VULKAN_FORMAT_R16G16B16A16_SFLOAT = VK_FORMAT_R16G16B16A16_SFLOAT, + VULKAN_FORMAT_R32_UINT = VK_FORMAT_R32_UINT, + VULKAN_FORMAT_R32_SINT = VK_FORMAT_R32_SINT, + VULKAN_FORMAT_R32_SFLOAT = VK_FORMAT_R32_SFLOAT, + VULKAN_FORMAT_R32G32_UINT = VK_FORMAT_R32G32_UINT, + VULKAN_FORMAT_R32G32_SINT = VK_FORMAT_R32G32_SINT, + VULKAN_FORMAT_R32G32_SFLOAT = VK_FORMAT_R32G32_SFLOAT, + VULKAN_FORMAT_R32G32B32_UINT = VK_FORMAT_R32G32B32_UINT, + VULKAN_FORMAT_R32G32B32_SINT = VK_FORMAT_R32G32B32_SINT, + VULKAN_FORMAT_R32G32B32_SFLOAT = VK_FORMAT_R32G32B32_SFLOAT, + VULKAN_FORMAT_R32G32B32A32_UINT = VK_FORMAT_R32G32B32A32_UINT, + VULKAN_FORMAT_R32G32B32A32_SINT = VK_FORMAT_R32G32B32A32_SINT, + VULKAN_FORMAT_R32G32B32A32_SFLOAT = VK_FORMAT_R32G32B32A32_SFLOAT, + VULKAN_FORMAT_R64_UINT = VK_FORMAT_R64_UINT, + VULKAN_FORMAT_R64_SINT = VK_FORMAT_R64_SINT, + VULKAN_FORMAT_R64_SFLOAT = VK_FORMAT_R64_SFLOAT, + VULKAN_FORMAT_R64G64_UINT = VK_FORMAT_R64G64_UINT, + VULKAN_FORMAT_R64G64_SINT = VK_FORMAT_R64G64_SINT, + VULKAN_FORMAT_R64G64_SFLOAT = VK_FORMAT_R64G64_SFLOAT, + VULKAN_FORMAT_R64G64B64_UINT = VK_FORMAT_R64G64B64_UINT, + VULKAN_FORMAT_R64G64B64_SINT = VK_FORMAT_R64G64B64_SINT, + VULKAN_FORMAT_R64G64B64_SFLOAT = VK_FORMAT_R64G64B64_SFLOAT, + VULKAN_FORMAT_R64G64B64A64_UINT = VK_FORMAT_R64G64B64A64_UINT, + VULKAN_FORMAT_R64G64B64A64_SINT = VK_FORMAT_R64G64B64A64_SINT, + VULKAN_FORMAT_R64G64B64A64_SFLOAT = VK_FORMAT_R64G64B64A64_SFLOAT, + VULKAN_FORMAT_B10G11R11_UFLOAT_PACK32 = VK_FORMAT_B10G11R11_UFLOAT_PACK32, + VULKAN_FORMAT_E5B9G9R9_UFLOAT_PACK32 = VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, + VULKAN_FORMAT_D16_UNORM = VK_FORMAT_D16_UNORM, + VULKAN_FORMAT_X8_D24_UNORM_PACK32 = VK_FORMAT_X8_D24_UNORM_PACK32, + VULKAN_FORMAT_D32_SFLOAT = VK_FORMAT_D32_SFLOAT, + VULKAN_FORMAT_S8_UINT = VK_FORMAT_S8_UINT, + VULKAN_FORMAT_D16_UNORM_S8_UINT = VK_FORMAT_D16_UNORM_S8_UINT, + VULKAN_FORMAT_D24_UNORM_S8_UINT = VK_FORMAT_D24_UNORM_S8_UINT, + VULKAN_FORMAT_D32_SFLOAT_S8_UINT = VK_FORMAT_D32_SFLOAT_S8_UINT, + VULKAN_FORMAT_BC1_RGB_UNORM_BLOCK = VK_FORMAT_BC1_RGB_UNORM_BLOCK, + VULKAN_FORMAT_BC1_RGB_SRGB_BLOCK = VK_FORMAT_BC1_RGB_SRGB_BLOCK, + VULKAN_FORMAT_BC1_RGBA_UNORM_BLOCK = VK_FORMAT_BC1_RGBA_UNORM_BLOCK, + VULKAN_FORMAT_BC1_RGBA_SRGB_BLOCK = VK_FORMAT_BC1_RGBA_SRGB_BLOCK, + VULKAN_FORMAT_BC2_UNORM_BLOCK = VK_FORMAT_BC2_UNORM_BLOCK, + VULKAN_FORMAT_BC2_SRGB_BLOCK = VK_FORMAT_BC2_SRGB_BLOCK, + VULKAN_FORMAT_BC3_UNORM_BLOCK = VK_FORMAT_BC3_UNORM_BLOCK, + VULKAN_FORMAT_BC3_SRGB_BLOCK = VK_FORMAT_BC3_SRGB_BLOCK, + VULKAN_FORMAT_BC4_UNORM_BLOCK = VK_FORMAT_BC4_UNORM_BLOCK, + VULKAN_FORMAT_BC4_SNORM_BLOCK = VK_FORMAT_BC4_SNORM_BLOCK, + VULKAN_FORMAT_BC5_UNORM_BLOCK = VK_FORMAT_BC5_UNORM_BLOCK, + VULKAN_FORMAT_BC5_SNORM_BLOCK = VK_FORMAT_BC5_SNORM_BLOCK, + VULKAN_FORMAT_BC6H_UFLOAT_BLOCK = VK_FORMAT_BC6H_UFLOAT_BLOCK, + VULKAN_FORMAT_BC6H_SFLOAT_BLOCK = VK_FORMAT_BC6H_SFLOAT_BLOCK, + VULKAN_FORMAT_BC7_UNORM_BLOCK = VK_FORMAT_BC7_UNORM_BLOCK, + VULKAN_FORMAT_BC7_SRGB_BLOCK = VK_FORMAT_BC7_SRGB_BLOCK, + VULKAN_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, + VULKAN_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, + VULKAN_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = + VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, + VULKAN_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, + VULKAN_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = + VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, + VULKAN_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, + VULKAN_FORMAT_EAC_R11_UNORM_BLOCK = VK_FORMAT_EAC_R11_UNORM_BLOCK, + VULKAN_FORMAT_EAC_R11_SNORM_BLOCK = VK_FORMAT_EAC_R11_SNORM_BLOCK, + VULKAN_FORMAT_EAC_R11G11_UNORM_BLOCK = VK_FORMAT_EAC_R11G11_UNORM_BLOCK, + VULKAN_FORMAT_EAC_R11G11_SNORM_BLOCK = VK_FORMAT_EAC_R11G11_SNORM_BLOCK, + VULKAN_FORMAT_ASTC_4x4_UNORM_BLOCK = VK_FORMAT_ASTC_4x4_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_4x4_SRGB_BLOCK = VK_FORMAT_ASTC_4x4_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_5x4_UNORM_BLOCK = VK_FORMAT_ASTC_5x4_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_5x4_SRGB_BLOCK = VK_FORMAT_ASTC_5x4_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_5x5_UNORM_BLOCK = VK_FORMAT_ASTC_5x5_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_5x5_SRGB_BLOCK = VK_FORMAT_ASTC_5x5_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_6x5_UNORM_BLOCK = VK_FORMAT_ASTC_6x5_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_6x5_SRGB_BLOCK = VK_FORMAT_ASTC_6x5_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_6x6_UNORM_BLOCK = VK_FORMAT_ASTC_6x6_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_6x6_SRGB_BLOCK = VK_FORMAT_ASTC_6x6_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_8x5_UNORM_BLOCK = VK_FORMAT_ASTC_8x5_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_8x5_SRGB_BLOCK = VK_FORMAT_ASTC_8x5_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_8x6_UNORM_BLOCK = VK_FORMAT_ASTC_8x6_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_8x6_SRGB_BLOCK = VK_FORMAT_ASTC_8x6_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_8x8_UNORM_BLOCK = VK_FORMAT_ASTC_8x8_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_8x8_SRGB_BLOCK = VK_FORMAT_ASTC_8x8_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_10x5_UNORM_BLOCK = VK_FORMAT_ASTC_10x5_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_10x5_SRGB_BLOCK = VK_FORMAT_ASTC_10x5_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_10x6_UNORM_BLOCK = VK_FORMAT_ASTC_10x6_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_10x6_SRGB_BLOCK = VK_FORMAT_ASTC_10x6_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_10x8_UNORM_BLOCK = VK_FORMAT_ASTC_10x8_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_10x8_SRGB_BLOCK = VK_FORMAT_ASTC_10x8_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_10x10_UNORM_BLOCK = VK_FORMAT_ASTC_10x10_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_10x10_SRGB_BLOCK = VK_FORMAT_ASTC_10x10_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_12x10_UNORM_BLOCK = VK_FORMAT_ASTC_12x10_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_12x10_SRGB_BLOCK = VK_FORMAT_ASTC_12x10_SRGB_BLOCK, + VULKAN_FORMAT_ASTC_12x12_UNORM_BLOCK = VK_FORMAT_ASTC_12x12_UNORM_BLOCK, + VULKAN_FORMAT_ASTC_12x12_SRGB_BLOCK = VK_FORMAT_ASTC_12x12_SRGB_BLOCK, +}; + +enum VulkanImageLayout +{ + VULKAN_IMAGE_LAYOUT_UNDEFINED = VK_IMAGE_LAYOUT_UNDEFINED, + VULKAN_IMAGE_LAYOUT_GENERAL = VK_IMAGE_LAYOUT_GENERAL, + VULKAN_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VULKAN_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, +}; + +enum VulkanImageUsage +{ + VULKAN_IMAGE_USAGE_TRANSFER_SRC = VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + VULKAN_IMAGE_USAGE_TRANSFER_DST = VK_IMAGE_USAGE_TRANSFER_DST_BIT, + VULKAN_IMAGE_USAGE_SAMPLED = VK_IMAGE_USAGE_SAMPLED_BIT, + VULKAN_IMAGE_USAGE_STORAGE = VK_IMAGE_USAGE_STORAGE_BIT, + VULKAN_IMAGE_USAGE_COLOR_ATTACHMENT = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + VULKAN_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT = + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + VULKAN_IMAGE_USAGE_TRANSIENT_ATTACHMENT = + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, + VULKAN_IMAGE_USAGE_INPUT_ATTACHMENT = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, + VULKAN_IMAGE_USAGE_TRANSFER_SRC_DST = + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + VULKAN_IMAGE_USAGE_STORAGE_TRANSFER_SRC_DST = VULKAN_IMAGE_USAGE_STORAGE + | VULKAN_IMAGE_USAGE_TRANSFER_SRC | VULKAN_IMAGE_USAGE_TRANSFER_DST, + VULKAN_IMAGE_USAGE_SAMPLED_STORAGE_TRANSFER_SRC_DST = + VK_IMAGE_USAGE_SAMPLED_BIT | VULKAN_IMAGE_USAGE_STORAGE + | VULKAN_IMAGE_USAGE_TRANSFER_SRC | VULKAN_IMAGE_USAGE_TRANSFER_DST +}; + +enum VulkanImageTiling +{ + VULKAN_IMAGE_TILING_OPTIMAL = VK_IMAGE_TILING_OPTIMAL, + VULKAN_IMAGE_TILING_LINEAR = VK_IMAGE_TILING_LINEAR +}; + +enum VulkanImageCreateFlag +{ + VULKAN_IMAGE_CREATE_FLAG_NONE = 0, + VULKAN_IMAGE_CREATE_FLAG_MUTABLE_FORMAT = + VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, + VULKAN_IMAGE_CREATE_FLAG_CUBE_COMPATIBLE = + VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, + VULKAN_IMAGE_CREATE_FLAG_CUBE_COMPATIBLE_MUTABLE_FORMAT = + VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT | VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT +}; + +enum VulkanImageViewType +{ + VULKAN_IMAGE_VIEW_TYPE_1D = VK_IMAGE_VIEW_TYPE_1D, + VULKAN_IMAGE_VIEW_TYPE_2D = VK_IMAGE_VIEW_TYPE_2D, + VULKAN_IMAGE_VIEW_TYPE_3D = VK_IMAGE_VIEW_TYPE_3D, + VULKAN_IMAGE_VIEW_TYPE_CUBE = VK_IMAGE_VIEW_TYPE_CUBE, + VULKAN_IMAGE_VIEW_TYPE_1D_ARRAY = VK_IMAGE_VIEW_TYPE_1D_ARRAY, + VULKAN_IMAGE_VIEW_TYPE_2D_ARRAY = VK_IMAGE_VIEW_TYPE_2D_ARRAY, + VULKAN_IMAGE_VIEW_TYPE_CUBE_ARRAY = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, +}; + +#endif // _vulkan_wrapper_types_hpp_