godot/thirdparty/oidn/core/device.cpp
2021-01-14 18:02:07 +01:00

239 lines
7.0 KiB
C++

// ======================================================================== //
// Copyright 2009-2019 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#include "device.h"
#include "autoencoder.h"
namespace oidn {
thread_local Device::ErrorState Device::globalError;
Device::Device()
{
if (!mayiuse(sse41))
throw Exception(Error::UnsupportedHardware, "SSE4.1 support is required at minimum");
}
Device::~Device()
{
// -- GODOT start --
//observer.reset();
// -- GODOT end --
}
void Device::setError(Device* device, Error code, const std::string& message)
{
// Update the stored error only if the previous error was queried
if (device)
{
ErrorState& curError = device->error.get();
if (curError.code == Error::None)
{
curError.code = code;
curError.message = message;
}
// Print the error message in verbose mode
if (device->isVerbose())
std::cerr << "Error: " << message << std::endl;
// Call the error callback function
ErrorFunction errorFunc;
void* errorUserPtr;
{
std::lock_guard<std::mutex> lock(device->mutex);
errorFunc = device->errorFunc;
errorUserPtr = device->errorUserPtr;
}
if (errorFunc)
errorFunc(errorUserPtr, code, (code == Error::None) ? nullptr : message.c_str());
}
else
{
if (globalError.code == Error::None)
{
globalError.code = code;
globalError.message = message;
}
}
}
Error Device::getError(Device* device, const char** outMessage)
{
// Return and clear the stored error code, but keep the error message so pointers to it will
// remain valid until the next getError call
if (device)
{
ErrorState& curError = device->error.get();
const Error code = curError.code;
if (outMessage)
*outMessage = (code == Error::None) ? nullptr : curError.message.c_str();
curError.code = Error::None;
return code;
}
else
{
const Error code = globalError.code;
if (outMessage)
*outMessage = (code == Error::None) ? nullptr : globalError.message.c_str();
globalError.code = Error::None;
return code;
}
}
void Device::setErrorFunction(ErrorFunction func, void* userPtr)
{
errorFunc = func;
errorUserPtr = userPtr;
}
int Device::get1i(const std::string& name)
{
if (name == "numThreads")
return numThreads;
else if (name == "setAffinity")
return setAffinity;
else if (name == "verbose")
return verbose;
else if (name == "version")
return OIDN_VERSION;
else if (name == "versionMajor")
return OIDN_VERSION_MAJOR;
else if (name == "versionMinor")
return OIDN_VERSION_MINOR;
else if (name == "versionPatch")
return OIDN_VERSION_PATCH;
else
throw Exception(Error::InvalidArgument, "invalid parameter");
}
void Device::set1i(const std::string& name, int value)
{
if (name == "numThreads")
numThreads = value;
else if (name == "setAffinity")
setAffinity = value;
else if (name == "verbose")
{
verbose = value;
error.verbose = value;
}
dirty = true;
}
void Device::commit()
{
if (isCommitted())
throw Exception(Error::InvalidOperation, "device can be committed only once");
// -- GODOT start --
#if 0
// -- GODOT end --
// Get the optimal thread affinities
if (setAffinity)
{
affinity = std::make_shared<ThreadAffinity>(1, verbose); // one thread per core
if (affinity->getNumThreads() == 0)
affinity.reset();
}
// Create the task arena
const int maxNumThreads = affinity ? affinity->getNumThreads() : tbb::this_task_arena::max_concurrency();
numThreads = (numThreads > 0) ? min(numThreads, maxNumThreads) : maxNumThreads;
arena = std::make_shared<tbb::task_arena>(numThreads);
// Automatically set the thread affinities
if (affinity)
observer = std::make_shared<PinningObserver>(affinity, *arena);
// -- GODOT start --
#endif
numThreads = 1;
// -- GODOT end --
dirty = false;
if (isVerbose())
print();
}
void Device::checkCommitted()
{
if (dirty)
throw Exception(Error::InvalidOperation, "changes to the device are not committed");
}
Ref<Buffer> Device::newBuffer(size_t byteSize)
{
checkCommitted();
return makeRef<Buffer>(Ref<Device>(this), byteSize);
}
Ref<Buffer> Device::newBuffer(void* ptr, size_t byteSize)
{
checkCommitted();
return makeRef<Buffer>(Ref<Device>(this), ptr, byteSize);
}
Ref<Filter> Device::newFilter(const std::string& type)
{
checkCommitted();
if (isVerbose())
std::cout << "Filter: " << type << std::endl;
Ref<Filter> filter;
// -- GODOT start --
// Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
#if 0
// -- GODOT end --
if (type == "RT")
filter = makeRef<RTFilter>(Ref<Device>(this));
// -- GODOT start --
// Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
#endif
if (type == "RTLightmap")
// -- GODOT end --
filter = makeRef<RTLightmapFilter>(Ref<Device>(this));
else
throw Exception(Error::InvalidArgument, "unknown filter type");
return filter;
}
void Device::print()
{
std::cout << std::endl;
std::cout << "Intel(R) Open Image Denoise " << OIDN_VERSION_STRING << std::endl;
std::cout << " Compiler: " << getCompilerName() << std::endl;
std::cout << " Build : " << getBuildName() << std::endl;
std::cout << " Platform: " << getPlatformName() << std::endl;
// -- GODOT start --
// std::cout << " Tasking :";
// std::cout << " TBB" << TBB_VERSION_MAJOR << "." << TBB_VERSION_MINOR;
// std::cout << " TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << tbb::TBB_runtime_interface_version();
// std::cout << std::endl;
// -- GODOT end --
std::cout << std::endl;
}
} // namespace oidn