mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-13 00:08:26 +08:00
CUDA 13.2 samples update (#432)
- Added Python samples for CUDA Python 1.0 release - Renamed top-level `Samples` directory to `cpp` to accommodate Python samples.
This commit is contained in:
18
cpp/5_Domain_Specific/simpleVulkanMMAP/.vscode/c_cpp_properties.json
vendored
Normal file
18
cpp/5_Domain_Specific/simpleVulkanMMAP/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/../../../Common"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/local/cuda/bin/nvcc",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "gnu++14",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
7
cpp/5_Domain_Specific/simpleVulkanMMAP/.vscode/extensions.json
vendored
Normal file
7
cpp/5_Domain_Specific/simpleVulkanMMAP/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"nvidia.nsight-vscode-edition",
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.makefile-tools"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
For Windows:
|
||||
Follow these steps once you have installed Vulkan SDK for Windows from https://www.lunarg.com/vulkan-sdk/
|
||||
-- Install GLFW3 library at suitable location
|
||||
-- Open the simpleVulkan VS project file.
|
||||
To add the GLFW3 library path
|
||||
-- Right click on Project name "simpleVulkan" click on "Properties"
|
||||
-- In Property pages window go to Linker -> General. Here in "Additional Libraries Directories" edit and add path to glfw3dll.lib
|
||||
To add the GLFW3 headers path
|
||||
-- Right click on Project name "simpleVulkan" click on "Properties"
|
||||
-- In Property pages window go to "VC++ Directories" section. Here in "Include Directories" edit and add path to GLFW3 headers include directory location.
|
||||
** Make sure to add path to glfw3.dll in your PATH environment variable**
|
||||
|
||||
|
||||
For Linux:
|
||||
-- Install the Vulkan SDK from https://www.lunarg.com/vulkan-sdk/ and follow environment setup instructions.
|
||||
-- Install GLFW3 library through your OS package repository. For example: apt-get for Ubuntu and dnf for RHEL/CentOS. Below is for Ubuntu:
|
||||
sudo apt-get install libglfw3
|
||||
sudo apt-get install libglfw3-dev
|
||||
-- Install "libxcb1-dev" and "xorg-dev" as GLFW3 is depended on it
|
||||
-- Add Vulkan and GLFW3 libraries directories to LD_LIBRARY_PATH
|
||||
|
||||
|
||||
For Linux aarch64(L4T):
|
||||
-- Install GLFW3 library using "sudo apt-get install libglfw3-dev" this will provide glfw3
|
||||
-- install above will also provide libvulkan-dev as dependencies
|
||||
-- Add Vulkan and GLFW3 libraries directories to LD_LIBRARY_PATH
|
||||
-- Pass path to vulkan sdk while building 'make VULKAN_SDK_PATH=<PATH_TO_VULKAN_SDK>', VULKAN_SDK_PATH in this scenario is typically "/usr"
|
||||
|
||||
|
||||
For Shader changes:
|
||||
-- Update the montecarlo.vert and/or montecarlo.frag shader source file as required
|
||||
-- Use the glslc shader compiler from the installed Vulkan SDK's bin directory to compile shaders as:
|
||||
glslc montecarlo.vert -o vert.spv
|
||||
glslc montecarlo.frag -o frag.spv
|
||||
** Make sure to add glslc's path in your PATH environment variable **
|
||||
114
cpp/5_Domain_Specific/simpleVulkanMMAP/CMakeLists.txt
Normal file
114
cpp/5_Domain_Specific/simpleVulkanMMAP/CMakeLists.txt
Normal file
@@ -0,0 +1,114 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/Modules")
|
||||
|
||||
project(simpleVulkanMMAP LANGUAGES C CXX CUDA)
|
||||
|
||||
find_package(CUDAToolkit REQUIRED)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set(CMAKE_CUDA_ARCHITECTURES 75 80 86 87 89 90 100 110 120)
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Wno-deprecated-gpu-targets")
|
||||
if(ENABLE_CUDA_DEBUG)
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -G") # enable cuda-gdb (may significantly affect performance on some targets)
|
||||
else()
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -lineinfo") # add line information to all builds for debug tools (exclusive to -G option)
|
||||
endif()
|
||||
|
||||
# Include directories and libraries
|
||||
include_directories(../../../Common)
|
||||
|
||||
find_package(Vulkan)
|
||||
find_package(OpenGL)
|
||||
|
||||
# Include the check_include_file macro
|
||||
include(CheckIncludeFile)
|
||||
|
||||
# Check for the GLFW/glfw3.h header
|
||||
check_include_file("GLFW/glfw3.h" HAVE_GLFW3_H)
|
||||
|
||||
# Check for SUSE Linux
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
file(READ "/etc/os-release" OS_RELEASE_CONTENTS)
|
||||
if(OS_RELEASE_CONTENTS MATCHES "ID=[^ ]*suse[^ ]*")
|
||||
message(STATUS "SUSE Linux detected")
|
||||
set(SUSE_LINUX TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Find GLFW header and lib for Windows and SUSE Linux
|
||||
if(WIN32 OR CMAKE_CROSSCOMPILING OR SUSE_LINUX)
|
||||
set(GLFW_INCLUDE_DIRS "${GLFW_INCLUDE_DIR}" "${CMAKE_INCLUDE_PATH}")
|
||||
find_file(GLFW3_H "GLFW/glfw3.h" PATHS ${GLFW_INCLUDE_DIRS})
|
||||
find_library(GLFW3_LIB
|
||||
NAMES glfw3 glfw
|
||||
PATHS "${GLFW_LIB_DIR}"
|
||||
PATH_SUFFIXES lib lib64)
|
||||
if(GLFW3_H AND GLFW3_LIB)
|
||||
message(STATUS "Found GLFW/glfw3.h and GLFW library.")
|
||||
set(HAVE_GLFW3_H 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Source file
|
||||
if(${Vulkan_FOUND})
|
||||
if(${OPENGL_FOUND})
|
||||
if(${HAVE_GLFW3_H})
|
||||
# Add target for simpleVulkanMMAP
|
||||
add_executable(simpleVulkanMMAP ../../../Common/helper_multiprocess.cpp MonteCarloPi.cu VulkanBaseApp.cpp main.cpp)
|
||||
|
||||
target_compile_options(simpleVulkanMMAP PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--extended-lambda>)
|
||||
|
||||
target_compile_features(simpleVulkanMMAP PRIVATE cxx_std_17 cuda_std_17)
|
||||
|
||||
set_target_properties(simpleVulkanMMAP PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
|
||||
|
||||
target_include_directories(simpleVulkanMMAP PUBLIC
|
||||
${Vulkan_INCLUDE_DIRS}
|
||||
${CUDAToolkit_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(simpleVulkanMMAP
|
||||
${Vulkan_LIBRARIES}
|
||||
OpenGL::GL
|
||||
CUDA::cuda_driver
|
||||
)
|
||||
if(WIN32 OR CMAKE_CROSSCOMPILING OR SUSE_LINUX)
|
||||
target_include_directories(simpleVulkanMMAP PUBLIC
|
||||
${GLFW_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(simpleVulkanMMAP
|
||||
${GLFW3_LIB}
|
||||
)
|
||||
else()
|
||||
target_link_libraries(simpleVulkanMMAP
|
||||
glfw
|
||||
)
|
||||
endif()
|
||||
# Need to add X11 for SUSE Linux explicitly
|
||||
if(SUSE_LINUX)
|
||||
target_link_libraries(simpleVulkanMMAP
|
||||
X11
|
||||
)
|
||||
endif()
|
||||
add_custom_command(TARGET simpleVulkanMMAP POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/montecarlo.frag
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/montecarlo.vert
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vert.spv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/frag.spv
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
else()
|
||||
message(STATUS "glfw3 not found - will not build sample 'simpleVulkanMMAP'")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "GLFW not found - will not build sample 'simpleVulkanMMAP'")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Vulkan not found - will not build sample 'simpleVulkanMMAP'")
|
||||
endif()
|
||||
|
||||
# Include installation configuration
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/InstallSamples.cmake)
|
||||
setup_samples_install()
|
||||
290
cpp/5_Domain_Specific/simpleVulkanMMAP/MonteCarloPi.cu
Normal file
290
cpp/5_Domain_Specific/simpleVulkanMMAP/MonteCarloPi.cu
Normal file
@@ -0,0 +1,290 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* See: https://www.piday.org/million/
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "MonteCarloPi.h"
|
||||
#define CUDA_DRIVER_API
|
||||
#include <helper_cuda.h>
|
||||
#include <iostream>
|
||||
|
||||
#define ROUND_UP_TO_GRANULARITY(x, n) (((x + n - 1) / n) * n)
|
||||
|
||||
// `ipcHandleTypeFlag` specifies the platform specific handle type this sample
|
||||
// uses for importing and exporting memory allocation. On Linux this sample
|
||||
// specifies the type as CU_MEM_HANDLE_TYPE_POSIX_FILE_DESCRIPTOR meaning that
|
||||
// file descriptors will be used. On Windows this sample specifies the type as
|
||||
// CU_MEM_HANDLE_TYPE_WIN32 meaning that NT HANDLEs will be used. The
|
||||
// ipcHandleTypeFlag variable is a convenience variable and is passed by value
|
||||
// to individual requests.
|
||||
#if defined(__linux__)
|
||||
CUmemAllocationHandleType ipcHandleTypeFlag = CU_MEM_HANDLE_TYPE_POSIX_FILE_DESCRIPTOR;
|
||||
#else
|
||||
CUmemAllocationHandleType ipcHandleTypeFlag = CU_MEM_HANDLE_TYPE_WIN32;
|
||||
#endif
|
||||
|
||||
// Windows-specific LPSECURITYATTRIBUTES
|
||||
void getDefaultSecurityDescriptor(CUmemAllocationProp *prop)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
return;
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
|
||||
static const char sddl[] = "D:P(OA;;GARCSDWDWOCCDCLCSWLODTWPRPCRFA;;;WD)";
|
||||
static OBJECT_ATTRIBUTES objAttributes;
|
||||
static bool objAttributesConfigured = false;
|
||||
|
||||
if (!objAttributesConfigured) {
|
||||
PSECURITY_DESCRIPTOR secDesc;
|
||||
BOOL result = ConvertStringSecurityDescriptorToSecurityDescriptorA(sddl, SDDL_REVISION_1, &secDesc, NULL);
|
||||
if (result == 0) {
|
||||
printf("IPC failure: getDefaultSecurityDescriptor Failed! (%d)\n", GetLastError());
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&objAttributes, NULL, 0, NULL, secDesc);
|
||||
|
||||
objAttributesConfigured = true;
|
||||
}
|
||||
|
||||
prop->win32HandleMetaData = &objAttributes;
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
__global__ void monte_carlo_kernel(vec2 *xyVector,
|
||||
float *pointsInsideCircle,
|
||||
float *numPointsInCircle,
|
||||
unsigned int numPoints,
|
||||
float time)
|
||||
{
|
||||
const size_t stride = gridDim.x * blockDim.x;
|
||||
size_t tid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
float count = 0.0f;
|
||||
|
||||
curandState rgnState;
|
||||
curand_init((unsigned long long)time, tid, 0, &rgnState);
|
||||
|
||||
for (; tid < numPoints; tid += stride) {
|
||||
float x = curand_uniform(&rgnState);
|
||||
float y = curand_uniform(&rgnState);
|
||||
x = (2.0f * x) - 1.0f;
|
||||
y = (2.0f * y) - 1.0f;
|
||||
xyVector[tid][0] = x;
|
||||
xyVector[tid][1] = y;
|
||||
|
||||
// Compute the distance of this point form the center(0, 0)
|
||||
float dist = sqrtf((x * x) + (y * y));
|
||||
|
||||
// If distance is less than the radius of the unit circle, the point lies in
|
||||
// the circle.
|
||||
pointsInsideCircle[tid] = (dist <= 1.0f);
|
||||
count += (dist <= 1.0f);
|
||||
}
|
||||
atomicAdd(numPointsInCircle, count);
|
||||
}
|
||||
|
||||
MonteCarloPiSimulation::MonteCarloPiSimulation(size_t num_points)
|
||||
: m_xyVector(nullptr)
|
||||
, m_pointsInsideCircle(nullptr)
|
||||
, m_totalPointsInsideCircle(0)
|
||||
, m_totalPointsSimulated(0)
|
||||
, m_numPoints(num_points)
|
||||
{
|
||||
}
|
||||
|
||||
MonteCarloPiSimulation::~MonteCarloPiSimulation()
|
||||
{
|
||||
if (m_numPointsInCircle) {
|
||||
checkCudaErrors(cudaFree(m_numPointsInCircle));
|
||||
m_numPointsInCircle = nullptr;
|
||||
}
|
||||
if (m_hostNumPointsInCircle) {
|
||||
checkCudaErrors(cudaFreeHost(m_hostNumPointsInCircle));
|
||||
m_hostNumPointsInCircle = nullptr;
|
||||
}
|
||||
|
||||
cleanupSimulationAllocations();
|
||||
}
|
||||
|
||||
void MonteCarloPiSimulation::initSimulation(int cudaDevice, cudaStream_t stream)
|
||||
{
|
||||
m_cudaDevice = cudaDevice;
|
||||
getIdealExecutionConfiguration();
|
||||
|
||||
// Allocate a position buffer that contains random location of the points in
|
||||
// XY cartesian plane.
|
||||
// Allocate a bitmap buffer which holds information of whether a point in the
|
||||
// position buffer is inside the unit circle or not.
|
||||
setupSimulationAllocations();
|
||||
|
||||
checkCudaErrors(cudaMalloc((float **)&m_numPointsInCircle, sizeof(*m_numPointsInCircle)));
|
||||
checkCudaErrors(cudaMallocHost((float **)&m_hostNumPointsInCircle, sizeof(*m_hostNumPointsInCircle)));
|
||||
}
|
||||
|
||||
void MonteCarloPiSimulation::stepSimulation(float time, cudaStream_t stream)
|
||||
{
|
||||
checkCudaErrors(cudaMemsetAsync(m_numPointsInCircle, 0, sizeof(*m_numPointsInCircle), stream));
|
||||
|
||||
monte_carlo_kernel<<<m_blocks, m_threads, 0, stream>>>(
|
||||
m_xyVector, m_pointsInsideCircle, m_numPointsInCircle, m_numPoints, time);
|
||||
getLastCudaError("Failed to launch CUDA simulation");
|
||||
|
||||
checkCudaErrors(cudaMemcpyAsync(
|
||||
m_hostNumPointsInCircle, m_numPointsInCircle, sizeof(*m_numPointsInCircle), cudaMemcpyDeviceToHost, stream));
|
||||
|
||||
// Queue up a stream callback to compute and print the PI value.
|
||||
checkCudaErrors(cudaLaunchHostFunc(stream, this->computePiCallback, (void *)this));
|
||||
}
|
||||
|
||||
void MonteCarloPiSimulation::computePiCallback(void *args)
|
||||
{
|
||||
MonteCarloPiSimulation *cbData = (MonteCarloPiSimulation *)args;
|
||||
cbData->m_totalPointsInsideCircle += *(cbData->m_hostNumPointsInCircle);
|
||||
cbData->m_totalPointsSimulated += cbData->m_numPoints;
|
||||
double piValue = 4.0 * ((double)cbData->m_totalPointsInsideCircle / (double)cbData->m_totalPointsSimulated);
|
||||
printf("Approximate Pi value for %zd data points: %lf \n", cbData->m_totalPointsSimulated, piValue);
|
||||
}
|
||||
|
||||
void MonteCarloPiSimulation::getIdealExecutionConfiguration()
|
||||
{
|
||||
int warpSize = 0;
|
||||
int multiProcessorCount = 0;
|
||||
|
||||
checkCudaErrors(cudaSetDevice(m_cudaDevice));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&warpSize, cudaDevAttrWarpSize, m_cudaDevice));
|
||||
|
||||
// We don't need large block sizes, since there's not much inter-thread
|
||||
// communication
|
||||
m_threads = warpSize;
|
||||
|
||||
// Use the occupancy calculator and fill the gpu as best as we can
|
||||
checkCudaErrors(cudaOccupancyMaxActiveBlocksPerMultiprocessor(&m_blocks, monte_carlo_kernel, warpSize, 0));
|
||||
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&multiProcessorCount, cudaDevAttrMultiProcessorCount, m_cudaDevice));
|
||||
m_blocks *= multiProcessorCount;
|
||||
|
||||
// Go ahead and the clamp the blocks to the minimum needed for this
|
||||
// height/width
|
||||
m_blocks = std::min(m_blocks, (int)((m_numPoints + m_threads - 1) / m_threads));
|
||||
}
|
||||
|
||||
void MonteCarloPiSimulation::setupSimulationAllocations()
|
||||
{
|
||||
CUdeviceptr d_ptr = 0U;
|
||||
size_t granularity = 0;
|
||||
CUmemGenericAllocationHandle cudaPositionHandle, cudaInCircleHandle;
|
||||
|
||||
CUmemAllocationProp allocProp = {};
|
||||
allocProp.type = CU_MEM_ALLOCATION_TYPE_PINNED;
|
||||
allocProp.location.type = CU_MEM_LOCATION_TYPE_DEVICE;
|
||||
allocProp.location.id = m_cudaDevice;
|
||||
allocProp.win32HandleMetaData = NULL;
|
||||
allocProp.requestedHandleTypes = ipcHandleTypeFlag;
|
||||
|
||||
// Windows-specific LPSECURITYATTRIBUTES is required when
|
||||
// CU_MEM_HANDLE_TYPE_WIN32 is used. The security attribute defines the scope
|
||||
// of which exported allocations may be tranferred to other processes. For all
|
||||
// other handle types, pass NULL.
|
||||
getDefaultSecurityDescriptor(&allocProp);
|
||||
|
||||
// Get the recommended granularity for m_cudaDevice.
|
||||
checkCudaErrors(cuMemGetAllocationGranularity(&granularity, &allocProp, CU_MEM_ALLOC_GRANULARITY_RECOMMENDED));
|
||||
|
||||
size_t xyPositionVecSize = m_numPoints * sizeof(*m_xyVector);
|
||||
size_t inCircleVecSize = m_numPoints * sizeof(*m_pointsInsideCircle);
|
||||
|
||||
size_t xyPositionSize = ROUND_UP_TO_GRANULARITY(xyPositionVecSize, granularity);
|
||||
size_t inCircleSize = ROUND_UP_TO_GRANULARITY(inCircleVecSize, granularity);
|
||||
m_totalAllocationSize = (xyPositionSize + inCircleSize);
|
||||
|
||||
// Reserve the required contiguous VA space for the allocations
|
||||
checkCudaErrors(cuMemAddressReserve(&d_ptr, m_totalAllocationSize, granularity, 0U, 0));
|
||||
|
||||
// Create the allocations as a pinned allocation on this device.
|
||||
// Create an allocation to store all the positions of points on the xy plane
|
||||
// and a second allocation which stores information if the corresponding
|
||||
// position is inside the unit circle or not.
|
||||
checkCudaErrors(cuMemCreate(&cudaPositionHandle, xyPositionSize, &allocProp, 0));
|
||||
checkCudaErrors(cuMemCreate(&cudaInCircleHandle, inCircleSize, &allocProp, 0));
|
||||
|
||||
// Export the allocation to a platform-specific handle. The type of handle
|
||||
// requested here must match the requestedHandleTypes field in the prop
|
||||
// structure passed to cuMemCreate. The handle obtained here will be passed to
|
||||
// vulkan to import the allocation.
|
||||
checkCudaErrors(
|
||||
cuMemExportToShareableHandle((void *)&m_posShareableHandle, cudaPositionHandle, ipcHandleTypeFlag, 0));
|
||||
checkCudaErrors(
|
||||
cuMemExportToShareableHandle((void *)&m_inCircleShareableHandle, cudaInCircleHandle, ipcHandleTypeFlag, 0));
|
||||
|
||||
CUdeviceptr va_position = d_ptr;
|
||||
CUdeviceptr va_InCircle = va_position + xyPositionSize;
|
||||
m_pointsInsideCircle = (float *)va_InCircle;
|
||||
m_xyVector = (vec2 *)va_position;
|
||||
|
||||
// Assign the chunk to the appropriate VA range
|
||||
checkCudaErrors(cuMemMap(va_position, xyPositionSize, 0, cudaPositionHandle, 0));
|
||||
checkCudaErrors(cuMemMap(va_InCircle, inCircleSize, 0, cudaInCircleHandle, 0));
|
||||
|
||||
// Release the handles for the allocation. Since the allocation is currently
|
||||
// mapped to a VA range with a previous call to cuMemMap the actual freeing of
|
||||
// memory allocation will happen on an eventual call to cuMemUnmap. Thus the
|
||||
// allocation will be kept live until it is unmapped.
|
||||
checkCudaErrors(cuMemRelease(cudaPositionHandle));
|
||||
checkCudaErrors(cuMemRelease(cudaInCircleHandle));
|
||||
|
||||
CUmemAccessDesc accessDescriptor = {};
|
||||
accessDescriptor.location.id = m_cudaDevice;
|
||||
accessDescriptor.location.type = CU_MEM_LOCATION_TYPE_DEVICE;
|
||||
accessDescriptor.flags = CU_MEM_ACCESS_FLAGS_PROT_READWRITE;
|
||||
|
||||
// Apply the access descriptor to the whole VA range. Essentially enables
|
||||
// Read-Write access to the range.
|
||||
checkCudaErrors(cuMemSetAccess(d_ptr, m_totalAllocationSize, &accessDescriptor, 1));
|
||||
}
|
||||
|
||||
void MonteCarloPiSimulation::cleanupSimulationAllocations()
|
||||
{
|
||||
if (m_xyVector && m_pointsInsideCircle) {
|
||||
// Unmap the mapped virtual memory region
|
||||
// Since the handles to the mapped backing stores have already been released
|
||||
// by cuMemRelease, and these are the only/last mappings referencing them,
|
||||
// The backing stores will be freed.
|
||||
checkCudaErrors(cuMemUnmap((CUdeviceptr)m_xyVector, m_totalAllocationSize));
|
||||
|
||||
checkIpcErrors(ipcCloseShareableHandle(m_posShareableHandle));
|
||||
checkIpcErrors(ipcCloseShareableHandle(m_inCircleShareableHandle));
|
||||
|
||||
// Free the virtual address region.
|
||||
checkCudaErrors(cuMemAddressFree((CUdeviceptr)m_xyVector, m_totalAllocationSize));
|
||||
|
||||
m_xyVector = nullptr;
|
||||
m_pointsInsideCircle = nullptr;
|
||||
}
|
||||
}
|
||||
94
cpp/5_Domain_Specific/simpleVulkanMMAP/MonteCarloPi.h
Normal file
94
cpp/5_Domain_Specific/simpleVulkanMMAP/MonteCarloPi.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __PISIM_H__
|
||||
#define __PISIM_H__
|
||||
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <curand.h>
|
||||
#include <curand_kernel.h>
|
||||
#include <vector>
|
||||
|
||||
#include "helper_multiprocess.h"
|
||||
|
||||
typedef float vec2[2];
|
||||
|
||||
class MonteCarloPiSimulation
|
||||
{
|
||||
size_t m_numPoints;
|
||||
|
||||
// Pointers to Cuda allocated buffers which are imported and used by vulkan as
|
||||
// vertex buffer
|
||||
vec2 *m_xyVector;
|
||||
float *m_pointsInsideCircle;
|
||||
|
||||
// Pointers to device and host allocated memories storing number of points
|
||||
// that are inside the unit circle
|
||||
float *m_numPointsInCircle;
|
||||
float *m_hostNumPointsInCircle;
|
||||
|
||||
int m_blocks, m_threads;
|
||||
|
||||
// Total size of allocations created by cuMemMap Apis. This size is the sum of
|
||||
// sizes of m_xyVector and m_pointsInsideCircle buffers.
|
||||
size_t m_totalAllocationSize;
|
||||
|
||||
// Shareable Handles(a file descriptor on Linux and NT Handle on Windows),
|
||||
// used for sharing cuda
|
||||
// allocated memory with Vulkan
|
||||
ShareableHandle m_posShareableHandle, m_inCircleShareableHandle;
|
||||
|
||||
// Cuda Device corresponding to the Vulkan Physical device
|
||||
int m_cudaDevice;
|
||||
|
||||
// Track and accumulate total points that have been simulated since start of
|
||||
// the sample. The idea is to get a closer approximation to PI with time.
|
||||
size_t m_totalPointsInsideCircle;
|
||||
size_t m_totalPointsSimulated;
|
||||
|
||||
void setupSimulationAllocations();
|
||||
void cleanupSimulationAllocations();
|
||||
void getIdealExecutionConfiguration();
|
||||
|
||||
public:
|
||||
MonteCarloPiSimulation(size_t num_points);
|
||||
~MonteCarloPiSimulation();
|
||||
void initSimulation(int cudaDevice, cudaStream_t stream = 0);
|
||||
void stepSimulation(float time, cudaStream_t stream = 0);
|
||||
static void computePiCallback(void *args);
|
||||
|
||||
size_t getNumPoints() const { return m_numPoints; }
|
||||
|
||||
float getNumPointsInCircle() const { return *m_hostNumPointsInCircle; }
|
||||
|
||||
ShareableHandle &getPositionShareableHandle() { return m_posShareableHandle; }
|
||||
ShareableHandle &getInCircleShareableHandle() { return m_inCircleShareableHandle; }
|
||||
};
|
||||
|
||||
#endif // __PISIM_H__
|
||||
39
cpp/5_Domain_Specific/simpleVulkanMMAP/README.md
Normal file
39
cpp/5_Domain_Specific/simpleVulkanMMAP/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# simpleVulkanMMAP - Vulkan CUDA Interop PI Approximation
|
||||
|
||||
## Description
|
||||
|
||||
This sample demonstrates Vulkan CUDA Interop via cuMemMap APIs. CUDA exports buffers that Vulkan imports as vertex buffer. CUDA invokes kernels to operate on vertices and synchronizes with Vulkan through vulkan semaphores imported by CUDA. This sample depends on Vulkan SDK, GLFW3 libraries, for building this sample please refer to "Build_instructions.txt" provided in this sample's directory
|
||||
|
||||
## Key Concepts
|
||||
|
||||
cuMemMap IPC, MMAP, Graphics Interop, CUDA Vulkan Interop, Data Parallel Algorithms
|
||||
|
||||
## Supported SM Architectures
|
||||
|
||||
[SM 5.0 ](https://developer.nvidia.com/cuda-gpus) [SM 5.2 ](https://developer.nvidia.com/cuda-gpus) [SM 5.3 ](https://developer.nvidia.com/cuda-gpus) [SM 6.0 ](https://developer.nvidia.com/cuda-gpus) [SM 6.1 ](https://developer.nvidia.com/cuda-gpus) [SM 7.0 ](https://developer.nvidia.com/cuda-gpus) [SM 7.2 ](https://developer.nvidia.com/cuda-gpus) [SM 7.5 ](https://developer.nvidia.com/cuda-gpus) [SM 8.0 ](https://developer.nvidia.com/cuda-gpus) [SM 8.6 ](https://developer.nvidia.com/cuda-gpus) [SM 8.7 ](https://developer.nvidia.com/cuda-gpus) [SM 8.9 ](https://developer.nvidia.com/cuda-gpus) [SM 9.0 ](https://developer.nvidia.com/cuda-gpus)
|
||||
|
||||
## Supported OSes
|
||||
|
||||
Linux, Windows
|
||||
|
||||
## Supported CPU Architecture
|
||||
|
||||
x86_64, aarch64
|
||||
|
||||
## CUDA APIs involved
|
||||
|
||||
### [CUDA Driver API](http://docs.nvidia.com/cuda/cuda-driver-api/index.html)
|
||||
cuMemCreate, cuMemAddressReserve, cuMemGetAllocationGranularity, cuMemAddressFree, cuMemUnmap, cuMemMap, cuMemRelease, cuMemExportToShareableHandle, cuMemSetAccess
|
||||
|
||||
### [CUDA Runtime API](http://docs.nvidia.com/cuda/cuda-runtime-api/index.html)
|
||||
cudaWaitExternalSemaphoresAsync, cudaImportExternalSemaphore, cudaDeviceGetAttribute, cudaSetDevice, cudaLaunchHostFunc, cudaMallocHost, cudaSignalExternalSemaphoresAsync, cudaFreeHost, cudaMemsetAsync, cudaMemcpyAsync, cudaGetDeviceCount, cudaStreamCreateWithFlags, cudaStreamDestroy, cudaDestroyExternalSemaphore, cudaSignalSemaphore, cudaWaitSemaphore, cudaFree, cudaStreamSynchronize, cudaMalloc, cudaOccupancyMaxActiveBlocksPerMultiprocessor, cudaGetDeviceProperties
|
||||
|
||||
## Dependencies needed to build/run
|
||||
[X11](../../../README.md#x11), [VULKAN](../../../README.md#vulkan), [GLFW](../../../README.md#glfw)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Download and install the [CUDA Toolkit](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
|
||||
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
|
||||
|
||||
## References (for more details)
|
||||
1794
cpp/5_Domain_Specific/simpleVulkanMMAP/VulkanBaseApp.cpp
Normal file
1794
cpp/5_Domain_Specific/simpleVulkanMMAP/VulkanBaseApp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
163
cpp/5_Domain_Specific/simpleVulkanMMAP/VulkanBaseApp.h
Normal file
163
cpp/5_Domain_Specific/simpleVulkanMMAP/VulkanBaseApp.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __VULKANBASEAPP_H__
|
||||
#define __VULKANBASEAPP_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan.h>
|
||||
#ifdef _WIN64
|
||||
#define NOMINMAX
|
||||
// Add windows.h to the include path firstly as dependency for other Windows headers
|
||||
#include <windows.h>
|
||||
// Add other Windows headers
|
||||
#include <vulkan/vulkan_win32.h>
|
||||
#endif /* _WIN64 */
|
||||
|
||||
struct GLFWwindow;
|
||||
|
||||
class VulkanBaseApp
|
||||
{
|
||||
public:
|
||||
VulkanBaseApp(const std::string &appName, bool enableValidation = false);
|
||||
static VkExternalSemaphoreHandleTypeFlagBits getDefaultSemaphoreHandleType();
|
||||
static VkExternalMemoryHandleTypeFlagBits getDefaultMemHandleType();
|
||||
virtual ~VulkanBaseApp();
|
||||
void init();
|
||||
void *getMemHandle(VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagBits handleType);
|
||||
void *getSemaphoreHandle(VkSemaphore semaphore, VkExternalSemaphoreHandleTypeFlagBits handleType);
|
||||
bool isVkPhysicalDeviceUuid(void *Uuid);
|
||||
void createExternalSemaphore(VkSemaphore &semaphore, VkExternalSemaphoreHandleTypeFlagBits handleType);
|
||||
void createBuffer(VkDeviceSize size,
|
||||
VkBufferUsageFlags usage,
|
||||
VkMemoryPropertyFlags properties,
|
||||
VkBuffer &buffer,
|
||||
VkDeviceMemory &bufferMemory);
|
||||
void createExternalBuffer(VkDeviceSize size,
|
||||
VkBufferUsageFlags usage,
|
||||
VkMemoryPropertyFlags properties,
|
||||
VkExternalMemoryHandleTypeFlagsKHR extMemHandleType,
|
||||
VkBuffer &buffer,
|
||||
VkDeviceMemory &bufferMemory);
|
||||
void importExternalBuffer(void *handle,
|
||||
VkExternalMemoryHandleTypeFlagBits handleType,
|
||||
size_t size,
|
||||
VkBufferUsageFlags usage,
|
||||
VkMemoryPropertyFlags properties,
|
||||
VkBuffer &buffer,
|
||||
VkDeviceMemory &memory);
|
||||
void copyBuffer(VkBuffer dst, VkBuffer src, VkDeviceSize size);
|
||||
VkCommandBuffer beginSingleTimeCommands();
|
||||
void endSingleTimeCommands(VkCommandBuffer commandBuffer);
|
||||
void mainLoop();
|
||||
|
||||
protected:
|
||||
const std::string m_appName;
|
||||
const bool m_enableValidation;
|
||||
VkInstance m_instance;
|
||||
VkDebugUtilsMessengerEXT m_debugMessenger;
|
||||
VkSurfaceKHR m_surface;
|
||||
VkPhysicalDevice m_physicalDevice;
|
||||
uint8_t m_deviceUUID[VK_UUID_SIZE];
|
||||
VkDevice m_device;
|
||||
VkQueue m_graphicsQueue;
|
||||
VkQueue m_presentQueue;
|
||||
VkSwapchainKHR m_swapChain;
|
||||
std::vector<VkImage> m_swapChainImages;
|
||||
VkFormat m_swapChainFormat;
|
||||
VkExtent2D m_swapChainExtent;
|
||||
std::vector<VkImageView> m_swapChainImageViews;
|
||||
std::vector<std::pair<VkShaderStageFlagBits, std::string>> m_shaderFiles;
|
||||
VkRenderPass m_renderPass;
|
||||
VkPipelineLayout m_pipelineLayout;
|
||||
VkPipeline m_graphicsPipeline;
|
||||
std::vector<VkFramebuffer> m_swapChainFramebuffers;
|
||||
VkCommandPool m_commandPool;
|
||||
std::vector<VkCommandBuffer> m_commandBuffers;
|
||||
std::vector<VkSemaphore> m_imageAvailableSemaphores;
|
||||
std::vector<VkSemaphore> m_renderFinishedSemaphores;
|
||||
std::vector<VkFence> m_inFlightFences;
|
||||
std::vector<VkBuffer> m_uniformBuffers;
|
||||
std::vector<VkDeviceMemory> m_uniformMemory;
|
||||
VkDescriptorSetLayout m_descriptorSetLayout;
|
||||
VkDescriptorPool m_descriptorPool;
|
||||
std::vector<VkDescriptorSet> m_descriptorSets;
|
||||
|
||||
VkImage m_depthImage;
|
||||
VkDeviceMemory m_depthImageMemory;
|
||||
VkImageView m_depthImageView;
|
||||
size_t m_currentFrame;
|
||||
bool m_framebufferResized;
|
||||
|
||||
virtual void initVulkanApp() {}
|
||||
virtual void fillRenderingCommandBuffer(VkCommandBuffer &buffer) {}
|
||||
virtual std::vector<const char *> getRequiredExtensions() const;
|
||||
virtual std::vector<const char *> getRequiredDeviceExtensions() const;
|
||||
virtual void getVertexDescriptions(std::vector<VkVertexInputBindingDescription> &bindingDesc,
|
||||
std::vector<VkVertexInputAttributeDescription> &attribDesc);
|
||||
virtual void getAssemblyStateInfo(VkPipelineInputAssemblyStateCreateInfo &info);
|
||||
virtual void getWaitFrameSemaphores(std::vector<VkSemaphore> &wait,
|
||||
std::vector<VkPipelineStageFlags> &waitStages) const;
|
||||
virtual void getSignalFrameSemaphores(std::vector<VkSemaphore> &signal) const;
|
||||
virtual VkDeviceSize getUniformSize() const;
|
||||
virtual void updateUniformBuffer(uint32_t imageIndex, size_t globalFrame);
|
||||
virtual void drawFrame();
|
||||
|
||||
private:
|
||||
GLFWwindow *m_window;
|
||||
|
||||
void initWindow();
|
||||
void initVulkan();
|
||||
void createInstance();
|
||||
void createSurface();
|
||||
void createDevice();
|
||||
void createSwapChain();
|
||||
void createImageViews();
|
||||
void createRenderPass();
|
||||
void createDescriptorSetLayout();
|
||||
void createGraphicsPipeline();
|
||||
void createFramebuffers();
|
||||
void createCommandPool();
|
||||
void createDepthResources();
|
||||
void createUniformBuffers();
|
||||
void createDescriptorPool();
|
||||
void createDescriptorSets();
|
||||
void createCommandBuffers();
|
||||
void createSyncObjects();
|
||||
|
||||
void cleanupSwapChain();
|
||||
void recreateSwapChain();
|
||||
|
||||
bool isSuitableDevice(VkPhysicalDevice dev) const;
|
||||
static void resizeCallback(GLFWwindow *window, int width, int height);
|
||||
};
|
||||
|
||||
void readFile(std::istream &s, std::vector<char> &data);
|
||||
|
||||
#endif /* __VULKANBASEAPP_H__ */
|
||||
78
cpp/5_Domain_Specific/simpleVulkanMMAP/VulkanCudaInterop.h
Normal file
78
cpp/5_Domain_Specific/simpleVulkanMMAP/VulkanCudaInterop.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __VKCUDA_H__
|
||||
#define __VKCUDA_H__
|
||||
|
||||
#include <cuda_runtime_api.h>
|
||||
|
||||
#include "cuda.h"
|
||||
#define CUDA_DRIVER_API
|
||||
#include <helper_cuda.h>
|
||||
|
||||
bool isDeviceCompatible(void *Uuid, size_t size)
|
||||
{
|
||||
int cudaDevice = cudaInvalidDeviceId;
|
||||
int deviceCount;
|
||||
checkCudaErrors(cudaGetDeviceCount(&deviceCount));
|
||||
|
||||
for (int i = 0; i < deviceCount; ++i) {
|
||||
cudaDeviceProp devProp = {};
|
||||
checkCudaErrors(cudaGetDeviceProperties(&devProp, i));
|
||||
if (!memcmp(&devProp.uuid, Uuid, size)) {
|
||||
cudaDevice = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cudaDevice == cudaInvalidDeviceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int deviceSupportsHandle = 0;
|
||||
int attributeVal = 0;
|
||||
int deviceComputeMode = 0;
|
||||
|
||||
checkCudaErrors(cuDeviceGetAttribute(&deviceComputeMode, CU_DEVICE_ATTRIBUTE_COMPUTE_MODE, cudaDevice));
|
||||
checkCudaErrors(
|
||||
cuDeviceGetAttribute(&attributeVal, CU_DEVICE_ATTRIBUTE_VIRTUAL_ADDRESS_MANAGEMENT_SUPPORTED, cudaDevice));
|
||||
|
||||
#if defined(__linux__)
|
||||
checkCudaErrors(cuDeviceGetAttribute(
|
||||
&deviceSupportsHandle, CU_DEVICE_ATTRIBUTE_HANDLE_TYPE_POSIX_FILE_DESCRIPTOR_SUPPORTED, cudaDevice));
|
||||
#else
|
||||
checkCudaErrors(cuDeviceGetAttribute(
|
||||
&deviceSupportsHandle, CU_DEVICE_ATTRIBUTE_HANDLE_TYPE_WIN32_HANDLE_SUPPORTED, cudaDevice));
|
||||
#endif
|
||||
|
||||
if ((deviceComputeMode != CU_COMPUTEMODE_DEFAULT) || !attributeVal || !deviceSupportsHandle) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // __VKCUDA_H__
|
||||
BIN
cpp/5_Domain_Specific/simpleVulkanMMAP/frag.spv
Normal file
BIN
cpp/5_Domain_Specific/simpleVulkanMMAP/frag.spv
Normal file
Binary file not shown.
348
cpp/5_Domain_Specific/simpleVulkanMMAP/main.cpp
Normal file
348
cpp/5_Domain_Specific/simpleVulkanMMAP/main.cpp
Normal file
@@ -0,0 +1,348 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This sample demonstrates CUDA Interop with Vulkan using cuMemMap APIs.
|
||||
* Allocating device memory and updating values in those allocations are
|
||||
* performed by CUDA and the contents of the allocation are visualized by
|
||||
* Vulkan.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cuda.h>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include "MonteCarloPi.h"
|
||||
#include "VulkanBaseApp.h"
|
||||
#include "helper_cuda.h"
|
||||
#include "helper_multiprocess.h"
|
||||
|
||||
// #define DEBUG
|
||||
#ifdef NDEBUG
|
||||
#define ENABLE_VALIDATION (false)
|
||||
#else
|
||||
#define ENABLE_VALIDATION (true)
|
||||
#endif
|
||||
|
||||
#define NUM_SIMULATION_POINTS 50000
|
||||
|
||||
std::string execution_path;
|
||||
|
||||
class VulkanCudaPi : public VulkanBaseApp
|
||||
{
|
||||
typedef struct UniformBufferObject_st
|
||||
{
|
||||
float frame;
|
||||
} UniformBufferObject;
|
||||
|
||||
VkBuffer m_inCircleBuffer, m_xyPositionBuffer;
|
||||
VkDeviceMemory m_inCircleMemory, m_xyPositionMemory;
|
||||
VkSemaphore m_vkWaitSemaphore, m_vkSignalSemaphore;
|
||||
MonteCarloPiSimulation m_sim;
|
||||
UniformBufferObject m_ubo;
|
||||
cudaStream_t m_stream;
|
||||
cudaExternalSemaphore_t m_cudaWaitSemaphore, m_cudaSignalSemaphore;
|
||||
using chrono_tp = std::chrono::time_point<std::chrono::high_resolution_clock>;
|
||||
chrono_tp m_lastTime;
|
||||
size_t m_lastFrame;
|
||||
|
||||
public:
|
||||
VulkanCudaPi(size_t num_points)
|
||||
: VulkanBaseApp("simpleVulkanMMAP", ENABLE_VALIDATION)
|
||||
, m_inCircleBuffer(VK_NULL_HANDLE)
|
||||
, m_xyPositionBuffer(VK_NULL_HANDLE)
|
||||
, m_inCircleMemory(VK_NULL_HANDLE)
|
||||
, m_xyPositionMemory(VK_NULL_HANDLE)
|
||||
, m_sim(num_points)
|
||||
, m_ubo()
|
||||
, m_stream(0)
|
||||
, m_vkWaitSemaphore(VK_NULL_HANDLE)
|
||||
, m_vkSignalSemaphore(VK_NULL_HANDLE)
|
||||
, m_cudaWaitSemaphore()
|
||||
, m_cudaSignalSemaphore()
|
||||
, m_lastFrame(0)
|
||||
{
|
||||
// Add our compiled vulkan shader files
|
||||
char *vertex_shader_path = sdkFindFilePath("vert.spv", execution_path.c_str());
|
||||
char *fragment_shader_path = sdkFindFilePath("frag.spv", execution_path.c_str());
|
||||
m_shaderFiles.push_back(std::make_pair(VK_SHADER_STAGE_VERTEX_BIT, vertex_shader_path));
|
||||
m_shaderFiles.push_back(std::make_pair(VK_SHADER_STAGE_FRAGMENT_BIT, fragment_shader_path));
|
||||
}
|
||||
|
||||
~VulkanCudaPi()
|
||||
{
|
||||
if (m_stream) {
|
||||
// Make sure there's no pending work before we start tearing down
|
||||
checkCudaErrors(cudaStreamSynchronize(m_stream));
|
||||
checkCudaErrors(cudaStreamDestroy(m_stream));
|
||||
}
|
||||
|
||||
if (m_vkSignalSemaphore != VK_NULL_HANDLE) {
|
||||
checkCudaErrors(cudaDestroyExternalSemaphore(m_cudaSignalSemaphore));
|
||||
vkDestroySemaphore(m_device, m_vkSignalSemaphore, nullptr);
|
||||
}
|
||||
if (m_vkWaitSemaphore != VK_NULL_HANDLE) {
|
||||
checkCudaErrors(cudaDestroyExternalSemaphore(m_cudaWaitSemaphore));
|
||||
vkDestroySemaphore(m_device, m_vkWaitSemaphore, nullptr);
|
||||
}
|
||||
if (m_xyPositionBuffer != VK_NULL_HANDLE) {
|
||||
vkDestroyBuffer(m_device, m_xyPositionBuffer, nullptr);
|
||||
}
|
||||
if (m_xyPositionMemory != VK_NULL_HANDLE) {
|
||||
vkFreeMemory(m_device, m_xyPositionMemory, nullptr);
|
||||
}
|
||||
if (m_inCircleBuffer != VK_NULL_HANDLE) {
|
||||
vkDestroyBuffer(m_device, m_inCircleBuffer, nullptr);
|
||||
}
|
||||
if (m_inCircleMemory != VK_NULL_HANDLE) {
|
||||
vkFreeMemory(m_device, m_inCircleMemory, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void fillRenderingCommandBuffer(VkCommandBuffer &commandBuffer)
|
||||
{
|
||||
VkBuffer vertexBuffers[] = {m_inCircleBuffer, m_xyPositionBuffer};
|
||||
VkDeviceSize offsets[] = {0, 0};
|
||||
vkCmdBindVertexBuffers(
|
||||
commandBuffer, 0, sizeof(vertexBuffers) / sizeof(vertexBuffers[0]), vertexBuffers, offsets);
|
||||
vkCmdDraw(commandBuffer, (uint32_t)(m_sim.getNumPoints()), 1, 0, 0);
|
||||
}
|
||||
|
||||
void getVertexDescriptions(std::vector<VkVertexInputBindingDescription> &bindingDesc,
|
||||
std::vector<VkVertexInputAttributeDescription> &attribDesc)
|
||||
{
|
||||
bindingDesc.resize(2);
|
||||
attribDesc.resize(2);
|
||||
|
||||
bindingDesc[0].binding = 0;
|
||||
bindingDesc[0].stride = sizeof(float);
|
||||
bindingDesc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
|
||||
bindingDesc[1].binding = 1;
|
||||
bindingDesc[1].stride = sizeof(vec2);
|
||||
bindingDesc[1].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
|
||||
attribDesc[0].binding = 0;
|
||||
attribDesc[0].location = 0;
|
||||
attribDesc[0].format = VK_FORMAT_R32_SFLOAT;
|
||||
attribDesc[0].offset = 0;
|
||||
|
||||
attribDesc[1].binding = 1;
|
||||
attribDesc[1].location = 1;
|
||||
attribDesc[1].format = VK_FORMAT_R32G32_SFLOAT;
|
||||
attribDesc[1].offset = 0;
|
||||
}
|
||||
|
||||
void getAssemblyStateInfo(VkPipelineInputAssemblyStateCreateInfo &info)
|
||||
{
|
||||
info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
info.primitiveRestartEnable = VK_FALSE;
|
||||
}
|
||||
|
||||
void getWaitFrameSemaphores(std::vector<VkSemaphore> &wait, std::vector<VkPipelineStageFlags> &waitStages) const
|
||||
{
|
||||
if (m_currentFrame != 0) {
|
||||
// Have vulkan wait until cuda is done with the vertex buffer before
|
||||
// rendering
|
||||
// We don't do this on the first frame, as the wait semaphore hasn't been
|
||||
// initialized yet
|
||||
wait.push_back(m_vkWaitSemaphore);
|
||||
// We want to wait until all the pipeline commands are complete before
|
||||
// letting cuda work
|
||||
waitStages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
void getSignalFrameSemaphores(std::vector<VkSemaphore> &signal) const
|
||||
{
|
||||
// Add this semaphore for vulkan to signal once the vertex buffer is ready
|
||||
// for cuda to modify
|
||||
signal.push_back(m_vkSignalSemaphore);
|
||||
}
|
||||
|
||||
void initVulkanApp()
|
||||
{
|
||||
const size_t nVerts = m_sim.getNumPoints();
|
||||
|
||||
// Obtain cuda device id for the device corresponding to the Vulkan physical
|
||||
// device
|
||||
int deviceCount;
|
||||
int cudaDevice = cudaInvalidDeviceId;
|
||||
checkCudaErrors(cudaGetDeviceCount(&deviceCount));
|
||||
for (int dev = 0; dev < deviceCount; ++dev) {
|
||||
cudaDeviceProp devProp = {};
|
||||
checkCudaErrors(cudaGetDeviceProperties(&devProp, dev));
|
||||
if (isVkPhysicalDeviceUuid(&devProp.uuid)) {
|
||||
cudaDevice = dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cudaDevice == cudaInvalidDeviceId) {
|
||||
throw std::runtime_error("No Suitable device found!");
|
||||
}
|
||||
|
||||
// On the corresponding cuda device, create the cuda stream we'll using
|
||||
checkCudaErrors(cudaSetDevice(cudaDevice));
|
||||
checkCudaErrors(cudaStreamCreateWithFlags(&m_stream, cudaStreamNonBlocking));
|
||||
m_sim.initSimulation(cudaDevice, m_stream);
|
||||
|
||||
importExternalBuffer((void *)(uintptr_t)m_sim.getPositionShareableHandle(),
|
||||
getDefaultMemHandleType(),
|
||||
nVerts * sizeof(vec2),
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
m_xyPositionBuffer,
|
||||
m_xyPositionMemory);
|
||||
|
||||
importExternalBuffer((void *)(uintptr_t)m_sim.getInCircleShareableHandle(),
|
||||
getDefaultMemHandleType(),
|
||||
nVerts * sizeof(float),
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
m_inCircleBuffer,
|
||||
m_inCircleMemory);
|
||||
|
||||
// Create the semaphore vulkan will signal when it's done with the vertex
|
||||
// buffer
|
||||
createExternalSemaphore(m_vkSignalSemaphore, getDefaultSemaphoreHandleType());
|
||||
// Create the semaphore vulkan will wait for before using the vertex buffer
|
||||
createExternalSemaphore(m_vkWaitSemaphore, getDefaultSemaphoreHandleType());
|
||||
// Import the semaphore cuda will use -- vulkan's signal will be cuda's wait
|
||||
importCudaExternalSemaphore(m_cudaWaitSemaphore, m_vkSignalSemaphore, getDefaultSemaphoreHandleType());
|
||||
// Import the semaphore cuda will use -- cuda's signal will be vulkan's wait
|
||||
importCudaExternalSemaphore(m_cudaSignalSemaphore, m_vkWaitSemaphore, getDefaultSemaphoreHandleType());
|
||||
}
|
||||
|
||||
void importCudaExternalSemaphore(cudaExternalSemaphore_t &cudaSem,
|
||||
VkSemaphore &vkSem,
|
||||
VkExternalSemaphoreHandleTypeFlagBits handleType)
|
||||
{
|
||||
cudaExternalSemaphoreHandleDesc externalSemaphoreHandleDesc = {};
|
||||
|
||||
if (handleType & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT) {
|
||||
externalSemaphoreHandleDesc.type = cudaExternalSemaphoreHandleTypeOpaqueWin32;
|
||||
}
|
||||
else if (handleType & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT) {
|
||||
externalSemaphoreHandleDesc.type = cudaExternalSemaphoreHandleTypeOpaqueWin32Kmt;
|
||||
}
|
||||
else if (handleType & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) {
|
||||
externalSemaphoreHandleDesc.type = cudaExternalSemaphoreHandleTypeOpaqueFd;
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("Unknown handle type requested!");
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
externalSemaphoreHandleDesc.handle.win32.handle = (HANDLE)getSemaphoreHandle(vkSem, handleType);
|
||||
#else
|
||||
externalSemaphoreHandleDesc.handle.fd = (int)(uintptr_t)getSemaphoreHandle(vkSem, handleType);
|
||||
#endif
|
||||
|
||||
externalSemaphoreHandleDesc.flags = 0;
|
||||
|
||||
checkCudaErrors(cudaImportExternalSemaphore(&cudaSem, &externalSemaphoreHandleDesc));
|
||||
}
|
||||
|
||||
VkDeviceSize getUniformSize() const { return sizeof(UniformBufferObject); }
|
||||
|
||||
void updateUniformBuffer(uint32_t imageIndex, size_t globalFrame)
|
||||
{
|
||||
m_ubo.frame = (float)globalFrame;
|
||||
void *data;
|
||||
vkMapMemory(m_device, m_uniformMemory[imageIndex], 0, getUniformSize(), 0, &data);
|
||||
memcpy(data, &m_ubo, sizeof(m_ubo));
|
||||
vkUnmapMemory(m_device, m_uniformMemory[imageIndex]);
|
||||
}
|
||||
|
||||
std::vector<const char *> getRequiredExtensions() const
|
||||
{
|
||||
std::vector<const char *> extensions;
|
||||
extensions.push_back(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
|
||||
extensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
|
||||
extensions.push_back(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME);
|
||||
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
return extensions;
|
||||
}
|
||||
|
||||
std::vector<const char *> getRequiredDeviceExtensions() const
|
||||
{
|
||||
std::vector<const char *> extensions;
|
||||
|
||||
extensions.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
|
||||
extensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
|
||||
#ifdef _WIN64
|
||||
extensions.push_back(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
|
||||
extensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME);
|
||||
#else
|
||||
extensions.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
|
||||
extensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
|
||||
#endif /* _WIN64 */
|
||||
return extensions;
|
||||
}
|
||||
|
||||
void drawFrame()
|
||||
{
|
||||
static chrono_tp startTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
chrono_tp currentTime = std::chrono::high_resolution_clock::now();
|
||||
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
|
||||
|
||||
if (m_currentFrame == 0) {
|
||||
m_lastTime = startTime;
|
||||
}
|
||||
|
||||
cudaExternalSemaphoreWaitParams waitParams = {};
|
||||
waitParams.flags = 0;
|
||||
waitParams.params.fence.value = 0;
|
||||
|
||||
cudaExternalSemaphoreSignalParams signalParams = {};
|
||||
signalParams.flags = 0;
|
||||
signalParams.params.fence.value = 0;
|
||||
|
||||
// Have vulkan draw the current frame...
|
||||
VulkanBaseApp::drawFrame();
|
||||
// Wait for vulkan to complete it's work
|
||||
checkCudaErrors(cudaWaitExternalSemaphoresAsync(&m_cudaWaitSemaphore, &waitParams, 1, m_stream));
|
||||
// Now step the simulation
|
||||
m_sim.stepSimulation(time, m_stream);
|
||||
|
||||
// Signal vulkan to continue with the updated buffers
|
||||
checkCudaErrors(cudaSignalExternalSemaphoresAsync(&m_cudaSignalSemaphore, &signalParams, 1, m_stream));
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
execution_path = argv[0];
|
||||
VulkanCudaPi app(NUM_SIMULATION_POINTS);
|
||||
app.init();
|
||||
app.mainLoop();
|
||||
return 0;
|
||||
}
|
||||
37
cpp/5_Domain_Specific/simpleVulkanMMAP/montecarlo.frag
Normal file
37
cpp/5_Domain_Specific/simpleVulkanMMAP/montecarlo.frag
Normal file
@@ -0,0 +1,37 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(location = 0) in vec3 fragColor;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(fragColor, 1.0);
|
||||
}
|
||||
55
cpp/5_Domain_Specific/simpleVulkanMMAP/montecarlo.vert
Normal file
55
cpp/5_Domain_Specific/simpleVulkanMMAP/montecarlo.vert
Normal file
@@ -0,0 +1,55 @@
|
||||
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject {
|
||||
float frame;
|
||||
} ubo;
|
||||
|
||||
layout(location = 0) in float pointInsideCircle;
|
||||
layout(location = 1) in vec2 xyPos;
|
||||
|
||||
layout(location = 0) out vec3 fragColor;
|
||||
|
||||
const float PI = 3.1415926;
|
||||
|
||||
out gl_PerVertex
|
||||
{
|
||||
vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_PointSize = 1.0;
|
||||
gl_Position = vec4(xyPos.xy, 0.0f, 1.0f);
|
||||
float color_r = 1.0f + 0.5f * sin(ubo.frame / 100.0f);
|
||||
float color_g = 1.0f + 0.5f * sin((ubo.frame / 100.0f) + (2.0f*PI/3.0f));
|
||||
float color_b = 1.0f;
|
||||
fragColor = vec3(pointInsideCircle.x * color_r, pointInsideCircle.x * color_g, color_b);
|
||||
}
|
||||
BIN
cpp/5_Domain_Specific/simpleVulkanMMAP/vert.spv
Normal file
BIN
cpp/5_Domain_Specific/simpleVulkanMMAP/vert.spv
Normal file
Binary file not shown.
Reference in New Issue
Block a user