/*!****************************************************************************
 @Function		Init
 @Input			ErrorStr	In case of error, any error messages will be stored
				in this string
 @Return		true if successfully completed, false otherwise.
 @Description	Initializes any state that needs to be created by the class itself.
				Init WILL NOT initialize objects that need to be set by a caller,
				most importantly:
				* The vertex buffer that will contain the actual particles
				* The actual Spheres
				* The actual number of particles (SetNumberOfParticles actually
				allocates memory for the particles)
******************************************************************************/
bool ParticleSystemGPU::Init(CPVRTString& errorStr)
{
	if (!CompileComputeShader(errorStr)) { return false; }

	if (m_ParticleConfigUbo == 0) { glGenBuffers(1, &m_ParticleConfigUbo); }
	if (m_SpheresUbo == 0) { glGenBuffers(1, &m_SpheresUbo); }

	glBindBuffer(GL_UNIFORM_BUFFER, m_SpheresUbo);
	glBindBuffer(GL_UNIFORM_BUFFER, m_ParticleConfigUbo);

	glBufferData(GL_UNIFORM_BUFFER, sizeof(ParticleConfig), &m_ParticleConfigData, GL_STREAM_DRAW);

	glBindBufferBase(GL_UNIFORM_BUFFER, SPHERES_UBO_BINDING_INDEX, m_SpheresUbo);
	glBindBufferBase(GL_UNIFORM_BUFFER, PARTICLE_CONFIG_UBO_BINDING_INDEX, m_ParticleConfigUbo);

	glBindBuffer(GL_UNIFORM_BUFFER, 0);
	glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

	return true;
}
void GPUParticleSystem::InitialiseSystem(ID3D11Device* device, ID3D11DeviceContext* deviceContext)
{
	HRESULT hr;

	//Compile the shaders
	ID3DBlob* pVertexShaderBuffer = NULL;
	hr = CompileShaderFromFile(L"VertexShader.hlsl", "VS", "vs_4_0", &pVertexShaderBuffer);

	ID3DBlob* pGeometryShaderBuffer = NULL;
	hr = CompileShaderFromFile(L"VertexShader.hlsl", "GS", "gs_4_0", &pGeometryShaderBuffer);

	ID3DBlob* pPixelShaderBuffer = NULL;
	hr = CompileShaderFromFile(L"VertexShader.hlsl", "PS", "ps_4_0", &pPixelShaderBuffer);

	// Create the shaders
	device->CreateVertexShader(pVertexShaderBuffer->GetBufferPointer(), pVertexShaderBuffer->GetBufferSize(), NULL, &vertexShader);

	device->CreateGeometryShader(pGeometryShaderBuffer->GetBufferPointer(), pGeometryShaderBuffer->GetBufferSize(), NULL, &geometryShader);

	device->CreatePixelShader(pPixelShaderBuffer->GetBufferPointer(), pPixelShaderBuffer->GetBufferSize(), NULL, &pixelShader);

	pVertexShaderBuffer->Release();
	pPixelShaderBuffer->Release();

	//Create buffer constant buffer for draw calls
	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof(MatricesConstantBuffer);
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = 0;
	
	device->CreateBuffer(&bd, NULL, &mConstBuffer);

	//Create constant buffer for per frame variables
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof(PerFrameVariables);
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = 0;

	device->CreateBuffer(&bd, NULL, &perFrameVariablesBuffer);

	//Create constant buffer for emitter variables
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = D3D11_USAGE_DYNAMIC;
	bd.ByteWidth = sizeof(EmitterParameters);
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	device->CreateBuffer(&bd, NULL, &emitterVariablesBuffer);

	//Create constant buffer for variances
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = D3D11_USAGE_DYNAMIC;
	bd.ByteWidth = sizeof(EmitterParameters);
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	device->CreateBuffer(&bd, NULL, &variancesCB);
	
	//Compile and create compute shaders
	ID3DBlob *csInitBlob = nullptr;
	ID3DBlob *csEmitBlob = nullptr;
	ID3DBlob *csUpdateBlob = nullptr;

	ID3DBlob *errorBlob;

	hr = CompileComputeShader(L"InitialiseDeadList.hlsl", "main", device, &csInitBlob);
	hr = CompileComputeShader(L"EmitParticles.hlsl", "main", device, &csEmitBlob);	
	//hr = CompileComputeShader(L"UpdateParticles.hlsl", "main", device, &csUpdateBlob);

	//Assembles shader code for UpdateParticles
	shaderFactory->ShaderAssembly();

	//Compiles the code that has been put together in the shader factory
	hr = D3DCompile(shaderFactory->updateShaderCode.c_str(), shaderFactory->updateShaderCode.length(), NULL, NULL, NULL,
		"main", "cs_5_0", D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG, NULL, &csUpdateBlob, &errorBlob);
	if (FAILED(hr))
	{
		std::string error = std::string((char*)errorBlob->GetBufferPointer());
		errorBlob->Release();

		return;
	}
	
	//Creates the compute shaders
	hr = device->CreateComputeShader(csInitBlob->GetBufferPointer(), csInitBlob->GetBufferSize(), nullptr, &initialiseDeadListCS);
	
	hr = device->CreateComputeShader(csEmitBlob->GetBufferPointer(), csEmitBlob->GetBufferSize(), nullptr, &emitParticlesCS);

	hr = device->CreateComputeShader(csUpdateBlob->GetBufferPointer(), csUpdateBlob->GetBufferSize(), nullptr, &updateParticlesCS);

	// The dead particle index list. Created as an append buffer
	D3D11_BUFFER_DESC desc;
	desc.ByteWidth = sizeof(UINT) * g_maxParticles;
	desc.Usage = D3D11_USAGE_DEFAULT;
	desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
	desc.CPUAccessFlags = 0;
	desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
	desc.StructureByteStride = sizeof(UINT);

	device->CreateBuffer(&desc, nullptr, &particleDeadListBuffer);

	// Create constant buffers to copy the dead and alive list counters into
	ZeroMemory(&desc, sizeof(desc));
	desc.Usage = D3D11_USAGE_DEFAULT;
	desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	desc.CPUAccessFlags = 0;
	desc.ByteWidth = 4 * sizeof(UINT);
	device->CreateBuffer(&desc, nullptr, &particleDeadListConstantBuffer);

	D3D11_UNORDERED_ACCESS_VIEW_DESC uav;
	ZeroMemory(&uav, sizeof(uav));
	uav.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
	uav.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_APPEND;
	uav.Buffer.FirstElement = 0;
	uav.Format = DXGI_FORMAT_UNKNOWN;
	uav.Buffer.NumElements = g_maxParticles;

	device->CreateUnorderedAccessView(particleDeadListBuffer, &uav, &particleDeadListUAV);

	//Initialise list of particles that are able to be emitted
	InitialiseDeadList(deviceContext);

	//Create the particle buffer/UAV/SRV
	D3D11_BUFFER_DESC buffDesc;
	ZeroMemory(&buffDesc, sizeof(buffDesc));
	buffDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
	buffDesc.ByteWidth = sizeof(Particle)* g_maxParticles;
	buffDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
	buffDesc.StructureByteStride = sizeof(Particle);
	buffDesc.Usage = D3D11_USAGE_DEFAULT;
	
	Particle* particleList = new Particle[g_maxParticles];

	//Initial particle values that are never used and are just for initialisation
	for (int i = 0; i < g_maxParticles; ++i)
	{
		particleList[i].position = DirectX::XMFLOAT3(9999.0f, 0.0f, 9999.0f);
		particleList[i].velocity = DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f);
		particleList[i].life = 0.0f;
		particleList[i].age = 0.0f;
		particleList[i].alive = false;
		particleList[i].startSize = 0.0f;
		particleList[i].endSize = 0.0f;
		particleList[i].startColour = DirectX::XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f);
		particleList[i].endColour = DirectX::XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f);
		particleList[i].currentColour = DirectX::XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f);
		particleList[i].currentSize = 0.0f;
	}

	D3D11_SUBRESOURCE_DATA	data;
	ZeroMemory(&data, sizeof(data));
	data.pSysMem = particleList;

	device->CreateBuffer(&buffDesc, &data, &particles);

	delete[] particleList;

	D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
	ZeroMemory(&srvDesc, sizeof(srvDesc));
	srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
	srvDesc.Buffer.FirstElement = 0;
	srvDesc.Format = DXGI_FORMAT_UNKNOWN;
	srvDesc.Buffer.NumElements = g_maxParticles;

	device->CreateShaderResourceView(particles, &srvDesc, &particlesSRV);

	D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
	ZeroMemory(&uavDesc, sizeof(uavDesc));
	uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
	uavDesc.Buffer.Flags = 0;
	uavDesc.Buffer.FirstElement = 0;
	uavDesc.Format = DXGI_FORMAT_UNKNOWN;
	uavDesc.Buffer.NumElements = g_maxParticles;

	device->CreateUnorderedAccessView(particles, &uavDesc, &particlesUAV);

	//Buffer for the particle count
	ZeroMemory(&desc, sizeof(desc));
	desc.Usage = D3D11_USAGE_STAGING;
	desc.BindFlags = 0;
	desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
	desc.ByteWidth = sizeof(UINT);
	device->CreateBuffer(&desc, nullptr, &debugCounterBuffer);

	//Loads in smoke particle texture to use with the particles using DirectXTK texture loader
	hr = DirectX::CreateWICTextureFromFile(device, deviceContext, L"smoke.jpg", nullptr, &texture);
}
Esempio n. 3
0
int main()
{
    // Create Device
    const D3D_FEATURE_LEVEL lvl[] = { D3D_FEATURE_LEVEL_11_1 };

    UINT createDeviceFlags = 0;
#ifdef _DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    /* ================================== */
    printf("Creating device...");
    ID3D11Device* device = nullptr;
    HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, lvl, _countof(lvl), D3D11_SDK_VERSION, &device, nullptr, nullptr);
    if (FAILED(hr))
    {
        printf("Failed creating Direct3D 11 device %08X\n", hr);
        return returnDBG(-1);
    }

    /* ================================== */
    printf("Compile Compute Shader...");
    ID3DBlob *csBlob = nullptr;
    hr = CompileComputeShader(L"ComputeShader.hlsl", "main", device, &csBlob);
    if (FAILED(hr))
    {
        device->Release();
        printf("Failed compiling shader %08X\n", hr);
        return returnDBG(-1);
    }

    /* ================================== */
    printf("Create Compute Shader...");
    ID3D11ComputeShader* computeShader = nullptr;
    hr = device->CreateComputeShader(csBlob->GetBufferPointer(), csBlob->GetBufferSize(), nullptr, &computeShader);
            
    /* ================================== */
    printf("Creating buffers and filling them with initial data...");
    for (int i = 0; i < NUM_ELEMENTS; ++i)
    {
        g_vBuf0[i].i = i;
        g_vBuf0[i].f = (float)i;

        g_vBuf1[i].i = i;
        g_vBuf1[i].f = (float)i;
    }

    CreateRawBuffer(g_pDevice, NUM_ELEMENTS * sizeof(BufType), &g_vBuf0[0], &g_pBuf0);
    CreateRawBuffer(g_pDevice, NUM_ELEMENTS * sizeof(BufType), &g_vBuf1[0], &g_pBuf1);
    CreateRawBuffer(g_pDevice, NUM_ELEMENTS * sizeof(BufType), nullptr, &g_pBufResult);

    /* ================================== */
    printf("Running Compute Shader...");
    ID3D11ShaderResourceView* aRViews[2] = { g_pBuf0SRV, g_pBuf1SRV };
    RunComputeShader(g_pContext, g_pCS, 2, aRViews, nullptr, nullptr, 0, g_pBufResultUAV, NUM_ELEMENTS, 1, 1);
    printf("done\n");
    
    
    
    csBlob->Release();

    if (FAILED(hr))
    {
        device->Release();
    }

    printf("Success\n");



    // Clean up
    computeShader->Release();

    device->Release();

    return returnDBG(0);
}