Make all backend::ShaderModule get SPIRV from the frontend

This will make it easier to support SPIRV as a chained sub-descriptor of
ShaderModuleDescriptor in follow-up CLs.

Also fix a couple style and formatting issues.

Bug: dawn:22
Change-Id: Iddaf1f87edee65687e17670b70024835918a0382
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/19864
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Corentin Wallez 2020-04-21 07:57:30 +00:00 committed by Commit Bot service account
parent 3966eb1175
commit 21744d0fb8
11 changed files with 70 additions and 63 deletions

View File

@ -324,7 +324,7 @@ namespace dawn_native {
// ShaderModuleBase // ShaderModuleBase
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor) ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor)
: CachedObject(device), mCode(descriptor->code, descriptor->code + descriptor->codeSize) { : CachedObject(device), mSpirv(descriptor->code, descriptor->code + descriptor->codeSize) {
mFragmentOutputFormatBaseTypes.fill(Format::Other); mFragmentOutputFormatBaseTypes.fill(Format::Other);
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvcParser)) { if (GetDevice()->IsToggleEnabled(Toggle::UseSpvcParser)) {
mSpvcContext.SetUseSpvcParser(true); mSpvcContext.SetUseSpvcParser(true);
@ -836,7 +836,7 @@ namespace dawn_native {
size_t ShaderModuleBase::HashFunc::operator()(const ShaderModuleBase* module) const { size_t ShaderModuleBase::HashFunc::operator()(const ShaderModuleBase* module) const {
size_t hash = 0; size_t hash = 0;
for (uint32_t word : module->mCode) { for (uint32_t word : module->mSpirv) {
HashCombine(&hash, word); HashCombine(&hash, word);
} }
@ -845,7 +845,7 @@ namespace dawn_native {
bool ShaderModuleBase::EqualityFunc::operator()(const ShaderModuleBase* a, bool ShaderModuleBase::EqualityFunc::operator()(const ShaderModuleBase* a,
const ShaderModuleBase* b) const { const ShaderModuleBase* b) const {
return a->mCode == b->mCode; return a->mSpirv == b->mSpirv;
} }
MaybeError ShaderModuleBase::CheckSpvcSuccess(shaderc_spvc_status status, MaybeError ShaderModuleBase::CheckSpvcSuccess(shaderc_spvc_status status,
@ -856,7 +856,15 @@ namespace dawn_native {
return {}; return {};
} }
shaderc_spvc::CompileOptions ShaderModuleBase::GetCompileOptions() { shaderc_spvc::Context* ShaderModuleBase::GetContext() {
return &mSpvcContext;
}
const std::vector<uint32_t>& ShaderModuleBase::GetSpirv() const {
return mSpirv;
}
shaderc_spvc::CompileOptions ShaderModuleBase::GetCompileOptions() const {
shaderc_spvc::CompileOptions options; shaderc_spvc::CompileOptions options;
options.SetValidate(GetDevice()->IsValidationEnabled()); options.SetValidate(GetDevice()->IsValidationEnabled());
return options; return options;

View File

@ -83,13 +83,12 @@ namespace dawn_native {
bool operator()(const ShaderModuleBase* a, const ShaderModuleBase* b) const; bool operator()(const ShaderModuleBase* a, const ShaderModuleBase* b) const;
}; };
shaderc_spvc::Context* GetContext() { shaderc_spvc::Context* GetContext();
return &mSpvcContext; const std::vector<uint32_t>& GetSpirv() const;
}
protected: protected:
static MaybeError CheckSpvcSuccess(shaderc_spvc_status status, const char* error_msg); static MaybeError CheckSpvcSuccess(shaderc_spvc_status status, const char* error_msg);
shaderc_spvc::CompileOptions GetCompileOptions(); shaderc_spvc::CompileOptions GetCompileOptions() const;
shaderc_spvc::Context mSpvcContext; shaderc_spvc::Context mSpvcContext;
@ -103,9 +102,7 @@ namespace dawn_native {
MaybeError ExtractSpirvInfoWithSpvc(); MaybeError ExtractSpirvInfoWithSpvc();
MaybeError ExtractSpirvInfoWithSpirvCross(const spirv_cross::Compiler& compiler); MaybeError ExtractSpirvInfoWithSpirvCross(const spirv_cross::Compiler& compiler);
// TODO(cwallez@chromium.org): The code is only stored for deduplication. We could maybe std::vector<uint32_t> mSpirv;
// store a cryptographic hash of the code instead?
std::vector<uint32_t> mCode;
ModuleBindingInfo mBindingInfo; ModuleBindingInfo mBindingInfo;
std::bitset<kMaxVertexAttributes> mUsedVertexAttributes; std::bitset<kMaxVertexAttributes> mUsedVertexAttributes;

View File

@ -28,7 +28,7 @@ namespace dawn_native { namespace d3d12 {
ResultOrError<ShaderModule*> ShaderModule::Create(Device* device, ResultOrError<ShaderModule*> ShaderModule::Create(Device* device,
const ShaderModuleDescriptor* descriptor) { const ShaderModuleDescriptor* descriptor) {
Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor)); Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor));
DAWN_TRY(module->Initialize(descriptor)); DAWN_TRY(module->Initialize());
return module.Detach(); return module.Detach();
} }
@ -36,8 +36,9 @@ namespace dawn_native { namespace d3d12 {
: ShaderModuleBase(device, descriptor) { : ShaderModuleBase(device, descriptor) {
} }
MaybeError ShaderModule::Initialize(const ShaderModuleDescriptor* descriptor) { MaybeError ShaderModule::Initialize() {
mSpirv.assign(descriptor->code, descriptor->code + descriptor->codeSize); const std::vector<uint32_t>& spirv = GetSpirv();
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) { if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
shaderc_spvc::CompileOptions options = GetCompileOptions(); shaderc_spvc::CompileOptions options = GetCompileOptions();
@ -52,7 +53,7 @@ namespace dawn_native { namespace d3d12 {
options.SetHLSLPointSizeCompat(true); options.SetHLSLPointSizeCompat(true);
DAWN_TRY(CheckSpvcSuccess( DAWN_TRY(CheckSpvcSuccess(
mSpvcContext.InitializeForHlsl(descriptor->code, descriptor->codeSize, options), mSpvcContext.InitializeForHlsl(spirv.data(), spirv.size(), options),
"Unable to initialize instance of spvc")); "Unable to initialize instance of spvc"));
spirv_cross::Compiler* compiler; spirv_cross::Compiler* compiler;
@ -60,14 +61,17 @@ namespace dawn_native { namespace d3d12 {
"Unable to get cross compiler")); "Unable to get cross compiler"));
DAWN_TRY(ExtractSpirvInfo(*compiler)); DAWN_TRY(ExtractSpirvInfo(*compiler));
} else { } else {
spirv_cross::CompilerHLSL compiler(descriptor->code, descriptor->codeSize); spirv_cross::CompilerHLSL compiler(spirv);
DAWN_TRY(ExtractSpirvInfo(compiler)); DAWN_TRY(ExtractSpirvInfo(compiler));
} }
return {}; return {};
} }
ResultOrError<std::string> ShaderModule::GetHLSLSource(PipelineLayout* layout) { ResultOrError<std::string> ShaderModule::GetHLSLSource(PipelineLayout* layout) {
std::unique_ptr<spirv_cross::CompilerHLSL> compiler_impl; ASSERT(!IsError());
const std::vector<uint32_t>& spirv = GetSpirv();
std::unique_ptr<spirv_cross::CompilerHLSL> compilerImpl;
spirv_cross::CompilerHLSL* compiler = nullptr; spirv_cross::CompilerHLSL* compiler = nullptr;
if (!GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) { if (!GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
// If these options are changed, the values in DawnSPIRVCrossHLSLFastFuzzer.cpp need to // If these options are changed, the values in DawnSPIRVCrossHLSLFastFuzzer.cpp need to
@ -87,8 +91,8 @@ namespace dawn_native { namespace d3d12 {
options_hlsl.point_coord_compat = true; options_hlsl.point_coord_compat = true;
options_hlsl.point_size_compat = true; options_hlsl.point_size_compat = true;
compiler_impl = std::make_unique<spirv_cross::CompilerHLSL>(mSpirv); compilerImpl = std::make_unique<spirv_cross::CompilerHLSL>(spirv);
compiler = compiler_impl.get(); compiler = compilerImpl.get();
compiler->set_common_options(options_glsl); compiler->set_common_options(options_glsl);
compiler->set_hlsl_options(options_hlsl); compiler->set_hlsl_options(options_hlsl);
} }

View File

@ -32,9 +32,7 @@ namespace dawn_native { namespace d3d12 {
private: private:
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor); ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
~ShaderModule() override = default; ~ShaderModule() override = default;
MaybeError Initialize(const ShaderModuleDescriptor* descriptor); MaybeError Initialize();
std::vector<uint32_t> mSpirv;
}; };
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -51,14 +51,9 @@ namespace dawn_native { namespace metal {
private: private:
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor); ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
~ShaderModule() override = default; ~ShaderModule() override = default;
MaybeError Initialize(const ShaderModuleDescriptor* descriptor); MaybeError Initialize();
shaderc_spvc::CompileOptions GetMSLCompileOptions(); shaderc_spvc::CompileOptions GetMSLCompileOptions();
// Calling compile on CompilerMSL somehow changes internal state that makes subsequent
// compiles return invalid MSL. We keep the spirv around and recreate the compiler everytime
// we need to use it.
std::vector<uint32_t> mSpirv;
}; };
}} // namespace dawn_native::metal }} // namespace dawn_native::metal

View File

@ -58,7 +58,7 @@ namespace dawn_native { namespace metal {
ResultOrError<ShaderModule*> ShaderModule::Create(Device* device, ResultOrError<ShaderModule*> ShaderModule::Create(Device* device,
const ShaderModuleDescriptor* descriptor) { const ShaderModuleDescriptor* descriptor) {
Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor)); Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor));
DAWN_TRY(module->Initialize(descriptor)); DAWN_TRY(module->Initialize());
return module.Detach(); return module.Detach();
} }
@ -66,13 +66,14 @@ namespace dawn_native { namespace metal {
: ShaderModuleBase(device, descriptor) { : ShaderModuleBase(device, descriptor) {
} }
MaybeError ShaderModule::Initialize(const ShaderModuleDescriptor* descriptor) { MaybeError ShaderModule::Initialize() {
mSpirv.assign(descriptor->code, descriptor->code + descriptor->codeSize); const std::vector<uint32_t>& spirv = GetSpirv();
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) { if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
shaderc_spvc::CompileOptions options = GetMSLCompileOptions(); shaderc_spvc::CompileOptions options = GetMSLCompileOptions();
DAWN_TRY(CheckSpvcSuccess( DAWN_TRY(
mSpvcContext.InitializeForMsl(descriptor->code, descriptor->codeSize, options), CheckSpvcSuccess(mSpvcContext.InitializeForMsl(spirv.data(), spirv.size(), options),
"Unable to initialize instance of spvc")); "Unable to initialize instance of spvc"));
spirv_cross::CompilerMSL* compiler; spirv_cross::CompilerMSL* compiler;
@ -80,7 +81,7 @@ namespace dawn_native { namespace metal {
"Unable to get cross compiler")); "Unable to get cross compiler"));
DAWN_TRY(ExtractSpirvInfo(*compiler)); DAWN_TRY(ExtractSpirvInfo(*compiler));
} else { } else {
spirv_cross::CompilerMSL compiler(mSpirv); spirv_cross::CompilerMSL compiler(spirv);
DAWN_TRY(ExtractSpirvInfo(compiler)); DAWN_TRY(ExtractSpirvInfo(compiler));
} }
return {}; return {};
@ -92,13 +93,15 @@ namespace dawn_native { namespace metal {
ShaderModule::MetalFunctionData* out) { ShaderModule::MetalFunctionData* out) {
ASSERT(!IsError()); ASSERT(!IsError());
ASSERT(out); ASSERT(out);
std::unique_ptr<spirv_cross::CompilerMSL> compiler_impl; const std::vector<uint32_t>& spirv = GetSpirv();
std::unique_ptr<spirv_cross::CompilerMSL> compilerImpl;
spirv_cross::CompilerMSL* compiler; spirv_cross::CompilerMSL* compiler;
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) { if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
// Initializing the compiler is needed every call, because this method uses reflection // Initializing the compiler is needed every call, because this method uses reflection
// to mutate the compiler's IR. // to mutate the compiler's IR.
DAWN_TRY(CheckSpvcSuccess( DAWN_TRY(CheckSpvcSuccess(
mSpvcContext.InitializeForMsl(mSpirv.data(), mSpirv.size(), GetMSLCompileOptions()), mSpvcContext.InitializeForMsl(spirv.data(), spirv.size(), GetMSLCompileOptions()),
"Unable to initialize instance of spvc")); "Unable to initialize instance of spvc"));
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetCompiler(reinterpret_cast<void**>(&compiler)), DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetCompiler(reinterpret_cast<void**>(&compiler)),
"Unable to get cross compiler")); "Unable to get cross compiler"));
@ -118,8 +121,8 @@ namespace dawn_native { namespace metal {
// the shader storage buffer lengths. // the shader storage buffer lengths.
options_msl.buffer_size_buffer_index = kBufferLengthBufferSlot; options_msl.buffer_size_buffer_index = kBufferLengthBufferSlot;
compiler_impl = std::make_unique<spirv_cross::CompilerMSL>(mSpirv); compilerImpl = std::make_unique<spirv_cross::CompilerMSL>(spirv);
compiler = compiler_impl.get(); compiler = compilerImpl.get();
compiler->set_msl_options(options_msl); compiler->set_msl_options(options_msl);
} }

View File

@ -125,14 +125,14 @@ namespace dawn_native { namespace null {
} }
ResultOrError<ShaderModuleBase*> Device::CreateShaderModuleImpl( ResultOrError<ShaderModuleBase*> Device::CreateShaderModuleImpl(
const ShaderModuleDescriptor* descriptor) { const ShaderModuleDescriptor* descriptor) {
auto module = new ShaderModule(this, descriptor); Ref<ShaderModule> module = AcquireRef(new ShaderModule(this, descriptor));
if (IsToggleEnabled(Toggle::UseSpvc)) { if (IsToggleEnabled(Toggle::UseSpvc)) {
shaderc_spvc::CompileOptions options; shaderc_spvc::CompileOptions options;
options.SetValidate(IsValidationEnabled()); options.SetValidate(IsValidationEnabled());
shaderc_spvc::Context* context = module->GetContext(); shaderc_spvc::Context* context = module->GetContext();
shaderc_spvc_status status = shaderc_spvc_status status = context->InitializeForGlsl(
context->InitializeForGlsl(descriptor->code, descriptor->codeSize, options); module->GetSpirv().data(), module->GetSpirv().size(), options);
if (status != shaderc_spvc_status_success) { if (status != shaderc_spvc_status_success) {
return DAWN_VALIDATION_ERROR("Unable to initialize instance of spvc"); return DAWN_VALIDATION_ERROR("Unable to initialize instance of spvc");
} }
@ -144,10 +144,10 @@ namespace dawn_native { namespace null {
} }
DAWN_TRY(module->ExtractSpirvInfo(*compiler)); DAWN_TRY(module->ExtractSpirvInfo(*compiler));
} else { } else {
spirv_cross::Compiler compiler(descriptor->code, descriptor->codeSize); spirv_cross::Compiler compiler(module->GetSpirv());
DAWN_TRY(module->ExtractSpirvInfo(compiler)); DAWN_TRY(module->ExtractSpirvInfo(compiler));
} }
return module; return module.Detach();
} }
ResultOrError<SwapChainBase*> Device::CreateSwapChainImpl( ResultOrError<SwapChainBase*> Device::CreateSwapChainImpl(
const SwapChainDescriptor* descriptor) { const SwapChainDescriptor* descriptor) {

View File

@ -51,7 +51,7 @@ namespace dawn_native { namespace opengl {
ResultOrError<ShaderModule*> ShaderModule::Create(Device* device, ResultOrError<ShaderModule*> ShaderModule::Create(Device* device,
const ShaderModuleDescriptor* descriptor) { const ShaderModuleDescriptor* descriptor) {
Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor)); Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor));
DAWN_TRY(module->Initialize(descriptor)); DAWN_TRY(module->Initialize());
return module.Detach(); return module.Detach();
} }
@ -67,10 +67,11 @@ namespace dawn_native { namespace opengl {
: ShaderModuleBase(device, descriptor) { : ShaderModuleBase(device, descriptor) {
} }
MaybeError ShaderModule::Initialize(const ShaderModuleDescriptor* descriptor) { MaybeError ShaderModule::Initialize() {
std::unique_ptr<spirv_cross::CompilerGLSL> compiler_impl; const std::vector<uint32_t>& spirv = GetSpirv();
spirv_cross::CompilerGLSL* compiler;
std::unique_ptr<spirv_cross::CompilerGLSL> compilerImpl;
spirv_cross::CompilerGLSL* compiler;
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) { if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
// If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to // If these options are changed, the values in DawnSPIRVCrossGLSLFastFuzzer.cpp need to
// be updated. // be updated.
@ -90,7 +91,7 @@ namespace dawn_native { namespace opengl {
options.SetGLSLLanguageVersion(440); options.SetGLSLLanguageVersion(440);
#endif #endif
DAWN_TRY(CheckSpvcSuccess( DAWN_TRY(CheckSpvcSuccess(
mSpvcContext.InitializeForGlsl(descriptor->code, descriptor->codeSize, options), mSpvcContext.InitializeForGlsl(spirv.data(), spirv.size(), options),
"Unable to initialize instance of spvc")); "Unable to initialize instance of spvc"));
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetCompiler(reinterpret_cast<void**>(&compiler)), DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetCompiler(reinterpret_cast<void**>(&compiler)),
"Unable to get cross compiler")); "Unable to get cross compiler"));
@ -113,9 +114,8 @@ namespace dawn_native { namespace opengl {
options.version = 440; options.version = 440;
#endif #endif
compiler_impl = compilerImpl = std::make_unique<spirv_cross::CompilerGLSL>(spirv);
std::make_unique<spirv_cross::CompilerGLSL>(descriptor->code, descriptor->codeSize); compiler = compilerImpl.get();
compiler = compiler_impl.get();
compiler->set_common_options(options); compiler->set_common_options(options);
} }

View File

@ -51,7 +51,7 @@ namespace dawn_native { namespace opengl {
private: private:
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor); ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
~ShaderModule() override = default; ~ShaderModule() override = default;
MaybeError Initialize(const ShaderModuleDescriptor* descriptor); MaybeError Initialize();
CombinedSamplerInfo mCombinedInfo; CombinedSamplerInfo mCombinedInfo;
std::string mGlslSource; std::string mGlslSource;

View File

@ -28,7 +28,7 @@ namespace dawn_native { namespace vulkan {
Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor)); Ref<ShaderModule> module = AcquireRef(new ShaderModule(device, descriptor));
if (!module) if (!module)
return DAWN_VALIDATION_ERROR("Unable to create ShaderModule"); return DAWN_VALIDATION_ERROR("Unable to create ShaderModule");
DAWN_TRY(module->Initialize(descriptor)); DAWN_TRY(module->Initialize());
return module.Detach(); return module.Detach();
} }
@ -36,14 +36,16 @@ namespace dawn_native { namespace vulkan {
: ShaderModuleBase(device, descriptor) { : ShaderModuleBase(device, descriptor) {
} }
MaybeError ShaderModule::Initialize(const ShaderModuleDescriptor* descriptor) { MaybeError ShaderModule::Initialize() {
const std::vector<uint32_t>& spirv = GetSpirv();
// Use SPIRV-Cross to extract info from the SPIRV even if Vulkan consumes SPIRV. We want to // Use SPIRV-Cross to extract info from the SPIRV even if Vulkan consumes SPIRV. We want to
// have a translation step eventually anyway. // have a translation step eventually anyway.
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) { if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
shaderc_spvc::CompileOptions options = GetCompileOptions(); shaderc_spvc::CompileOptions options = GetCompileOptions();
DAWN_TRY(CheckSpvcSuccess( DAWN_TRY(CheckSpvcSuccess(
mSpvcContext.InitializeForVulkan(descriptor->code, descriptor->codeSize, options), mSpvcContext.InitializeForVulkan(spirv.data(), spirv.size(), options),
"Unable to initialize instance of spvc")); "Unable to initialize instance of spvc"));
spirv_cross::Compiler* compiler; spirv_cross::Compiler* compiler;
@ -51,7 +53,7 @@ namespace dawn_native { namespace vulkan {
"Unable to get cross compiler")); "Unable to get cross compiler"));
DAWN_TRY(ExtractSpirvInfo(*compiler)); DAWN_TRY(ExtractSpirvInfo(*compiler));
} else { } else {
spirv_cross::Compiler compiler(descriptor->code, descriptor->codeSize); spirv_cross::Compiler compiler(spirv);
DAWN_TRY(ExtractSpirvInfo(compiler)); DAWN_TRY(ExtractSpirvInfo(compiler));
} }
@ -69,8 +71,8 @@ namespace dawn_native { namespace vulkan {
createInfo.codeSize = vulkanSource.size() * sizeof(uint32_t); createInfo.codeSize = vulkanSource.size() * sizeof(uint32_t);
createInfo.pCode = vulkanSource.data(); createInfo.pCode = vulkanSource.data();
} else { } else {
createInfo.codeSize = descriptor->codeSize * sizeof(uint32_t); createInfo.codeSize = spirv.size() * sizeof(uint32_t);
createInfo.pCode = descriptor->code; createInfo.pCode = spirv.data();
} }
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());

View File

@ -34,7 +34,7 @@ namespace dawn_native { namespace vulkan {
private: private:
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor); ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
~ShaderModule() override; ~ShaderModule() override;
MaybeError Initialize(const ShaderModuleDescriptor* descriptor); MaybeError Initialize();
VkShaderModule mHandle = VK_NULL_HANDLE; VkShaderModule mHandle = VK_NULL_HANDLE;
}; };