|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "core/core.h" |
|
|
#include "core/maths.h" |
|
|
|
|
|
#include "include/NvFlex.h" |
|
|
#include "include/NvFlexExt.h" |
|
|
|
|
|
#include "src/dx/context/context.h" |
|
|
#include "src/dx/context/device.h" |
|
|
|
|
|
#include "flexExt_dx_common.h" |
|
|
|
|
|
#include "shaders\flexExt.UpdateForceFields.h" |
|
|
|
|
|
|
|
|
struct NvFlexExtForceFieldCallback |
|
|
{ |
|
|
NvFlexExtForceFieldCallback(NvFlexSolver* solver) : mSolver(solver) |
|
|
{ |
|
|
|
|
|
mMaxForceFields = 0; |
|
|
mNumForceFields = 0; |
|
|
|
|
|
mForceFieldsGpu = NULL; |
|
|
|
|
|
mDevice = NULL; |
|
|
mContext = NULL; |
|
|
|
|
|
NvFlexLibrary* lib = NvFlexGetSolverLibrary(solver); |
|
|
NvFlexGetDeviceAndContext(lib, (void**)&mDevice, (void**)&mContext); |
|
|
|
|
|
{ |
|
|
|
|
|
NvFlex::ComputeShaderDesc desc{}; |
|
|
desc.cs = (void*)g_flexExt_UpdateForceFields; |
|
|
desc.cs_length = sizeof(g_flexExt_UpdateForceFields); |
|
|
desc.label = L"NvFlexExtForceFieldCallback"; |
|
|
desc.NvAPI_Slot = 0; |
|
|
|
|
|
mShaderUpdateForceFields = mContext->createComputeShader(&desc); |
|
|
} |
|
|
|
|
|
{ |
|
|
|
|
|
NvFlex::ConstantBufferDesc desc; |
|
|
desc.stride = sizeof(int); |
|
|
desc.dim = 4; |
|
|
desc.uploadAccess = true; |
|
|
|
|
|
mConstantBuffer = mContext->createConstantBuffer(&desc); |
|
|
} |
|
|
} |
|
|
|
|
|
~NvFlexExtForceFieldCallback() |
|
|
{ |
|
|
|
|
|
delete mForceFieldsGpu; |
|
|
delete mConstantBuffer; |
|
|
delete mShaderUpdateForceFields; |
|
|
} |
|
|
|
|
|
NvFlex::Buffer* mForceFieldsGpu; |
|
|
|
|
|
|
|
|
NvFlex::ComputeShader* mShaderUpdateForceFields; |
|
|
NvFlex::ConstantBuffer* mConstantBuffer; |
|
|
|
|
|
int mMaxForceFields; |
|
|
int mNumForceFields; |
|
|
|
|
|
|
|
|
NvFlex::Device* mDevice; |
|
|
NvFlex::Context* mContext; |
|
|
|
|
|
NvFlexSolver* mSolver; |
|
|
|
|
|
}; |
|
|
|
|
|
NvFlexExtForceFieldCallback* NvFlexExtCreateForceFieldCallback(NvFlexSolver* solver) |
|
|
{ |
|
|
return new NvFlexExtForceFieldCallback(solver); |
|
|
} |
|
|
|
|
|
void NvFlexExtDestroyForceFieldCallback(NvFlexExtForceFieldCallback* callback) |
|
|
{ |
|
|
delete callback; |
|
|
} |
|
|
|
|
|
void ApplyForceFieldsCallback(NvFlexSolverCallbackParams params) |
|
|
{ |
|
|
|
|
|
|
|
|
NvFlexExtForceFieldCallback* c = (NvFlexExtForceFieldCallback*)params.userData; |
|
|
|
|
|
if (params.numActive && c->mNumForceFields) |
|
|
{ |
|
|
const unsigned int numThreadsPerBlock = 256; |
|
|
const unsigned int kNumBlocks = (params.numActive + numThreadsPerBlock - 1) / numThreadsPerBlock; |
|
|
|
|
|
NvFlex::Buffer* particles = (NvFlex::Buffer*)params.particles; |
|
|
NvFlex::Buffer* velocities = (NvFlex::Buffer*)params.velocities; |
|
|
|
|
|
|
|
|
{ |
|
|
FlexExtConstParams constBuffer; |
|
|
|
|
|
constBuffer.kNumParticles = params.numActive; |
|
|
constBuffer.kNumForceFields = c->mNumForceFields; |
|
|
constBuffer.kDt = params.dt; |
|
|
|
|
|
memcpy(c->mContext->map(c->mConstantBuffer), &constBuffer, sizeof(FlexExtConstParams)); |
|
|
c->mContext->unmap(c->mConstantBuffer); |
|
|
} |
|
|
|
|
|
{ |
|
|
NvFlex::DispatchParams params = {}; |
|
|
params.shader = c->mShaderUpdateForceFields; |
|
|
params.readWrite[0] = velocities->getResourceRW(); |
|
|
params.readOnly[0] = particles->getResource(); |
|
|
params.readOnly[1] = c->mForceFieldsGpu->getResource(); |
|
|
params.gridDim = { kNumBlocks , 1, 1 }; |
|
|
params.rootConstantBuffer = c->mConstantBuffer; |
|
|
|
|
|
c->mContext->dispatch(¶ms); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
void NvFlexExtSetForceFields(NvFlexExtForceFieldCallback* c, const NvFlexExtForceField* forceFields, int numForceFields) |
|
|
{ |
|
|
|
|
|
if (numForceFields > c->mMaxForceFields) |
|
|
{ |
|
|
delete c->mForceFieldsGpu; |
|
|
|
|
|
NvFlex::BufferDesc desc {}; |
|
|
desc.dim = numForceFields; |
|
|
desc.stride = sizeof(NvFlexExtForceField); |
|
|
desc.bufferType = NvFlex::eBuffer | NvFlex::eUAV_SRV | NvFlex::eStructured | NvFlex::eStage; |
|
|
desc.format = NvFlexFormat::eNvFlexFormat_unknown; |
|
|
desc.data = NULL; |
|
|
|
|
|
c->mForceFieldsGpu = c->mContext->createBuffer(&desc); |
|
|
|
|
|
c->mMaxForceFields = numForceFields; |
|
|
} |
|
|
c->mNumForceFields = numForceFields; |
|
|
|
|
|
if (numForceFields > 0) |
|
|
{ |
|
|
|
|
|
void* dstPtr = c->mContext->map(c->mForceFieldsGpu, NvFlex::eMapWrite); |
|
|
memcpy(dstPtr, forceFields, numForceFields*sizeof(NvFlexExtForceField)); |
|
|
c->mContext->unmap(c->mForceFieldsGpu); |
|
|
|
|
|
|
|
|
c->mContext->upload(c->mForceFieldsGpu, 0, numForceFields*sizeof(NvFlexExtForceField)); |
|
|
|
|
|
} |
|
|
|
|
|
NvFlexSolverCallback callback; |
|
|
callback.function = ApplyForceFieldsCallback; |
|
|
callback.userData = c; |
|
|
|
|
|
|
|
|
NvFlexRegisterSolverCallback(c->mSolver, callback, eNvFlexStageUpdateEnd); |
|
|
} |
|
|
|