mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-08 22:12:59 +08:00
Create enum wrapper for drm engine class values
Related-To: NEO-6852, NEO-6999 Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
1e7d789e63
commit
0420df780d
@@ -51,7 +51,7 @@ class DrmPrelimMock : public DrmMock {
|
||||
}
|
||||
|
||||
bool queryEngineInfo() override {
|
||||
uint16_t computeEngineClass = getIoctlHelper()->getComputeEngineClass();
|
||||
uint16_t computeEngineClass = getIoctlHelper()->getDrmParamValue(DrmParam::EngineClassCompute);
|
||||
std::vector<EngineCapabilities> engines(4);
|
||||
engines[0].engine = {computeEngineClass, 0};
|
||||
engines[0].capabilities = 0;
|
||||
@@ -82,7 +82,7 @@ class DrmPrelimMock : public DrmMock {
|
||||
}
|
||||
|
||||
bool queryEngineInfo1SubDevice() {
|
||||
uint16_t computeEngineClass = getIoctlHelper()->getComputeEngineClass();
|
||||
uint16_t computeEngineClass = getIoctlHelper()->getDrmParamValue(DrmParam::EngineClassCompute);
|
||||
std::vector<EngineCapabilities> engines(1);
|
||||
engines[0].engine = {computeEngineClass, 0};
|
||||
engines[0].capabilities = 0;
|
||||
|
||||
@@ -324,7 +324,7 @@ void Drm::setLowPriorityContextParam(uint32_t drmContextId) {
|
||||
int Drm::getQueueSliceCount(GemContextParamSseu *sseu) {
|
||||
GemContextParam contextParam = {};
|
||||
contextParam.param = I915_CONTEXT_PARAM_SSEU;
|
||||
sseu->engine.engineClass = I915_ENGINE_CLASS_RENDER;
|
||||
sseu->engine.engineClass = ioctlHelper->getDrmParamValue(DrmParam::EngineClassRender);
|
||||
sseu->engine.engineInstance = I915_EXEC_DEFAULT;
|
||||
contextParam.value = reinterpret_cast<uint64_t>(sseu);
|
||||
contextParam.size = sizeof(struct GemContextParamSseu);
|
||||
@@ -1016,25 +1016,18 @@ bool Drm::queryEngineInfo(bool isSysmanEnabled) {
|
||||
distanceInfo.region = region.region;
|
||||
|
||||
for (const auto &engine : engines) {
|
||||
switch (engine.engine.engineClass) {
|
||||
case I915_ENGINE_CLASS_RENDER:
|
||||
case I915_ENGINE_CLASS_COPY:
|
||||
if (engine.engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassCompute) ||
|
||||
engine.engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassRender) ||
|
||||
engine.engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassCopy)) {
|
||||
distanceInfo.engine = engine.engine;
|
||||
distanceInfos.push_back(distanceInfo);
|
||||
break;
|
||||
case I915_ENGINE_CLASS_VIDEO:
|
||||
case I915_ENGINE_CLASS_VIDEO_ENHANCE:
|
||||
if (isSysmanEnabled == true) {
|
||||
} else if (isSysmanEnabled) {
|
||||
|
||||
if (engine.engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassVideo) ||
|
||||
engine.engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassVideoEnhance)) {
|
||||
distanceInfo.engine = engine.engine;
|
||||
distanceInfos.push_back(distanceInfo);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (engine.engine.engineClass == ioctlHelper->getComputeEngineClass()) {
|
||||
distanceInfo.engine = engine.engine;
|
||||
distanceInfos.push_back(distanceInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1218,14 +1211,14 @@ unsigned int Drm::bindDrmContext(uint32_t drmContextId, uint32_t deviceIndex, au
|
||||
|
||||
bool setupVirtualEngines = false;
|
||||
unsigned int engineCount = static_cast<unsigned int>(numberOfCCS);
|
||||
if (useVirtualEnginesForCcs && engine->engineClass == ioctlHelper->getComputeEngineClass() && numberOfCCS > 1u) {
|
||||
if (useVirtualEnginesForCcs && engine->engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassCompute) && numberOfCCS > 1u) {
|
||||
numEnginesInContext = numberOfCCS + 1;
|
||||
balancer.num_siblings = numberOfCCS;
|
||||
setupVirtualEngines = true;
|
||||
}
|
||||
|
||||
bool includeMainCopyEngineInGroup = false;
|
||||
if (useVirtualEnginesForBcs && engine->engineClass == I915_ENGINE_CLASS_COPY && numberOfBCS > 1u) {
|
||||
if (useVirtualEnginesForBcs && engine->engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassCopy) && numberOfBCS > 1u) {
|
||||
numEnginesInContext = static_cast<uint32_t>(numberOfBCS) + 1;
|
||||
balancer.num_siblings = numberOfBCS;
|
||||
setupVirtualEngines = true;
|
||||
@@ -1242,11 +1235,11 @@ unsigned int Drm::bindDrmContext(uint32_t drmContextId, uint32_t deviceIndex, au
|
||||
if (setupVirtualEngines) {
|
||||
balancer.base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE;
|
||||
contextEngines.extensions = castToUint64(&balancer);
|
||||
contextEngines.engines[0].engine_class = I915_ENGINE_CLASS_INVALID;
|
||||
contextEngines.engines[0].engine_instance = I915_ENGINE_CLASS_INVALID_NONE;
|
||||
contextEngines.engines[0].engine_class = ioctlHelper->getDrmParamValue(DrmParam::EngineClassInvalid);
|
||||
contextEngines.engines[0].engine_instance = ioctlHelper->getDrmParamValue(DrmParam::EngineClassInvalidNone);
|
||||
|
||||
for (auto engineIndex = 0u; engineIndex < engineCount; engineIndex++) {
|
||||
if (useVirtualEnginesForBcs && engine->engineClass == I915_ENGINE_CLASS_COPY) {
|
||||
if (useVirtualEnginesForBcs && engine->engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassCopy)) {
|
||||
auto mappedBcsEngineType = static_cast<aub_stream::EngineType>(EngineHelpers::mapBcsIndexToEngineType(engineIndex, includeMainCopyEngineInGroup));
|
||||
bool isBcsEnabled = rootDeviceEnvironment.getHardwareInfo()->featureTable.ftrBcsInfo.test(EngineHelpers::getBcsIndex(mappedBcsEngineType));
|
||||
|
||||
@@ -1258,7 +1251,7 @@ unsigned int Drm::bindDrmContext(uint32_t drmContextId, uint32_t deviceIndex, au
|
||||
}
|
||||
UNRECOVERABLE_IF(!engine);
|
||||
|
||||
if (useVirtualEnginesForCcs && engine->engineClass == ioctlHelper->getComputeEngineClass()) {
|
||||
if (useVirtualEnginesForCcs && engine->engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassCompute)) {
|
||||
engine = engineInfo->getEngineInstance(deviceIndex, static_cast<aub_stream::EngineType>(EngineHelpers::mapCcsIndexToEngineType(engineIndex)));
|
||||
}
|
||||
UNRECOVERABLE_IF(!engine);
|
||||
|
||||
@@ -236,5 +236,15 @@ enum class DrmIoctl {
|
||||
GemCacheReserve,
|
||||
};
|
||||
|
||||
enum class DrmParam {
|
||||
EngineClassRender,
|
||||
EngineClassCompute,
|
||||
EngineClassCopy,
|
||||
EngineClassVideo,
|
||||
EngineClassVideoEnhance,
|
||||
EngineClassInvalid,
|
||||
EngineClassInvalidNone,
|
||||
};
|
||||
|
||||
unsigned int getIoctlRequestValue(DrmIoctl ioctlRequest, IoctlHelper *ioctlHelper);
|
||||
} // namespace NEO
|
||||
|
||||
@@ -55,24 +55,20 @@ EngineInfo::EngineInfo(Drm *drm, HardwareInfo *hwInfo, const std::vector<EngineC
|
||||
uint32_t numHostLinkCopyEngines = 0;
|
||||
uint32_t numScaleUpLinkCopyEngines = 0;
|
||||
|
||||
auto ioctlHelper = drm->getIoctlHelper();
|
||||
|
||||
for (const auto &engineInfo : engineInfos) {
|
||||
auto &engine = engineInfo.engine;
|
||||
tileToEngineMap.emplace(0, engine);
|
||||
switch (engine.engineClass) {
|
||||
case I915_ENGINE_CLASS_RENDER:
|
||||
if (engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassRender)) {
|
||||
tileToEngineToInstanceMap[0][EngineHelpers::remapEngineTypeToHwSpecific(aub_stream::EngineType::ENGINE_RCS, *hwInfo)] = engine;
|
||||
break;
|
||||
case I915_ENGINE_CLASS_COPY:
|
||||
assignCopyEngine(EngineInfo::getBaseCopyEngineType(drm->getIoctlHelper(), engineInfo.capabilities), 0, engine,
|
||||
} else if (engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassCopy)) {
|
||||
assignCopyEngine(EngineInfo::getBaseCopyEngineType(ioctlHelper, engineInfo.capabilities), 0, engine,
|
||||
bcsInfoMask, numHostLinkCopyEngines, numScaleUpLinkCopyEngines);
|
||||
break;
|
||||
default:
|
||||
if (engine.engineClass == drm->getIoctlHelper()->getComputeEngineClass()) {
|
||||
} else if (engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassCompute)) {
|
||||
tileToEngineToInstanceMap[0][static_cast<aub_stream::EngineType>(aub_stream::ENGINE_CCS + computeEngines)] = engine;
|
||||
computeEngines++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
setSupportedEnginesInfo(hwInfo, computeEngines, bcsInfoMask);
|
||||
}
|
||||
@@ -82,6 +78,7 @@ EngineInfo::EngineInfo(Drm *drm, HardwareInfo *hwInfo, uint32_t tileCount, const
|
||||
auto tile = 0u;
|
||||
auto computeEnginesPerTile = 0u;
|
||||
auto copyEnginesPerTile = 0u;
|
||||
auto ioctlHelper = drm->getIoctlHelper();
|
||||
for (auto i = 0u; i < distanceInfos.size(); i++) {
|
||||
if (i > 0u && distanceInfos[i].region.memoryInstance != distanceInfos[i - 1u].region.memoryInstance) {
|
||||
tile++;
|
||||
@@ -93,21 +90,15 @@ EngineInfo::EngineInfo(Drm *drm, HardwareInfo *hwInfo, uint32_t tileCount, const
|
||||
|
||||
auto engine = distanceInfos[i].engine;
|
||||
tileToEngineMap.emplace(tile, engine);
|
||||
switch (engine.engineClass) {
|
||||
case I915_ENGINE_CLASS_RENDER:
|
||||
if (engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassRender)) {
|
||||
tileToEngineToInstanceMap[tile][EngineHelpers::remapEngineTypeToHwSpecific(aub_stream::EngineType::ENGINE_RCS, *hwInfo)] = engine;
|
||||
break;
|
||||
case I915_ENGINE_CLASS_COPY:
|
||||
} else if (engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassCopy)) {
|
||||
tileToEngineToInstanceMap[tile][DrmEngineMappingHelper::engineMapping[copyEnginesPerTile]] = engine;
|
||||
copyEnginesPerTile++;
|
||||
break;
|
||||
default:
|
||||
if (engine.engineClass == drm->getIoctlHelper()->getComputeEngineClass()) {
|
||||
} else if (engine.engineClass == ioctlHelper->getDrmParamValue(DrmParam::EngineClassCompute)) {
|
||||
tileToEngineToInstanceMap[tile][static_cast<aub_stream::EngineType>(aub_stream::ENGINE_CCS + computeEnginesPerTile)] = engine;
|
||||
computeEnginesPerTile++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BcsInfoMask bcsInfoMask = maxNBitValue(copyEnginesPerTile);
|
||||
|
||||
@@ -106,4 +106,23 @@ uint32_t IoctlHelper::createDrmContext(Drm &drm, const OsContext &osContext, uin
|
||||
return drmContextId;
|
||||
}
|
||||
|
||||
int IoctlHelper::getDrmParamValueBase(DrmParam drmParam) const {
|
||||
switch (drmParam) {
|
||||
case DrmParam::EngineClassRender:
|
||||
return I915_ENGINE_CLASS_RENDER;
|
||||
case DrmParam::EngineClassCopy:
|
||||
return I915_ENGINE_CLASS_COPY;
|
||||
case DrmParam::EngineClassVideo:
|
||||
return I915_ENGINE_CLASS_VIDEO;
|
||||
case DrmParam::EngineClassVideoEnhance:
|
||||
return I915_ENGINE_CLASS_VIDEO_ENHANCE;
|
||||
case DrmParam::EngineClassInvalid:
|
||||
return I915_ENGINE_CLASS_INVALID;
|
||||
case DrmParam::EngineClassInvalidNone:
|
||||
return I915_ENGINE_CLASS_INVALID_NONE;
|
||||
default:
|
||||
UNRECOVERABLE_IF(true);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace NEO
|
||||
|
||||
@@ -91,7 +91,6 @@ class IoctlHelper {
|
||||
virtual uint64_t getFlagsForVmBind(bool bindCapture, bool bindImmediate, bool bindMakeResident) = 0;
|
||||
virtual std::vector<EngineCapabilities> translateToEngineCaps(const std::vector<uint8_t> &data) = 0;
|
||||
virtual uint32_t queryDistances(Drm *drm, std::vector<QueryItem> &queryItems, std::vector<DistanceInfo> &distanceInfos) = 0;
|
||||
virtual int32_t getComputeEngineClass() = 0;
|
||||
virtual uint16_t getWaitUserFenceSoftFlag() = 0;
|
||||
virtual int execBuffer(Drm *drm, ExecBuffer *execBuffer, uint64_t completionGpuAddress, uint32_t counterValue) = 0;
|
||||
virtual bool completionFenceExtensionSupported(const bool isVmBindAvailable) = 0;
|
||||
@@ -116,6 +115,7 @@ class IoctlHelper {
|
||||
virtual int setContextDebugFlag(Drm *drm, uint32_t drmContextId) = 0;
|
||||
virtual bool isDebugAttachAvailable() = 0;
|
||||
virtual unsigned int getIoctlRequestValue(DrmIoctl ioctlRequest) = 0;
|
||||
virtual int getDrmParamValue(DrmParam drmParam) const = 0;
|
||||
|
||||
uint32_t createDrmContext(Drm &drm, const OsContext &osContext, uint32_t drmVmId);
|
||||
|
||||
@@ -124,6 +124,7 @@ class IoctlHelper {
|
||||
|
||||
void fillExecBuffer(ExecBuffer &execBuffer, uintptr_t buffersPtr, uint32_t bufferCount, uint32_t startOffset, uint32_t size, uint64_t flags, uint32_t drmContextId);
|
||||
void logExecBuffer(const ExecBuffer &execBuffer, std::stringstream &logger);
|
||||
int getDrmParamValueBase(DrmParam drmParam) const;
|
||||
};
|
||||
|
||||
class IoctlHelperUpstream : public IoctlHelper {
|
||||
@@ -151,7 +152,6 @@ class IoctlHelperUpstream : public IoctlHelper {
|
||||
uint64_t getFlagsForVmBind(bool bindCapture, bool bindImmediate, bool bindMakeResident) override;
|
||||
std::vector<EngineCapabilities> translateToEngineCaps(const std::vector<uint8_t> &data) override;
|
||||
uint32_t queryDistances(Drm *drm, std::vector<QueryItem> &queryItems, std::vector<DistanceInfo> &distanceInfos) override;
|
||||
int32_t getComputeEngineClass() override;
|
||||
uint16_t getWaitUserFenceSoftFlag() override;
|
||||
int execBuffer(Drm *drm, ExecBuffer *execBuffer, uint64_t completionGpuAddress, uint32_t counterValue) override;
|
||||
bool completionFenceExtensionSupported(const bool isVmBindAvailable) override;
|
||||
@@ -176,6 +176,7 @@ class IoctlHelperUpstream : public IoctlHelper {
|
||||
int setContextDebugFlag(Drm *drm, uint32_t drmContextId) override;
|
||||
bool isDebugAttachAvailable() override;
|
||||
unsigned int getIoctlRequestValue(DrmIoctl ioctlRequest) override;
|
||||
int getDrmParamValue(DrmParam drmParam) const override;
|
||||
};
|
||||
|
||||
template <PRODUCT_FAMILY gfxProduct>
|
||||
@@ -217,7 +218,6 @@ class IoctlHelperPrelim20 : public IoctlHelper {
|
||||
uint64_t getFlagsForVmBind(bool bindCapture, bool bindImmediate, bool bindMakeResident) override;
|
||||
std::vector<EngineCapabilities> translateToEngineCaps(const std::vector<uint8_t> &data) override;
|
||||
uint32_t queryDistances(Drm *drm, std::vector<QueryItem> &queryItems, std::vector<DistanceInfo> &distanceInfos) override;
|
||||
int32_t getComputeEngineClass() override;
|
||||
uint16_t getWaitUserFenceSoftFlag() override;
|
||||
int execBuffer(Drm *drm, ExecBuffer *execBuffer, uint64_t completionGpuAddress, uint32_t counterValue) override;
|
||||
bool completionFenceExtensionSupported(const bool isVmBindAvailable) override;
|
||||
@@ -242,6 +242,7 @@ class IoctlHelperPrelim20 : public IoctlHelper {
|
||||
int setContextDebugFlag(Drm *drm, uint32_t drmContextId) override;
|
||||
bool isDebugAttachAvailable() override;
|
||||
unsigned int getIoctlRequestValue(DrmIoctl ioctlRequest) override;
|
||||
int getDrmParamValue(DrmParam drmParam) const override;
|
||||
};
|
||||
|
||||
} // namespace NEO
|
||||
|
||||
@@ -338,10 +338,6 @@ uint32_t IoctlHelperPrelim20::queryDistances(Drm *drm, std::vector<QueryItem> &q
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t IoctlHelperPrelim20::getComputeEngineClass() {
|
||||
return PRELIM_I915_ENGINE_CLASS_COMPUTE;
|
||||
}
|
||||
|
||||
std::optional<int> IoctlHelperPrelim20::getHasPageFaultParamId() {
|
||||
return PRELIM_I915_PARAM_HAS_PAGE_FAULT;
|
||||
};
|
||||
@@ -636,6 +632,15 @@ unsigned int IoctlHelperPrelim20::getIoctlRequestValue(DrmIoctl ioctlRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
int IoctlHelperPrelim20::getDrmParamValue(DrmParam drmParam) const {
|
||||
switch (drmParam) {
|
||||
case DrmParam::EngineClassCompute:
|
||||
return PRELIM_I915_ENGINE_CLASS_COMPUTE;
|
||||
default:
|
||||
return getDrmParamValueBase(drmParam);
|
||||
}
|
||||
}
|
||||
|
||||
static_assert(sizeof(MemoryClassInstance) == sizeof(prelim_drm_i915_gem_memory_class_instance));
|
||||
static_assert(offsetof(MemoryClassInstance, memoryClass) == offsetof(prelim_drm_i915_gem_memory_class_instance, memory_class));
|
||||
static_assert(offsetof(MemoryClassInstance, memoryInstance) == offsetof(prelim_drm_i915_gem_memory_class_instance, memory_instance));
|
||||
|
||||
@@ -152,10 +152,6 @@ uint32_t IoctlHelperUpstream::queryDistances(Drm *drm, std::vector<QueryItem> &q
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t IoctlHelperUpstream::getComputeEngineClass() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
uint16_t IoctlHelperUpstream::getWaitUserFenceSoftFlag() {
|
||||
return 0;
|
||||
}
|
||||
@@ -295,4 +291,13 @@ unsigned int IoctlHelperUpstream::getIoctlRequestValue(DrmIoctl ioctlRequest) {
|
||||
return 0u;
|
||||
}
|
||||
}
|
||||
|
||||
int IoctlHelperUpstream::getDrmParamValue(DrmParam drmParam) const {
|
||||
switch (drmParam) {
|
||||
case DrmParam::EngineClassCompute:
|
||||
return 4;
|
||||
default:
|
||||
return getDrmParamValueBase(drmParam);
|
||||
}
|
||||
}
|
||||
} // namespace NEO
|
||||
|
||||
@@ -79,7 +79,7 @@ TEST(EngineInfoTest, whenCreateEngineInfoWithCcsThenCorrectHwInfoSet) {
|
||||
|
||||
auto hwInfo = *defaultHwInfo.get();
|
||||
std::vector<EngineCapabilities> engines(2);
|
||||
uint16_t ccsClass = drm->getIoctlHelper()->getComputeEngineClass();
|
||||
uint16_t ccsClass = drm->getIoctlHelper()->getDrmParamValue(DrmParam::EngineClassCompute);
|
||||
engines[0].engine = {ccsClass, 0};
|
||||
engines[0].capabilities = 0;
|
||||
engines[1].engine = {I915_ENGINE_CLASS_COPY, 0};
|
||||
|
||||
@@ -1224,3 +1224,17 @@ TEST(DrmWrapperTest, WhenGettingIoctlStringValueThenProperStringIsReturned) {
|
||||
EXPECT_STREQ(IoctlToStringHelper::getIoctlString(ioctlCodeString.first).c_str(), ioctlCodeString.second);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(IoctlHelperTest, whenGettingDrmParamValueThenProperValueIsReturned) {
|
||||
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
|
||||
DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]};
|
||||
auto ioctlHelper = drm.getIoctlHelper();
|
||||
EXPECT_EQ(static_cast<int>(I915_ENGINE_CLASS_RENDER), ioctlHelper->getDrmParamValue(DrmParam::EngineClassRender));
|
||||
EXPECT_EQ(static_cast<int>(I915_ENGINE_CLASS_COPY), ioctlHelper->getDrmParamValue(DrmParam::EngineClassCopy));
|
||||
EXPECT_EQ(static_cast<int>(I915_ENGINE_CLASS_VIDEO), ioctlHelper->getDrmParamValue(DrmParam::EngineClassVideo));
|
||||
EXPECT_EQ(static_cast<int>(I915_ENGINE_CLASS_VIDEO_ENHANCE), ioctlHelper->getDrmParamValue(DrmParam::EngineClassVideoEnhance));
|
||||
EXPECT_EQ(static_cast<int>(I915_ENGINE_CLASS_INVALID), ioctlHelper->getDrmParamValue(DrmParam::EngineClassInvalid));
|
||||
EXPECT_EQ(static_cast<int>(I915_ENGINE_CLASS_INVALID_NONE), ioctlHelper->getDrmParamValue(DrmParam::EngineClassInvalidNone));
|
||||
|
||||
EXPECT_THROW(ioctlHelper->getDrmParamValueBase(DrmParam::EngineClassCompute), std::runtime_error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user