Re: computeshader & rendertexture in cryengine 5

#3
You can use compute shaders and rendertargets in cryengine ofcourse with lightning speeds since you have access to source code itself. The render stages are packed nicely in cryrender. Add a stage to standardgraphics pipeline, and implement a compute shader in it. Also add a manager with an interface in crycommon to set get data from buffers. Rendering done in a different thread as usual. There are predefined passes like scene, fullscreen etc where you can do all sorts of things. I have made an infinite terrain doing all height and normal calculation in gpu so yes. Cryengine is a huge program, the renderer written very well. It was a good read.

Re: computeshader & rendertexture in cryengine 5

#5
Okey, here is an example.

Code: Select all

//// These are stucts for gpu in CryCommon IRenderNode.h //////////////////
struct TerrainDataIn
{
   Matrix44 heightfield;
   float findex_x;
   float findex_y;
};

struct TerrainDataOut
{
   Vec3 position;
   Vec3 tangent;
   Vec3 bitangent;
};
/////////////////////////////////////////////////////////////


Code: Select all

//// A Manager to communicate with render thread. This is in IRenderer.h and implemented in CD3D9Renderer ////
class ITerrainManager
{
public:
   .....
   virtual void PushTerrainComputeItem(TerrainComputeItem* pTerrainItem) = 0;
   virtual TerrainComputeItem* PopTerrainComputeItem(int pId) = 0;
};
////////////////////////////////////////////////////////////


Code: Select all

//// An example stage TerrainStage.h implemented in CryRenderD3D11/GraphicsPipeline ////
#pragma once

#include "Gpu/GpuComputeBackend.h"
#include "Common/GraphicsPipelineStage.h"
#include "GraphicsPipeline/Common/ComputeRenderPass.h"

class CTerrainStage : public CGraphicsPipelineStage
{
public:
   CTerrainStage();
   ~CTerrainStage();
   
   void Init() final;
   
   void Execute();

   CTerrainManager* GetTerrainManager() { return m_pTerrainManager.get(); }

private:
   std::unique_ptr<CTerrainManager> m_pTerrainManager;
   
   CGpuBuffer m_bufferIn;
   
   gpu::CTypedResource<TerrainDataOut, gpu::BufferFlagsReadWriteReadback> m_bufferOut;

   CComputeRenderPass m_Pass;
};


Code: Select all

//// TerrainStage.cpp implemented at CryRenderD3D11/GraphicsPipeline ////
#include "StdAfx.h"
#include "TerrainStage.h"
#include "../../Common/RenderPipeline.h"
#include "DriverD3D.h"

CTerrainStage::CTerrainStage()
   : m_Pass(CComputeRenderPass::eFlags_None),
   m_bufferOut(VertexCount) // Total number of vertices in a patch, defined in somewhere
{
   m_bufferOut.CreateDeviceBuffer();
}

CTerrainStage::~CTerrainStage()
{
   m_bufferOut.FreeDeviceBuffer();
   m_bufferIn.Release();

   m_Pass.Reset();
}

void CTerrainStage::Init()
{
   if (!m_pTerrainManager)
      m_pTerrainManager = std::unique_ptr<CTerrainManager>(new CTerrainManager());

   m_bufferIn.Create(VertexCount, sizeof(TerrainDataIn), DXGI_FORMAT_UNKNOWN, CDeviceObjectFactory::USAGE_STRUCTURED | CDeviceObjectFactory::BIND_SHADER_RESOURCE, NULL);
}

void CTerrainStage::Execute()
{
   PROFILE_LABEL_SCOPE("TERRAIN_STAGE");
      
   TerrainComputeItem* item = m_pTerrainManager->PopTerrainComputeItem();
   TerrainDataIn* data = item->m_Data;

   CDeviceCommandListRef pCoreInterface(GetDeviceObjectFactory().GetCoreCommandList());

   m_bufferIn.UpdateBufferContent(data, sizeof(TerrainDataIn));

   static CCryNameTSCRC technique("ComputeTerrain"); // This name should be same as in cfx file
   m_Pass.SetTechnique(CShaderMan::s_shDeferredShading, technique, 0);

   m_Pass.SetBuffer(0, &m_bufferIn); // bind input
   m_Pass.SetOutputUAV(0, &m_bufferOut.GetBuffer()); // bind output

   m_Pass.PrepareResourcesForUse(pCoreInterface);

   const bool bAsynchronousCompute = CRenderer::CV_r_D3D12AsynchronousCompute & BIT((eStage_Terrain - eStage_FIRST_ASYNC_COMPUTE)) ? true : false;

   SScopedComputeCommandList computeCommandList(bAsynchronousCompute);

   m_Pass.Execute(computeCommandList, EShaderStage_Compute);
   
   m_bufferOut.Readback(VertexCount);
   const TerrainDataOut* out = m_bufferOut.Map(VertexCount); // Get the output
   if (out)
   {
      // Do stuff, pass data out
   }
   m_bufferOut.Unmap();
   
   // clean
   uint clearNull[4] = { 0 };
   pCoreInterface.GetComputeInterface()->ClearUAV(m_bufferOut.GetBuffer().GetDevBuffer()->LookupUAV(EDefaultResourceViews::UnorderedAccess), clearNull, 0, nullptr);
}

ITerrainManager* CD3D9Renderer::GetTerrainManager()
{
   return GetGraphicsPipeline().GetTerrainStage()->GetTerrainManager();
}

Who is online

Users browsing this forum: No registered users and 1 guest