Skip to content

Commit

Permalink
feat: #98 Implete compile compute shader
Browse files Browse the repository at this point in the history
  • Loading branch information
ducphamhong committed Jul 24, 2020
1 parent a80f0e5 commit b076479
Show file tree
Hide file tree
Showing 12 changed files with 410 additions and 14 deletions.
45 changes: 45 additions & 0 deletions Projects/Irrlicht/Include/IGPUCompute.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (C) 2020 Pham Hong Duc
// This file is part of the "Skylicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
// Add irrlicht compute shader feature

#ifndef __I_GPU_COMPUTE_H_INCLUDED__
#define __I_GPU_COMPUTE_H_INCLUDED__

#include "IrrCompileConfig.h"

#include "IReferenceCounted.h"
#include "EDriverTypes.h"

namespace irr
{
namespace video
{
class IRWBuffer;
class ITexture;

class IGPUCompute : public virtual IReferenceCounted
{
public:
IGPUCompute() :
DriverType(EDT_NULL)
{

}

E_DRIVER_TYPE getDriverType() const { return DriverType; };

virtual void setTexture(int slot, ITexture *texture) = 0;

virtual void setBuffer(int slot, IRWBuffer *buffer) = 0;

virtual void dispatch(int threadGroupX, int threadGroupY, int threadGroupZ) = 0;

protected:

E_DRIVER_TYPE DriverType;
};
}
}

#endif
11 changes: 11 additions & 0 deletions Projects/Irrlicht/Include/IGPUProgrammingServices.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "EPrimitiveTypes.h"
#include "path.h"

#include "IGPUCompute.h"

namespace irr
{

Expand All @@ -23,6 +25,7 @@ namespace video

class IVideoDriver;
class IShaderConstantSetCallBack;
class IGPUCompute;

//! Enumeration for different types of shading languages
enum E_GPU_SHADING_LANGUAGE
Expand Down Expand Up @@ -124,6 +127,14 @@ class IGPUProgrammingServices
callback, baseMaterial, userData, shadingLang);
}

virtual IGPUCompute* createComputeProgram(const c8* computeShaderProgram,
const c8* computeShaderEntryPointName = "main",
E_COMPUTE_SHADER_TYPE csCompileTarget = ECST_CS_5_0) = 0;

virtual IGPUCompute* createComputeProgramFromFile(const io::path& computeShaderFileName,
const c8* computeShaderEntryPointName = "main",
E_COMPUTE_SHADER_TYPE csCompileTarget = ECST_CS_5_0) = 0;

//! convenience function for use with many defaults, without geometry shader
/** All shader names are set to "main" and compile targets are shader
type 1.1.
Expand Down
4 changes: 0 additions & 4 deletions Projects/Irrlicht/Include/IRWBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@
#include "IrrCompileConfig.h"

#include "IReferenceCounted.h"
#include "IImage.h"
#include "dimension2d.h"
#include "EDriverTypes.h"
#include "path.h"
#include "matrix4.h"

namespace irr
{
Expand Down
2 changes: 1 addition & 1 deletion Projects/Irrlicht/Include/IVideoDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ namespace video
\return The gpu buffer object.
If you no longer need the image, you should call IImage::drop().
See IReferenceCounted::drop() for more information. */
virtual IRWBuffer* createRWBuffer(video::ECOLOR_FORMAT format, u32 numElements) = 0;
virtual IRWBuffer* createRWBuffer(video::ECOLOR_FORMAT format, u32 numElements, void *initialData = NULL) = 0;

