mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-23 13:18:16 +08:00
Add and update samples for cuda 10.2 support
This commit is contained in:
160
Common/dynlink_d3d11.h
Normal file
160
Common/dynlink_d3d11.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// File: dynlink_d3d11.h
|
||||
//
|
||||
// Shortcut macros and functions for using DX objects
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#ifndef _DYNLINK_D3D11_H_
|
||||
#define _DYNLINK_D3D11_H_
|
||||
|
||||
// Standard Windows includes
|
||||
#include <windows.h>
|
||||
#include <initguid.h>
|
||||
#include <assert.h>
|
||||
#include <wchar.h>
|
||||
#include <mmsystem.h>
|
||||
#include <commctrl.h> // for InitCommonControls()
|
||||
#include <shellapi.h> // for ExtractIcon()
|
||||
#include <new.h> // for placement new
|
||||
#include <shlobj.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// CRT's memory leak detection
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
// Direct3D10 includes
|
||||
#include <dxgi.h>
|
||||
#include <d3d11.h>
|
||||
// #include <..\Samples\C++\Effects11\Inc\d3dx11effect.h>
|
||||
|
||||
// XInput includes
|
||||
#include <xinput.h>
|
||||
|
||||
// strsafe.h deprecates old unsecure string functions. If you
|
||||
// really do not want to it to (not recommended), then uncomment the next line
|
||||
//#define STRSAFE_NO_DEPRECATE
|
||||
|
||||
#ifndef STRSAFE_NO_DEPRECATE
|
||||
#pragma deprecated("strncpy")
|
||||
#pragma deprecated("wcsncpy")
|
||||
#pragma deprecated("_tcsncpy")
|
||||
#pragma deprecated("wcsncat")
|
||||
#pragma deprecated("strncat")
|
||||
#pragma deprecated("_tcsncat")
|
||||
#endif
|
||||
|
||||
#pragma warning( disable : 4996 ) // disable deprecated warning
|
||||
#include <strsafe.h>
|
||||
#pragma warning( default : 4996 )
|
||||
|
||||
typedef HRESULT(WINAPI *LPCREATEDXGIFACTORY)(REFIID, void **);
|
||||
typedef HRESULT(WINAPI *LPD3D11CREATEDEVICEANDSWAPCHAIN)(__in_opt IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, __in_ecount_opt(FeatureLevels) CONST D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, __in_opt CONST DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, __out_opt IDXGISwapChain **ppSwapChain, __out_opt ID3D11Device **ppDevice, __out_opt D3D_FEATURE_LEVEL *pFeatureLevel, __out_opt ID3D11DeviceContext **ppImmediateContext);
|
||||
typedef HRESULT(WINAPI *LPD3D11CREATEDEVICE)(IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT32, D3D_FEATURE_LEVEL *, UINT, UINT32, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **);
|
||||
|
||||
static HMODULE s_hModDXGI = NULL;
|
||||
static LPCREATEDXGIFACTORY sFnPtr_CreateDXGIFactory = NULL;
|
||||
static HMODULE s_hModD3D11 = NULL;
|
||||
static LPD3D11CREATEDEVICE sFnPtr_D3D11CreateDevice = NULL;
|
||||
static LPD3D11CREATEDEVICEANDSWAPCHAIN sFnPtr_D3D11CreateDeviceAndSwapChain = NULL;
|
||||
|
||||
// unload the D3D10 DLLs
|
||||
static bool dynlinkUnloadD3D11API(void)
|
||||
{
|
||||
if (s_hModDXGI)
|
||||
{
|
||||
FreeLibrary(s_hModDXGI);
|
||||
s_hModDXGI = NULL;
|
||||
}
|
||||
|
||||
if (s_hModD3D11)
|
||||
{
|
||||
FreeLibrary(s_hModD3D11);
|
||||
s_hModD3D11 = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Dynamically load the D3D11 DLLs loaded and map the function pointers
|
||||
static bool dynlinkLoadD3D11API(void)
|
||||
{
|
||||
// If both modules are non-NULL, this function has already been called. Note
|
||||
// that this doesn't guarantee that all ProcAddresses were found.
|
||||
if (s_hModD3D11 != NULL && s_hModDXGI != NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 1
|
||||
// This may fail if Direct3D 11 isn't installed
|
||||
s_hModD3D11 = LoadLibrary("d3d11.dll");
|
||||
|
||||
if (s_hModD3D11 != NULL)
|
||||
{
|
||||
sFnPtr_D3D11CreateDevice = (LPD3D11CREATEDEVICE)GetProcAddress(s_hModD3D11, "D3D11CreateDevice");
|
||||
sFnPtr_D3D11CreateDeviceAndSwapChain = (LPD3D11CREATEDEVICEANDSWAPCHAIN)GetProcAddress(s_hModD3D11, "D3D11CreateDeviceAndSwapChain");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\nLoad d3d11.dll failed\n");
|
||||
fflush(0);
|
||||
}
|
||||
|
||||
if (!sFnPtr_CreateDXGIFactory)
|
||||
{
|
||||
s_hModDXGI = LoadLibrary("dxgi.dll");
|
||||
|
||||
if (s_hModDXGI)
|
||||
{
|
||||
sFnPtr_CreateDXGIFactory = (LPCREATEDXGIFACTORY)GetProcAddress(s_hModDXGI, "CreateDXGIFactory1");
|
||||
}
|
||||
|
||||
return (s_hModDXGI != NULL) && (s_hModD3D11 != NULL);
|
||||
}
|
||||
|
||||
return (s_hModD3D11 != NULL);
|
||||
#else
|
||||
sFnPtr_D3D11CreateDevice = (LPD3D11CREATEDEVICE)D3D11CreateDeviceAndSwapChain;
|
||||
sFnPtr_D3D11CreateDeviceAndSwapChain = (LPD3D11CREATEDEVICEANDSWAPCHAIN)D3D11CreateDeviceAndSwapChain;
|
||||
//sFnPtr_D3DX11CreateEffectFromMemory = ( LPD3DX11CREATEEFFECTFROMMEMORY )D3DX11CreateEffectFromMemory;
|
||||
sFnPtr_D3DX11CompileFromMemory = (LPD3DX11COMPILEFROMMEMORY)D3DX11CompileFromMemory;
|
||||
sFnPtr_CreateDXGIFactory = (LPCREATEDXGIFACTORY)CreateDXGIFactory;
|
||||
return true;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -579,24 +579,12 @@ static const char *_cudaGetErrorEnum(NppStatus error) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DRIVER_TYPES_H__
|
||||
#ifndef DEVICE_RESET
|
||||
#define DEVICE_RESET cudaDeviceReset();
|
||||
#endif
|
||||
#else
|
||||
#ifndef DEVICE_RESET
|
||||
#define DEVICE_RESET
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
void check(T result, char const *const func, const char *const file,
|
||||
int const line) {
|
||||
if (result) {
|
||||
fprintf(stderr, "CUDA error at %s:%d code=%d(%s) \"%s\" \n", file, line,
|
||||
static_cast<unsigned int>(result), _cudaGetErrorEnum(result), func);
|
||||
DEVICE_RESET
|
||||
// Make sure we call CUDA Device Reset before exiting
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -619,7 +607,6 @@ inline void __getLastCudaError(const char *errorMessage, const char *file,
|
||||
" %s : (%d) %s.\n",
|
||||
file, line, errorMessage, static_cast<int>(err),
|
||||
cudaGetErrorString(err));
|
||||
DEVICE_RESET
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -696,6 +683,50 @@ inline int _ConvertSMVer2Cores(int major, int minor) {
|
||||
major, minor, nGpuArchCoresPerSM[index - 1].Cores);
|
||||
return nGpuArchCoresPerSM[index - 1].Cores;
|
||||
}
|
||||
|
||||
inline const char* _ConvertSMVer2ArchName(int major, int minor) {
|
||||
// Defines for GPU Architecture types (using the SM version to determine
|
||||
// the GPU Arch name)
|
||||
typedef struct {
|
||||
int SM; // 0xMm (hexidecimal notation), M = SM Major version,
|
||||
// and m = SM minor version
|
||||
const char* name;
|
||||
} sSMtoArchName;
|
||||
|
||||
sSMtoArchName nGpuArchNameSM[] = {
|
||||
{0x30, "Kepler"},
|
||||
{0x32, "Kepler"},
|
||||
{0x35, "Kepler"},
|
||||
{0x37, "Kepler"},
|
||||
{0x50, "Maxwell"},
|
||||
{0x52, "Maxwell"},
|
||||
{0x53, "Maxwell"},
|
||||
{0x60, "Pascal"},
|
||||
{0x61, "Pascal"},
|
||||
{0x62, "Pascal"},
|
||||
{0x70, "Volta"},
|
||||
{0x72, "Xavier"},
|
||||
{0x75, "Turing"},
|
||||
{-1, "Graphics Device"}};
|
||||
|
||||
int index = 0;
|
||||
|
||||
while (nGpuArchNameSM[index].SM != -1) {
|
||||
if (nGpuArchNameSM[index].SM == ((major << 4) + minor)) {
|
||||
return nGpuArchNameSM[index].name;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
// If we don't find the values, we default use the previous one
|
||||
// to run properly
|
||||
printf(
|
||||
"MapSMtoArchName for SM %d.%d is undefined."
|
||||
" Default to use %s\n",
|
||||
major, minor, nGpuArchNameSM[index - 1].name);
|
||||
return nGpuArchNameSM[index - 1].name;
|
||||
}
|
||||
// end of GPU Architecture definitions
|
||||
|
||||
#ifdef __CUDA_RUNTIME_H__
|
||||
@@ -727,23 +758,24 @@ inline int gpuDeviceInit(int devID) {
|
||||
return -devID;
|
||||
}
|
||||
|
||||
cudaDeviceProp deviceProp;
|
||||
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, devID));
|
||||
|
||||
if (deviceProp.computeMode == cudaComputeModeProhibited) {
|
||||
int computeMode = -1, major = 0, minor = 0;
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&computeMode, cudaDevAttrComputeMode, devID));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&major, cudaDevAttrComputeCapabilityMajor, devID));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&minor, cudaDevAttrComputeCapabilityMinor, devID));
|
||||
if (computeMode == cudaComputeModeProhibited) {
|
||||
fprintf(stderr,
|
||||
"Error: device is running in <Compute Mode "
|
||||
"Prohibited>, no threads can use cudaSetDevice().\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (deviceProp.major < 1) {
|
||||
if (major < 1) {
|
||||
fprintf(stderr, "gpuDeviceInit(): GPU device does not support CUDA.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
checkCudaErrors(cudaSetDevice(devID));
|
||||
printf("gpuDeviceInit() CUDA Device [%d]: \"%s\n", devID, deviceProp.name);
|
||||
printf("gpuDeviceInit() CUDA Device [%d]: \"%s\n", devID, _ConvertSMVer2ArchName(major, minor));
|
||||
|
||||
return devID;
|
||||
}
|
||||
@@ -756,7 +788,6 @@ inline int gpuGetMaxGflopsDeviceId() {
|
||||
int devices_prohibited = 0;
|
||||
|
||||
uint64_t max_compute_perf = 0;
|
||||
cudaDeviceProp deviceProp;
|
||||
checkCudaErrors(cudaGetDeviceCount(&device_count));
|
||||
|
||||
if (device_count == 0) {
|
||||
@@ -770,20 +801,24 @@ inline int gpuGetMaxGflopsDeviceId() {
|
||||
current_device = 0;
|
||||
|
||||
while (current_device < device_count) {
|
||||
cudaGetDeviceProperties(&deviceProp, current_device);
|
||||
int computeMode = -1, major = 0, minor = 0;
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&computeMode, cudaDevAttrComputeMode, current_device));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&major, cudaDevAttrComputeCapabilityMajor, current_device));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&minor, cudaDevAttrComputeCapabilityMinor, current_device));
|
||||
|
||||
// If this GPU is not running on Compute Mode prohibited,
|
||||
// then we can add it to the list
|
||||
if (deviceProp.computeMode != cudaComputeModeProhibited) {
|
||||
if (deviceProp.major == 9999 && deviceProp.minor == 9999) {
|
||||
if (computeMode != cudaComputeModeProhibited) {
|
||||
if (major == 9999 && minor == 9999) {
|
||||
sm_per_multiproc = 1;
|
||||
} else {
|
||||
sm_per_multiproc =
|
||||
_ConvertSMVer2Cores(deviceProp.major, deviceProp.minor);
|
||||
_ConvertSMVer2Cores(major, minor);
|
||||
}
|
||||
|
||||
uint64_t compute_perf = (uint64_t)deviceProp.multiProcessorCount *
|
||||
sm_per_multiproc * deviceProp.clockRate;
|
||||
int multiProcessorCount = 0, clockRate = 0;
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&multiProcessorCount, cudaDevAttrMultiProcessorCount, current_device));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&clockRate, cudaDevAttrClockRate, current_device));
|
||||
uint64_t compute_perf = (uint64_t)multiProcessorCount * sm_per_multiproc * clockRate;
|
||||
|
||||
if (compute_perf > max_compute_perf) {
|
||||
max_compute_perf = compute_perf;
|
||||
@@ -808,7 +843,6 @@ inline int gpuGetMaxGflopsDeviceId() {
|
||||
|
||||
// Initialization code to find the best CUDA Device
|
||||
inline int findCudaDevice(int argc, const char **argv) {
|
||||
cudaDeviceProp deviceProp;
|
||||
int devID = 0;
|
||||
|
||||
// If the command-line has a device number specified, use it
|
||||
@@ -830,9 +864,12 @@ inline int findCudaDevice(int argc, const char **argv) {
|
||||
// Otherwise pick the device with highest Gflops/s
|
||||
devID = gpuGetMaxGflopsDeviceId();
|
||||
checkCudaErrors(cudaSetDevice(devID));
|
||||
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, devID));
|
||||
printf("GPU Device %d: \"%s\" with compute capability %d.%d\n\n", devID,
|
||||
deviceProp.name, deviceProp.major, deviceProp.minor);
|
||||
int major = 0, minor = 0;
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&major, cudaDevAttrComputeCapabilityMajor, devID));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&minor, cudaDevAttrComputeCapabilityMinor, devID));
|
||||
printf("GPU Device %d: \"%s\" with compute capability %d.%d\n\n",
|
||||
devID, _ConvertSMVer2ArchName(major, minor), major, minor);
|
||||
|
||||
}
|
||||
|
||||
return devID;
|
||||
@@ -843,7 +880,6 @@ inline int findIntegratedGPU() {
|
||||
int device_count = 0;
|
||||
int devices_prohibited = 0;
|
||||
|
||||
cudaDeviceProp deviceProp;
|
||||
checkCudaErrors(cudaGetDeviceCount(&device_count));
|
||||
|
||||
if (device_count == 0) {
|
||||
@@ -853,17 +889,19 @@ inline int findIntegratedGPU() {
|
||||
|
||||
// Find the integrated GPU which is compute capable
|
||||
while (current_device < device_count) {
|
||||
cudaGetDeviceProperties(&deviceProp, current_device);
|
||||
|
||||
int computeMode = -1, integrated = -1;
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&computeMode, cudaDevAttrComputeMode, current_device));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&integrated, cudaDevAttrIntegrated, current_device));
|
||||
// If GPU is integrated and is not running on Compute Mode prohibited,
|
||||
// then cuda can map to GLES resource
|
||||
if (deviceProp.integrated &&
|
||||
(deviceProp.computeMode != cudaComputeModeProhibited)) {
|
||||
if (integrated && (computeMode != cudaComputeModeProhibited)) {
|
||||
checkCudaErrors(cudaSetDevice(current_device));
|
||||
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, current_device));
|
||||
|
||||
int major = 0, minor = 0;
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&major, cudaDevAttrComputeCapabilityMajor, current_device));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&minor, cudaDevAttrComputeCapabilityMinor, current_device));
|
||||
printf("GPU Device %d: \"%s\" with compute capability %d.%d\n\n",
|
||||
current_device, deviceProp.name, deviceProp.major,
|
||||
deviceProp.minor);
|
||||
current_device, _ConvertSMVer2ArchName(major, minor), major, minor);
|
||||
|
||||
return current_device;
|
||||
} else {
|
||||
@@ -885,19 +923,18 @@ inline int findIntegratedGPU() {
|
||||
|
||||
// General check for CUDA GPU SM Capabilities
|
||||
inline bool checkCudaCapabilities(int major_version, int minor_version) {
|
||||
cudaDeviceProp deviceProp;
|
||||
deviceProp.major = 0;
|
||||
deviceProp.minor = 0;
|
||||
int dev;
|
||||
int major = 0, minor = 0;
|
||||
|
||||
checkCudaErrors(cudaGetDevice(&dev));
|
||||
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, dev));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&major, cudaDevAttrComputeCapabilityMajor, dev));
|
||||
checkCudaErrors(cudaDeviceGetAttribute(&minor, cudaDevAttrComputeCapabilityMinor, dev));
|
||||
|
||||
if ((deviceProp.major > major_version) ||
|
||||
(deviceProp.major == major_version &&
|
||||
deviceProp.minor >= minor_version)) {
|
||||
if ((major > major_version) ||
|
||||
(major == major_version &&
|
||||
minor >= minor_version)) {
|
||||
printf(" Device %d: <%16s >, Compute SM %d.%d detected\n", dev,
|
||||
deviceProp.name, deviceProp.major, deviceProp.minor);
|
||||
_ConvertSMVer2ArchName(major, minor), major, minor);
|
||||
return true;
|
||||
} else {
|
||||
printf(
|
||||
|
||||
@@ -29,150 +29,534 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
int sharedMemoryCreate(const char *name, size_t sz, sharedMemoryInfo *info)
|
||||
{
|
||||
int sharedMemoryCreate(const char *name, size_t sz, sharedMemoryInfo *info) {
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
|
||||
info->size = sz;
|
||||
info->shmHandle = CreateFileMapping(INVALID_HANDLE_VALUE,
|
||||
NULL,
|
||||
PAGE_READWRITE,
|
||||
0,
|
||||
(DWORD)sz,
|
||||
name);
|
||||
if (info->shmHandle == 0) {
|
||||
return GetLastError();
|
||||
}
|
||||
info->size = sz;
|
||||
info->shmHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
|
||||
PAGE_READWRITE, 0, (DWORD)sz, name);
|
||||
if (info->shmHandle == 0) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
info->addr = MapViewOfFile(info->shmHandle, FILE_MAP_ALL_ACCESS, 0, 0, sz);
|
||||
if (info->addr == NULL) {
|
||||
return GetLastError();
|
||||
}
|
||||
info->addr = MapViewOfFile(info->shmHandle, FILE_MAP_ALL_ACCESS, 0, 0, sz);
|
||||
if (info->addr == NULL) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
#else
|
||||
int status = 0;
|
||||
int status = 0;
|
||||
|
||||
info->size = sz;
|
||||
info->size = sz;
|
||||
|
||||
info->shmFd = shm_open(name, O_RDWR | O_CREAT, 0777);
|
||||
if (info->shmFd < 0) {
|
||||
return errno;
|
||||
}
|
||||
info->shmFd = shm_open(name, O_RDWR | O_CREAT, 0777);
|
||||
if (info->shmFd < 0) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
status = ftruncate(info->shmFd, sz);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
status = ftruncate(info->shmFd, sz);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
info->addr = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_SHARED, info->shmFd, 0);
|
||||
if (info->addr == NULL) {
|
||||
return errno;
|
||||
}
|
||||
info->addr = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_SHARED, info->shmFd, 0);
|
||||
if (info->addr == NULL) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int sharedMemoryOpen(const char *name, size_t sz, sharedMemoryInfo *info)
|
||||
{
|
||||
int sharedMemoryOpen(const char *name, size_t sz, sharedMemoryInfo *info) {
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
|
||||
info->size = sz;
|
||||
info->size = sz;
|
||||
|
||||
info->shmHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
|
||||
if (info->shmHandle == 0) {
|
||||
return GetLastError();
|
||||
}
|
||||
info->shmHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
|
||||
if (info->shmHandle == 0) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
info->addr = MapViewOfFile(info->shmHandle, FILE_MAP_ALL_ACCESS, 0, 0, sz);
|
||||
if (info->addr == NULL) {
|
||||
return GetLastError();
|
||||
}
|
||||
info->addr = MapViewOfFile(info->shmHandle, FILE_MAP_ALL_ACCESS, 0, 0, sz);
|
||||
if (info->addr == NULL) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
#else
|
||||
info->size = sz;
|
||||
info->size = sz;
|
||||
|
||||
info->shmFd = shm_open(name, O_RDWR, 0777);
|
||||
if (info->shmFd < 0) {
|
||||
return errno;
|
||||
}
|
||||
info->shmFd = shm_open(name, O_RDWR, 0777);
|
||||
if (info->shmFd < 0) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
info->addr = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_SHARED, info->shmFd, 0);
|
||||
if (info->addr == NULL) {
|
||||
return errno;
|
||||
}
|
||||
info->addr = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_SHARED, info->shmFd, 0);
|
||||
if (info->addr == NULL) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void sharedMemoryClose(sharedMemoryInfo *info)
|
||||
{
|
||||
void sharedMemoryClose(sharedMemoryInfo *info) {
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
|
||||
if (info->addr) {
|
||||
UnmapViewOfFile(info->addr);
|
||||
}
|
||||
if (info->shmHandle) {
|
||||
CloseHandle(info->shmHandle);
|
||||
}
|
||||
if (info->addr) {
|
||||
UnmapViewOfFile(info->addr);
|
||||
}
|
||||
if (info->shmHandle) {
|
||||
CloseHandle(info->shmHandle);
|
||||
}
|
||||
#else
|
||||
if (info->addr) {
|
||||
munmap(info->addr, info->size);
|
||||
}
|
||||
if (info->shmFd) {
|
||||
close(info->shmFd);
|
||||
}
|
||||
if (info->addr) {
|
||||
munmap(info->addr, info->size);
|
||||
}
|
||||
if (info->shmFd) {
|
||||
close(info->shmFd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int spawnProcess(Process *process, const char *app, char * const *args)
|
||||
{
|
||||
int spawnProcess(Process *process, const char *app, char *const *args) {
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
|
||||
STARTUPINFO si = {0};
|
||||
BOOL status;
|
||||
size_t arglen = 0;
|
||||
size_t argIdx = 0;
|
||||
std::string arg_string;
|
||||
memset(process, 0, sizeof(*process));
|
||||
STARTUPINFO si = {0};
|
||||
BOOL status;
|
||||
size_t arglen = 0;
|
||||
size_t argIdx = 0;
|
||||
std::string arg_string;
|
||||
memset(process, 0, sizeof(*process));
|
||||
|
||||
while (*args) {
|
||||
arg_string.append(*args).append(1, ' ');
|
||||
args++;
|
||||
}
|
||||
while (*args) {
|
||||
arg_string.append(*args).append(1, ' ');
|
||||
args++;
|
||||
}
|
||||
|
||||
status = CreateProcess(app, LPSTR(arg_string.c_str()), NULL, NULL, FALSE, 0, NULL, NULL, &si, process);
|
||||
status = CreateProcess(app, LPSTR(arg_string.c_str()), NULL, NULL, FALSE, 0,
|
||||
NULL, NULL, &si, process);
|
||||
|
||||
return status ? 0 : GetLastError();
|
||||
return status ? 0 : GetLastError();
|
||||
#else
|
||||
*process = fork();
|
||||
if (*process == 0) {
|
||||
if (0 > execvp(app, args)) {
|
||||
return errno;
|
||||
}
|
||||
*process = fork();
|
||||
if (*process == 0) {
|
||||
if (0 > execvp(app, args)) {
|
||||
return errno;
|
||||
}
|
||||
else if (*process < 0) {
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
} else if (*process < 0) {
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int waitProcess(Process *process)
|
||||
{
|
||||
int waitProcess(Process *process) {
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
|
||||
DWORD exitCode;
|
||||
WaitForSingleObject(process->hProcess, INFINITE);
|
||||
GetExitCodeProcess(process->hProcess, &exitCode);
|
||||
CloseHandle(process->hProcess);
|
||||
CloseHandle(process->hThread);
|
||||
return (int)exitCode;
|
||||
DWORD exitCode;
|
||||
WaitForSingleObject(process->hProcess, INFINITE);
|
||||
GetExitCodeProcess(process->hProcess, &exitCode);
|
||||
CloseHandle(process->hProcess);
|
||||
CloseHandle(process->hThread);
|
||||
return (int)exitCode;
|
||||
#else
|
||||
int status = 0;
|
||||
do {
|
||||
if (0 > waitpid(*process, &status, 0)) {
|
||||
return errno;
|
||||
}
|
||||
} while (!WIFEXITED(status));
|
||||
return WEXITSTATUS(status);
|
||||
int status = 0;
|
||||
do {
|
||||
if (0 > waitpid(*process, &status, 0)) {
|
||||
return errno;
|
||||
}
|
||||
} while (!WIFEXITED(status));
|
||||
return WEXITSTATUS(status);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
int ipcCreateSocket(ipcHandle *&handle, const char *name,
|
||||
const std::vector<Process> &processes) {
|
||||
int server_fd;
|
||||
struct sockaddr_un servaddr;
|
||||
|
||||
handle = new ipcHandle;
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
handle->socket = -1;
|
||||
handle->socketName = NULL;
|
||||
|
||||
// Creating socket file descriptor
|
||||
if ((server_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == 0) {
|
||||
perror("IPC failure: Socket creation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
unlink(name);
|
||||
bzero(&servaddr, sizeof(servaddr));
|
||||
servaddr.sun_family = AF_UNIX;
|
||||
|
||||
size_t len = strlen(name);
|
||||
if (len > (sizeof(servaddr.sun_path) - 1)) {
|
||||
perror("IPC failure: Cannot bind provided name to socket. Name too large");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(servaddr.sun_path, name, len);
|
||||
|
||||
if (bind(server_fd, (struct sockaddr *)&servaddr, SUN_LEN(&servaddr)) < 0) {
|
||||
perror("IPC failure: Binding socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle->socketName = new char[strlen(name) + 1];
|
||||
strcpy(handle->socketName, name);
|
||||
handle->socket = server_fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcOpenSocket(ipcHandle *&handle) {
|
||||
int sock = 0;
|
||||
struct sockaddr_un cliaddr;
|
||||
|
||||
handle = new ipcHandle;
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
|
||||
perror("IPC failure:Socket creation error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero(&cliaddr, sizeof(cliaddr));
|
||||
cliaddr.sun_family = AF_UNIX;
|
||||
char temp[10];
|
||||
|
||||
// Create unique name for the socket.
|
||||
sprintf(temp, "%u", getpid());
|
||||
|
||||
strcpy(cliaddr.sun_path, temp);
|
||||
if (bind(sock, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0) {
|
||||
perror("IPC failure: Binding socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle->socket = sock;
|
||||
handle->socketName = new char[strlen(temp) + 1];
|
||||
strcpy(handle->socketName, temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcCloseSocket(ipcHandle *handle) {
|
||||
if (!handle) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (handle->socketName) {
|
||||
unlink(handle->socketName);
|
||||
delete[] handle->socketName;
|
||||
}
|
||||
close(handle->socket);
|
||||
delete handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcRecvShareableHandle(ipcHandle *handle, ShareableHandle *shHandle) {
|
||||
struct msghdr msg = {0};
|
||||
struct iovec iov[1];
|
||||
struct cmsghdr cm;
|
||||
|
||||
// Union to guarantee alignment requirements for control array
|
||||
union {
|
||||
struct cmsghdr cm;
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
} control_un;
|
||||
|
||||
struct cmsghdr *cmptr;
|
||||
ssize_t n;
|
||||
int receivedfd;
|
||||
char dummy_buffer[1];
|
||||
ssize_t sendResult;
|
||||
|
||||
msg.msg_control = control_un.control;
|
||||
msg.msg_controllen = sizeof(control_un.control);
|
||||
|
||||
iov[0].iov_base = (void *)dummy_buffer;
|
||||
iov[0].iov_len = sizeof(dummy_buffer);
|
||||
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
if ((n = recvmsg(handle->socket, &msg, 0)) <= 0) {
|
||||
perror("IPC failure: Receiving data over socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((cmptr = CMSG_FIRSTHDR(&msg)) != NULL) &&
|
||||
(cmptr->cmsg_len == CMSG_LEN(sizeof(int)))) {
|
||||
if ((cmptr->cmsg_level != SOL_SOCKET) || (cmptr->cmsg_type != SCM_RIGHTS)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memmove(&receivedfd, CMSG_DATA(cmptr), sizeof(receivedfd));
|
||||
*(int *)shHandle = receivedfd;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcRecvDataFromClient(ipcHandle *serverHandle, void *data, size_t size) {
|
||||
ssize_t readResult;
|
||||
struct sockaddr_un cliaddr;
|
||||
socklen_t len = sizeof(cliaddr);
|
||||
|
||||
readResult = recvfrom(serverHandle->socket, data, size, 0,
|
||||
(struct sockaddr *)&cliaddr, &len);
|
||||
if (readResult == -1) {
|
||||
perror("IPC failure: Receiving data over socket failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcSendDataToServer(ipcHandle *handle, const char *serverName,
|
||||
const void *data, size_t size) {
|
||||
ssize_t sendResult;
|
||||
struct sockaddr_un serveraddr;
|
||||
|
||||
bzero(&serveraddr, sizeof(serveraddr));
|
||||
serveraddr.sun_family = AF_UNIX;
|
||||
strncpy(serveraddr.sun_path, serverName, sizeof(serveraddr.sun_path) - 1);
|
||||
|
||||
sendResult = sendto(handle->socket, data, size, 0,
|
||||
(struct sockaddr *)&serveraddr, sizeof(serveraddr));
|
||||
if (sendResult <= 0) {
|
||||
perror("IPC failure: Sending data over socket failed");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcSendShareableHandle(ipcHandle *handle,
|
||||
const std::vector<ShareableHandle> &shareableHandles,
|
||||
Process process, int data) {
|
||||
struct msghdr msg;
|
||||
struct iovec iov[1];
|
||||
|
||||
union {
|
||||
struct cmsghdr cm;
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
} control_un;
|
||||
|
||||
struct cmsghdr *cmptr;
|
||||
ssize_t readResult;
|
||||
struct sockaddr_un cliaddr;
|
||||
socklen_t len = sizeof(cliaddr);
|
||||
|
||||
// Construct client address to send this SHareable handle to
|
||||
bzero(&cliaddr, sizeof(cliaddr));
|
||||
cliaddr.sun_family = AF_UNIX;
|
||||
char temp[10];
|
||||
sprintf(temp, "%u", process);
|
||||
strcpy(cliaddr.sun_path, temp);
|
||||
len = sizeof(cliaddr);
|
||||
|
||||
// Send corresponding shareable handle to the client
|
||||
int sendfd = (int)shareableHandles[data];
|
||||
|
||||
msg.msg_control = control_un.control;
|
||||
msg.msg_controllen = sizeof(control_un.control);
|
||||
|
||||
cmptr = CMSG_FIRSTHDR(&msg);
|
||||
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmptr->cmsg_level = SOL_SOCKET;
|
||||
cmptr->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
memmove(CMSG_DATA(cmptr), &sendfd, sizeof(sendfd));
|
||||
|
||||
msg.msg_name = (void *)&cliaddr;
|
||||
msg.msg_namelen = sizeof(struct sockaddr_un);
|
||||
|
||||
iov[0].iov_base = (void *)"";
|
||||
iov[0].iov_len = 1;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
ssize_t sendResult = sendmsg(handle->socket, &msg, 0);
|
||||
if (sendResult <= 0) {
|
||||
perror("IPC failure: Sending data over socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcSendShareableHandles(
|
||||
ipcHandle *handle, const std::vector<ShareableHandle> &shareableHandles,
|
||||
const std::vector<Process> &processes) {
|
||||
// Send all shareable handles to every single process.
|
||||
for (int i = 0; i < shareableHandles.size(); i++) {
|
||||
for (int j = 0; j < processes.size(); j++) {
|
||||
checkIpcErrors(
|
||||
ipcSendShareableHandle(handle, shareableHandles, processes[j], i));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcRecvShareableHandles(ipcHandle *handle,
|
||||
std::vector<ShareableHandle> &shareableHandles) {
|
||||
for (int i = 0; i < shareableHandles.size(); i++) {
|
||||
checkIpcErrors(ipcRecvShareableHandle(handle, &shareableHandles[i]));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcCloseShareableHandle(ShareableHandle shHandle) {
|
||||
return close(shHandle);
|
||||
}
|
||||
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
|
||||
// Generic name to build individual Mailslot names by appending process ids.
|
||||
LPTSTR SlotName = (LPTSTR)TEXT("\\\\.\\mailslot\\sample_mailslot_");
|
||||
|
||||
int ipcCreateSocket(ipcHandle *&handle, const char *name,
|
||||
const std::vector<Process> &processes) {
|
||||
handle = new ipcHandle;
|
||||
handle->hMailslot.resize(processes.size());
|
||||
|
||||
// Open Mailslots of all clients and store respective handles.
|
||||
for (int i = 0; i < handle->hMailslot.size(); ++i) {
|
||||
std::basic_string<TCHAR> childSlotName(SlotName);
|
||||
char tempBuf[20];
|
||||
_itoa_s(processes[i].dwProcessId, tempBuf, 10);
|
||||
childSlotName += TEXT(tempBuf);
|
||||
|
||||
HANDLE hFile =
|
||||
CreateFile(TEXT(childSlotName.c_str()), GENERIC_WRITE, FILE_SHARE_READ,
|
||||
(LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
printf("IPC failure: Opening Mailslot by CreateFile failed with %d\n",
|
||||
GetLastError());
|
||||
return -1;
|
||||
}
|
||||
handle->hMailslot[i] = hFile;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcOpenSocket(ipcHandle *&handle) {
|
||||
handle = new ipcHandle;
|
||||
HANDLE hSlot;
|
||||
|
||||
std::basic_string<TCHAR> clientSlotName(SlotName);
|
||||
char tempBuf[20];
|
||||
_itoa_s(GetCurrentProcessId(), tempBuf, 10);
|
||||
clientSlotName += TEXT(tempBuf);
|
||||
|
||||
hSlot = CreateMailslot((LPSTR)clientSlotName.c_str(), 0,
|
||||
MAILSLOT_WAIT_FOREVER, (LPSECURITY_ATTRIBUTES)NULL);
|
||||
if (hSlot == INVALID_HANDLE_VALUE) {
|
||||
printf("IPC failure: CreateMailslot failed for client with %d\n",
|
||||
GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle->hMailslot.push_back(hSlot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcSendData(HANDLE mailslot, const void *data, size_t sz) {
|
||||
BOOL result;
|
||||
DWORD cbWritten;
|
||||
|
||||
result = WriteFile(mailslot, data, (DWORD)sz, &cbWritten, (LPOVERLAPPED)NULL);
|
||||
if (!result) {
|
||||
printf("IPC failure: WriteFile failed with %d.\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcRecvData(ipcHandle *handle, void *data, size_t sz) {
|
||||
DWORD cbMessage, cMessage, cbRead;
|
||||
BOOL fResult;
|
||||
|
||||
cbMessage = cMessage = cbRead = 0;
|
||||
HANDLE mailslot = handle->hMailslot[0];
|
||||
|
||||
pollMailSlot:
|
||||
fResult = GetMailslotInfo(mailslot, (LPDWORD)NULL, &cbMessage, &cMessage,
|
||||
(LPDWORD)NULL);
|
||||
if (!fResult) {
|
||||
printf("IPC failure: GetMailslotInfo failed with %d.\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cbMessage == MAILSLOT_NO_MESSAGE) {
|
||||
goto pollMailSlot;
|
||||
}
|
||||
|
||||
while (cMessage != 0) {
|
||||
fResult = ReadFile(mailslot, data, (DWORD)sz, &cbRead, NULL);
|
||||
if (!fResult) {
|
||||
printf("IPC failure: ReadFile failed with %d.\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
fResult = GetMailslotInfo(mailslot, (LPDWORD)NULL, &cbMessage, &cMessage,
|
||||
(LPDWORD)NULL);
|
||||
if (!fResult) {
|
||||
printf("IPC failure: GetMailslotInfo failed (%d)\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcSendShareableHandles(
|
||||
ipcHandle *handle, const std::vector<ShareableHandle> &shareableHandles,
|
||||
const std::vector<Process> &processes) {
|
||||
// Send all shareable handles to every single process.
|
||||
for (int i = 0; i < processes.size(); i++) {
|
||||
HANDLE hProcess =
|
||||
OpenProcess(PROCESS_DUP_HANDLE, FALSE, processes[i].dwProcessId);
|
||||
if (hProcess == INVALID_HANDLE_VALUE) {
|
||||
printf("IPC failure: OpenProcess failed (%d)\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int j = 0; j < shareableHandles.size(); j++) {
|
||||
HANDLE hDup = INVALID_HANDLE_VALUE;
|
||||
// Duplicate the handle into the target process's space
|
||||
if (!DuplicateHandle(GetCurrentProcess(), shareableHandles[j], hProcess,
|
||||
&hDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
|
||||
printf("IPC failure: DuplicateHandle failed (%d)\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
checkIpcErrors(ipcSendData(handle->hMailslot[i], &hDup, sizeof(HANDLE)));
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcRecvShareableHandles(ipcHandle *handle,
|
||||
std::vector<ShareableHandle> &shareableHandles) {
|
||||
for (int i = 0; i < shareableHandles.size(); i++) {
|
||||
checkIpcErrors(
|
||||
ipcRecvData(handle, &shareableHandles[i], sizeof(shareableHandles[i])));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcCloseSocket(ipcHandle *handle) {
|
||||
for (int i = 0; i < handle->hMailslot.size(); i++) {
|
||||
CloseHandle(handle->hMailslot[i]);
|
||||
}
|
||||
delete handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipcCloseShareableHandle(ShareableHandle shHandle) {
|
||||
CloseHandle(shHandle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,13 +33,26 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <strsafe.h>
|
||||
#include <sddl.h>
|
||||
#include <aclapi.h>
|
||||
#include <winternl.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <memory.h>
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
#include <vector>
|
||||
|
||||
typedef struct sharedMemoryInfo_st {
|
||||
void *addr;
|
||||
@@ -68,4 +81,40 @@ int spawnProcess(Process *process, const char *app, char * const *args);
|
||||
|
||||
int waitProcess(Process *process);
|
||||
|
||||
#define checkIpcErrors(ipcFuncResult) \
|
||||
if (ipcFuncResult == -1) { fprintf(stderr, "Failure at %u %s\n", __LINE__, __FILE__); exit(EXIT_FAILURE); }
|
||||
|
||||
#if defined(__linux__)
|
||||
struct ipcHandle_st {
|
||||
int socket;
|
||||
char *socketName;
|
||||
};
|
||||
typedef int ShareableHandle;
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
|
||||
struct ipcHandle_st {
|
||||
std::vector<HANDLE> hMailslot; // 1 Handle in case of child and `num children` Handles for parent.
|
||||
};
|
||||
typedef HANDLE ShareableHandle;
|
||||
#endif
|
||||
|
||||
typedef struct ipcHandle_st ipcHandle;
|
||||
|
||||
int
|
||||
ipcCreateSocket(ipcHandle *&handle, const char *name, const std::vector<Process>& processes);
|
||||
|
||||
int
|
||||
ipcOpenSocket(ipcHandle *&handle);
|
||||
|
||||
int
|
||||
ipcCloseSocket(ipcHandle *handle);
|
||||
|
||||
int
|
||||
ipcRecvShareableHandles(ipcHandle *handle, std::vector<ShareableHandle>& shareableHandles);
|
||||
|
||||
int
|
||||
ipcSendShareableHandles(ipcHandle *handle, const std::vector<ShareableHandle>& shareableHandles, const std::vector<Process>& processes);
|
||||
|
||||
int
|
||||
ipcCloseShareableHandle(ShareableHandle shHandle);
|
||||
|
||||
#endif // HELPER_MULTIPROCESS_H
|
||||
|
||||
@@ -297,6 +297,19 @@ int writeBMPi(const char *filename, const unsigned char *d_RGB, int pitch,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inputDirExists(const char *pathname) {
|
||||
struct stat info;
|
||||
if (stat(pathname, &info) != 0) {
|
||||
return 0; // Directory does not exists
|
||||
} else if (info.st_mode & S_IFDIR) {
|
||||
// is a directory
|
||||
return 1;
|
||||
} else {
|
||||
// is not a directory
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int readInput(const std::string &sInputPath,
|
||||
std::vector<std::string> &filelist) {
|
||||
int error_code = 1;
|
||||
@@ -315,15 +328,18 @@ int readInput(const std::string &sInputPath,
|
||||
if (dir_handle) {
|
||||
error_code = 0;
|
||||
while ((dir = readdir(dir_handle)) != NULL) {
|
||||
if (dir->d_type == DT_REG) {
|
||||
std::string sFileName = sInputPath + dir->d_name;
|
||||
filelist.push_back(sFileName);
|
||||
} else if (dir->d_type == DT_DIR) {
|
||||
std::string sFileName = sInputPath + dir->d_name;
|
||||
if (inputDirExists(sFileName.c_str()))
|
||||
{
|
||||
std::string sname = dir->d_name;
|
||||
if (sname != "." && sname != "..") {
|
||||
readInput(sInputPath + sname + "/", filelist);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
filelist.push_back(sFileName);
|
||||
}
|
||||
}
|
||||
closedir(dir_handle);
|
||||
} else {
|
||||
@@ -360,18 +376,6 @@ int readInput(const std::string &sInputPath,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inputDirExists(const char *pathname) {
|
||||
struct stat info;
|
||||
if (stat(pathname, &info) != 0) {
|
||||
return 0; // Directory does not exists
|
||||
} else if (info.st_mode & S_IFDIR) {
|
||||
// is a directory
|
||||
return 1;
|
||||
} else {
|
||||
// is not a directory
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int getInputDir(std::string &input_dir, const char *executable_path) {
|
||||
int found = 0;
|
||||
@@ -399,6 +403,7 @@ int getInputDir(std::string &input_dir, const char *executable_path) {
|
||||
"../../../Samples/<executable_name>/images",
|
||||
"../../Samples/<executable_name>/images"};
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(searchPath) / sizeof(char *); ++i) {
|
||||
std::string pathname(searchPath[i]);
|
||||
size_t executable_name_pos = pathname.find("<executable_name>");
|
||||
@@ -420,4 +425,4 @@ int getInputDir(std::string &input_dir, const char *executable_path) {
|
||||
return found;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
124
Common/rendercheck_d3d11.cpp
Normal file
124
Common/rendercheck_d3d11.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Utility funcs to wrap up saving a surface or the back buffer as a PPM file
|
||||
// In addition, wraps up a threshold comparision of two PPMs.
|
||||
//
|
||||
// These functions are designed to be used to implement an automated QA testing for SDK samples.
|
||||
//
|
||||
// Author: Bryan Dudash
|
||||
// Email: sdkfeedback@nvidia.com
|
||||
//
|
||||
// Copyright (c) NVIDIA Corporation. All rights reserved.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <helper_functions.h>
|
||||
#include <rendercheck_d3d11.h>
|
||||
|
||||
HRESULT CheckRenderD3D11::ActiveRenderTargetToPPM(ID3D11Device *pDevice, const char *zFileName)
|
||||
{
|
||||
ID3D11DeviceContext *pDeviceCtxt;
|
||||
pDevice->GetImmediateContext(&pDeviceCtxt);
|
||||
ID3D11RenderTargetView *pRTV = NULL;
|
||||
pDeviceCtxt->OMGetRenderTargets(1,&pRTV,NULL);
|
||||
|
||||
ID3D11Resource *pSourceResource = NULL;
|
||||
pRTV->GetResource(&pSourceResource);
|
||||
|
||||
return ResourceToPPM(pDevice,pSourceResource,zFileName);
|
||||
}
|
||||
|
||||
HRESULT CheckRenderD3D11::ResourceToPPM(ID3D11Device *pDevice, ID3D11Resource *pResource, const char *zFileName)
|
||||
{
|
||||
ID3D11DeviceContext *pDeviceCtxt;
|
||||
pDevice->GetImmediateContext(&pDeviceCtxt);
|
||||
D3D11_RESOURCE_DIMENSION rType;
|
||||
pResource->GetType(&rType);
|
||||
|
||||
if (rType != D3D11_RESOURCE_DIMENSION_TEXTURE2D)
|
||||
{
|
||||
printf("SurfaceToPPM: pResource is not a 2D texture! Aborting...\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
ID3D11Texture2D *pSourceTexture = (ID3D11Texture2D *)pResource;
|
||||
ID3D11Texture2D *pTargetTexture = NULL;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
pSourceTexture->GetDesc(&desc);
|
||||
desc.BindFlags = 0;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
|
||||
if (FAILED(pDevice->CreateTexture2D(&desc,NULL,&pTargetTexture)))
|
||||
{
|
||||
printf("SurfaceToPPM: Unable to create target Texture resoruce! Aborting... \n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
pDeviceCtxt->CopyResource(pTargetTexture,pSourceTexture);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mappedTex2D;
|
||||
pDeviceCtxt->Map(pTargetTexture, 0, D3D11_MAP_READ,0,&mappedTex2D);
|
||||
|
||||
// Need to convert from dx pitch to pitch=width
|
||||
unsigned char *pPPMData = new unsigned char[desc.Width*desc.Height*4];
|
||||
|
||||
for (unsigned int iHeight = 0; iHeight<desc.Height; iHeight++)
|
||||
{
|
||||
memcpy(&(pPPMData[iHeight*desc.Width*4]),(unsigned char *)(mappedTex2D.pData)+iHeight*mappedTex2D.RowPitch,desc.Width*4);
|
||||
}
|
||||
|
||||
pDeviceCtxt->Unmap(pTargetTexture, 0);
|
||||
|
||||
// Prepends the PPM header info and bumps byte data afterwards
|
||||
sdkSavePPM4ub(zFileName, pPPMData, desc.Width, desc.Height);
|
||||
|
||||
delete [] pPPMData;
|
||||
pTargetTexture->Release();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
bool CheckRenderD3D11::PPMvsPPM(const char *src_file, const char *ref_file, const char *exec_path,
|
||||
const float epsilon, const float threshold)
|
||||
{
|
||||
char *ref_file_path = sdkFindFilePath(ref_file, exec_path);
|
||||
|
||||
if (ref_file_path == NULL)
|
||||
{
|
||||
printf("CheckRenderD3D11::PPMvsPPM unable to find <%s> in <%s> Aborting comparison!\n", ref_file, exec_path);
|
||||
printf(">>> Check info.xml and [project//data] folder <%s> <<<\n", ref_file);
|
||||
printf("Aborting comparison!\n");
|
||||
printf(" FAILURE!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return sdkComparePPM(src_file,ref_file_path,epsilon,threshold,true) == true;
|
||||
}
|
||||
52
Common/rendercheck_d3d11.h
Normal file
52
Common/rendercheck_d3d11.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* Copyright (c) 2019, 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 _RENDERCHECK_D3D11_H_
|
||||
#define _RENDERCHECK_D3D11_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <d3d11.h>
|
||||
|
||||
class CheckRenderD3D11
|
||||
{
|
||||
public:
|
||||
|
||||
CheckRenderD3D11() {}
|
||||
|
||||
static HRESULT ActiveRenderTargetToPPM(ID3D11Device *pDevice, const char *zFileName);
|
||||
static HRESULT ResourceToPPM(ID3D11Device *pDevice, ID3D11Resource *pResource, const char *zFileName);
|
||||
|
||||
static bool PPMvsPPM(const char *src_file, const char *ref_file, const char *exec_path,
|
||||
const float epsilon, const float threshold = 0.0f);
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user