Compute shader example

Problems building or running the engine, queries about how to use features etc.
ShadyAbyss
Gnoblar
Posts: 8
Joined: Wed Apr 12, 2023 4:55 pm

Compute shader example

Post by ShadyAbyss »

Ogre Version: :14.2:
Operating System: :Windows:
Render System: :DX11:

I'm trying to get run a compute HLSL shader. I want to pass a 2D texture and some parameters to the shader and obtain a structure with few floats as the result. I want to run this shader once when my application starts. This will prepare some data what I need to read back. Unfortunately, I did not find such example.

The samples folder contains one compute sample which utilizes the Compositor manager. However this is designed for compute shaders during render operation. What is not my case. I wonder how should I approach this. Here is my testing code what I did not try to run yet. Not sure how to bind the vertex buffer to my shader.

Code: Select all

auto spComputeProg = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(
	"InstGen", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "hlsl", Ogre::GpuProgramType::GPT_COMPUTE_PROGRAM);
spComputeProg->setSourceFile("instgen.hlsl");
spComputeProg->setParameter("entry_point", "main");
spComputeProg->setParameter("target", "cs_5_0");
spComputeProg->load();

// Create and initialize the vertex buffer
size_t nCount = 32;
auto spOutBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
	sizeof(float), nCount, Ogre::HBU_GPU_TO_CPU, true);  // shadow since we will read the data from GPU

{
	Ogre::HardwareBufferLockGuard lock(spOutBuffer, Ogre::HardwareBuffer::HBL_WRITE_ONLY);
	auto pData = static_cast<float*>(lock.pData);

for (size_t ndx = 0; ndx < nCount; ++ndx)
	pData[ndx] = (float)ndx;
}

auto spParams = spComputeProg->getDefaultParameters();
spParams->setNamedConstant("outBuff", 0);

auto pRS = Ogre::Root::getSingleton().getRenderSystem();
pRS->bindGpuProgram(spComputeProg->_getBindingDelegate());

// !!! How to bind my vertex buffer to the GPU program? !!!

pRS->_dispatchCompute(Ogre::Vector3i((nCount - 1) / 8 + 1, (nCount - 1) / 8 + 1, 1));

// Verify the result
{
	Ogre::HardwareBufferLockGuard lock(spOutBuffer, Ogre::HardwareBuffer::HBL_READ_ONLY);
	auto pData = static_cast<float*>(lock.pData);

for (size_t ndx = 0; ndx < nCount; ++ndx) {
	float fVal = (float)ndx;
	bool bOK = pData[ndx] != fVal * fVal;
}
}

// Cleanup
Ogre::GpuProgramManager::getSingleton().remove(spComputeProg);

Code: Select all

RWStructuredBuffer<float> outBuff: register(u0);

[numthreads(8, 1, 1)]
void main(uint3 id : SV_DispatchThreadID)
{
    uint index = id.x;
    outBuff[index] = 2.0 * outBuff[index];"
};

Thanks for any help :-)
Abyss

rpgplayerrobin
Orc Shaman
Posts: 710
Joined: Wed Mar 18, 2009 3:03 am
x 391

Re: Compute shader example

Post by rpgplayerrobin »

You can get the necessary variables by:

Code: Select all

#include "RenderSystems/Direct3D11/OgreD3D11HLSLProgram.h"
#include "RenderSystems/Direct3D11/OgreD3D11Device.h"
#include "RenderSystems/Direct3D11/OgreD3D11Texture.h"
#pragma warning( push )
#pragma warning( disable : 4996 )
#include "RenderSystems/Direct3D11/OgreD3D11RenderSystem.h"
#pragma warning( pop )
D3D11RenderSystem* tmpSpecificRenderSystem = static_cast<D3D11RenderSystem*>(app->m_RenderSystem);
D3D11Device& tmpDevice = tmpSpecificRenderSystem->_getDevice();
ID3D11DeviceContextN* tmpDeviceContext = tmpDevice.GetImmediateContext();
GpuProgramPtr tmpGpuProgramPtr = GpuProgramManager::getSingleton().getByName(gpuProgramName);
D3D11HLSLProgram* tmpSpecificProgram = static_cast<D3D11HLSLProgram*>(tmpGpuProgramPtr.get());
ID3D11ComputeShader* tmpComputeShader = tmpSpecificProgram->getComputeShader();
// And if you use a texture:
DXGI_FORMAT tmpPixelFormat = D3D11Mappings::_getPF(texturePtr->getFormat());
D3D11Texture* tmpSpecificTexture = static_cast<D3D11Texture*>(texturePtr.get());
ID3D11Texture2D* tmpInputTexture = tmpSpecificTexture->GetTex2D();

Then simply check online for samples of compute shaders and try them easily with the code above.