Compare commits

..

No commits in common. "1b042838d9fdaa956917728658f3c3fa39faf72a" and "cc734292286f85f9c48305d94d7fd22f42838522" have entirely different histories.

13 changed files with 8 additions and 295 deletions

View File

@ -428,11 +428,6 @@ SD_API const char* sd_get_system_info();
SD_API bool sd_ctx_supports_image_generation(const sd_ctx_t* sd_ctx);
SD_API bool sd_ctx_supports_video_generation(const sd_ctx_t* sd_ctx);
// ControlNet hot-swap APIs are not safe to call while generation is in flight.
SD_API bool sd_ctx_load_control_net(sd_ctx_t* sd_ctx, const char* path);
SD_API bool sd_ctx_unload_control_net(sd_ctx_t* sd_ctx);
SD_API bool sd_ctx_has_control_net(const sd_ctx_t* sd_ctx);
SD_API const char* sd_type_name(enum sd_type_t type);
SD_API enum sd_type_t str_to_sd_type(const char* str);
SD_API const char* sd_rng_type_name(enum rng_type_t rng_type);

View File

@ -294,7 +294,7 @@ public:
auto net_0 = std::dynamic_pointer_cast<UnaryBlock>(blocks["net.0"]);
auto net_2 = std::dynamic_pointer_cast<Linear>(blocks["net.2"]);
if (sd_backend_is(ctx->backend, "Vulkan") || sd_backend_is(ctx->backend, "ROCm")) {
if (sd_backend_is(ctx->backend, "Vulkan")) {
net_2->set_force_prec_f32(true);
}

View File

@ -199,7 +199,7 @@ namespace Boogu {
auto linear_2 = std::dynamic_pointer_cast<Linear>(blocks["linear_2"]);
auto linear_3 = std::dynamic_pointer_cast<Linear>(blocks["linear_3"]);
if (sd_backend_is(ctx->backend, "Vulkan") || sd_backend_is(ctx->backend, "ROCm")) {
if (sd_backend_is(ctx->backend, "Vulkan")) {
linear_2->set_force_prec_f32(true);
}
@ -259,7 +259,7 @@ namespace Boogu {
auto norm_k = std::dynamic_pointer_cast<RMSNorm>(blocks["norm_k"]);
auto to_out_0 = std::dynamic_pointer_cast<Linear>(blocks["to_out.0"]);
if (sd_backend_is(ctx->backend, "Vulkan") || sd_backend_is(ctx->backend, "ROCm")) {
if (sd_backend_is(ctx->backend, "Vulkan")) {
to_out_0->set_force_prec_f32(true);
}
@ -383,7 +383,7 @@ namespace Boogu {
auto instruct_out = std::dynamic_pointer_cast<Linear>(blocks["processor.instruct_out"]);
auto img_out = std::dynamic_pointer_cast<Linear>(blocks["processor.img_out"]);
if (sd_backend_is(ctx->backend, "Vulkan") || sd_backend_is(ctx->backend, "ROCm")) {
if (sd_backend_is(ctx->backend, "Vulkan")) {
to_out_0->set_force_prec_f32(true);
}

View File

@ -267,7 +267,7 @@ namespace Krea2 {
auto knorm = std::dynamic_pointer_cast<KreaRMSNorm>(blocks["qknorm.knorm"]);
auto wo = std::dynamic_pointer_cast<Linear>(blocks["wo"]);
if (sd_backend_is(ctx->backend, "Vulkan") || sd_backend_is(ctx->backend, "ROCm")) {
if (sd_backend_is(ctx->backend, "Vulkan")) {
wo->set_force_prec_f32(true);
}

View File

@ -183,7 +183,7 @@ namespace Qwen {
auto to_v = std::dynamic_pointer_cast<Linear>(blocks["to_v"]);
auto to_out_0 = std::dynamic_pointer_cast<Linear>(blocks["to_out.0"]);
if (sd_backend_is(ctx->backend, "Vulkan") || sd_backend_is(ctx->backend, "ROCm")) {
if (sd_backend_is(ctx->backend, "Vulkan")) {
to_out_0->set_force_prec_f32(true);
}

View File

@ -150,8 +150,6 @@ namespace ZImage {
if (sd_backend_is(ctx->backend, "ROCm")) {
out_proj->set_scale(1.f / 16.f);
out_proj->set_force_prec_f32(true);
qkv_proj->set_force_prec_f32(true);
}
auto qkv = qkv_proj->forward(ctx, x); // [N, n_token, (num_heads + num_kv_heads*2)*head_dim]
@ -229,7 +227,7 @@ namespace ZImage {
auto w2 = std::dynamic_pointer_cast<Linear>(blocks["w2"]);
auto w3 = std::dynamic_pointer_cast<Linear>(blocks["w3"]);
if (sd_backend_is(ctx->backend, "Vulkan") || sd_backend_is(ctx->backend, "ROCm")) {
if (sd_backend_is(ctx->backend, "Vulkan")) {
w2->set_force_prec_f32(true);
}

View File

@ -3,19 +3,15 @@
#include <algorithm>
#include <cstdint>
#include <exception>
#include <filesystem>
#include <fstream>
#include <ostream>
#include <string>
#include <unordered_set>
#include <vector>
#include "binary_io.h"
#include "core/util.h"
#include "json.hpp"
namespace fs = std::filesystem;
static constexpr size_t ST_HEADER_SIZE_LEN = 8;
static void set_error(std::string* error, const std::string& message) {
@ -24,14 +20,6 @@ static void set_error(std::string* error, const std::string& message) {
}
}
static std::string resolve_index_shard_path(const std::string& index_path, const std::string& shard_path) {
fs::path shard_fs_path(shard_path);
if (shard_fs_path.is_absolute()) {
return shard_fs_path.lexically_normal().string();
}
return (fs::path(index_path).parent_path() / shard_fs_path).lexically_normal().string();
}
bool is_safetensors_file(const std::string& file_path) {
std::ifstream file(file_path, std::ios::binary);
if (!file.is_open()) {
@ -242,52 +230,6 @@ bool read_safetensors_file(const std::string& file_path,
return true;
}
bool read_safetensors_index_file(const std::string& file_path,
std::vector<std::string>& shard_paths,
std::string* error) {
shard_paths.clear();
std::ifstream file(file_path);
if (!file.is_open()) {
set_error(error, "failed to open '" + file_path + "'");
return false;
}
nlohmann::json index;
try {
index = nlohmann::json::parse(file);
} catch (const std::exception&) {
set_error(error, "parsing safetensors index failed: '" + file_path + "'");
return false;
}
if (!index.is_object() || !index.contains("weight_map") || !index["weight_map"].is_object()) {
set_error(error, "invalid safetensors index '" + file_path + "'");
return false;
}
std::unordered_set<std::string> seen_shard_paths;
for (const auto& item : index["weight_map"].items()) {
if (!item.value().is_string()) {
set_error(error, "invalid shard path for tensor '" + item.key() + "'");
return false;
}
std::string shard_path = resolve_index_shard_path(file_path,
item.value().get<std::string>());
if (seen_shard_paths.insert(shard_path).second) {
shard_paths.push_back(std::move(shard_path));
}
}
if (shard_paths.empty()) {
set_error(error, "safetensors index has no tensors: '" + file_path + "'");
return false;
}
return true;
}
static bool ggml_type_to_safetensors_dtype(ggml_type type, std::string* dtype) {
switch (type) {
case GGML_TYPE_F16:

View File

@ -11,9 +11,6 @@ bool is_safetensors_file(const std::string& file_path);
bool read_safetensors_file(const std::string& file_path,
std::vector<TensorStorage>& tensor_storages,
std::string* error = nullptr);
bool read_safetensors_index_file(const std::string& file_path,
std::vector<std::string>& shard_paths,
std::string* error = nullptr);
bool write_safetensors_file(const std::string& file_path,
const std::vector<TensorWriteInfo>& tensors,
std::string* error = nullptr);

View File

@ -235,9 +235,6 @@ bool ModelLoader::init_from_file(const std::string& file_path, const std::string
} else if (is_gguf_file(file_path)) {
LOG_INFO("load %s using gguf format", file_path.c_str());
return init_from_gguf_file(file_path, prefix);
} else if (ends_with(file_path, ".json")) {
LOG_INFO("load %s using safetensors index format", file_path.c_str());
return init_from_safetensors_index_file(file_path, prefix);
} else if (is_safetensors_file(file_path)) {
LOG_INFO("load %s using safetensors format", file_path.c_str());
return init_from_safetensors_file(file_path, prefix);
@ -342,25 +339,6 @@ bool ModelLoader::init_from_safetensors_file(const std::string& file_path, const
return true;
}
bool ModelLoader::init_from_safetensors_index_file(const std::string& file_path, const std::string& prefix) {
LOG_DEBUG("init from safetensors index '%s', prefix = '%s'", file_path.c_str(), prefix.c_str());
std::vector<std::string> shard_paths;
std::string error;
if (!read_safetensors_index_file(file_path, shard_paths, &error)) {
LOG_ERROR("%s", error.c_str());
return false;
}
for (const std::string& shard_path : shard_paths) {
if (!init_from_file(shard_path, prefix)) {
return false;
}
}
return true;
}
/*================================================= TorchLegacyModelLoader ==================================================*/
bool ModelLoader::init_from_torch_legacy_file(const std::string& file_path, const std::string& prefix) {

View File

@ -43,7 +43,6 @@ protected:
bool init_from_gguf_file(const std::string& file_path, const std::string& prefix = "");
bool init_from_safetensors_file(const std::string& file_path, const std::string& prefix = "");
bool init_from_safetensors_index_file(const std::string& file_path, const std::string& prefix = "");
bool init_from_torch_zip_file(const std::string& file_path, const std::string& prefix = "");
bool init_from_torch_legacy_file(const std::string& file_path, const std::string& prefix = "");
bool init_from_diffusers_file(const std::string& file_path, const std::string& prefix = "");

View File

@ -179,102 +179,6 @@ bool ModelManager::register_param_tensors(const std::string& desc,
return true;
}
bool ModelManager::unregister_param_tensors(const std::string& desc, size_t* registered_tensor_size) {
if (desc.empty()) {
return true;
}
std::unordered_set<TensorState*> target_states;
size_t released_size = 0;
for (auto& state : tensor_states_) {
if (state == nullptr || state->desc != desc) {
continue;
}
if (state->active_prepare_count > 0) {
LOG_ERROR("model manager cannot unregister active %s tensor '%s'",
desc.c_str(),
state->name.c_str());
return false;
}
target_states.insert(state.get());
if (state->tensor != nullptr) {
released_size += ggml_nbytes(state->tensor);
}
}
if (target_states.empty()) {
return true;
}
release_compute_staging_blocks(false);
std::vector<ParamsStorageBlock*> storage_blocks_to_release;
std::unordered_set<TensorState*> affected_storage_states;
for (const auto& block : params_storage_blocks_) {
if (block == nullptr) {
continue;
}
bool has_target_state = false;
for (TensorState* state : block->states) {
if (state != nullptr && target_states.count(state) > 0) {
has_target_state = true;
break;
}
}
if (!has_target_state) {
continue;
}
storage_blocks_to_release.push_back(block.get());
for (TensorState* state : block->states) {
if (state != nullptr) {
affected_storage_states.insert(state);
}
}
}
for (TensorState* state : affected_storage_states) {
if (state == nullptr) {
continue;
}
if (state->active_prepare_count > 0 || state->staged_to_compute_backend) {
LOG_ERROR("model manager cannot unregister %s while tensor '%s' is active",
desc.c_str(),
state->name.c_str());
return false;
}
}
for (ParamsStorageBlock* block : storage_blocks_to_release) {
if (block != nullptr) {
free_params_storage_block(*block);
erase_params_storage_block(block);
}
}
for (auto it = tensor_states_by_name_.begin(); it != tensor_states_by_name_.end();) {
if (target_states.count(it->second) > 0) {
it = tensor_states_by_name_.erase(it);
} else {
++it;
}
}
tensor_states_.erase(std::remove_if(tensor_states_.begin(),
tensor_states_.end(),
[&](const std::unique_ptr<TensorState>& s) {
return s == nullptr || target_states.count(s.get()) > 0;
}),
tensor_states_.end());
if (registered_tensor_size != nullptr) {
if (released_size > *registered_tensor_size) {
*registered_tensor_size = 0;
} else {
*registered_tensor_size -= released_size;
}
}
return true;
}
bool ModelManager::load_all_params_eagerly() {
std::vector<TensorState*> all_states;
all_states.reserve(tensor_states_.size());

View File

@ -134,9 +134,6 @@ public:
bool allow_split_buffer = false,
bool params_follow_compute_backend = false);
bool unregister_param_tensors(const std::string& desc,
size_t* registered_tensor_size = nullptr);
template <typename Runner>
bool register_runner_params(const std::string& desc,
Runner& runner,

View File

@ -222,13 +222,9 @@ public:
std::string split_mode_spec;
bool auto_fit_enabled = false;
bool diffusion_conv_direct = false;
bool is_using_v_parameterization = false;
bool is_using_edm_v_parameterization = false;
size_t control_net_params_mem_size = 0;
std::shared_ptr<ModelManager> model_manager;
std::shared_ptr<Denoiser> denoiser = std::make_shared<CompVisDenoiser>();
@ -498,76 +494,6 @@ public:
params_follow_runtime);
}
bool unload_control_net() {
if (control_net == nullptr) {
return true;
}
if (model_manager != nullptr) {
if (!model_manager->unregister_param_tensors("ControlNet", &control_net_params_mem_size)) {
return false;
}
}
control_net.reset();
control_net_params_mem_size = 0;
return true;
}
bool load_control_net_from_file(const std::string& path) {
if (path.empty()) {
LOG_ERROR("sd_ctx_load_control_net: empty path");
return false;
}
if (model_manager == nullptr) {
LOG_ERROR("sd_ctx_load_control_net: model_manager not initialized");
return false;
}
if (!unload_control_net()) {
return false;
}
ModelLoader& shared_loader = model_manager->loader();
if (!shared_loader.init_from_file(path)) {
LOG_ERROR("sd_ctx_load_control_net: failed to load '%s'", path.c_str());
return false;
}
shared_loader.convert_tensors_name();
if (!ensure_backend_pair(SDBackendModule::CONTROL_NET)) {
LOG_ERROR("sd_ctx_load_control_net: control_net backend unavailable");
return false;
}
control_net = std::make_shared<ControlNet>(backend_for(SDBackendModule::CONTROL_NET),
params_backend_for(SDBackendModule::CONTROL_NET),
shared_loader.get_tensor_storage_map(),
version,
"",
model_manager);
if (diffusion_conv_direct) {
LOG_INFO("Using Conv2d direct in the control net");
control_net->set_conv2d_direct_enabled(true);
}
if (!register_runner_params("ControlNet",
control_net,
SDBackendModule::CONTROL_NET,
&control_net_params_mem_size)) {
LOG_ERROR("sd_ctx_load_control_net: register_runner_params failed");
control_net.reset();
control_net_params_mem_size = 0;
return false;
}
if (!model_manager->validate_registered_tensors()) {
LOG_ERROR("sd_ctx_load_control_net: registered tensors validation failed");
unload_control_net();
return false;
}
LOG_INFO("sd_ctx_load_control_net: loaded '%s' (%.2f MB)",
path.c_str(),
control_net_params_mem_size / 1024.0 / 1024.0);
return true;
}
bool init_backend() {
std::string error;
if (!backend_manager.init(backend_spec.c_str(),
@ -926,12 +852,10 @@ public:
model_loader.process_model_files(enable_mmap, needs_writable_mmap);
load_alphas_cumprod(model_loader);
diffusion_conv_direct = sd_ctx_params->diffusion_conv_direct;
size_t text_encoder_params_mem_size = 0;
size_t unet_params_mem_size = 0;
size_t vae_params_mem_size = 0;
control_net_params_mem_size = 0;
size_t control_net_params_mem_size = 0;
size_t extension_params_mem_size = 0;
bool tae_preview_only = sd_ctx_params->tae_preview_only;
@ -3505,27 +3429,6 @@ SD_API bool sd_ctx_supports_video_generation(const sd_ctx_t* sd_ctx) {
return sd_version_supports_video_generation(sd_ctx->sd->version);
}
SD_API bool sd_ctx_load_control_net(sd_ctx_t* sd_ctx, const char* path) {
if (sd_ctx == nullptr || sd_ctx->sd == nullptr || path == nullptr) {
return false;
}
return sd_ctx->sd->load_control_net_from_file(path);
}
SD_API bool sd_ctx_unload_control_net(sd_ctx_t* sd_ctx) {
if (sd_ctx == nullptr || sd_ctx->sd == nullptr) {
return false;
}
return sd_ctx->sd->unload_control_net();
}
SD_API bool sd_ctx_has_control_net(const sd_ctx_t* sd_ctx) {
if (sd_ctx == nullptr || sd_ctx->sd == nullptr) {
return false;
}
return sd_ctx->sd->control_net != nullptr;
}
enum sample_method_t sd_get_default_sample_method(const sd_ctx_t* sd_ctx) {
if (sd_ctx != nullptr && sd_ctx->sd != nullptr) {
if (sd_version_is_pid(sd_ctx->sd->version)) {