30 #include <platform/engines/optix6/OptiX6Engine_generated_Cones.cu.ptx.h>
31 #include <platform/engines/optix6/OptiX6Engine_generated_Cylinders.cu.ptx.h>
32 #include <platform/engines/optix6/OptiX6Engine_generated_Fields.cu.ptx.h>
33 #include <platform/engines/optix6/OptiX6Engine_generated_SDFGeometries.cu.ptx.h>
34 #include <platform/engines/optix6/OptiX6Engine_generated_Spheres.cu.ptx.h>
35 #include <platform/engines/optix6/OptiX6Engine_generated_Streamlines.cu.ptx.h>
36 #include <platform/engines/optix6/OptiX6Engine_generated_TriangleMesh.cu.ptx.h>
37 #include <platform/engines/optix6/OptiX6Engine_generated_Volumes.cu.ptx.h>
43 static const char* CUDA_SPHERES = OptiX6Engine_generated_Spheres_cu_ptx;
44 static const char* CUDA_CYLINDERS = OptiX6Engine_generated_Cylinders_cu_ptx;
45 static const char* CUDA_CONES = OptiX6Engine_generated_Cones_cu_ptx;
46 static const char* CUDA_SDF_GEOMETRIES = OptiX6Engine_generated_SDFGeometries_cu_ptx;
47 static const char* CUDA_TRIANGLES_MESH = OptiX6Engine_generated_TriangleMesh_cu_ptx;
48 static const char* CUDA_VOLUMES = OptiX6Engine_generated_Volumes_cu_ptx;
49 static const char* CUDA_STREAMLINES = OptiX6Engine_generated_Streamlines_cu_ptx;
50 static const char* CUDA_FIELDS = OptiX6Engine_generated_Fields_cu_ptx;
68 void textureToOptix(T* ptr_dst,
const core::Texture2D& texture,
const uint8_t face,
const uint8_t mipLevel,
71 uint16_t width = texture.
width;
72 uint16_t height = texture.
height;
73 for (uint8_t i = 0; i < mipLevel; ++i)
80 const auto rawData = texture.
getRawData<T>(face, mipLevel);
81 for (uint16_t y = 0; y < height; ++y)
83 for (uint16_t x = 0; x < width; ++x)
85 ptr_dst[idx_dst] = rawData[idx_src];
86 ptr_dst[idx_dst + 1u] = rawData[idx_src + 1u];
87 ptr_dst[idx_dst + 2u] = rawData[idx_src + 2u];
88 ptr_dst[idx_dst + 3u] = hasAlpha ? rawData[idx_src + 3u] : white<T>();
90 idx_src += hasAlpha ? 4u : 3u;
100 return RT_WRAP_CLAMP_TO_BORDER;
102 return RT_WRAP_CLAMP_TO_EDGE;
104 return RT_WRAP_MIRROR;
107 return RT_WRAP_REPEAT;
113 #define RT_CHECK_ERROR_NO_CONTEXT(func) \
116 RTresult code = func; \
117 if (code != RT_SUCCESS) \
118 throw std::runtime_error("Optix error in function '" + std::string(#func) + "'"); \
127 std::unique_ptr<OptiXContext> OptiXContext::_context;
129 OptiXContext::OptiXContext()
131 _printSystemInformation();
137 _rendererPrograms.clear();
138 _cameraPrograms.clear();
155 return _optixContext->createMaterial();
160 _rendererPrograms[name] = program;
165 auto it = _rendererPrograms.find(name);
166 if (it == _rendererPrograms.end())
167 throw std::runtime_error(
"Shader program not found for renderer '" + name +
"'");
173 _cameraPrograms[name] = program;
178 auto it = _cameraPrograms.find(name);
179 if (it == _cameraPrograms.end())
180 throw std::runtime_error(
"Camera program not found for camera '" + name +
"'");
187 _optixContext->setRayGenerationProgram(0, camera->getRayGenerationProgram());
188 _optixContext->setMissProgram(0, camera->getMissProgram());
189 _optixContext->setExceptionProgram(0, camera->getExceptionProgram());
194 uint16_t nx = texture->width;
195 uint16_t ny = texture->height;
196 const uint16_t channels = texture->channels;
197 const uint16_t optixChannels = 4;
198 const bool hasAlpha = optixChannels == channels;
200 const bool useFloat = texture->depth == 4;
201 const bool useByte = texture->depth == 1;
203 if (!useFloat && !useByte)
204 throw std::runtime_error(
"Only byte or float textures are supported");
206 const bool createMipmaps = texture->getMipLevels() == 1 && useByte && !texture->isCubeMap();
207 uint16_t mipMapLevels = texture->getMipLevels();
209 mipMapLevels = texture->getPossibleMipMapsLevels();
211 if (createMipmaps && !useByte)
212 throw std::runtime_error(
213 "Non 8-bits textures are not supported for automatic mipmaps "
216 RTformat optixFormat = useByte ? RT_FORMAT_UNSIGNED_BYTE4 : RT_FORMAT_FLOAT4;
219 ::optix::TextureSampler sampler = _optixContext->createTextureSampler();
220 const auto wrapMode = wrapModeToOptix(texture->getWrapMode());
221 sampler->setWrapMode(0, wrapMode);
222 sampler->setWrapMode(1, wrapMode);
223 sampler->setWrapMode(2, wrapMode);
224 sampler->setIndexingMode(RT_TEXTURE_INDEX_NORMALIZED_COORDINATES);
225 sampler->setReadMode(RT_TEXTURE_READ_NORMALIZED_FLOAT);
226 sampler->setMaxAnisotropy(8.0f);
229 ::optix::Buffer buffer;
230 if (texture->isCubeMap())
231 buffer = _optixContext->createCubeBuffer(RT_BUFFER_INPUT, optixFormat, nx, ny, mipMapLevels);
233 buffer = _optixContext->createMipmappedBuffer(RT_BUFFER_INPUT, optixFormat, nx, ny, mipMapLevels);
235 std::vector<void*> mipMapBuffers(mipMapLevels);
236 for (uint8_t currentLevel = 0u; currentLevel < mipMapLevels; ++currentLevel)
237 mipMapBuffers[currentLevel] = buffer->map(currentLevel);
241 uint8_t* ptr_dst = (uint8_t*)mipMapBuffers[0];
244 const auto rawData = texture->getRawData<
unsigned char>();
245 for (uint16_t y = 0; y < ny; ++y)
247 for (uint16_t x = 0; x < nx; ++x)
249 ptr_dst[idx_dst] = rawData[idx_src];
250 ptr_dst[idx_dst + 1u] = rawData[idx_src + 1u];
251 ptr_dst[idx_dst + 2u] = rawData[idx_src + 2u];
252 ptr_dst[idx_dst + 3u] = hasAlpha ? rawData[idx_src + 3u] : 255u;
254 idx_src += hasAlpha ? 4u : 3u;
260 for (uint8_t currentLevel = 1u; currentLevel < mipMapLevels; ++currentLevel)
262 ptr_dst = (uint8_t*)mipMapBuffers[currentLevel];
263 uint8_t* ptr_src = (uint8_t*)mipMapBuffers[currentLevel - 1u];
264 for (uint16_t y = 0u; y < ny; ++y)
266 for (uint16_t x = 0u; x < nx; ++x)
268 ptr_dst[(y * nx + x) * 4u] =
269 (ptr_src[(y * 2u * nx + x) * 8u] + ptr_src[((y * 2u * nx + x) * 2u + 1u) * 4u] +
270 ptr_src[((y * 2u + 1u) * nx + x) * 8u] + ptr_src[(((y * 2u + 1u) * nx + x) * 2u + 1u) * 4u]) /
272 ptr_dst[(y * nx + x) * 4u + 1u] =
273 (ptr_src[(y * 2u * nx + x) * 8u + 1u] + ptr_src[((y * 2u * nx + x) * 2u + 1u) * 4u + 1u] +
274 ptr_src[((y * 2u + 1u) * nx + x) * 8u + 1u] +
275 ptr_src[(((y * 2u + 1u) * nx + x) * 2u + 1u) * 4u + 1u]) /
277 ptr_dst[(y * nx + x) * 4u + 2u] =
278 (ptr_src[(y * 2u * nx + x) * 8u + 2u] + ptr_src[((y * 2u * nx + x) * 2u + 1u) * 4u + 2u] +
279 ptr_src[((y * 2u + 1u) * nx + x) * 8u + 2u] +
280 ptr_src[(((y * 2u + 1u) * nx + x) * 2u + 1u) * 4u + 2u]) /
282 ptr_dst[(y * nx + x) * 4u + 3u] =
283 (ptr_src[(y * 2u * nx + x) * 8u + 3u] + ptr_src[((y * 2u * nx + x) * 2u + 1u) * 4u + 3u] +
284 ptr_src[((y * 2u + 1u) * nx + x) * 8u + 3u] +
285 ptr_src[(((y * 2u + 1u) * nx + x) * 2u + 1u) * 4u + 3u]) /
288 if (texture->isNormalMap())
290 glm::vec3 normalized =
291 glm::normalize(glm::vec3(2.0f * (
float)ptr_dst[(y * nx + x) * 4u] / 255.0f - 1.0f,
292 2.0f * (
float)ptr_dst[(y * nx + x) * 4u + 1u] / 255.0f - 1.0f,
293 2.0f * (
float)ptr_dst[(y * nx + x) * 4u + 2u] / 255.0f - 1.0f));
294 ptr_dst[(y * nx + x) * 4u] = 255.0f * (0.5f * normalized.x + 0.5f);
295 ptr_dst[(y * nx + x) * 4u + 1u] = 255.0f * (0.5f * normalized.y + 0.5f);
296 ptr_dst[(y * nx + x) * 4u + 2u] = 255.0f * (0.5f * normalized.z + 0.5f);
306 for (uint8_t face = 0; face < texture->getNumFaces(); ++face)
310 for (uint16_t mip = 0; mip < mipMapLevels; ++mip)
314 auto dst = (uint8_t*)mipMapBuffers[mip];
315 dst += face * mipWidth * mipHeight * 4;
316 textureToOptix<uint8_t>(dst, *texture, face, mip, hasAlpha);
320 auto dst = (
float*)mipMapBuffers[mip];
321 dst += face * mipWidth * mipHeight * 4;
322 textureToOptix<float>(dst, *texture, face, mip, hasAlpha);
330 for (uint8_t currentLevel = 0u; currentLevel < mipMapLevels; ++currentLevel)
331 buffer->unmap(currentLevel);
334 sampler->setBuffer(buffer);
335 sampler->setFilteringModes(RT_FILTER_LINEAR, RT_FILTER_LINEAR,
336 mipMapLevels > 1 ? RT_FILTER_LINEAR : RT_FILTER_NONE);
341 void OptiXContext::_initialize()
344 _optixContext = ::optix::Context::create();
347 throw(std::runtime_error(
"Failed to initialize OptiX"));
350 _optixContext->setPrintEnabled(
false);
352 _optixContext->setPrintEnabled(
true);
353 _optixContext->setPrintBufferSize(1024);
359 _optixContext->setMaxTraceDepth(DEFAULT_RENDERER_MAX_RAY_DEPTH);
362 _optixContext->createProgramFromPTXString(CUDA_CONES, OPTIX_CUDA_FUNCTION_BOUNDS);
364 _optixContext->createProgramFromPTXString(CUDA_CONES, OPTIX_CUDA_FUNCTION_INTERSECTION);
367 _optixContext->createProgramFromPTXString(CUDA_CYLINDERS, OPTIX_CUDA_FUNCTION_BOUNDS);
369 _optixContext->createProgramFromPTXString(CUDA_CYLINDERS, OPTIX_CUDA_FUNCTION_INTERSECTION);
372 _optixContext->createProgramFromPTXString(CUDA_SPHERES, OPTIX_CUDA_FUNCTION_BOUNDS);
374 _optixContext->createProgramFromPTXString(CUDA_SPHERES, OPTIX_CUDA_FUNCTION_INTERSECTION);
377 _optixContext->createProgramFromPTXString(CUDA_TRIANGLES_MESH, OPTIX_CUDA_FUNCTION_BOUNDS);
379 _optixContext->createProgramFromPTXString(CUDA_TRIANGLES_MESH, OPTIX_CUDA_FUNCTION_INTERSECTION);
382 _optixContext->createProgramFromPTXString(CUDA_VOLUMES, OPTIX_CUDA_FUNCTION_BOUNDS);
384 _optixContext->createProgramFromPTXString(CUDA_VOLUMES, OPTIX_CUDA_FUNCTION_INTERSECTION);
385 _optixContext[CONTEXT_VOLUME_SIZE]->setUint(
sizeof(
VolumeGeometry) /
sizeof(
float));
388 _optixContext->createProgramFromPTXString(CUDA_STREAMLINES, OPTIX_CUDA_FUNCTION_BOUNDS);
390 _optixContext->createProgramFromPTXString(CUDA_STREAMLINES, OPTIX_CUDA_FUNCTION_INTERSECTION);
393 _optixContext->createProgramFromPTXString(CUDA_SDF_GEOMETRIES, OPTIX_CUDA_FUNCTION_BOUNDS);
395 _optixContext->createProgramFromPTXString(CUDA_SDF_GEOMETRIES, OPTIX_CUDA_FUNCTION_INTERSECTION);
398 _optixContext->createProgramFromPTXString(CUDA_FIELDS, OPTIX_CUDA_FUNCTION_BOUNDS);
400 _optixContext->createProgramFromPTXString(CUDA_FIELDS, OPTIX_CUDA_FUNCTION_INTERSECTION);
401 _optixContext[CONTEXT_FIELD_SIZE]->setUint(
sizeof(
FieldGeometry) /
sizeof(
float));
404 _optixContext[CONTEXT_EXCEPTION_BAD_COLOR]->setFloat(1.0f, 0.0f, 0.0f, 1.f);
408 void OptiXContext::_printSystemInformation()
const
410 unsigned int optixVersion;
413 unsigned int major = optixVersion / 1000;
419 major = optixVersion / 10000;
420 minor = (optixVersion % 10000) / 100;
421 micro = optixVersion % 100;
425 minor = (optixVersion % 1000) / 10;
426 micro = optixVersion % 10;
428 PLUGIN_INFO(
"OptiX " << major <<
"." << minor <<
"." << micro);
430 unsigned int numberOfDevices = 0;
432 PLUGIN_INFO(
"Number of Devices = " << numberOfDevices);
434 for (
unsigned int i = 0; i < numberOfDevices; ++i)
440 int computeCapability[2] = {0, 0};
442 sizeof(computeCapability), &computeCapability));
443 PLUGIN_INFO(
" Compute Support: " << computeCapability[0] <<
"." << computeCapability[1]);
445 RTsize totalMemory = 0;
447 rtDeviceGetAttribute(i, RT_DEVICE_ATTRIBUTE_TOTAL_MEMORY,
sizeof(totalMemory), &totalMemory));
448 PLUGIN_INFO(
" Total Memory: " << (
unsigned long long)(totalMemory / 1024 / 1024) <<
" MB");
452 rtDeviceGetAttribute(i, RT_DEVICE_ATTRIBUTE_CLOCK_RATE,
sizeof(clockRate), &clockRate));
453 PLUGIN_INFO(
" Clock Rate: " << (clockRate / 1000) <<
" MHz");
455 int maxThreadsPerBlock = 0;
457 sizeof(maxThreadsPerBlock), &maxThreadsPerBlock));
458 PLUGIN_INFO(
" Max. Threads per Block: " << maxThreadsPerBlock);
462 rtDeviceGetAttribute(i, RT_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
sizeof(smCount), &smCount));
463 PLUGIN_INFO(
" Streaming Multiprocessor Count: " << smCount);
465 int executionTimeoutEnabled = 0;
467 sizeof(executionTimeoutEnabled), &executionTimeoutEnabled));
468 PLUGIN_INFO(
" Execution Timeout Enabled: " << executionTimeoutEnabled);
470 int maxHardwareTextureCount = 0;
472 sizeof(maxHardwareTextureCount), &maxHardwareTextureCount));
473 PLUGIN_INFO(
" Max. Hardware Texture Count: " << maxHardwareTextureCount);
477 rtDeviceGetAttribute(i, RT_DEVICE_ATTRIBUTE_TCC_DRIVER,
sizeof(tccDriver), &tccDriver));
480 int cudaDeviceOrdinal = 0;
482 sizeof(cudaDeviceOrdinal), &cudaDeviceOrdinal));
483 PLUGIN_INFO(
" CUDA Device Ordinal: " << cudaDeviceOrdinal);
489 ::optix::Geometry geometry = _optixContext->createGeometry();
490 geometry->setBoundingBoxProgram(_optixBoundsPrograms[type]);
491 geometry->setIntersectionProgram(_optixIntersectionPrograms[type]);
497 auto group = _optixContext->createGeometryGroup();
499 _optixContext->createAcceleration(
compact ? OPTIX_ACCELERATION_TYPE_SBVH : DEFAULT_ACCELERATION_STRUCTURE);
500 accel->setProperty(OPTIX_ACCELERATION_VERTEX_BUFFER_NAME,
"vertices_buffer");
501 accel->setProperty(OPTIX_ACCELERATION_VERTEX_BUFFER_STRIDE,
"12");
502 accel->setProperty(OPTIX_ACCELERATION_INDEX_BUFFER_NAME,
"indices_buffer");
503 accel->setProperty(OPTIX_ACCELERATION_INDEX_BUFFER_STRIDE,
"12");
504 group->setAcceleration(accel);
510 auto group = _optixContext->createGroup();
511 group->setAcceleration(_optixContext->createAcceleration(DEFAULT_ACCELERATION_STRUCTURE));
const size_t OPTIX_STACK_SIZE
const size_t OPTIX_ENTRY_POINT_COUNT
const size_t OPTIX_RAY_TYPE_COUNT
#define RT_CHECK_ERROR_NO_CONTEXT(func)
#define RT_DESTROY_MAP(__map)
#define RT_DESTROY(__object)
const T * getRawData(const uint8_t face=0, const uint8_t mip=0) const
OptiXCameraProgramPtr getCamera(const std::string &name)
void addCamera(const std::string &name, OptiXCameraProgramPtr program)
OptiXShaderProgramPtr getRenderer(const std::string &name)
::optix::GeometryGroup createGeometryGroup(const bool compact)
::optix::Group createGroup()
static OptiXContext & get()
::optix::Material createMaterial()
::optix::Geometry createGeometry(const OptixGeometryType type)
void addRenderer(const std::string &name, OptiXShaderProgramPtr program)
::optix::TextureSampler createTextureSampler(Texture2DPtr texture)
void setCamera(const std::string &name)
std::shared_ptr< OptiXCameraProgram > OptiXCameraProgramPtr
std::shared_ptr< OptixShaderProgram > OptiXShaderProgramPtr
std::shared_ptr< Texture2D > Texture2DPtr