particle simulation fixes, editor updates

This commit is contained in:
turanszkij
2017-10-31 17:14:05 +00:00
parent 8c099e3c76
commit 87442b0fcb
15 changed files with 283 additions and 190 deletions
+2
View File
@@ -1309,6 +1309,8 @@ void EditorComponent::Update(float dt)
SAFE_DELETE(history);
}
emitterWnd->UpdateData();
__super::Update(dt);
renderPath->Update(dt);
+59 -10
View File
@@ -54,11 +54,6 @@ EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui)
if (emitter != nullptr)
{
emitter->SetMaxParticleCount((uint32_t)args.iValue);
stringstream ss("");
ss.precision(2);
ss << "Memort Budget: " << emitter->GetMemorySizeInBytes() / 1024.0f / 1024.0f << " MB";
memoryBudgetLabel->SetText(ss.str());
}
});
maxParticlesSlider->SetEnabled(false);
@@ -195,6 +190,29 @@ EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui)
emitMotionBlurSlider->SetTooltip("Set the motion blur amount for the particle system.");
emitterWindow->AddWidget(emitMotionBlurSlider);
y += 30;
//////////////////////////////////////////////////////////////////////////////////////////////////
debugCheckBox = new wiCheckBox("DEBUG: ");
debugCheckBox->SetPos(XMFLOAT2(x, y += step));
debugCheckBox->OnClick([&](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->DEBUG = args.bValue;
}
});
debugCheckBox->SetCheck(false);
debugCheckBox->SetTooltip("Enable debug info for the emitter. This involves reading back GPU data, so rendering can slow down.");
emitterWindow->AddWidget(debugCheckBox);
debugDataLabel = new wiLabel("EmitterDebugDataLabel");
debugDataLabel->SetText("Enable DEBUG to view debugging data");
debugDataLabel->SetSize(XMFLOAT2(300, 100));
debugDataLabel->SetPos(XMFLOAT2(x + step, y));
emitterWindow->AddWidget(debugDataLabel);
emitterWindow->Translate(XMFLOAT3(200, 50, 0));
emitterWindow->SetVisible(false);
@@ -212,6 +230,12 @@ EmitterWindow::~EmitterWindow()
void EmitterWindow::SetObject(Object* obj)
{
// first try to turn off any debug readbacks for emitters:
if (GetEmitter() != nullptr)
{
GetEmitter()->DEBUG = false;
}
object = obj;
emitterComboBox->ClearItems();
@@ -229,11 +253,6 @@ void EmitterWindow::SetObject(Object* obj)
{
maxParticlesSlider->SetValue((float)emitter->GetMaxParticleCount());
stringstream ss("");
ss.precision(2);
ss << "Memort Budget: " << emitter->GetMemorySizeInBytes() / 1024.0f / 1024.0f << " MB";
memoryBudgetLabel->SetText(ss.str());
emitCountSlider->SetValue(emitter->count);
emitSizeSlider->SetValue(emitter->size);
emitRotationSlider->SetValue(emitter->rotation);
@@ -277,3 +296,33 @@ wiEmittedParticle* EmitterWindow::GetEmitter()
return nullptr;
}
void EmitterWindow::UpdateData()
{
auto emitter = GetEmitter();
if (emitter == nullptr)
{
return;
}
if (emitter->DEBUG)
{
auto data = emitter->GetDebugData();
stringstream ss("");
ss << "Alive Particle Count [CURRENT] = " << data.aliveCount_CURRENT << endl;
ss << "Alive Particle Count [NEW] = " << data.aliveCount_NEW << endl;
ss << "Dead Particle Count = " << data.deadCount << endl;
ss << "GPU Emit count = " << data.realEmitCount << endl;
debugDataLabel->SetText(ss.str());
}
else
{
debugDataLabel->SetText("Enable DEBUG to view debugging data");
}
stringstream ss("");
ss.precision(2);
ss << "Memort Budget: " << emitter->GetMemorySizeInBytes() / 1024.0f / 1024.0f << " MB";
memoryBudgetLabel->SetText(ss.str());
}
+4
View File
@@ -18,6 +18,7 @@ public:
~EmitterWindow();
void SetObject(Object* obj);
void UpdateData();
Object* object;
wiEmittedParticle* GetEmitter();
@@ -38,5 +39,8 @@ public:
wiSlider* emitRandomnessSlider;
wiSlider* emitLifeRandomnessSlider;
wiSlider* emitMotionBlurSlider;
wiCheckBox* debugCheckBox;
wiLabel* debugDataLabel;
};
+1
View File
@@ -1,5 +1,6 @@
This file contains changelog of wiArchive versions
11: serialize additional emitter properties
10: serialize force fields
9: refactored emitter particle system
8: refactored vertex wind weight
@@ -17,6 +17,13 @@ struct Particle
float2 mirror;
};
struct ParticleCounters
{
uint aliveCount_CURRENT;
uint deadCount;
uint aliveCount_NEW;
uint realEmitCount;
};
CBUFFER(EmittedParticleCB, CBSLOT_OTHER_EMITTEDPARTICLE)
{
+3 -5
View File
@@ -1,18 +1,16 @@
#include "globals.hlsli"
#include "ShaderInterop_EmittedParticle.h"
RWSTRUCTUREDBUFFER(counterBuffer, uint4, 4); // alive count, dead count, new alive count
RWRAWBUFFER(indirectDrawBuffer, 6); // indirectdrawinstanced args
RWSTRUCTUREDBUFFER(counterBuffer, ParticleCounters, 4);
RWRAWBUFFER(indirectDrawBuffer, 5); // indirectdrawinstanced args
[numthreads(1, 1, 1)]
void main(uint3 DTid : SV_DispatchThreadID)
{
uint aliveCount_NEW = counterBuffer[0][2];
// Fill Draw arguments for drawing:
// VertexCountPerInstance;
// InstanceCount;
// StartVertexLocation;
// StartInstanceLocation;
indirectDrawBuffer.Store4(0, uint4(aliveCount_NEW * 6, 1, 0, 0));
indirectDrawBuffer.Store4(24, uint4(counterBuffer[0].aliveCount_NEW * 6, 1, 0, 0));
}
+4 -4
View File
@@ -5,7 +5,7 @@ RWSTRUCTUREDBUFFER(particleBuffer, Particle, 0);
RWSTRUCTUREDBUFFER(aliveBuffer_OLD, uint, 1);
RWSTRUCTUREDBUFFER(aliveBuffer_NEW, uint, 2);
RWSTRUCTUREDBUFFER(deadBuffer, uint, 3);
RWSTRUCTUREDBUFFER(counterBuffer, uint4, 4);
RWSTRUCTUREDBUFFER(counterBuffer, ParticleCounters, 4);
TEXTURE2D(randomTex, float4, TEXSLOT_ONDEMAND0);
TYPEDBUFFER(meshIndexBuffer, uint, TEXSLOT_ONDEMAND1);
@@ -16,7 +16,7 @@ RAWBUFFER(meshVertexBuffer_NOR, TEXSLOT_ONDEMAND3);
[numthreads(THREADCOUNT_EMIT, 1, 1)]
void main(uint3 DTid : SV_DispatchThreadID)
{
uint emitCount = counterBuffer[0][3];
uint emitCount = counterBuffer[0].realEmitCount;
if(DTid.x < emitCount)
{
@@ -92,7 +92,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
// new particle index retrieved from dead list (pop):
uint deadCount;
InterlockedAdd(counterBuffer[0][1], -1, deadCount);
InterlockedAdd(counterBuffer[0].deadCount, -1, deadCount);
uint newParticleIndex = deadBuffer[deadCount - 1];
// write out the new particle:
@@ -100,7 +100,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
// and add index to the alive list (push):
uint aliveCount_OLD;
InterlockedAdd(counterBuffer[0][0], 1, aliveCount_OLD);
InterlockedAdd(counterBuffer[0].aliveCount_CURRENT, 1, aliveCount_OLD);
aliveBuffer_OLD[aliveCount_OLD] = newParticleIndex;
}
}
@@ -1,13 +1,13 @@
#include "globals.hlsli"
#include "ShaderInterop_EmittedParticle.h"
RWSTRUCTUREDBUFFER(counterBuffer, uint4, 4); // alive count, dead count, new alive count, realEmitCount
RWSTRUCTUREDBUFFER(counterBuffer, ParticleCounters, 4);
RWRAWBUFFER(indirectDispatchBuffer, 5); // indirect kickoff args
[numthreads(1, 1, 1)]
void main(uint3 DTid : SV_DispatchThreadID)
{
uint deadCount = counterBuffer[0][1];
uint deadCount = counterBuffer[0].deadCount;
// we can not emit more than there are free slots in the dead list:
uint realEmitCount = min(deadCount, xEmitCount);
@@ -15,12 +15,12 @@ void main(uint3 DTid : SV_DispatchThreadID)
// Fill dispatch argument buffer for simulation:
indirectDispatchBuffer.Store3(0, uint3(ceil((float)realEmitCount / (float)THREADCOUNT_EMIT), 1, 1));
// copy new alivelistcount to oldalivelistcount:
counterBuffer[0][0] = counterBuffer[0][2];
// copy new alivelistcount to current alivelistcount:
counterBuffer[0].aliveCount_CURRENT = counterBuffer[0].aliveCount_NEW;
// also reset the new alive list count:
counterBuffer[0][2] = 0;
counterBuffer[0].aliveCount_NEW = 0;
// and write real emit count:
counterBuffer[0][3] = realEmitCount;
counterBuffer[0].realEmitCount = realEmitCount;
}
+4 -4
View File
@@ -5,7 +5,7 @@ RWSTRUCTUREDBUFFER(particleBuffer, Particle, 0);
RWSTRUCTUREDBUFFER(aliveBuffer_OLD, uint, 1);
RWSTRUCTUREDBUFFER(aliveBuffer_NEW, uint, 2);
RWSTRUCTUREDBUFFER(deadBuffer, uint, 3);
RWSTRUCTUREDBUFFER(counterBuffer, uint4, 4);
RWSTRUCTUREDBUFFER(counterBuffer, ParticleCounters, 4);
#define NUM_LDS_FORCEFIELDS 32
struct LDS_ForceField
@@ -26,7 +26,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex)
// Read alive particle count and store in LDS:
if (Gid == 0)
{
aliveParticleCount = counterBuffer[0][0];
aliveParticleCount = counterBuffer[0].aliveCount_CURRENT;
}
// Load the forcefields into LDS:
@@ -91,14 +91,14 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex)
// add to new alive list:
uint newAliveIndex;
InterlockedAdd(counterBuffer[0][2], 1, newAliveIndex);
InterlockedAdd(counterBuffer[0].aliveCount_NEW, 1, newAliveIndex);
aliveBuffer_NEW[newAliveIndex] = particleIndex;
}
else
{
// kill:
uint deadIndex;
InterlockedAdd(counterBuffer[0][1], 1, deadIndex);
InterlockedAdd(counterBuffer[0].deadCount, 1, deadIndex);
deadBuffer[deadIndex] = particleIndex;
}
}
@@ -1,14 +1,12 @@
#include "globals.hlsli"
#include "ShaderInterop_EmittedParticle.h"
RWSTRUCTUREDBUFFER(counterBuffer, uint4, 4); // alive count, dead count, new alive count, realEmitCount
RWRAWBUFFER(indirectDispatchBuffer, 5); // indirectdispatch args
RWSTRUCTUREDBUFFER(counterBuffer, ParticleCounters, 4);
RWRAWBUFFER(indirectDispatchBuffer, 5); // indirect simulation args
[numthreads(1, 1, 1)]
void main( uint3 DTid : SV_DispatchThreadID )
{
uint aliveCount_OLD = counterBuffer[0][0];
// Fill dispatch argument buffer for simulation:
indirectDispatchBuffer.Store3(0, uint3(ceil((float)aliveCount_OLD / (float)THREADCOUNT_SIMULATION), 1, 1));
indirectDispatchBuffer.Store3(12, uint3(ceil((float)counterBuffer[0].aliveCount_CURRENT / (float)THREADCOUNT_SIMULATION), 1, 1));
}
+1 -1
View File
@@ -7,7 +7,7 @@
using namespace std;
// this should always be only INCREMENTED and only if a new serialization is implemeted somewhere!
uint64_t __archiveVersion = 10;
uint64_t __archiveVersion = 11;
// this is the version number of which below the archive is not compatible with the current version
uint64_t __archiveVersionBarrier = 1;
+63 -32
View File
@@ -50,9 +50,9 @@ wiEmittedParticle::wiEmittedParticle()
SAFE_INIT(aliveList[1]);
SAFE_INIT(deadList);
SAFE_INIT(counterBuffer);
SAFE_INIT(indirectDispatchBuffer);
SAFE_INIT(indirectDrawBuffer);
SAFE_INIT(indirectBuffers);
SAFE_INIT(constantBuffer);
SAFE_INIT(debugDataReadbackBuffer);
SetMaxParticleCount(10000);
}
@@ -91,9 +91,9 @@ wiEmittedParticle::wiEmittedParticle(const std::string& newName, const std::stri
SAFE_INIT(aliveList[1]);
SAFE_INIT(deadList);
SAFE_INIT(counterBuffer);
SAFE_INIT(indirectDispatchBuffer);
SAFE_INIT(indirectDrawBuffer);
SAFE_INIT(indirectBuffers);
SAFE_INIT(constantBuffer);
SAFE_INIT(debugDataReadbackBuffer);
SetMaxParticleCount(10000);
}
@@ -121,38 +121,44 @@ wiEmittedParticle::wiEmittedParticle(const wiEmittedParticle& other)
SAFE_INIT(aliveList[1]);
SAFE_INIT(deadList);
SAFE_INIT(counterBuffer);
SAFE_INIT(indirectDispatchBuffer);
SAFE_INIT(indirectDrawBuffer);
SAFE_INIT(indirectBuffers);
SAFE_INIT(constantBuffer);
SAFE_INIT(debugDataReadbackBuffer);
SetMaxParticleCount(other.GetMaxParticleCount());
}
void wiEmittedParticle::SetMaxParticleCount(uint32_t value)
{
buffersUpToDate = false;
MAX_PARTICLES = value;
CreateSelfBuffers();
}
void wiEmittedParticle::CreateSelfBuffers()
{
if (buffersUpToDate)
{
return;
}
buffersUpToDate = true;
SAFE_DELETE(particleBuffer);
SAFE_DELETE(aliveList[0]);
SAFE_DELETE(aliveList[1]);
SAFE_DELETE(deadList);
SAFE_DELETE(counterBuffer);
SAFE_DELETE(indirectDispatchBuffer);
SAFE_DELETE(indirectDrawBuffer);
SAFE_DELETE(indirectBuffers);
SAFE_DELETE(constantBuffer);
SAFE_DELETE(debugDataReadbackBuffer);
particleBuffer = new GPUBuffer;
aliveList[0] = new GPUBuffer;
aliveList[1] = new GPUBuffer;
deadList = new GPUBuffer;
counterBuffer = new GPUBuffer;
indirectDispatchBuffer = new GPUBuffer;
indirectDrawBuffer = new GPUBuffer;
indirectBuffers = new GPUBuffer;
constantBuffer = new GPUBuffer;
debugDataReadbackBuffer = new GPUBuffer;
GPUBufferDesc bd;
bd.Usage = USAGE_DEFAULT;
@@ -182,8 +188,13 @@ void wiEmittedParticle::CreateSelfBuffers()
data.pSysMem = nullptr;
uint32_t counters[] = { 0, MAX_PARTICLES, 0, 0 }; // aliveCount, deadCount, newAliveCount, realEmitCount
data.pSysMem = counters;
ParticleCounters counters;
counters.aliveCount_CURRENT = 0;
counters.deadCount = MAX_PARTICLES;
counters.aliveCount_NEW = 0;
counters.realEmitCount = 0;
data.pSysMem = &counters;
bd.ByteWidth = sizeof(counters);
bd.StructureByteStride = sizeof(counters);
wiRenderer::GetDevice()->CreateBuffer(&bd, &data, counterBuffer);
@@ -192,10 +203,8 @@ void wiEmittedParticle::CreateSelfBuffers()
bd.BindFlags = BIND_UNORDERED_ACCESS;
bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS | RESOURCE_MISC_DRAWINDIRECT_ARGS;
bd.ByteWidth = sizeof(wiGraphicsTypes::IndirectDrawArgsInstanced);
wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, indirectDrawBuffer);
bd.ByteWidth = sizeof(wiGraphicsTypes::IndirectDispatchArgs);
wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, indirectDispatchBuffer);
bd.ByteWidth = sizeof(wiGraphicsTypes::IndirectDispatchArgs) + sizeof(wiGraphicsTypes::IndirectDispatchArgs) + sizeof(wiGraphicsTypes::IndirectDrawArgsInstanced);
wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, indirectBuffers);
bd.Usage = USAGE_DYNAMIC;
@@ -204,6 +213,14 @@ void wiEmittedParticle::CreateSelfBuffers()
bd.CPUAccessFlags = CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, constantBuffer);
{
GPUBufferDesc debugBufDesc = counterBuffer->GetDesc();
debugBufDesc.Usage = USAGE_STAGING;
debugBufDesc.CPUAccessFlags = CPU_ACCESS_READ;
debugBufDesc.BindFlags = 0;
wiRenderer::GetDevice()->CreateBuffer(&debugBufDesc, nullptr, debugDataReadbackBuffer);
}
}
uint32_t wiEmittedParticle::GetMemorySizeInBytes() const
@@ -215,8 +232,7 @@ uint32_t wiEmittedParticle::GetMemorySizeInBytes() const
retVal += aliveList[1]->GetDesc().ByteWidth;
retVal += deadList->GetDesc().ByteWidth;
retVal += counterBuffer->GetDesc().ByteWidth;
retVal += indirectDispatchBuffer->GetDesc().ByteWidth;
retVal += indirectDrawBuffer->GetDesc().ByteWidth;
retVal += indirectBuffers->GetDesc().ByteWidth;
retVal += constantBuffer->GetDesc().ByteWidth;
return retVal;
@@ -240,6 +256,8 @@ void wiEmittedParticle::Burst(float num)
void wiEmittedParticle::UpdateRenderData(GRAPHICSTHREAD threadID)
{
CreateSelfBuffers();
GraphicsDevice* device = wiRenderer::GetDevice();
device->EventBegin("UpdateEmittedParticles", threadID);
@@ -265,12 +283,11 @@ void wiEmittedParticle::UpdateRenderData(GRAPHICSTHREAD threadID)
const GPUUnorderedResource* uavs[] = {
static_cast<GPUUnorderedResource*>(particleBuffer),
static_cast<GPUUnorderedResource*>(aliveList[0]), // last alivelist
static_cast<GPUUnorderedResource*>(aliveList[1]), // new alivelist
static_cast<GPUUnorderedResource*>(aliveList[0]), // CURRENT alivelist
static_cast<GPUUnorderedResource*>(aliveList[1]), // NEW alivelist
static_cast<GPUUnorderedResource*>(deadList),
static_cast<GPUUnorderedResource*>(counterBuffer),
static_cast<GPUUnorderedResource*>(indirectDispatchBuffer),
static_cast<GPUUnorderedResource*>(indirectDrawBuffer),
static_cast<GPUUnorderedResource*>(indirectBuffers),
};
device->BindUnorderedAccessResourcesCS(uavs, 0, ARRAYSIZE(uavs), threadID);
@@ -289,15 +306,15 @@ void wiEmittedParticle::UpdateRenderData(GRAPHICSTHREAD threadID)
// emit the required amount if there are free slots in dead list
device->BindCS(emitCS, threadID);
device->DispatchIndirect(indirectDispatchBuffer, 0, threadID);
device->DispatchIndirect(indirectBuffers, 0, threadID);
// kick off simulation based on OLD alivelist count
// kick off simulation based on CURRENT alivelist count
device->BindCS(simulateargsCS, threadID);
device->Dispatch(1, 1, 1, threadID);
// update OLD alive list, write NEW alive list
// update CURRENT alive list, write NEW alive list
device->BindCS(simulateCS, threadID);
device->DispatchIndirect(indirectDispatchBuffer, 0, threadID);
device->DispatchIndirect(indirectBuffers, sizeof(wiGraphicsTypes::IndirectDispatchArgs), threadID);
// update the draw arguments
device->BindCS(drawargsCS, threadID);
@@ -310,9 +327,14 @@ void wiEmittedParticle::UpdateRenderData(GRAPHICSTHREAD threadID)
device->EventEnd(threadID);
// Swap OLD alivelist with NEW alivelist
// Swap CURRENT alivelist with NEW alivelist
SwapPtr(aliveList[0], aliveList[1]);
emit -= (UINT)emit;
if (DEBUG)
{
device->DownloadBuffer(counterBuffer, debugDataReadbackBuffer, &debugData, threadID, false);
}
}
void wiEmittedParticle::Draw(GRAPHICSTHREAD threadID)
@@ -342,8 +364,7 @@ void wiEmittedParticle::Draw(GRAPHICSTHREAD threadID)
device->BindResourcePS(material->texture, TEXSLOT_ONDEMAND0, threadID);
}
//device->Draw((int)points.size() * 6, threadID);
device->DrawInstancedIndirect(indirectDrawBuffer, 0, threadID);
device->DrawInstancedIndirect(indirectBuffers, sizeof(wiGraphicsTypes::IndirectDispatchArgs) * 2, threadID);
device->EventEnd(threadID);
}
@@ -356,9 +377,9 @@ void wiEmittedParticle::CleanUp()
SAFE_DELETE(aliveList[1]);
SAFE_DELETE(deadList);
SAFE_DELETE(counterBuffer);
SAFE_DELETE(indirectDispatchBuffer);
SAFE_DELETE(indirectDrawBuffer);
SAFE_DELETE(indirectBuffers);
SAFE_DELETE(constantBuffer);
SAFE_DELETE(debugDataReadbackBuffer);
}
@@ -527,6 +548,11 @@ void wiEmittedParticle::Serialize(wiArchive& archive)
string lightName;
archive >> lightName;
}
if (archive.GetVersion() >= 11)
{
archive >> MAX_PARTICLES;
archive >> SORTING;
}
}
else
@@ -544,5 +570,10 @@ void wiEmittedParticle::Serialize(wiArchive& archive)
archive << scaleY;
archive << rotation;
archive << motionBlurAmount;
if (archive.GetVersion() >= 11)
{
archive << MAX_PARTICLES;
archive << SORTING;
}
}
}
+9 -2
View File
@@ -17,13 +17,14 @@ class wiArchive;
class wiEmittedParticle
{
private:
ParticleCounters debugData = {};
wiGraphicsTypes::GPUBuffer* debugDataReadbackBuffer;
wiGraphicsTypes::GPUBuffer* particleBuffer;
wiGraphicsTypes::GPUBuffer* aliveList[2];
wiGraphicsTypes::GPUBuffer* deadList;
wiGraphicsTypes::GPUBuffer* counterBuffer;
wiGraphicsTypes::GPUBuffer* indirectDispatchBuffer;
wiGraphicsTypes::GPUBuffer* indirectDrawBuffer;
wiGraphicsTypes::GPUBuffer* indirectBuffers; // kickoff, simulation, draw
wiGraphicsTypes::GPUBuffer* constantBuffer;
void CreateSelfBuffers();
@@ -42,6 +43,7 @@ private:
float emit;
bool buffersUpToDate = false;
uint32_t MAX_PARTICLES;
public:
@@ -60,6 +62,11 @@ public:
void Draw(GRAPHICSTHREAD threadID);
void CleanUp();
bool DEBUG = false;
ParticleCounters GetDebugData() { return debugData; }
bool SORTING = false;
std::string name;
Object* object;
std::string materialName;
+116 -120
View File
@@ -1394,10 +1394,10 @@ void wiRenderer::SetUpStates()
bd.AlphaToCoverageEnable = false;
GetDevice()->CreateBlendState(&bd, blendStates[BSTYPE_ENVIRONMENTALLIGHT]);
bd.RenderTarget[0].SrcBlend = BLEND_INV_DEST_COLOR;
bd.RenderTarget[0].DestBlend = BLEND_ZERO;
bd.RenderTarget[0].SrcBlend = BLEND_INV_SRC_COLOR;
bd.RenderTarget[0].DestBlend = BLEND_INV_DEST_COLOR;
bd.RenderTarget[0].BlendOp = BLEND_OP_ADD;
bd.RenderTarget[0].SrcBlendAlpha = BLEND_ZERO;
bd.RenderTarget[0].SrcBlendAlpha = BLEND_ONE;
bd.RenderTarget[0].DestBlendAlpha = BLEND_ONE;
bd.RenderTarget[0].BlendOpAlpha = BLEND_OP_ADD;
bd.RenderTarget[0].BlendEnable = true;
@@ -1856,119 +1856,10 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID)
UpdateFrameCB(threadID);
BindPersistentState(threadID);
wiProfiler::GetInstance().BeginRange("Skinning", wiProfiler::DOMAIN_GPU, threadID);
GetDevice()->EventBegin("Skinning", threadID);
{
bool streamOutSetUp = false;
for (Model* model : GetScene().models)
{
// Update material constant buffers:
MaterialCB materialGPUData;
for (auto& it : model->materials)
{
Material* material = it.second;
materialGPUData.Create(*material);
// These will probably not change every time so only issue a GPU memory update if it is necessary:
if (memcmp(&material->gpuData, &materialGPUData, sizeof(MaterialCB)) != 0)
{
material->gpuData = materialGPUData;
GetDevice()->UpdateBuffer(&material->constantBuffer, &materialGPUData, threadID);
}
}
// Skinning:
for (MeshCollection::iterator iter = model->meshes.begin(); iter != model->meshes.end(); ++iter)
{
Mesh* mesh = iter->second;
if (mesh->hasArmature() && !mesh->hasDynamicVB() && mesh->renderable && !mesh->vertices_POS.empty()
&& mesh->streamoutBuffer_POS.IsValid() && mesh->vertexBuffer_POS.IsValid())
{
Armature* armature = mesh->armature;
if (!streamOutSetUp)
{
// Set up skinning shader
streamOutSetUp = true;
GetDevice()->BindVertexLayout(nullptr, threadID);
GPUBuffer* vbs[] = {
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr
};
const UINT strides[] = {
0,0,0,0,0,0,0,0
};
GetDevice()->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, nullptr, threadID);
GetDevice()->BindCS(computeShaders[CSTYPE_SKINNING], threadID);
}
// Upload bones for skinning to shader
for (unsigned int k = 0; k < armature->boneCollection.size(); k++)
{
armature->boneData[k].Create(armature->boneCollection[k]->boneRelativity);
}
GetDevice()->UpdateBuffer(&armature->boneBuffer, armature->boneData.data(), threadID, (int)(sizeof(Armature::ShaderBoneType) * armature->boneCollection.size()));
GetDevice()->BindResourceCS(&armature->boneBuffer, SKINNINGSLOT_IN_BONEBUFFER, threadID);
// Do the skinning
const GPUResource* vbs[] = {
static_cast<const GPUResource*>(&mesh->vertexBuffer_POS),
static_cast<const GPUResource*>(&mesh->vertexBuffer_NOR),
static_cast<const GPUResource*>(&mesh->vertexBuffer_BON),
};
const GPUUnorderedResource* sos[] = {
static_cast<const GPUUnorderedResource*>(&mesh->streamoutBuffer_POS),
static_cast<const GPUUnorderedResource*>(&mesh->streamoutBuffer_NOR),
static_cast<const GPUUnorderedResource*>(&mesh->streamoutBuffer_PRE),
};
GetDevice()->BindResourcesCS(vbs, SKINNINGSLOT_IN_VERTEX_POS, ARRAYSIZE(vbs), threadID);
GetDevice()->BindUnorderedAccessResourcesCS(sos, 0, ARRAYSIZE(sos), threadID);
GetDevice()->Dispatch((UINT)ceilf((float)mesh->vertices_POS.size() / SKINNING_COMPUTE_THREADCOUNT), 1, 1, threadID);
}
else if (mesh->hasDynamicVB())
{
// Upload CPU skinned vertex buffer (Soft body VB)
mesh->bufferOffset_POS = GetDevice()->AppendRingBuffer(dynamicVertexBufferPool, mesh->vertices_Transformed_POS.data(), sizeof(Mesh::Vertex_POS)*mesh->vertices_Transformed_POS.size(), threadID);
mesh->bufferOffset_NOR = GetDevice()->AppendRingBuffer(dynamicVertexBufferPool, mesh->vertices_Transformed_NOR.data(), sizeof(Mesh::Vertex_NOR)*mesh->vertices_Transformed_NOR.size(), threadID);
mesh->bufferOffset_PRE = GetDevice()->AppendRingBuffer(dynamicVertexBufferPool, mesh->vertices_Transformed_PRE.data(), sizeof(Mesh::Vertex_POS)*mesh->vertices_Transformed_PRE.size(), threadID);
}
}
}
if (streamOutSetUp)
{
// Unload skinning shader
GetDevice()->BindCS(nullptr, threadID);
GetDevice()->UnBindUnorderedAccessResources(0, 3, threadID);
GetDevice()->UnBindResources(SKINNINGSLOT_IN_VERTEX_POS, 4, threadID);
}
}
GetDevice()->EventEnd(threadID);
wiProfiler::GetInstance().EndRange(threadID); // skinning
RefreshEnvProbes(threadID);
// Bind environment probes:
{
const GPUResource* envMaps[] = {
globalEnvProbes[0] == nullptr ? enviroMap : globalEnvProbes[0]->cubeMap.GetTexture(),
globalEnvProbes[1] == nullptr ? enviroMap : globalEnvProbes[1]->cubeMap.GetTexture(),
};
GetDevice()->BindResourcesPS(envMaps, TEXSLOT_ENV0, ARRAYSIZE(envMaps), threadID);
GetDevice()->BindResourcesCS(envMaps, TEXSLOT_ENV0, ARRAYSIZE(envMaps), threadID);
}
ManageDecalAtlas(threadID);
const FrameCulling& mainCameraCulling = frameCullings[getCamera()];
ManageDecalAtlas(threadID);
// Fill Light Array with lights + decals in the frustum:
{
const CulledList& culledLights = mainCameraCulling.culledLights;
@@ -2125,7 +2016,7 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID)
GetDevice()->BindResourcesCS(resources, SBSLOT_ENTITYARRAY, ARRAYSIZE(resources), threadID);
}
// Update visible particlesystem vertices:
// Particle system simulation/sorting/culling:
for (auto& x : emitterSystems)
{
x->UpdateRenderData(threadID);
@@ -2134,6 +2025,114 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID)
{
hair->ComputeCulling(getCamera(), threadID);
}
wiProfiler::GetInstance().BeginRange("Skinning", wiProfiler::DOMAIN_GPU, threadID);
GetDevice()->EventBegin("Skinning", threadID);
{
bool streamOutSetUp = false;
for (Model* model : GetScene().models)
{
// Update material constant buffers:
MaterialCB materialGPUData;
for (auto& it : model->materials)
{
Material* material = it.second;
materialGPUData.Create(*material);
// These will probably not change every time so only issue a GPU memory update if it is necessary:
if (memcmp(&material->gpuData, &materialGPUData, sizeof(MaterialCB)) != 0)
{
material->gpuData = materialGPUData;
GetDevice()->UpdateBuffer(&material->constantBuffer, &materialGPUData, threadID);
}
}
// Skinning:
for (MeshCollection::iterator iter = model->meshes.begin(); iter != model->meshes.end(); ++iter)
{
Mesh* mesh = iter->second;
if (mesh->hasArmature() && !mesh->hasDynamicVB() && mesh->renderable && !mesh->vertices_POS.empty()
&& mesh->streamoutBuffer_POS.IsValid() && mesh->vertexBuffer_POS.IsValid())
{
Armature* armature = mesh->armature;
if (!streamOutSetUp)
{
// Set up skinning shader
streamOutSetUp = true;
GetDevice()->BindVertexLayout(nullptr, threadID);
GPUBuffer* vbs[] = {
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr
};
const UINT strides[] = {
0,0,0,0,0,0,0,0
};
GetDevice()->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, nullptr, threadID);
GetDevice()->BindCS(computeShaders[CSTYPE_SKINNING], threadID);
}
// Upload bones for skinning to shader
for (unsigned int k = 0; k < armature->boneCollection.size(); k++)
{
armature->boneData[k].Create(armature->boneCollection[k]->boneRelativity);
}
GetDevice()->UpdateBuffer(&armature->boneBuffer, armature->boneData.data(), threadID, (int)(sizeof(Armature::ShaderBoneType) * armature->boneCollection.size()));
GetDevice()->BindResourceCS(&armature->boneBuffer, SKINNINGSLOT_IN_BONEBUFFER, threadID);
// Do the skinning
const GPUResource* vbs[] = {
static_cast<const GPUResource*>(&mesh->vertexBuffer_POS),
static_cast<const GPUResource*>(&mesh->vertexBuffer_NOR),
static_cast<const GPUResource*>(&mesh->vertexBuffer_BON),
};
const GPUUnorderedResource* sos[] = {
static_cast<const GPUUnorderedResource*>(&mesh->streamoutBuffer_POS),
static_cast<const GPUUnorderedResource*>(&mesh->streamoutBuffer_NOR),
static_cast<const GPUUnorderedResource*>(&mesh->streamoutBuffer_PRE),
};
GetDevice()->BindResourcesCS(vbs, SKINNINGSLOT_IN_VERTEX_POS, ARRAYSIZE(vbs), threadID);
GetDevice()->BindUnorderedAccessResourcesCS(sos, 0, ARRAYSIZE(sos), threadID);
GetDevice()->Dispatch((UINT)ceilf((float)mesh->vertices_POS.size() / SKINNING_COMPUTE_THREADCOUNT), 1, 1, threadID);
}
else if (mesh->hasDynamicVB())
{
// Upload CPU skinned vertex buffer (Soft body VB)
mesh->bufferOffset_POS = GetDevice()->AppendRingBuffer(dynamicVertexBufferPool, mesh->vertices_Transformed_POS.data(), sizeof(Mesh::Vertex_POS)*mesh->vertices_Transformed_POS.size(), threadID);
mesh->bufferOffset_NOR = GetDevice()->AppendRingBuffer(dynamicVertexBufferPool, mesh->vertices_Transformed_NOR.data(), sizeof(Mesh::Vertex_NOR)*mesh->vertices_Transformed_NOR.size(), threadID);
mesh->bufferOffset_PRE = GetDevice()->AppendRingBuffer(dynamicVertexBufferPool, mesh->vertices_Transformed_PRE.data(), sizeof(Mesh::Vertex_POS)*mesh->vertices_Transformed_PRE.size(), threadID);
}
}
}
if (streamOutSetUp)
{
// Unload skinning shader
GetDevice()->BindCS(nullptr, threadID);
GetDevice()->UnBindUnorderedAccessResources(0, 3, threadID);
GetDevice()->UnBindResources(SKINNINGSLOT_IN_VERTEX_POS, 4, threadID);
}
}
GetDevice()->EventEnd(threadID);
wiProfiler::GetInstance().EndRange(threadID); // skinning
// Render out of date environment probes:
RefreshEnvProbes(threadID);
// Bind environment probes:
{
const GPUResource* envMaps[] = {
globalEnvProbes[0] == nullptr ? enviroMap : globalEnvProbes[0]->cubeMap.GetTexture(),
globalEnvProbes[1] == nullptr ? enviroMap : globalEnvProbes[1]->cubeMap.GetTexture(),
};
GetDevice()->BindResourcesPS(envMaps, TEXSLOT_ENV0, ARRAYSIZE(envMaps), threadID);
GetDevice()->BindResourcesCS(envMaps, TEXSLOT_ENV0, ARRAYSIZE(envMaps), threadID);
}
}
void wiRenderer::OcclusionCulling_Render(GRAPHICSTHREAD threadID)
{
@@ -2765,7 +2764,7 @@ void wiRenderer::DrawDebugEmitters(Camera* camera, GRAPHICSTHREAD threadID)
GetDevice()->BindRasterizerState(rasterizers[RSTYPE_WIRE_DOUBLESIDED_SMOOTH], threadID);
GetDevice()->BindDepthStencilState(depthStencils[DSSTYPE_DEPTHREAD], STENCILREF_EMPTY, threadID);
GetDevice()->BindBlendState(blendStates[BSTYPE_INVERSE], threadID);
GetDevice()->BindBlendState(blendStates[BSTYPE_OPAQUE], threadID);
GetDevice()->BindPS(pixelShaders[PSTYPE_OBJECT_DEBUG], threadID);
@@ -2777,7 +2776,7 @@ void wiRenderer::DrawDebugEmitters(Camera* camera, GRAPHICSTHREAD threadID)
if (x->object != nullptr && x->object->mesh != nullptr)
{
sb.mTransform = XMMatrixTranspose(XMLoadFloat4x4(&x->object->world)*camera->GetViewProjection());
sb.mColor = XMFLOAT4(1, 1, 1, 1);
sb.mColor = XMFLOAT4(0, 1, 0, 1);
GetDevice()->UpdateBuffer(constantBuffers[CBTYPE_MISC], &sb, threadID);
const GPUBuffer* vbs[] = {
@@ -2789,10 +2788,7 @@ void wiRenderer::DrawDebugEmitters(Camera* camera, GRAPHICSTHREAD threadID)
GetDevice()->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, nullptr, threadID);
GetDevice()->BindIndexBuffer(&x->object->mesh->indexBuffer, x->object->mesh->GetIndexFormat(), 0, threadID);
for (auto& y : x->object->mesh->subsets)
{
GetDevice()->DrawIndexed((int)y.subsetIndices.size(), y.indexBufferOffset, 0, threadID);
}
GetDevice()->DrawIndexed((int)x->object->mesh->indices.size(), 0, 0, threadID);
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 13;
// minor bug fixes, alterations, refactors, updates
const int revision = 70;
const int revision = 71;
long GetVersion()