mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-06 02:18:05 +08:00
Source Level Debugger - adding notifications
- notifySourceCode, notifyKernelDebugData, notifyDeviceDestruction - added processDebugData method in Program - change options when SLD is active - add space at the beginning of extension list options Change-Id: Iac1e52f849544dbfda62407e112cde83fa94e3ad
This commit is contained in:
committed by
sys_ocldev
parent
cec056f3c4
commit
b59a5f1910
@@ -108,6 +108,10 @@ Device::~Device() {
|
||||
commandStreamReceiver = nullptr;
|
||||
}
|
||||
|
||||
if (deviceInfo.sourceLevelDebuggerActive && sourceLevelDebugger) {
|
||||
sourceLevelDebugger->notifyDeviceDestruction();
|
||||
}
|
||||
|
||||
if (memoryManager) {
|
||||
if (preemptionAllocation) {
|
||||
memoryManager->freeGraphicsMemory(preemptionAllocation);
|
||||
|
||||
@@ -136,6 +136,7 @@ class Device : public BaseObject<_cl_device_id> {
|
||||
std::string deviceExtensions;
|
||||
bool getEnabled64kbPages();
|
||||
bool isSourceLevelDebuggerActive() const;
|
||||
SourceLevelDebugger *getSourceLevelDebugger() { return sourceLevelDebugger.get(); }
|
||||
|
||||
protected:
|
||||
Device() = delete;
|
||||
|
||||
@@ -83,7 +83,7 @@ std::string convertEnabledExtensionsToCompilerInternalOptions(const char *enable
|
||||
while ((pos = extensionsList.find(" ", pos)) != std::string::npos) {
|
||||
extensionsList.replace(pos, 1, ",+");
|
||||
}
|
||||
extensionsList = "-cl-ext=-all,+" + extensionsList;
|
||||
extensionsList = " -cl-ext=-all,+" + extensionsList;
|
||||
return extensionsList;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "runtime/compiler_interface/compiler_options.h"
|
||||
#include "runtime/os_interface/debug_settings_manager.h"
|
||||
#include "runtime/platform/platform.h"
|
||||
#include "runtime/source_level_debugger/source_level_debugger.h"
|
||||
#include "runtime/helpers/validators.h"
|
||||
#include "program.h"
|
||||
#include <cstring>
|
||||
@@ -91,13 +92,24 @@ cl_int Program::build(
|
||||
break;
|
||||
}
|
||||
|
||||
internalOptions.append(platform()->peekCompilerExtensions());
|
||||
|
||||
if (isKernelDebugEnabled()) {
|
||||
internalOptions.append(CompilerOptions::debugKernelEnable);
|
||||
options.append(" -g ");
|
||||
if (pDevice->getSourceLevelDebugger()) {
|
||||
if (pDevice->getSourceLevelDebugger()->isOptimizationDisabled()) {
|
||||
options.append("-cl-opt-disable ");
|
||||
}
|
||||
std::string filename;
|
||||
pDevice->getSourceLevelDebugger()->notifySourceCode(sourceCode.c_str(), sourceCode.size(), filename);
|
||||
if (!filename.empty()) {
|
||||
// Add "-s" flag first so it will be ignored by clang in case the options already have this flag set.
|
||||
options = std::string("-s ") + filename + " " + options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internalOptions.append(platform()->peekCompilerExtensions());
|
||||
|
||||
inputArgs.pInput = (char *)(sourceCode.c_str());
|
||||
inputArgs.InputSize = (uint32_t)sourceCode.size();
|
||||
inputArgs.pOptions = options.c_str();
|
||||
@@ -122,6 +134,15 @@ cl_int Program::build(
|
||||
break;
|
||||
}
|
||||
|
||||
if (isKernelDebugEnabled()) {
|
||||
processDebugData();
|
||||
if (pDevice->getSourceLevelDebugger()) {
|
||||
for (size_t i = 0; i < kernelInfoArray.size(); i++) {
|
||||
pDevice->getSourceLevelDebugger()->notifyKernelDebugData(kernelInfoArray[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
separateBlockKernels();
|
||||
} while (false);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "runtime/compiler_interface/compiler_interface.h"
|
||||
#include "runtime/compiler_interface/compiler_options.h"
|
||||
#include "runtime/platform/platform.h"
|
||||
#include "runtime/source_level_debugger/source_level_debugger.h"
|
||||
#include "runtime/helpers/validators.h"
|
||||
#include "program.h"
|
||||
#include <cstring>
|
||||
@@ -155,6 +156,16 @@ cl_int Program::compile(
|
||||
if (isKernelDebugEnabled()) {
|
||||
internalOptions.append(CompilerOptions::debugKernelEnable);
|
||||
options.append(" -g ");
|
||||
if (pDevice->getSourceLevelDebugger()) {
|
||||
if (pDevice->getSourceLevelDebugger()->isOptimizationDisabled()) {
|
||||
options.append("-cl-opt-disable ");
|
||||
}
|
||||
std::string filename;
|
||||
pDevice->getSourceLevelDebugger()->notifySourceCode(sourceCode.c_str(), sourceCode.size(), filename);
|
||||
if (!filename.empty()) {
|
||||
options = std::string("-s ") + filename + " " + options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inputArgs.pInput = pCompileData;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "runtime/compiler_interface/compiler_interface.h"
|
||||
#include "runtime/platform/platform.h"
|
||||
#include "runtime/helpers/validators.h"
|
||||
#include "runtime/source_level_debugger/source_level_debugger.h"
|
||||
#include "program.h"
|
||||
#include "elf/writer.h"
|
||||
#include <cstring>
|
||||
@@ -147,6 +148,13 @@ cl_int Program::link(
|
||||
break;
|
||||
}
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
|
||||
|
||||
if (isKernelDebugEnabled()) {
|
||||
processDebugData();
|
||||
for (size_t i = 0; i < kernelInfoArray.size(); i++) {
|
||||
pDevice->getSourceLevelDebugger()->notifyKernelDebugData(kernelInfoArray[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
retVal = pCompilerInterface->createLibrary(*this, inputArgs);
|
||||
if (retVal != CL_SUCCESS) {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "runtime/memory_manager/memory_manager.h"
|
||||
#include "patch_list.h"
|
||||
#include "patch_shared.h"
|
||||
#include "program_debug_data.h"
|
||||
#include "program.h"
|
||||
#include "runtime/kernel/kernel.h"
|
||||
|
||||
@@ -992,4 +993,34 @@ bool Program::validateGenBinaryHeader(const iOpenCL::SProgramBinaryHeader *pGenB
|
||||
pGenBinaryHeader->Version == CURRENT_ICBE_VERSION &&
|
||||
validateGenBinaryDevice(static_cast<GFXCORE_FAMILY>(pGenBinaryHeader->Device));
|
||||
}
|
||||
|
||||
void Program::processDebugData() {
|
||||
if (debugData != nullptr) {
|
||||
SProgramDebugDataHeaderIGC *programDebugHeader = reinterpret_cast<SProgramDebugDataHeaderIGC *>(debugData);
|
||||
|
||||
DEBUG_BREAK_IF(programDebugHeader->NumberOfKernels != kernelInfoArray.size());
|
||||
|
||||
const SKernelDebugDataHeaderIGC *kernelDebugHeader = reinterpret_cast<SKernelDebugDataHeaderIGC *>(ptrOffset(programDebugHeader, sizeof(SProgramDebugDataHeaderIGC)));
|
||||
const char *kernelName = nullptr;
|
||||
const char *kernelDebugData = nullptr;
|
||||
|
||||
for (uint32_t i = 0; i < programDebugHeader->NumberOfKernels; i++) {
|
||||
kernelName = reinterpret_cast<const char *>(ptrOffset(kernelDebugHeader, sizeof(SKernelDebugDataHeaderIGC)));
|
||||
|
||||
auto kernelInfo = kernelInfoArray[i];
|
||||
UNRECOVERABLE_IF(kernelInfo->name.compare(0, kernelInfo->name.size(), kernelName) != 0);
|
||||
|
||||
kernelDebugData = ptrOffset(kernelName, kernelDebugHeader->KernelNameSize);
|
||||
|
||||
kernelInfo->debugData.vIsa = kernelDebugData;
|
||||
kernelInfo->debugData.genIsa = ptrOffset(kernelDebugData, kernelDebugHeader->SizeVisaDbgInBytes);
|
||||
kernelInfo->debugData.vIsaSize = kernelDebugHeader->SizeVisaDbgInBytes;
|
||||
kernelInfo->debugData.genIsaSize = kernelDebugHeader->SizeGenIsaDbgInBytes;
|
||||
|
||||
kernelDebugData = ptrOffset(kernelDebugData, kernelDebugHeader->SizeVisaDbgInBytes + kernelDebugHeader->SizeGenIsaDbgInBytes);
|
||||
kernelDebugHeader = reinterpret_cast<const SKernelDebugDataHeaderIGC *>(kernelDebugData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OCLRT
|
||||
|
||||
@@ -87,6 +87,7 @@ Program::Program(Context *context, bool isBuiltIn) : context(context), isBuiltIn
|
||||
if (DebugManager.flags.DisableStatelessToStatefulOptimization.get()) {
|
||||
internalOptions += "-cl-intel-greater-than-4GB-buffer-required ";
|
||||
}
|
||||
kernelDebugEnabled = pDevice->isSourceLevelDebuggerActive();
|
||||
}
|
||||
|
||||
if (DebugManager.flags.EnableStatelessToStatefulBufferOffsetOpt.get()) {
|
||||
|
||||
@@ -188,6 +188,7 @@ class Program : public BaseObject<_cl_program> {
|
||||
void storeLlvmBinary(const void *pSrc, const size_t srcSize);
|
||||
|
||||
void storeDebugData(const void *pSrc, const size_t srcSize);
|
||||
void processDebugData();
|
||||
|
||||
void updateBuildLog(const Device *pDevice, const char *pErrorString, const size_t errorStringSize);
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ const char *SourceLevelDebugger::getDebuggerOptionSymbol = "getDebuggerOption";
|
||||
const char *SourceLevelDebugger::notifyKernelDebugDataSymbol = "notifyKernelDebugData";
|
||||
const char *SourceLevelDebugger::initSymbol = "init";
|
||||
const char *SourceLevelDebugger::isDebuggerActiveSymbol = "isDebuggerActive";
|
||||
const char *SourceLevelDebugger::notifyDeviceDestructionSymbol = "notifyDeviceDestruction";
|
||||
|
||||
class SourceLevelDebugger::SourceLevelDebuggerInterface {
|
||||
public:
|
||||
@@ -46,6 +47,7 @@ class SourceLevelDebugger::SourceLevelDebuggerInterface {
|
||||
typedef int (*NotifyKernelDebugDataFunction)(GfxDbgKernelDebugData *data);
|
||||
typedef int (*InitFunction)(GfxDbgTargetCaps *data);
|
||||
typedef int (*IsDebuggerActiveFunction)(void);
|
||||
typedef int (*NotifyDeviceDestructionFunction)(GfxDbgDeviceDestructionData *data);
|
||||
|
||||
NotifyNewDeviceFunction notifyNewDeviceFunc = nullptr;
|
||||
NotifySourceCodeFunction notifySourceCodeFunc = nullptr;
|
||||
@@ -53,6 +55,7 @@ class SourceLevelDebugger::SourceLevelDebuggerInterface {
|
||||
NotifyKernelDebugDataFunction notifyKernelDebugDataFunc = nullptr;
|
||||
InitFunction initFunc = nullptr;
|
||||
IsDebuggerActiveFunction isDebuggerActive = nullptr;
|
||||
NotifyDeviceDestructionFunction notifyDeviceDestructionFunc = nullptr;
|
||||
};
|
||||
|
||||
SourceLevelDebugger *SourceLevelDebugger::create() {
|
||||
@@ -88,6 +91,7 @@ SourceLevelDebugger::SourceLevelDebugger(OsLibrary *library) {
|
||||
UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyKernelDebugDataFunc == nullptr);
|
||||
UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyNewDeviceFunc == nullptr);
|
||||
UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifySourceCodeFunc == nullptr);
|
||||
UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyDeviceDestructionFunc == nullptr);
|
||||
isActive = true;
|
||||
}
|
||||
}
|
||||
@@ -111,31 +115,55 @@ void SourceLevelDebugger::getFunctions() {
|
||||
sourceLevelDebuggerInterface->notifyKernelDebugDataFunc = reinterpret_cast<SourceLevelDebuggerInterface::NotifyKernelDebugDataFunction>(debuggerLibrary->getProcAddress(notifyKernelDebugDataSymbol));
|
||||
sourceLevelDebuggerInterface->initFunc = reinterpret_cast<SourceLevelDebuggerInterface::InitFunction>(debuggerLibrary->getProcAddress(initSymbol));
|
||||
sourceLevelDebuggerInterface->isDebuggerActive = reinterpret_cast<SourceLevelDebuggerInterface::IsDebuggerActiveFunction>(debuggerLibrary->getProcAddress(isDebuggerActiveSymbol));
|
||||
sourceLevelDebuggerInterface->notifyDeviceDestructionFunc = reinterpret_cast<SourceLevelDebuggerInterface::NotifyDeviceDestructionFunction>(debuggerLibrary->getProcAddress(notifyDeviceDestructionSymbol));
|
||||
}
|
||||
|
||||
void SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) const {
|
||||
bool SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) {
|
||||
if (isActive) {
|
||||
GfxDbgNewDeviceData newDevice;
|
||||
newDevice.version = IGFXDBG_CURRENT_VERSION;
|
||||
newDevice.dh = reinterpret_cast<GfxDeviceHandle>(static_cast<uint64_t>(deviceHandle));
|
||||
newDevice.udh = GfxDeviceHandle(0);
|
||||
sourceLevelDebuggerInterface->notifyNewDeviceFunc(&newDevice);
|
||||
int result = sourceLevelDebuggerInterface->notifyNewDeviceFunc(&newDevice);
|
||||
DEBUG_BREAK_IF(static_cast<IgfxdbgRetVal>(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS);
|
||||
static_cast<void>(result);
|
||||
this->deviceHandle = deviceHandle;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void SourceLevelDebugger::notifySourceCode(uint32_t deviceHandle, const char *source, size_t sourceSize) const {
|
||||
|
||||
bool SourceLevelDebugger::notifyDeviceDestruction() {
|
||||
if (isActive) {
|
||||
GfxDbgDeviceDestructionData deviceDestruction;
|
||||
deviceDestruction.version = IGFXDBG_CURRENT_VERSION;
|
||||
deviceDestruction.dh = reinterpret_cast<GfxDeviceHandle>(static_cast<uint64_t>(this->deviceHandle));
|
||||
int result = sourceLevelDebuggerInterface->notifyDeviceDestructionFunc(&deviceDestruction);
|
||||
DEBUG_BREAK_IF(static_cast<IgfxdbgRetVal>(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS);
|
||||
static_cast<void>(result);
|
||||
this->deviceHandle = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SourceLevelDebugger::notifySourceCode(const char *source, size_t sourceSize, std::string &file) const {
|
||||
if (isActive) {
|
||||
GfxDbgSourceCode sourceCode;
|
||||
char fileName[FILENAME_MAX] = "";
|
||||
|
||||
sourceCode.version = IGFXDBG_CURRENT_VERSION;
|
||||
sourceCode.hDevice = reinterpret_cast<GfxDeviceHandle>(static_cast<uint64_t>(deviceHandle));
|
||||
sourceCode.hDevice = reinterpret_cast<GfxDeviceHandle>(static_cast<uint64_t>(this->deviceHandle));
|
||||
sourceCode.sourceCode = source;
|
||||
sourceCode.sourceCodeSize = static_cast<unsigned int>(sourceSize);
|
||||
sourceCode.sourceName = &fileName[0];
|
||||
sourceCode.sourceNameMaxLen = sizeof(fileName);
|
||||
|
||||
sourceLevelDebuggerInterface->notifySourceCodeFunc(&sourceCode);
|
||||
int result = sourceLevelDebuggerInterface->notifySourceCodeFunc(&sourceCode);
|
||||
DEBUG_BREAK_IF(static_cast<IgfxdbgRetVal>(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS);
|
||||
static_cast<void>(result);
|
||||
file = fileName;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SourceLevelDebugger::isOptimizationDisabled() const {
|
||||
@@ -157,10 +185,10 @@ bool SourceLevelDebugger::isOptimizationDisabled() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void SourceLevelDebugger::notifyKernelDebugData(uint32_t deviceHandle, const KernelInfo *kernelInfo) const {
|
||||
bool SourceLevelDebugger::notifyKernelDebugData(const KernelInfo *kernelInfo) const {
|
||||
if (isActive) {
|
||||
GfxDbgKernelDebugData kernelDebugData;
|
||||
kernelDebugData.hDevice = reinterpret_cast<GfxDeviceHandle>(static_cast<uint64_t>(deviceHandle));
|
||||
kernelDebugData.hDevice = reinterpret_cast<GfxDeviceHandle>(static_cast<uint64_t>(this->deviceHandle));
|
||||
kernelDebugData.version = IGFXDBG_CURRENT_VERSION;
|
||||
kernelDebugData.hProgram = reinterpret_cast<GenRtProgramHandle>(0);
|
||||
|
||||
@@ -173,11 +201,14 @@ void SourceLevelDebugger::notifyKernelDebugData(uint32_t deviceHandle, const Ker
|
||||
kernelDebugData.dbgGenIsaBuffer = kernelInfo->debugData.genIsa;
|
||||
kernelDebugData.dbgGenIsaSize = kernelInfo->debugData.genIsaSize;
|
||||
|
||||
sourceLevelDebuggerInterface->notifyKernelDebugDataFunc(&kernelDebugData);
|
||||
int result = sourceLevelDebuggerInterface->notifyKernelDebugDataFunc(&kernelDebugData);
|
||||
DEBUG_BREAK_IF(static_cast<IgfxdbgRetVal>(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS);
|
||||
static_cast<void>(result);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SourceLevelDebugger::initialize(bool useLocalMemory) {
|
||||
bool SourceLevelDebugger::initialize(bool useLocalMemory) {
|
||||
if (isActive) {
|
||||
GfxDbgTargetCaps caps = {IGFXDBG_CURRENT_VERSION, useLocalMemory};
|
||||
int result = sourceLevelDebuggerInterface->initFunc(&caps);
|
||||
@@ -185,5 +216,6 @@ void SourceLevelDebugger::initialize(bool useLocalMemory) {
|
||||
isActive = false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace OCLRT
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
#include "runtime/os_interface/os_library.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace OCLRT {
|
||||
struct KernelInfo;
|
||||
@@ -30,17 +31,18 @@ struct KernelInfo;
|
||||
class SourceLevelDebugger {
|
||||
public:
|
||||
SourceLevelDebugger(OsLibrary *library);
|
||||
~SourceLevelDebugger();
|
||||
virtual ~SourceLevelDebugger();
|
||||
SourceLevelDebugger(const SourceLevelDebugger &ref) = delete;
|
||||
SourceLevelDebugger &operator=(const SourceLevelDebugger &) = delete;
|
||||
static SourceLevelDebugger *create();
|
||||
|
||||
bool isDebuggerActive();
|
||||
void notifyNewDevice(uint32_t deviceHandle) const;
|
||||
void notifySourceCode(uint32_t deviceHandle, const char *sourceCode, size_t size) const;
|
||||
bool isOptimizationDisabled() const;
|
||||
void notifyKernelDebugData(uint32_t deviceHandle, const KernelInfo *kernelInfo) const;
|
||||
void initialize(bool useLocalMemory);
|
||||
MOCKABLE_VIRTUAL bool isDebuggerActive();
|
||||
MOCKABLE_VIRTUAL bool notifyNewDevice(uint32_t deviceHandle);
|
||||
MOCKABLE_VIRTUAL bool notifyDeviceDestruction();
|
||||
MOCKABLE_VIRTUAL bool notifySourceCode(const char *sourceCode, size_t size, std::string &filename) const;
|
||||
MOCKABLE_VIRTUAL bool isOptimizationDisabled() const;
|
||||
MOCKABLE_VIRTUAL bool notifyKernelDebugData(const KernelInfo *kernelInfo) const;
|
||||
MOCKABLE_VIRTUAL bool initialize(bool useLocalMemory);
|
||||
|
||||
protected:
|
||||
class SourceLevelDebuggerInterface;
|
||||
@@ -51,6 +53,7 @@ class SourceLevelDebugger {
|
||||
|
||||
std::unique_ptr<OsLibrary> debuggerLibrary;
|
||||
bool isActive = false;
|
||||
uint32_t deviceHandle = 0;
|
||||
|
||||
static const char *notifyNewDeviceSymbol;
|
||||
static const char *notifySourceCodeSymbol;
|
||||
@@ -58,6 +61,7 @@ class SourceLevelDebugger {
|
||||
static const char *notifyKernelDebugDataSymbol;
|
||||
static const char *initSymbol;
|
||||
static const char *isDebuggerActiveSymbol;
|
||||
static const char *notifyDeviceDestructionSymbol;
|
||||
// OS specific library name
|
||||
static const char *dllName;
|
||||
};
|
||||
|
||||
@@ -39,16 +39,28 @@ bool SourceLevelDebugger::isDebuggerActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) const {
|
||||
bool SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) {
|
||||
return false;
|
||||
}
|
||||
void SourceLevelDebugger::notifySourceCode(uint32_t deviceHandle, const char *sourceCode, size_t size) const {
|
||||
|
||||
bool SourceLevelDebugger::notifyDeviceDestruction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SourceLevelDebugger::notifySourceCode(const char *sourceCode, size_t size, std::string &filename) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SourceLevelDebugger::isOptimizationDisabled() const {
|
||||
return false;
|
||||
}
|
||||
void SourceLevelDebugger::notifyKernelDebugData(uint32_t deviceHandle, const KernelInfo *kernelInfo) const {
|
||||
|
||||
bool SourceLevelDebugger::notifyKernelDebugData(const KernelInfo *kernelInfo) const {
|
||||
return false;
|
||||
}
|
||||
void SourceLevelDebugger::initialize(bool useLocalMemory) {
|
||||
|
||||
bool SourceLevelDebugger::initialize(bool useLocalMemory) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace OCLRT
|
||||
|
||||
Reference in New Issue
Block a user