Coder Social home page Coder Social logo

rtxmu's Introduction

RTXMU - RTX Memory Utility

Please read the NVIDIA Blog post on how to use RTXMU: https://developer.nvidia.com/blog/reducing-acceleration-structure-memory-with-nvidia-rtxmu/

To generate a test project:

  1. Clone me
  2. at root directory mkdir build
  3. cd build
  4. cmake -G "Visual Studio 16 2019" -A x64 ..

RTXMU - RTX Memory Utility SDK.

The design of this SDK is to allow developers to use compaction and suballocation of acceleration structure buffers to reduce the memory footprint. Compaction is proven to reduce the total memory footprint by more than a half. Suballocation is proven to reduce memory as well by tightly packing acceleration structure buffers that are less than 64 KB.

The intended use of this SDK is to batch up all of the acceleration structure build inputs and pass them to RTXMU which in turn will perform all the suballocation memory requests and build details including compaction. Post build info is abstracted away by the SDK in order to do compaction under the hood. RTXMU returns acceleration structure handle ids that are used to reference the underlying memory buffers. These handle ids are passed into RTXMU to create compaction copy workloads, deallocate unused build resources or remove all memory associated with an acceleration structure.

Building Ray Traced Sample Application integrated with RTXMU:

Requirements: Windows or Linux, CMake 3.12, C++ 17, Operating system that supports DXR and/or Vulkan RT, Git

Build Steps for running the donut sample application:

  1. Clone the repository under the rtxmu branch using the command: git clone --recursive https://github.com/NVIDIAGameWorks/donut_examples.git
  2. Open CMake and point “Where is the source code:” to the donut_examples folder. Create a build folder in the donut_examples folder and point “Where to build the binaries:” to the build folder. Then select the cmake variable NVRHI_WITH_RTXMU to ON, click Configure at the bottom and once that is complete, click Generate. If you are building with Visual Studio then select 2019 and x64 version. Now you have a Visual Studio project you can build.
  3. Now open the donut_examples.sln file in Visual Studio and build the entire project.
  4. Find the rt_bindless application folder under Examples/Bindless Ray Tracing and right click the project and set as Startup Project.
  5. By default, Bindless Ray Tracing will run on DXR but if you want to run the Vulkan version just add -vk as a command line argument in the project.

Sample Application built on Nvidia’s Donut engine framework: https://github.com/NVIDIAGameWorks/donut_examples

RTXMU SDK library code: https://github.com/NVIDIAGameWorks/RTXMU

Pseudocode examples using the SDK:

// Grab RTXMU singleton
rtxmu::DxAccelStructManager rtxMemUtil(device);

// Initialize suballocator blocks to 8 MB
rtxMemUtil.Initialize(8388608);

// Batch up all the acceleration structure build inputs, can be compacted or non compacted
std::vector<D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS> bottomLevelBuildDescs;
for (auto entity : entityList)
{
    D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS bottomLevelInputs = {};

    bottomLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_ALLOW_COMPACTION;

    if (entity->isAnimated() == true)
    {
        bottomLevelInputs.Flags |=
            D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_ALLOW_UPDATE |
            D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_BUILD;
    }
    else
    {
        bottomLevelInputs.Flags |=
            D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
    }

    bottomLevelInputs.DescsLayout    = D3D12_ELEMENTS_LAYOUT_ARRAY;
    bottomLevelInputs.NumDescs       = 1;
    bottomLevelInputs.Type           = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL;
    bottomLevelInputs.pGeometryDescs = GetBlasGeometryDesc(entity);

    bottomLevelBuildDescs.push_back(bottomLevelInputs);
}

// Records all of the build calls and populates a list of acceleration structure ids
// that can be passed into the library to get the current GPUVA of the acceleration structure
std::vector<uint64_t> accelStructIds;
rtxMemUtil.PopulateBuildCommandList(commandList.Get(),
                                    bottomLevelBuildDescs.data(),
                                    bottomLevelBuildDescs.size(),
                                    accelStructIds);

// Receives acceleration structure inputs and places UAV barriers for them
rtxMemUtil.PopulateUAVBarriersCommandList(commandList.Get(), accelStructIds);

// Performs copies to bring over any compaction size data
rtxMemUtil.PopulateCompactionSizeCopiesCommandList(commandList, accelStructIds);

