Closed trsh closed 8 months ago
Hi! It's an interesting point. All information is already available in a method description. For example (from REBLUR_DIFFUSE
):
enum class Permanent
{
PREV_VIEWZ = PERMANENT_POOL_START,
PREV_NORMAL_ROUGHNESS,
PREV_INTERNAL_DATA,
DIFF_HISTORY,
DIFF_FAST_HISTORY_PING,
DIFF_FAST_HISTORY_PONG,
};
m_PermanentPool.push_back( {REBLUR_FORMAT_PREV_VIEWZ, w, h, 1} );
m_PermanentPool.push_back( {REBLUR_FORMAT_PREV_NORMAL_ROUGHNESS, w, h, 1} );
m_PermanentPool.push_back( {REBLUR_FORMAT_PREV_INTERNAL_DATA, w, h, 1} );
m_PermanentPool.push_back( {REBLUR_FORMAT, w, h, 1} );
m_PermanentPool.push_back( {REBLUR_FORMAT_FAST_HISTORY, w, h, 1} );
m_PermanentPool.push_back( {REBLUR_FORMAT_FAST_HISTORY, w, h, 1} );
enum class Transient
{
DATA1 = TRANSIENT_POOL_START,
DATA2,
DIFF_TMP1,
DIFF_TMP2
};
m_TransientPool.push_back( {Format::RG8_UNORM, w, h, 1} );
m_TransientPool.push_back( {Format::RG8_UNORM, w, h, 1} );
m_TransientPool.push_back( {REBLUR_FORMAT, w, h, 1} );
m_TransientPool.push_back( {REBLUR_FORMAT, w, h, 1} );
...
for (int i = 0; i < REBLUR_HISTORY_FIX_PERMUTATION_NUM; i++)
{
PushPass("History fix");
{
// Inputs
PushInput( AsUint(ResourceType::IN_NORMAL_ROUGHNESS) );
PushInput( AsUint(Transient::DATA1) );
PushInput( DIFF_TEMP2 );
PushInput( AsUint(ResourceType::IN_VIEWZ) );
PushInput( AsUint(Permanent::DIFF_FAST_HISTORY_PONG), 0, 1, AsUint(Permanent::DIFF_FAST_HISTORY_PING) );
// Outputs
PushOutput( DIFF_TEMP1 );
// Shaders
AddDispatch( REBLUR_Diffuse_HistoryFix, REBLUR_HISTORY_FIX_CONSTANT_NUM, REBLUR_HISTORY_FIX_NUM_THREADS, 1 );
AddDispatch( REBLUR_Perf_Diffuse_HistoryFix, REBLUR_HISTORY_FIX_CONSTANT_NUM, REBLUR_HISTORY_FIX_NUM_THREADS, 1 );
}
}
I.e. there is a hpp
file for each method. It contains all the logic, which I definitely don't want to repeat / echo in README. This logic defines:
Will it work for you?
To be honest I don't understand this. I have worked before on SVGF implementation, and the inputs where like albedo, depth map, variance map, output etc. Here we have permanent and transient pools, inputs that I also don't understand (AsUint(Transient::DATA1)
?), etc.
Update:
Ok I see ResourceType
has some useful comments. Still lot of investigating here...
Question
So pools are just free textures for RW to exchange information between passes?
Yes, of course "understanding of data" requires minimal knowledge of C/C++ but I clearly see that it can be "recreated" in other languages. There is an additional inconvenience, because in a single denoising method there are several code paths... do you need all of them? it's up to you. But most likely you need to choose one - using the one way or another understand the order of passes and grab the associated data.
NRD integration has NRD_INTEGRATION_DEBUG_LOGGING
macro which can be used to dump the sequence of passes for currently specified settings with all associated resources and their bindings.
AsUint(Transient::DATA1)
The resource DATA1
(the first one, because it's the beginning of the transient pool) from the transient pool.
Thank you for suggestions. I try to look into it and come back with results/questions.
Closing as "will never fix". High-level code of denoisers in NRD (C++ files in "Denoisers" folder) has been designed to be self-exploratory. Plus, since v4.4.0 shared C++/HLSL headers simplify understanding of shader constants.
By now we have game engines in Go, Rust, JavaScript, WebGpu, etc. that can make use of HLSL/GLSL shaders. Those could probably make good use of the shader side of this Library to implement nrd denoising. All we need would be something in a form of this:
1) Render pass 1 - [name] (is pass optional?) Description. Recommended dispatch size, etc. Bindings: 1) Binding 1 - name - description, format, etc. 2) Binding 2 - name - description, format, etc. 2) ...
Right now its just the
NRDSample
, huge 4k+ code with all stuff, nrd related and non directly nrd related.