//! Event handler for resize events. Only used by the engine internally.
/** Used to notify the driver that the window was resized.
Expand Down
18 changes: 17 additions & 1 deletion Projects/Irrlicht/Source/CD3D11Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "CD3D11HardwareBuffer.h"
#include "CD3D11VideoRT.h"
#include "CD3D11RWBuffer.h"
#include "CD3D11GPUCompute.h"

inline void unpack_texureBlendFunc(irr::video::E_BLEND_FACTOR &srcFact, irr::video::E_BLEND_FACTOR &dstFact,
irr::video::E_MODULATE_FUNC &modulo, irr::u32& alphaSource, const irr::f32 param)
Expand Down Expand Up @@ -1413,7 +1414,7 @@ namespace irr
}

//! creates a buffer stored on gpu
IRWBuffer* CD3D11Driver::createRWBuffer(video::ECOLOR_FORMAT format, u32 numElements)
IRWBuffer* CD3D11Driver::createRWBuffer(video::ECOLOR_FORMAT format, u32 numElements, void *initialData)
{
return new CD3D11RWBuffer(this, format, numElements);
}
Expand Down Expand Up @@ -2807,6 +2808,21 @@ namespace irr
return id;
}

IGPUCompute* CD3D11Driver::createComputeProgram(const c8* computeShaderProgram,
const c8* computeShaderEntryPointName,
E_COMPUTE_SHADER_TYPE csCompileTarget)
{
CD3D11GPUCompute *compute = new CD3D11GPUCompute(this);

if (compute->compile(computeShaderProgram, computeShaderEntryPointName, csCompileTarget) == true)
{
return compute;
}

compute->drop();
return NULL;
}

//! Adds a new material renderer to the VideoDriver, using pixel and/or
//! vertex shaders to render geometry.
s32 CD3D11Driver::addShaderMaterial(const c8* vertexShaderProgram,
Expand Down
7 changes: 6 additions & 1 deletion Projects/Irrlicht/Source/CD3D11Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace video
friend class CD3D11TextureArray;
friend class CD3D11VideoRT;
friend class CD3D11RWBuffer;
friend class CD3D11GPUCompute;

//! constructor
CD3D11Driver(const irr::SIrrlichtCreationParameters& params,
Expand Down Expand Up @@ -222,7 +223,7 @@ namespace video
virtual ITexture* getTextureArray(IImage** images, u32 num);

//! creates a buffer stored on gpu
virtual IRWBuffer* createRWBuffer(video::ECOLOR_FORMAT format, u32 numElements);
virtual IRWBuffer* createRWBuffer(video::ECOLOR_FORMAT format, u32 numElements, void *initialData = NULL);

//! Clears the ZBuffer.
virtual void clearZBuffer();
Expand Down Expand Up @@ -416,6 +417,10 @@ namespace video

virtual s32 addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData);

virtual IGPUCompute* createComputeProgram(const c8* computeShaderProgram,
const c8* computeShaderEntryPointName = "main",
E_COMPUTE_SHADER_TYPE csCompileTarget = ECST_CS_5_0);

void draw2D3DVertexPrimitiveList(const void* vertices, u32 vertexCount, u32 pVertexSize,
const void* indices, u32 primitiveCount, E_VERTEX_TYPE vType,
scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType, bool is3D, u32 numInstances = 0);
Expand Down
192 changes: 192 additions & 0 deletions Projects/Irrlicht/Source/CD3D11GPUCompute.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// Copyright (C) 2020 Pham Hong Duc
// This file is part of the "Skylicht Engine"
// Upgrade GPU Compute Shader feature

#include "pch.h"
#include "IrrCompileConfig.h"
#include "CD3D11Driver.h"
#include "CD3D11Texture.h"
#include "CD3D11RWBuffer.h"
#include "CD3D11GPUCompute.h"

#ifdef _IRR_COMPILE_WITH_DIRECT3D_11_

#include "irrOS.h"

#include "d3dcompiler.h"

namespace irr
{
namespace video
{
CD3D11GPUCompute::CD3D11GPUCompute(CD3D11Driver *driver) :
ComputeShader(NULL),
ShaderBuffer(NULL)
{
DriverType = EDT_DIRECT3D11;

Device = driver->getExposedVideoData().D3D11.D3DDev11;
if (Device)
{
Device->AddRef();
Device->GetImmediateContext(&Context);
}

for (int i = 0; i < NUM_PARAMS_SUPPORT; i++)
{
TextureSlot[i] = NULL;
BufferSlot[i] = NULL;
}
}

CD3D11GPUCompute::~CD3D11GPUCompute()
{
Device->Release();
Context->Release();

if (ComputeShader != NULL)
ComputeShader->Release();

if (ShaderBuffer != NULL)
ShaderBuffer->Release();
}

bool CD3D11GPUCompute::compile(const c8* computeShaderProgram,
const c8* computeShaderEntryPointName,
E_COMPUTE_SHADER_TYPE csCompileTarget)
{
ID3D10Blob* errorMsgs = 0;

ID3DInclude* includer = NULL;

UINT flags = 0;

#if !defined(WINDOWS_STORE)
if (csCompileTarget >= ECST_CS_5_0)
flags |= D3D10_SHADER_ENABLE_STRICTNESS;
else
{
flags |= D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY;
csCompileTarget = ECST_CS_4_0;
}

#ifdef _DEBUG
// These values allow use of PIX and shader debuggers
flags |= D3D10_SHADER_DEBUG;
flags |= D3D10_SHADER_SKIP_OPTIMIZATION;
#else
// These flags allow maximum performance
flags |= D3D10_SHADER_OPTIMIZATION_LEVEL3;
#endif

flags |= D3D10_SHADER_OPTIMIZATION_LEVEL3;
#endif

// last macro has to be NULL
core::array<D3D_SHADER_MACRO> macroArray;

D3D_SHADER_MACRO macro;
macro.Definition = NULL;
macro.Name = NULL;

macroArray.push_back(macro);

HRESULT hr = D3DCompile(
computeShaderProgram,
strlen(computeShaderProgram),
"",
&macroArray[0],
includer,
computeShaderEntryPointName,
COMPUTE_SHADER_TYPE_NAMES[csCompileTarget],
flags, 0,
&ShaderBuffer,
&errorMsgs);

if (FAILED(hr))
{
core::stringc errorMsg = "Could not compile shader";

if (errorMsgs)
{
errorMsg += ": ";
errorMsg += static_cast<const char*>(errorMsgs->GetBufferPointer());

errorMsgs->Release();
}

logFormatError(hr, errorMsg);

return false;
}
#ifdef _DEBUG
else if (errorMsgs)
{
core::stringc errorMsg = "Shader compilation warning: ";
errorMsg += static_cast<const char*>(errorMsgs->GetBufferPointer());

errorMsgs->Release();
errorMsgs = NULL;

os::Printer::log(errorMsg.c_str(), ELL_WARNING);
}
#endif

if (errorMsgs)
errorMsgs->Release();

if (!ShaderBuffer)
return false;

hr = Device->CreateComputeShader(
ShaderBuffer->GetBufferPointer(),
ShaderBuffer->GetBufferSize(),
NULL,
&ComputeShader);

if (FAILED(hr))
{
core::stringc errorMsg = "Could not create computeshader";
logFormatError(hr, errorMsg);
return false;
}

return true;
}

void CD3D11GPUCompute::setTexture(int slot, ITexture *texture)
{
TextureSlot[slot] = texture;
}

void CD3D11GPUCompute::setBuffer(int slot, IRWBuffer *buffer)
{
BufferSlot[slot] = buffer;
}

void CD3D11GPUCompute::dispatch(int threadGroupX, int threadGroupY, int threadGroupZ)
{
Context->CSSetShader(ComputeShader, NULL, 0);

for (int i = 0; i < NUM_PARAMS_SUPPORT; i++)
{
// Texture resource view
ID3D11ShaderResourceView* views = NULL;
if (TextureSlot[i])
views = ((CD3D11Texture*)TextureSlot[i])->getShaderResourceView();
Context->CSSetShaderResources(i, 1, &views);

// Buffer unorderred access view
ID3D11UnorderedAccessView* unorderedAccessView;
if (BufferSlot[i])
unorderedAccessView = ((CD3D11RWBuffer*)BufferSlot[i])->getUnorderedAccessView();
Context->CSSetUnorderedAccessViews(i, 1, &unorderedAccessView, NULL);
}

// do gpu compute
Context->Dispatch(threadGroupX, threadGroupY, threadGroupZ);
}
}
}

#endif
Loading

0 comments on commit b076479

Please sign in to comment.