// Create mapping of the accel struct ids to the model objects
for (int asBufferIndex = 0; asBufferIndex < bottomLevelBuildModels.size(); asBufferIndex++)
{
    _blasMap[bottomLevelBuildModels[asBufferIndex]] = accelStructIds[asBufferIndex];
}

// ----------------------------------------------------------------------------------- //
// Building the TLAS instance description arrays using AccelStructIds handle vector
// ----------------------------------------------------------------------------------- //
for (int instanceIndex = 0; instanceIndex < instanceCount; instanceIndex++)
{
    memcpy(&_instanceDesc[instanceIndex].Transform,
           &_blasTransforms[instanceIndex * (transformOffset / sizeof(float))],
           sizeof(float) * 12);

    _instanceDesc[instanceIndex].InstanceMask                        = 1;
    _instanceDesc[instanceIndex].Flags                               = D3D12_RAYTRACING_INSTANCE_FLAG_NONE;
    _instanceDesc[instanceIndex].InstanceID                          = 0;
    _instanceDesc[instanceIndex].InstanceContributionToHitGroupIndex = 0;

    // Use the acceleration structure handle to get either the result or the compaction buffer based
    //on the build state of the acceleration structure
    const uint64_t asHandle = _blasMap[entity->getModel()];
    _instanceDesc[instanceIndex].AccelerationStructure = rtxMemUtil.GetAccelStructGPUVA(asHandle);
}

// Executing all of the initial builds prior to generating the compaction workloads 
// because the compaction sizes aren't available in system memory until execution is finished

commandList->Close();
gfxQueue->ExecuteCommandLists(1, CommandListCast(commandList.GetAddressOf()));

int fenceValue = _gfxNextFenceValue[cmdListIndex]++;
_gfxQueue->Signal(_gfxCmdListFence[cmdListIndex].Get(), fenceValue);

HANDLE fenceWriteEventECL = CreateEvent(nullptr, FALSE, FALSE, nullptr);
// Wait for just-submitted command list to finish
_gfxCmdListFence[cmdListIndex]->SetEventOnCompletion(fenceValue, fenceWriteEventECL);
WaitForSingleObject(fenceWriteEventECL, INFINITE);

// Acceleration structures that have finished building on the GPU can now be queued to perform compaction
if (newBuildsToCompact.size() > 0)
{
    rtxMemUtil.PopulateCompactionCommandList(commandList.Get(), newBuildsToCompact);
}

// Executing all of the compaction workloads prior to cleaning up the initial larger
// acceleration structure buffer is required to peform the initial build to compaction build copy

commandList->Close();
gfxQueue->ExecuteCommandLists(1, CommandListCast(commandList.GetAddressOf()));

int fenceValue = _gfxNextFenceValue[cmdListIndex]++;
_gfxQueue->Signal(_gfxCmdListFence[cmdListIndex].Get(), fenceValue);

HANDLE fenceWriteEventECL = CreateEvent(nullptr, FALSE, FALSE, nullptr);
// Wait for just-submitted command list to finish
_gfxCmdListFence[cmdListIndex]->SetEventOnCompletion(fenceValue, fenceWriteEventECL);
WaitForSingleObject(fenceWriteEventECL, INFINITE);

// Acceleration structures that have finished building and compacting which means we can deallocate resources
// used in the build and compaction process (scratch and original build buffer memory).
if (newBuildsToGarbageCollect.size() > 0)
{
    rtxMemUtil.GarbageCollection(newBuildsToGarbageCollect);
}


// Removing acceleration structure no longer required
std::vector<uint64_t> accelStructIds;
for (auto model : modelCountsInEntities)
{
    if (model.second == 0)
    {
        // Push id onto remove list
        accelStructIds.push_back(_blasMap[model.first]);
        // Remove the blas entry from the list
        _blasMap.erase(model.first);
    }
}

// Remove all of the no longer referenced accel struct ids by calling RemoveAccelerationStructures
if (accelStructIds.size() > 0)
{
    rtxMemUtil.RemoveAccelerationStructures(accelStructIds);
}

License

RTXMU is licensed under the MIT License.

rtxmu's People

Contributors

pmorley-nv avatar octopusprime314 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.