New here - and to DirectX 11.
I’m trying to reproduce an example from the DX11 SDK called NBodyGravityCS11. The SDK example runs fine on my hardware, now I’m just trying to figure out how to do the same through Unity 4.1.2
The only error I get is: “DestroyBuffer can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don’t use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function”
I don’t exactly understand this error. However, I’m not sure this is the main issue either, since I already had this error in a DX11/Unity project that worked just fine.
What I get when I play the scene, appears to be all particles located at the center of the screen, but no movement whatsoever.
If there is any kind soul out there, who has the time to take a look at the code and know how to get it running properly, I’d very much appreciate any help. Thank you.
Script attached to camera:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public class GPUParticles : MonoBehaviour {
struct PosVelo
{
public Vector3 position;
public Vector3 velocity;
};
public int size = 1024;
public ComputeShader computeShader;
public float damping = 0.999f;
public Material material;
private ComputeBuffer oldPosVelo;
private ComputeBuffer newPosVelo;
private int blockSize = 128; // threads per block, should be multiple of 32 (warp size)
private int posVeloSizeOf;
private int dimx;
// Use this for initialization
void Start () {
PosVelo pv = new PosVelo();
posVeloSizeOf = Marshal.SizeOf(pv);
// create compute buffers
oldPosVelo = new ComputeBuffer(size, posVeloSizeOf);
newPosVelo = new ComputeBuffer(size, posVeloSizeOf);
PosVelo[] pvInitBuffer = new PosVelo;
for (int i = 0; i < size; i++)
{
pv = new PosVelo();
pv.position = Random.insideUnitSphere * 5;
pv.velocity = Random.insideUnitSphere;
pvInitBuffer *= pv;*
}
oldPosVelo.SetData(pvInitBuffer);
newPosVelo.SetData(pvInitBuffer);
-
}*
-
// Update is called once per frame*
-
void Update () {*
dimx = (size + (blockSize - 1)) / blockSize;
-
if (computeShader) {* -
// run compute shader*
computeShader.SetBuffer(0, “oldPosVelo”, oldPosVelo);
computeShader.SetBuffer(0, “newPosVelo”, newPosVelo);
-
computeShader.SetFloat("dt", Time.deltaTime);* -
computeShader.SetFloat("damping", damping);* -
computeShader.SetInts("numParticles", size);*
computeShader.SetInts(“dimx”, dimx);
computeShader.Dispatch(0, dimx, 1, 1);
-
}* -
}*
-
// called if script attached to the camera, after all regular rendering is done*
-
void OnPostRender () {*
-
if (material) {*
material.SetBuffer(“oldPosVelo”, oldPosVelo);
material.SetBuffer(“newPosVelo”, newPosVelo);
-
material.SetPass (0);* -
Graphics.DrawProcedural (MeshTopology.Points, size, 1);* -
}* - }*
void OnDisable()
{
//oldPosVelo.Release();
//newPosVelo.Release();
}
}
ComputeShader:
#pragma kernel CSUpdate
struct PosVelo
{
float3 position;
float3 velocity;
};
RWStructuredBuffer oldPosVelo;
RWStructuredBuffer newPosVelo;
float dt;
float damping;
uint numParticles;
uint dimx;
static float softeningSquared = 0.0012500000*0.0012500000;
static float fG = 6.67300e-11f * 10000.0f;
static float fParticleMass = fG*10000.0f * 10000.0f;
#define blockSize 128
groupshared float3 sharedPos[blockSize];
// Body to body interaction, acceleration of the particle at position bi is updated
void bodyBodyInteraction(inout float3 ai, float3 bj, float3 bi, float mass, int particles )
{
float3 r = bj.xyz - bi.xyz;
float distSqr = dot(r, r);
distSqr += softeningSquared;
float invDist = 1.0f / sqrt(distSqr);
_ float invDistCube = invDist * invDist * invDist;_
float s = mass * invDistCube * particles;
ai += r * s;
}
[numthreads(blockSize,1,1)]
void CSUpdate( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
// Each thread of the CS updates one of the particles
float3 pos = oldPosVelo[DTid.x].position;
float3 vel = oldPosVelo[DTid.x].velocity;
float3 accel = 0;
float mass = fParticleMass;
// Update current particle using all other particles
[loop]
for (uint tile = 0; tile < dimx; tile++)
{
// Cache a tile of particles unto shared memory to increase IO efficiency
sharedPos[GI] = oldPosVelo[tile * blockSize + GI].position;
GroupMemoryBarrierWithGroupSync();
[unroll]
for (uint counter = 0; counter < blockSize; counter+=8 )
{
bodyBodyInteraction(accel, sharedPos[counter], pos, mass, 1);
bodyBodyInteraction(accel, sharedPos[counter+1], pos, mass, 1);
bodyBodyInteraction(accel, sharedPos[counter+2], pos, mass, 1);
bodyBodyInteraction(accel, sharedPos[counter+3], pos, mass, 1);
bodyBodyInteraction(accel, sharedPos[counter+4], pos, mass, 1);
bodyBodyInteraction(accel, sharedPos[counter+5], pos, mass, 1);
bodyBodyInteraction(accel, sharedPos[counter+6], pos, mass, 1);
bodyBodyInteraction(accel, sharedPos[counter+7], pos, mass, 1);
}
GroupMemoryBarrierWithGroupSync();
}
// numParticles is the number of our particles, however this number might not be an exact multiple of the tile size.
// In such cases, out of bound reads occur in the process above, which means there will be
// tooManyParticles “phantom” particles generating false gravity at position (0, 0, 0), so we have to substract them here.
// NOTE, out of bound reads always return 0 in CS
const uint tooManyParticles = dimx * blockSize - numParticles;
bodyBodyInteraction(accel, float3(0, 0, 0), pos, mass, -tooManyParticles);
// Update the velocity and position of current particle using the acceleration computed above
vel.xyz += accel.xyz * dt; //deltaTime;
vel.xyz *= damping; //damping;
pos.xyz += vel.xyz * dt; //deltaTime;
if ( DTid.x < numParticles )
{
newPosVelo[DTid.x].position = pos;
newPosVelo[DTid.x].velocity = vel;
}
}
I just wanted to say that I'm getting "DestroyBuffer can only be called from the main thread." as well. I'm doing a bunch of compute work for texture generation in the editor, and I'm doing 'using(new ComputeBuffer())' to dispose of the buffers.
– CorngoodTurns out I was missing a couple of diposes (facepalm). No more errors now.
– Corngood