aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dx/context/Context.h410
-rw-r--r--src/dx/context/Device.h75
-rw-r--r--src/dx/context/Format.h22
-rw-r--r--src/dx/context/NvFlexTypes.h88
-rw-r--r--src/dx/context/README.md7
-rw-r--r--src/dx/context/Vector.h207
6 files changed, 809 insertions, 0 deletions
diff --git a/src/dx/context/Context.h b/src/dx/context/Context.h
new file mode 100644
index 0000000..31ddb95
--- /dev/null
+++ b/src/dx/context/Context.h
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, related documentation
+ * and any modifications thereto. Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
+ */
+
+#pragma once
+
+#include "NvFlexTypes.h"
+#include "Vector.h"
+#include <Windows.h>
+#include <vector>
+#include <atomic>
+#include <map>
+
+ // NV shader extensions
+#include "../../../external/nvapi/include/nvShaderExtnEnums.h"
+
+
+#define ENABLE_AMD_AGS 1 // enable AMD AGS shader extensions, used for warp shuffle based reductions
+#if ENABLE_AMD_AGS
+ // AMD shader extensions
+#include <external/ags_lib/inc/amd_ags.h>
+#endif
+
+#define USE_GPUBB 0 //Used for D3D12 shader debugging
+#define ENABLE_D3D12 1
+
+enum GpuVendorId
+{
+ VENDOR_ID_NVIDIA = 0x10DE,
+ VENDOR_ID_AMD = 0x1002,
+ VENDOR_ID_OTHERS = 0x00EE,
+};
+
+inline void ThrowIfFailed(HRESULT hr)
+{
+ if (FAILED(hr))
+ {
+ throw;
+ }
+}
+
+//! graphics API dependent descriptions
+struct NvFlexContextDesc;
+
+//! export interop buffers
+struct NvFlexBuffer;
+struct NvFlexTexture3D;
+
+//! graphics API dependent descriptions
+struct NvFlexBufferViewDesc;
+struct NvFlexTexture3DViewDesc;
+
+/// common object type
+struct NvFlexObject
+{
+ virtual NvFlexUint addRef() = 0;
+ virtual NvFlexUint release() = 0;
+};
+
+//struct NvFlexBuffer : public NvFlexObject {};
+//struct NvFlexTexture3D : public NvFlexObject {};
+
+namespace NvFlex
+{
+ struct Context;
+
+ struct Allocable
+ {
+ void* operator new(size_t size);
+ void* operator new[](size_t size);
+ void operator delete(void* ptr);
+ void operator delete[](void* ptr);
+ };
+
+ struct Object : public Allocable
+ {
+ virtual NvFlexUint addRefInternal();
+
+ virtual NvFlexUint releaseInternal();
+
+ virtual ~Object();
+
+ private:
+ std::atomic_uint32_t m_refCount = 1u;
+ };
+
+ #define NV_FLEX_OBJECT_IMPL \
+ virtual NvFlexUint addRef() { return Object::addRefInternal(); } \
+ virtual NvFlexUint release() { return Object::releaseInternal(); }
+
+ #define NV_FLEX_DISPATCH_MAX_READ_TEXTURES ( 30u )
+ #define NV_FLEX_DISPATCH_MAX_WRITE_TEXTURES ( 8u )
+
+ #define NV_FLEX_DRAW_MAX_READ_TEXTURES ( 8u )
+ #define NV_FLEX_DRAW_MAX_WRITE_TEXTURES ( 1u )
+
+ struct ConstantBufferDesc
+ {
+ NvFlexUint stride;
+ NvFlexUint dim;
+ bool uploadAccess;
+#if defined(_DEBUG)
+ const char* name;
+#endif
+ };
+
+ enum BufferTypes
+ {
+ eBuffer = 1 << 0,
+ eUAV_SRV = 1 << 1,
+ eStage = 1 << 2,
+ eRaw = 1 << 3,
+ eStructured = 1 << 4,
+ eIndirect = 1 << 5,
+ eShared = 1 << 6
+ };
+
+ struct BufferDesc
+ {
+ NvFlexFormat format;
+ NvFlexUint dim;
+ NvFlexUint stride;
+ unsigned int bufferType;
+ const void* data;
+#if defined(_DEBUG)
+ const char* name;
+#endif
+ };
+
+ struct BufferViewDesc
+ {
+ NvFlexFormat format;
+ };
+
+ struct Texture3DDesc
+ {
+ NvFlexFormat format;
+ NvFlexDim dim;
+ bool uploadAccess;
+ bool downloadAccess;
+ const void* data;
+#if defined(_DEBUG)
+ const char* name;
+#endif
+ };
+
+ struct ComputeShaderDesc
+ {
+ ComputeShaderDesc() : cs(nullptr), cs_length(0), label(L""), NvAPI_Slot(~0u) {}
+ ComputeShaderDesc(void* shaderByteCode, NvFlexUint64 byteCodeLength, wchar_t* shaderLabel = L"", NvFlexUint nvApiSlot = ~0u): cs(shaderByteCode), cs_length (byteCodeLength), label(shaderLabel), NvAPI_Slot(nvApiSlot){}
+ const void* cs;
+ NvFlexUint64 cs_length;
+ const wchar_t* label;
+ NvFlexUint NvAPI_Slot;
+ };
+
+ struct InputElementDesc
+ {
+ const char* semanticName;
+ NvFlexFormat format;
+ };
+
+ /// A basic map-discard constant buffer
+ struct ConstantBuffer : public NvFlexObject
+ {
+ virtual ~ConstantBuffer() {}
+
+ ConstantBufferDesc m_desc;
+ };
+
+ /// A GPU resource that supports read operations
+ struct Resource : public NvFlexObject {};
+
+ /// A GPU resource that supports read/write operations
+ /// includes a Resource
+ struct ResourceRW : public NvFlexObject
+ {
+ virtual Resource* getResource() = 0;
+ };
+
+
+ /// Context created resources
+ /// includes Resource, ResourceRW
+ struct Buffer : public NvFlexObject
+ {
+ virtual Resource* getResource() = 0;
+ virtual ResourceRW* getResourceRW() = 0;
+ virtual ~Buffer() {}
+ BufferDesc m_desc;
+ };
+
+ /// Staging resource
+ struct Stage : public NvFlexObject
+ {
+ virtual ~Stage() {}
+ BufferDesc m_desc;
+ };
+
+ /// includes Resource, ResourceRW
+ struct Texture3D : public NvFlexObject
+ {
+ virtual Resource* getResource() = 0;
+ virtual ResourceRW* getResourceRW() = 0;
+ virtual ~Texture3D() {}
+ Texture3DDesc m_desc;
+ };
+
+ struct ComputeShader : public NvFlexObject
+ {
+ virtual ~ComputeShader() {}
+ ComputeShaderDesc m_desc;
+ };
+
+ struct Timer : public NvFlexObject
+ {
+ virtual ~Timer() {}
+ };
+
+ struct Fence : public NvFlexObject
+ {
+ virtual ~Fence() {}
+ };
+
+ struct DispatchParams
+ {
+ ComputeShader* shader;
+ NvFlexDim gridDim;
+ ConstantBuffer* rootConstantBuffer;
+ ConstantBuffer* secondConstantBuffer;
+ Resource* readOnly[NV_FLEX_DISPATCH_MAX_READ_TEXTURES];
+ ResourceRW* readWrite[NV_FLEX_DISPATCH_MAX_WRITE_TEXTURES];
+ Buffer * IndirectLaunchArgs;
+ };
+
+ struct MappedData
+ {
+ void* data;
+ NvFlexUint rowPitch;
+ NvFlexUint depthPitch;
+ };
+
+ // D3D events are expensive to create and destroy, so this pool enables
+ // DxRangeTimers to be reused.
+ struct TimerPool
+ {
+ virtual ~TimerPool() {}
+ // We initialize new elements instead of std::vector doing it, to avoid
+ // having to allocate D3D11Query in a copy constructor
+ //returns an index to the timer in the pool
+ //virtual int alloc() = 0;
+
+ virtual int begin() = 0;
+ virtual void end(int index) = 0;
+
+ // synchronize timers between GPU and CPU
+ virtual void resolve() = 0;
+ // Copy timers to cpu
+ virtual void sync() = 0;
+
+ virtual void clear() = 0;
+
+ virtual float get(int index) = 0;
+ // Set the number of timers in the pool
+ // In D3D12 this results in a reallocation of the timer heap
+ virtual void reserve(size_t size) = 0;
+ static const int m_initPoolSize = 200;
+ size_t m_timerPoolSize = 0; //The size of the heap
+ size_t m_usedElemCount = 0; //How many elements are used
+ size_t m_requestedElemCount = 0; //How many timers were requested
+ };
+
+ // String comparison function for timer name to timer index map
+ struct ltstr
+ {
+ bool operator()(const char* s1, const char* s2) const
+ {
+ return strcmp(s1, s2) < 0;
+ }
+ };
+
+
+ // WString comparison function for timer name to timer index map
+ struct ltwstr
+ {
+ bool operator()(const wchar_t* s1, const wchar_t* s2) const
+ {
+ return wcscmp(s1, s2) < 0;
+ }
+ };
+
+ // Each named range can occur more than once, for example once per iteration
+ // So the map from name to timer has to be a multimap
+
+ typedef std::multimap<const char*, int, ltstr> NameToTimerMap;
+ typedef NameToTimerMap::iterator NameToTimerMapIter;
+
+ typedef std::multimap<const wchar_t*, int, ltwstr> NameToTimerMapW;
+ typedef NameToTimerMapW::iterator NameToTimerMapWIter;
+
+ struct Context
+ {
+ // ************ public interface *****************
+
+ virtual void updateContext(const NvFlexContextDesc* desc) = 0;
+
+ //virtual void updateBufferViewDesc(NvFlexBuffer* buffer, NvFlexBufferViewDesc* desc) = 0;
+
+ //virtual void updateTexture3DViewDesc(NvFlexTexture3D* buffer, NvFlexTexture3DViewDesc* desc) = 0;
+
+ // ************ internal resources ***************
+
+ virtual ConstantBuffer* createConstantBuffer(const ConstantBufferDesc* desc) = 0;
+
+ virtual void* map(ConstantBuffer* buffer) = 0;
+
+ virtual void unmap(ConstantBuffer* buffer) = 0;
+
+ virtual void copy(ConstantBuffer* dst, Buffer* src) = 0;
+
+ virtual Buffer* createBuffer(const BufferDesc* desc, void* ptr = 0) = 0;
+
+ virtual Buffer* createBufferView(Buffer* buffer, const BufferViewDesc* desc) = 0;
+
+ virtual void* map(Buffer* buffer) = 0;
+
+ virtual void* mapUpload(Buffer* buffer) = 0;
+
+ virtual void unmap(Buffer* buffer) = 0;
+
+ virtual void upload(Buffer* buffer) = 0;
+
+ virtual void upload(Buffer* buffer, NvFlexUint offset, NvFlexUint numBytes) = 0;
+
+ virtual void download(Buffer* buffer) = 0;
+
+ virtual void download(Buffer* buffer, NvFlexUint offset, NvFlexUint numBytes) = 0;
+
+ virtual void copy(Buffer* dst, unsigned dstByteOffset, Buffer* src, NvFlexUint srcByteOffset, NvFlexUint numBytes) = 0;
+
+ virtual void copyToNative(void* dst, unsigned dstByteOffset, Buffer* src, NvFlexUint srcByteOffset, NvFlexUint numBytes) = 0;
+
+ virtual void copyToDevice(Buffer* dst, unsigned dstByteOffset, Buffer* src, NvFlexUint srcByteOffset, NvFlexUint numBytes) = 0;
+
+ virtual void copyToHost(Buffer* dst, unsigned dstByteOffset, Buffer* src, NvFlexUint srcByteOffset, NvFlexUint numBytes) = 0;
+
+ virtual void clearUnorderedAccessViewUint(Buffer* buffer, const NvFlexUint * values) = 0;
+
+ virtual void copyResourceState(Buffer* bufferFrom, Buffer* bufferTo) = 0;
+
+ //virtual void updateSubresource(Buffer* bufferIn, const NvFlexUint * box, const void * data) = 0;
+
+ virtual Texture3D* createTexture3D(const Texture3DDesc* desc) = 0;
+
+ virtual MappedData map(Texture3D* buffer) = 0;
+
+ virtual void unmap(Texture3D* buffer) = 0;
+
+ virtual void download(Texture3D* buffer) = 0;
+
+ virtual MappedData mapDownload(Texture3D* buffer) = 0;
+
+ virtual void unmapDownload(Texture3D* buffer) = 0;
+
+ virtual void copy(Texture3D* dst, Texture3D* srv) = 0;
+
+ virtual ComputeShader* createComputeShader(const ComputeShaderDesc* desc) = 0;
+
+ // ***************** Operations ****************
+
+ virtual void dispatch(const DispatchParams* params) = 0;
+
+ virtual void dispatchIndirect(const DispatchParams* params) = 0;
+
+ virtual TimerPool * createTimerPool() = 0;
+
+ virtual Fence* createFence() = 0;
+
+ virtual void fenceSet(Fence * fence) = 0;
+
+ virtual void fenceWait(Fence * fence) = 0;
+
+ virtual void startFrame() = 0;
+
+ virtual void flush() = 0;
+
+ virtual void clearState() = 0;
+
+ // ***************** Profiling ****************
+
+ virtual void eventMarker(const wchar_t* label) = 0;
+
+ virtual void contextPush() = 0;
+
+ virtual void contextPop() = 0;
+
+ bool mEnableTimers;
+
+ NameToTimerMapW mNameToInternalTimerMap;
+ NameToTimerMap mNameToExternalTimerMap;
+
+ Context();
+ virtual ~Context();
+ };
+} \ No newline at end of file
diff --git a/src/dx/context/Device.h b/src/dx/context/Device.h
new file mode 100644
index 0000000..c3685a9
--- /dev/null
+++ b/src/dx/context/Device.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "Context.h"
+
+#include <d3d11.h>
+#include <d3d11_1.h>
+
+#if ENABLE_D3D12
+#include <d3d12.h>
+#endif
+
+#include <external/nvapi/include/nvapi.h>
+
+#include <dxgi.h>
+#include <string>
+#include <vector>
+
+#define ENABLE_LIVE_DEVICE_OBJECTS_REPORTING 0 // Provides detailed report of D3D object reference counts
+#define USE_NVAPI_DEVICE 0 // Enable this for D3D11 SCG
+
+struct FlexDeviceDesc
+{
+ FlexDeviceDesc() : mDeviceNumber(-1), mDevice(nullptr), mCommandQueue(nullptr), useComputeQueue(false), enablePresent(false) {}
+ virtual ~FlexDeviceDesc() {}
+ unsigned int mDeviceNumber; //!< Compute device number
+ void * mDevice; //!< pointer to existing device
+ void * mCommandQueue; //!< pointer to existing command queue for DX12
+ bool useComputeQueue; //!< Use the compute queue instead of the graphics queue for DX12
+ bool enablePresent; //!< Present after each frame to that APIC and PB dump work
+};
+
+namespace NvFlex
+{
+
+ struct Device : public NvFlexObject
+ {
+ Device();
+ virtual ~Device();
+
+ virtual Context* createContext() = 0;
+
+ virtual NvAPI_Status NvAPI_IsNvShaderExtnOpCodeSupported(NvU32 opCode, bool * pSupported) = 0;
+
+#if ENABLE_AMD_AGS
+ virtual AGSReturnCode AGS_DriverExtensions_Init(AGSContext* agsContext, unsigned int agsApiSlot, unsigned int *extensionsSupported) = 0;
+ virtual void AGS_DeInit(AGSContext* agsContext) = 0;
+#endif
+
+ virtual DXGI_ADAPTER_DESC1 getDXGIAdapter(void* d3ddevice, int & deviceNumber) = 0;
+ virtual DXGI_ADAPTER_DESC1 getDeviceNumber(const LUID adapterID, int & deviceNumber);
+ virtual std::vector<IDXGIAdapter1 *> enumerateDXGIAdapters();
+ virtual void queryDeviceCapabilities(void* d3ddevice);
+
+ virtual void reportLiveDeviceObjects() {}
+
+//#if APIC_CAPTURE
+ virtual void createWindow();
+ virtual void present() = 0;
+
+ WNDCLASSEX mWindowDesc;
+ RECT mWinRect;
+ HWND m_hWnd;
+ IDXGISwapChain* m_swapChain;
+//#endif
+
+ IDXGIFactory1* m_pFactory;
+
+ NvFlexUint mSMCount;
+ std::string mDeviceName;
+ // Gpu Vendor Id
+ GpuVendorId mGpuVendorId;
+ bool mD3D12Device;
+ Context* m_context;
+ };
+}
diff --git a/src/dx/context/Format.h b/src/dx/context/Format.h
new file mode 100644
index 0000000..389b3a8
--- /dev/null
+++ b/src/dx/context/Format.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, related documentation
+ * and any modifications thereto. Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
+ */
+
+#pragma once
+
+#include "NvFlexTypes.h"
+
+namespace NvFlex
+{
+ DXGI_FORMAT convertToDXGI(NvFlexFormat format);
+
+ NvFlexFormat convertToNvFlex(DXGI_FORMAT format);
+
+ NvFlexUint getFormatSizeInBytes(NvFlexFormat format);
+} \ No newline at end of file
diff --git a/src/dx/context/NvFlexTypes.h b/src/dx/context/NvFlexTypes.h
new file mode 100644
index 0000000..46e8269
--- /dev/null
+++ b/src/dx/context/NvFlexTypes.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, related documentation
+ * and any modifications thereto. Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
+ */
+
+#pragma once
+
+
+enum NvFlexResult
+{
+ eNvFlexSuccess = 0,
+ eNvFlexFail = 1
+};
+
+typedef int NvFlexInt;
+typedef unsigned int NvFlexUint;
+typedef unsigned long long NvFlexUint64;
+
+struct NvFlexDim
+{
+ NvFlexUint x, y, z;
+};
+
+struct NvFlexUint3
+{
+ NvFlexUint x, y, z;
+};
+
+struct NvFlexUint4
+{
+ NvFlexUint x, y, z, w;
+};
+
+struct NvFlexFloat3
+{
+ float x, y, z;
+};
+
+struct NvFlexFloat4
+{
+ float x, y, z, w;
+};
+
+struct NvFlexFloat4x4
+{
+ NvFlexFloat4 x, y, z, w;
+};
+
+enum NvFlexFormat
+{
+ eNvFlexFormat_unknown = 0,
+
+ eNvFlexFormat_r32_typeless = 1,
+
+ eNvFlexFormat_r32_float = 2,
+ eNvFlexFormat_r32g32_float = 3,
+ eNvFlexFormat_r32g32b32a32_float = 4,
+
+ eNvFlexFormat_r16_float = 5,
+ eNvFlexFormat_r16g16_float = 6,
+ eNvFlexFormat_r16g16b16a16_float = 7,
+
+ eNvFlexFormat_r32_uint = 8,
+ eNvFlexFormat_r32g32_uint = 9,
+ eNvFlexFormat_r32g32b32a32_uint = 10,
+
+ eNvFlexFormat_r8_unorm = 11,
+ eNvFlexFormat_r8g8_unorm = 12,
+ eNvFlexFormat_r8g8b8a8_unorm = 13,
+
+ eNvFlexFormat_r16_unorm = 14,
+ eNvFlexFormat_r16g16_unorm = 15,
+ eNvFlexFormat_r16g16b16a16_unorm = 16,
+
+ eNvFlexFormat_d32_float = 17,
+ eNvFlexFormat_d24_unorm_s8_uint = 18,
+
+ eNvFlexFormat_r8_snorm = 19,
+ eNvFlexFormat_r8g8_snorm = 20,
+ eNvFlexFormat_r8g8b8a8_snorm = 21,
+
+ eNvFlexFormat_max
+}; \ No newline at end of file
diff --git a/src/dx/context/README.md b/src/dx/context/README.md
new file mode 100644
index 0000000..7b45ecd
--- /dev/null
+++ b/src/dx/context/README.md
@@ -0,0 +1,7 @@
+The interfaces in this folder define a thin wrapper around D3D11 and D3D12 APIs that
+are used internally by the Flex solver. Some parts of the Flex API (e.g.: solver callbacks)
+will return pointers to these structures.
+
+See the extensions forcefield API for an example of how these wrappers may be used to implement
+Flex solver callbacks. Note that this code should not be modified or recompiled to ensure binary
+compatibility with the main Flex libraries.
diff --git a/src/dx/context/Vector.h b/src/dx/context/Vector.h
new file mode 100644
index 0000000..780faf6
--- /dev/null
+++ b/src/dx/context/Vector.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, related documentation
+ * and any modifications thereto. Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
+ */
+
+#pragma once
+
+#include "NvFlexTypes.h"
+
+#include <new>
+
+namespace NvFlex
+{
+
+ template<class T, NvFlexUint staticCapacity>
+ struct VectorCached : public Allocable
+ {
+ static const NvFlexUint s_staticCapacity = staticCapacity;
+
+ T* m_data;
+ NvFlexUint m_capacity;
+ T m_cache[staticCapacity];
+ NvFlexUint m_size = 0u;
+
+ T* allocate(NvFlexUint capacity)
+ {
+ T* ptr = (T*)operator new[](capacity*sizeof(T));
+ for (NvFlexUint i = 0; i < capacity; i++)
+ {
+ new(ptr + i) T;
+ }
+ return ptr;
+ }
+
+ void cleanup(T* data, NvFlexUint capacity)
+ {
+ if (m_cache != data)
+ {
+ for (NvFlexUint i = 0; i < capacity; i++)
+ {
+ data[i].~T();
+ }
+ operator delete[](data);
+ }
+ }
+
+ VectorCached(NvFlexUint capacity)
+ {
+ m_capacity = capacity;
+ if (capacity > staticCapacity)
+ {
+ m_data = allocate(capacity);
+ }
+ else
+ {
+ m_data = m_cache;
+ }
+ }
+
+ ~VectorCached()
+ {
+ if (m_capacity > staticCapacity)
+ {
+ cleanup(m_data, m_capacity);
+ }
+ m_data = nullptr;
+ }
+
+ T& operator[](unsigned int idx)
+ {
+ return m_data[idx];
+ }
+
+ NvFlexUint allocateBack()
+ {
+ // resize if needed
+ if (m_size + 1 > m_capacity)
+ {
+ NvFlexUint capacity = 2 * m_capacity;
+ T* newData = allocate(capacity);
+ // copy to new
+ for (NvFlexUint i = 0; i < m_size; i++)
+ {
+ new(&newData[i]) T(m_data[i]);
+ }
+ // cleanup old
+ cleanup(m_data, m_capacity);
+ // commit new
+ m_data = newData;
+ m_capacity = capacity;
+ }
+ m_size++;
+ return m_size - 1;
+ }
+
+ void reserve(NvFlexUint capacity)
+ {
+ if (capacity > m_capacity)
+ {
+ T* newData = allocate(capacity);
+ // copy to new
+ for (NvFlexUint i = 0; i < m_size; i++)
+ {
+ new(&newData[i]) T(m_data[i]);
+ }
+ // cleanup old
+ cleanup(m_data, m_capacity);
+ // commit new
+ m_data = newData;
+ m_capacity = capacity;
+ }
+ }
+ };
+
+ template <class T>
+ struct Image3D : public Allocable
+ {
+ T* m_data = nullptr;
+ NvFlexDim m_dim = { 0u, 0u, 0u };
+ NvFlexUint m_capacity = 0u;
+
+ Image3D() {}
+
+ void init(NvFlexDim dim)
+ {
+ m_dim = dim;
+ m_capacity = m_dim.x * m_dim.y * m_dim.z;
+
+ T* ptr = (T*)operator new[](m_capacity*sizeof(T));
+ for (NvFlexUint i = 0; i < m_capacity; i++)
+ {
+ new(ptr + i) T;
+ }
+ m_data = ptr;
+ }
+
+ ~Image3D()
+ {
+ if (m_data)
+ {
+ for (NvFlexUint i = 0; i < m_capacity; i++)
+ {
+ m_data[i].~T();
+ }
+ operator delete[](m_data);
+ m_data = nullptr;
+ }
+ }
+
+ T& operator[](unsigned int idx)
+ {
+ return m_data[idx];
+ }
+
+ T& operator()(NvFlexUint i, NvFlexUint j, NvFlexUint k)
+ {
+ return m_data[(k*m_dim.y + j) * m_dim.x + i];
+ }
+ };
+
+ template <class T>
+ struct Image1D : public Allocable
+ {
+ T* m_data = nullptr;
+ NvFlexUint m_dim = 0u;
+ NvFlexUint m_capacity = 0u;
+
+ Image1D() {}
+
+ void init(NvFlexUint dim)
+ {
+ m_dim = dim;
+ m_capacity = m_dim;
+
+ T* ptr = (T*)operator new[](m_capacity*sizeof(T));
+ for (NvFlexUint i = 0; i < m_capacity; i++)
+ {
+ new(ptr + i) T;
+ }
+ m_data = ptr;
+ }
+
+ ~Image1D()
+ {
+ if (m_data)
+ {
+ for (NvFlexUint i = 0; i < m_capacity; i++)
+ {
+ m_data[i].~T();
+ }
+ operator delete[](m_data);
+ m_data = nullptr;
+ }
+ }
+
+ T& operator[](unsigned int idx)
+ {
+ return m_data[idx];
+ }
+ };
+
+} \ No newline at end of file