NVIDIAGameWorks/RayTracingDenoiser

[RFE] Writing documentation that is useful outside the C++ ecosystem

trsh opened this issue · 5 comments

trsh commented

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.

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:

  • inputs & outputs
  • transient pool textures with sizes and formats
  • permanent pool textures with sizes and formats
  • passes with associated data and bindings (for all permutations)
  • pass invoking logic

Will it work for you?

trsh commented

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.

trsh commented

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.