diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f857dae..c11d5a6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ set(SOURCES StaticMeshComponent.cpp Utils.cpp stbi/stb_image.cpp + NanoVDBLoader.cpp ) set(HEADERS diff --git a/NanoVDBLoader.cpp b/NanoVDBLoader.cpp new file mode 100644 index 00000000..1d07216c --- /dev/null +++ b/NanoVDBLoader.cpp @@ -0,0 +1,117 @@ +#define NOMINMAX +#include "NanoVDBLoader.h" +#include +#include "BattleFireDirect.h" +#include +#include +#include +#include +#include + +bool LoadNanoVDB(const char* filePath, NanoVDBData& outData, ID3D12GraphicsCommandList* cmdList) { + try { + nanovdb::GridHandle gridHandle = nanovdb::io::readGrid(filePath); + + const uint64_t byteSize = gridHandle.buffer().bufferSize(); + const uint64_t elementCount = byteSize / sizeof(uint32_t); + + void* bufferData = malloc(byteSize); + if (!bufferData) { + std::cerr << "Failed to allocate memory for NanoVDB" << std::endl; + return false; + } + + memcpy(bufferData, gridHandle.buffer().data(), byteSize); + + outData.cpuData = bufferData; + outData.byteSize = byteSize; + outData.elementCount = elementCount; + + ID3D12Device* device = GetD3DDevice(); + D3D12_HEAP_PROPERTIES heapProps = {}; + heapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + + D3D12_RESOURCE_DESC resourceDesc = {}; + resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + resourceDesc.Width = byteSize; + resourceDesc.Height = 1; + resourceDesc.DepthOrArraySize = 1; + resourceDesc.MipLevels = 1; + resourceDesc.Format = DXGI_FORMAT_UNKNOWN; + resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + resourceDesc.SampleDesc.Count = 1; + + HRESULT hr = device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &resourceDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&outData.gpuBuffer) + ); + + if (FAILED(hr)) { + std::cerr << "Failed to create GPU buffer for NanoVDB" << std::endl; + free(bufferData); + return false; + } + + D3D12_HEAP_PROPERTIES uploadHeapProps = {}; + uploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD; + + ID3D12Resource* uploadBuffer = nullptr; + hr = device->CreateCommittedResource( + &uploadHeapProps, + D3D12_HEAP_FLAG_NONE, + &resourceDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&uploadBuffer) + ); + + if (SUCCEEDED(hr)) { + void* mappedData = nullptr; + D3D12_RANGE readRange = {0, 0}; + uploadBuffer->Map(0, &readRange, &mappedData); + memcpy(mappedData, bufferData, byteSize); + uploadBuffer->Unmap(0, nullptr); + + cmdList->CopyBufferRegion(outData.gpuBuffer, 0, uploadBuffer, 0, byteSize); + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = outData.gpuBuffer; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_GENERIC_READ; + cmdList->ResourceBarrier(1, &barrier); + + uploadBuffer->Release(); + } + + std::cout << "[NanoVDB] Loaded: " << byteSize << " bytes, " << elementCount << " elements" << std::endl; + std::cout.flush(); + return true; + } + catch (const std::exception& e) { + std::cerr << "[NanoVDB] Error: " << e.what() << std::endl; + std::cerr.flush(); + return false; + } +} + +void FreeNanoVDB(NanoVDBData& data) { + if (data.gpuBuffer) { + data.gpuBuffer->Release(); + data.gpuBuffer = nullptr; + } + if (data.cpuData) { + free(data.cpuData); + data.cpuData = nullptr; + } + data.byteSize = 0; + data.elementCount = 0; +} + + diff --git a/NanoVDBLoader.h b/NanoVDBLoader.h new file mode 100644 index 00000000..a07af38f --- /dev/null +++ b/NanoVDBLoader.h @@ -0,0 +1,15 @@ +#pragma once +#include +#include +#include + +struct NanoVDBData { + ID3D12Resource* gpuBuffer; + void* cpuData; + uint64_t byteSize; + uint64_t elementCount; +}; + +bool LoadNanoVDB(const char* filePath, NanoVDBData& outData, ID3D12GraphicsCommandList* cmdList = nullptr); +void FreeNanoVDB(NanoVDBData& data); + diff --git a/main.cpp b/main.cpp index 1d4a8939..46adc98c 100644 --- a/main.cpp +++ b/main.cpp @@ -1,8 +1,11 @@ #include +#include +#include #include "BattleFireDirect.h" #include "StaticMeshComponent.h" #include "stbi/stb_image.h" #include "Utils.h" +#include "NanoVDBLoader.h" #pragma comment(lib,"d3d12.lib") #pragma comment(lib,"dxgi.lib") @@ -11,6 +14,35 @@ LPCWSTR gWindowClassName = L"BattleFire"; +void RunNanoVDBTest() { + ID3D12GraphicsCommandList* commandList = GetCommandList(); + const char* vdbFiles[] = { + "Res/NanoVDB/sphere2.nvdb", + "Res/NanoVDB/bunny.nvdb", + "Res/NanoVDB/torus_knot_helix.nvdb", + "Res/NanoVDB/boat_points.nvdb", + "Res/NanoVDB/explosion.nvdb", + "Res/NanoVDB/nano_wdas_cloud_half.nvdb" + }; + + for (int i = 0; i < sizeof(vdbFiles) / sizeof(vdbFiles[0]); i++) { + const char* currentVdbFile = vdbFiles[i]; + printf("[NanoVDB Test] Loading: %s\n", currentVdbFile); + + NanoVDBData vdbData; + bool loadSuccess = LoadNanoVDB(currentVdbFile, vdbData, commandList); + if (loadSuccess) { + printf(" SUCCESS - %llu bytes, %llu elements\n", + (unsigned long long)vdbData.byteSize, + (unsigned long long)vdbData.elementCount); + FreeNanoVDB(vdbData); + } else { + printf(" FAILED\n"); + } + } + printf("[NanoVDB Test] Done.\n"); +} + LRESULT CALLBACK WindowProc(HWND inHWND, UINT inMSG, WPARAM inWParam, LPARAM inLParam) { switch (inMSG) { case WM_CLOSE: @@ -70,6 +102,17 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi StaticMeshComponent staticMeshComponent; staticMeshComponent.InitFromFile(commandList, "Res/Model/Sphere.lhsm"); + bool runTest = false; + for (int i = 0; i < __argc; i++) { + if (strcmp(__argv[i], "-test") == 0) { + runTest = true; + break; + } + } + if (runTest) { + RunNanoVDBTest(); + } + ID3D12RootSignature* rootSignature = InitRootSignature(); D3D12_SHADER_BYTECODE vs,gs,ps; CreateShaderFromFile(L"Res/Shader/gs.hlsl", "MainVS", "vs_5_1", &vs);