Hello,
I just came across a strange error: I’m trying to use the OptixDenoiser
when generating soft shadows (which takes place in a separate rendering class OptixRenderer
). So I wanted to separate the OptixDenoiser
from the rendering class in a separate class:
#include <optix.h>
#include <optix/CUDABuffer.h> // defines a class that manages cuda memory and offers the device ptr and the size of the buffer
#include <optix/LaunchParams.h> // defines frame information such as the float4* frame buffer, an integer vec2 with the size of the current frame and an int as the frame_id
class Denoiser
{
bool denoise;
bool accumulate;
OptixDenoiser denoiser = nullptr;
CUDABuffer denoiser_scratch;
CUDABuffer denoiser_state;
public:
Denoiser();
~Denoiser();
bool is_denoising();
bool is_accumulating();
void on_render(const FrameInfo& frame, const CUDABuffer& render_buffer, const CUDABuffer& denoised_buffer);
void on_resize(const OptixDeviceContext& device_context, const glm::ivec2& new_size);
};
And the implementation looks like this:
#include <optix/Denoiser.h>
#include <optix/OptixUtil.h> // contains functions for CUDA_CHECK and CUDA_SYNC
cgbv::optix::Denoiser::Denoiser()
{
denoise = false;
accumulate = false;
}
cgbv::optix::Denoiser::~Denoiser()
{
if (denoiser)
optix::error::check(optixDenoiserDestroy(denoiser));
}
bool cgbv::optix::Denoiser::is_denoising()
{
return denoise;
}
bool cgbv::optix::Denoiser::is_accumulating()
{
return accumulate;
}
void cgbv::optix::Denoiser::on_render(const FrameInfo& frame, const CUDABuffer& render_buffer, const CUDABuffer& denoised_buffer)
{
OptixDenoiserParams denoiser_params;
denoiser_params.denoiseAlpha = OPTIX_DENOISER_ALPHA_MODE_ALPHA_AS_AOV;
denoiser_params.hdrIntensity = static_cast<CUdeviceptr>(0);
denoiser_params.blendFactor = !accumulate ? 0.f : 1.f / static_cast<float>(frame.frame_id);
OptixImage2D input_layer;
input_layer.data = render_buffer.get_device_pointer();
input_layer.width = frame.size.x;
input_layer.height = frame.size.y;
input_layer.rowStrideInBytes = frame.size.x * sizeof(float4);
input_layer.pixelStrideInBytes = sizeof(float4);
input_layer.format = OPTIX_PIXEL_FORMAT_FLOAT4;
OptixImage2D output_layer;
output_layer.data = denoised_buffer.get_device_pointer();
output_layer.width = frame.size.x;
output_layer.height = frame.size.y;
output_layer.rowStrideInBytes = frame.size.x * sizeof(float4);
output_layer.pixelStrideInBytes = sizeof(float4);
output_layer.format = OPTIX_PIXEL_FORMAT_FLOAT4;
if (denoise)
{
OptixDenoiserGuideLayer denoiser_guide_layer = {};
OptixDenoiserLayer denoiser_layer = {};
denoiser_layer.input = input_layer;
denoiser_layer.output = output_layer;
optix::error::check(optixDenoiserInvoke(denoiser, 0, &denoiser_params, denoiser_state.get_device_pointer(), denoiser_state.get_size_in_bytes(), &denoiser_guide_layer, &denoiser_layer, 1, 0, 0, denoiser_scratch.get_device_pointer(), denoiser_scratch.get_size_in_bytes()));
}
else
{
cudaMemcpy((void*)output_layer.data, (void*)input_layer.data, output_layer.width * output_layer.height * sizeof(float4), cudaMemcpyDeviceToDevice);
}
}
void cgbv::optix::Denoiser::on_resize(const OptixDeviceContext& device_context, const glm::ivec2& new_size)
{
if (denoiser)
optix::error::check(optixDenoiserDestroy(denoiser));
OptixDenoiserOptions denoiser_options = {};
optix::error::check(optixDenoiserCreate(device_context, OPTIX_DENOISER_MODEL_KIND_LDR, &denoiser_options, &denoiser));
OptixDenoiserSizes denoiser_return_sizes;
optix::error::check(optixDenoiserComputeMemoryResources(denoiser, new_size.x, new_size.y, &denoiser_return_sizes));
denoiser_scratch.resize(std::max(denoiser_return_sizes.withOverlapScratchSizeInBytes, denoiser_return_sizes.withoutOverlapScratchSizeInBytes));
denoiser_state.resize(denoiser_return_sizes.stateSizeInBytes);
optix::error::check(optixDenoiserSetup(denoiser, 0, new_size.x, new_size.y, denoiser_state.get_device_pointer(), denoiser_state.get_size_in_bytes(), denoiser_scratch.get_device_pointer(), denoiser_scratch.get_size_in_bytes()));
}
So, if I encapsulate the OptixDenoiser like that, the linker gives me errors for unresolved symbols for basically any optixDenoiser
function called (like optixDenoiserSetup
, optixDenoiserComputeMemoryResources
, optixDenoiserCreate
etc.), however, if I place it directly inside the OptixRenderer
code, everything is fine.
I’m wondering why linking fails when I use the separate class instead of the directly nested code. It’s the same project with the same path settings for all files and since they are both *.cpp files, they are not compiled with nvcc but with a standard msvc.
Am I missing something regarding the compilation of OptixDenoiser
-related functions?
Thank you and kind regards,
Markus