blob: af44396402a1beee38d00a7cd141a232295f635f [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/*!
* \file vulkan_module.cc
* \brief Plugin-only Vulkan runtime module. Built only when USE_VULKAN=ON.
* No exported header — codegen-side construction goes through
* src/backend/vulkan/codegen/vulkan_fallback_module.h:VulkanModuleCreateWithFallback,
* which dispatches to "ffi.Module.create.vulkan" registered below
* when this file is linked into the build.
*/
#include <tvm/ffi/function.h>
#include <tvm/ffi/reflection/registry.h>
#include <tvm/support/io.h>
#include <string>
#include <utility>
#include "../../../support/bytes_io.h"
#include "spirv_shader.h"
#include "vulkan_wrapped_func.h"
namespace tvm {
namespace runtime {
namespace vulkan {
/*!
* \brief Deserialize a SPIRVShader from ffi::Bytes.
* Format: flag (uint32_t) followed by data (vector<uint32_t>) — matches
* the SPIRVShader::Save format in src/backend/vulkan/runtime/spirv_shader.h.
*/
static SPIRVShader DeserializeSPIRVShader(const ffi::Bytes& bytes) {
support::BytesInStream stream(bytes);
SPIRVShader shader;
TVM_FFI_ICHECK(stream.Read(&shader));
return shader;
}
static ffi::Module VulkanModuleCreateImpl(ffi::Map<ffi::String, ffi::Bytes> smap, ffi::String fmt,
ffi::Map<ffi::String, FunctionInfo> fmap,
ffi::Map<ffi::String, ffi::String> source) {
// Convert Map<String, Bytes> smap → unordered_map<string, SPIRVShader>
// for the in-memory module. SaveToBytes will re-emit Map<String, Bytes>
// form so the bytes shape stays uniform across backends.
std::unordered_map<std::string, SPIRVShader> internal_smap;
for (const auto& kv : smap) {
internal_smap[std::string(kv.first)] = DeserializeSPIRVShader(kv.second);
}
auto n = ffi::make_object<VulkanModuleNode>(std::move(internal_smap), std::move(smap),
std::move(fmt), std::move(fmap), std::move(source));
return ffi::Module(n);
}
static ffi::Module VulkanModuleLoadFromBytes(const ffi::Bytes& bytes) {
support::BytesInStream stream(bytes);
ffi::String fmt;
ffi::Map<ffi::String, FunctionInfo> fmap;
ffi::Map<ffi::String, ffi::Bytes> smap;
stream.Read(&fmt);
TVM_FFI_ICHECK(stream.Read(&fmap));
stream.Read(&smap);
// Source map is not serialized — reconstructed empty on load.
return VulkanModuleCreateImpl(std::move(smap), std::move(fmt), std::move(fmap),
ffi::Map<ffi::String, ffi::String>());
}
TVM_FFI_STATIC_INIT_BLOCK() {
namespace refl = tvm::ffi::reflection;
// Registry: "ffi.Module.create.vulkan" — codegen-time Vulkan module factory.
// Used by src/backend/vulkan/codegen/vulkan_fallback_module.h:VulkanModuleCreateWithFallback.
// Registry: "ffi.Module.load_from_bytes.vulkan" — disk loader. Only this
// (real) module registers a loader; the fallback is codegen-only.
refl::GlobalDef()
.def("ffi.Module.load_from_bytes.vulkan", VulkanModuleLoadFromBytes)
.def("ffi.Module.create.vulkan",
[](ffi::Map<ffi::String, ffi::Bytes> smap, ffi::String fmt,
ffi::Map<ffi::String, FunctionInfo> fmap, ffi::Map<ffi::String, ffi::String> source) {
return VulkanModuleCreateImpl(std::move(smap), std::move(fmt), std::move(fmap),
std::move(source));
});
}
} // namespace vulkan
} // namespace runtime
} // namespace tvm