Hi Guys,
This thread may not be super relevant to DirectX and XNA, however it's about GFX buffer management, so I guess most of you guys probably have encountered this before, and that's why I asked here. But if site admin think this should be in a different sub forum, please feel free to move it.
So my problem is maintaining a static 'list' of GPU RTs, I want to have a central place to write down all the configurations of each RTs (which also contains render irrelevant information like debug name, resize policy, debug viewable, etc), so it is easy for me to add/remove/edit RTs.
I also wish to use simple container to hold them, but still want to use debug name to index them.
When I first start my project, there is only few RTs, so I use naive separate arrays to manage my RTs : a string array to store RT debug name, a enum to map Idx to a readable name, an array of descriptor for each RTs. etc.. But as the number of RTs grows, the naive way won't work anymore since it's getting harder to ensure the consistence between all these arrays.. So I switch to use macro with def header to handle all these like the following:
surBuf_def.h
#ifndef DEF_SURFBUF
#error "DEF_SURFBUF() undefined"
#endif
DEF_SURFBUF(KINECT_COLOR, COLOR_SIZE, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(KINECT_DEPTH, DEPTH_SIZE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(KINECT_INFRA, DEPTH_SIZE, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(KINECT_DEPTH_VIS, DEPTH_SIZE, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(CONFIDENCE, DEPTH_SIZE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(KINECT_NORMAL, DEPTH_SIZE, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(TSDF_NORMAL, DEPTH_SIZE, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(FILTERED_DEPTH, DEPTH_SIZE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(TSDF_DEPTH, DEPTH_SIZE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(VISUAL_NORMAL, VARI_SIZE1, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(VISUAL_DEPTH, VARI_SIZE1, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_D32_FLOAT)
DEF_SURFBUF(DEBUG_A_DEPTH, DEPTH_SIZE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(DEBUG_A_NORMAL, DEPTH_SIZE, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(DEBUG_B_DEPTH, DEPTH_SIZE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(DEBUG_B_NORMAL, DEPTH_SIZE, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN)
DEF_SURFBUF(DEBUG_CONFIDENCE, DEPTH_SIZE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN)
main cpp file:
//=================================================================================================
// I still have separate arrays of my RT info, but consistency is ensured by the surfbuf_defs.h file
//=================================================================================================
struct SurfBuffer {
ViewSize sizeCode;
DXGI_FORMAT colorFormat;
DXGI_FORMAT depthFormat;
ColorBuffer* colBuf;
DepthBuffer* depBuf;
};
enum SurfBufId : uint8_t {
#define DEF_SURFBUF(_name, _size, _colformat, _depthformat) _name,
#include "surfbuf_defs.h"
#undef DEF_SURFBUF
SURFBUF_COUNT
};
const wchar_t* _bufNames[] = {
#define DEF_SURFBUF(_name, _size, _colformat, _depthformat) L"SURFBUF_" #_name,
#include "surfbuf_defs.h"
#undef DEF_SURFBUF
};
CASSERT(ARRAY_COUNT(_bufNames) == SURFBUF_COUNT);
SurfBuffer _surfBufs[] = {
#define DEF_SURFBUF(_name, _size, _colformat, _depthformat) \
{_size, _colformat, _depthformat, nullptr, nullptr},
#include "surfbuf_defs.h"
#undef DEF_SURFBUF
};
CASSERT(ARRAY_COUNT(_surfBufs) == SURFBUF_COUNT);
....
....
....
//=========================================================================================
// then in the application code, I can use enum to easily use all these RTs very efficiently
//=========================================================================================
// Request depthmap for ICP
_tsdfVolume.ExtractSurface(gfxCtx, GetColBuf(TSDF_DEPTH),
_vis ? GetColBuf(VISUAL_DEPTH) : nullptr, GetDepBuf(VISUAL_DEPTH));
cptCtx.ClearUAV(*GetColBuf(CONFIDENCE), ClearVal);
if (_vis) {
// Generate normalmap for visualized depthmap
_normalGen.OnProcessing(cptCtx, L"Norm_Vis",
GetColBuf(VISUAL_DEPTH), GetColBuf(VISUAL_NORMAL));
_tsdfVolume.RenderDebugGrid(
gfxCtx, GetColBuf(VISUAL_NORMAL), GetDepBuf(VISUAL_DEPTH));
}
// Generate normalmap for TSDF depthmap
_normalGen.OnProcessing(cptCtx, L"Norm_TSDF",
&*GetColBuf(TSDF_DEPTH), GetColBuf(TSDF_NORMAL));
// Pull new data from Kinect
bool newData = _sensorTexGen.OnRender(cmdCtx, GetColBuf(KINECT_DEPTH),
GetColBuf(KINECT_COLOR), GetColBuf(KINECT_INFRA),
GetColBuf(KINECT_DEPTH_VIS));
cmdCtx.Flush();
_tsdfVolume.UpdateGPUMatrixBuf(cptCtx, _sensorTexGen.GetVCamMatrixBuf());
// Bilateral filtering
_bilateralFilter.OnRender(gfxCtx, L"Filter_Raw", GetColBuf(KINECT_DEPTH),
GetColBuf(FILTERED_DEPTH), GetColBuf(CONFIDENCE));
// Generate normalmap for Kinect depthmap
_normalGen.OnProcessing(cptCtx, L"Norm_Raw",
_bilateralFilter.IsEnabled() ? GetColBuf(FILTERED_DEPTH)
: GetColBuf(KINECT_DEPTH),
GetColBuf(KINECT_NORMAL), GetColBuf(CONFIDENCE));
It works as I wish, and satisfied all my requirement, but it really confuses VS intellisense, and I end up get annoy intellisense errors (these errors are harmless, but really annoy)
Given the fact that the use of macro is discouraged after C++11, and all these intellisense errors. I hope to know how you guys dealing with buffer management in your engine.
I was thinking of having a structure contains all configure RT info, and then use an advanced container like unordered_map to relate debug name with actual RT to avoid using Macros, but string with those container like map is way too slower than the one I am currently using.
Please let me know what's your solutions: if you think the macro way is bad, why it's bad? and what are better solutions for my case? or if you think the macro way is good, then how to deal with the intellisense error?
Thanks in advance