Skip to content

Commit dbc36f6

Browse files
committed
support to load .dlc module file
1 parent 67278d7 commit dbc36f6

File tree

12 files changed

+409
-25
lines changed

12 files changed

+409
-25
lines changed

samples/python/real_esrgan_x4plus/real_esrgan_x4plus.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
MODEL_ID = "mnz1l2exq"
2929
MODEL_NAME = "real_esrgan_x4plus"
3030
MODEL_HELP_URL = "https://github.com/quic/ai-engine-direct-helper/tree/main/samples/python/" + MODEL_NAME + "#" + MODEL_NAME + "-qnn-models"
31-
IMAGE_SIZE = 512
31+
3232

3333
####################################################################
3434

@@ -42,8 +42,13 @@
4242
execution_ws = execution_ws / MODEL_NAME
4343

4444
model_dir = execution_ws / "models"
45-
model_path = model_dir / "{}.bin".format(MODEL_NAME)
4645

46+
#load .bin
47+
model_path = model_dir / "{}.bin".format(MODEL_NAME)
48+
IMAGE_SIZE = 512
49+
#load .dlc
50+
#model_path = model_dir / "{}.dlc".format(MODEL_NAME)
51+
#IMAGE_SIZE = 128
4752

4853
####################################################################
4954

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ set(APP_SOURCES "QnnSampleApp.cpp"
2424
"Utils/DataUtil.cpp"
2525
"Utils/DynamicLoadUtil.cpp"
2626
"Utils/IOTensor.cpp"
27+
"Utils/QnnDlcUtils.cpp"
2728
"Utils/QnnSampleAppUtils.cpp"
2829
"WrapperUtils/QnnWrapperUtils.cpp"
2930
"LibAppBuilder.cpp"

src/LibAppBuilder.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ namespace qnn {
5454
namespace tools {
5555
namespace libappbuilder {
5656

57+
std::string getFileNameFromPath(const std::string& path) {
58+
if (path.empty()) return {};
59+
size_t pos = path.find_last_of("/\\");
60+
if (pos == std::string::npos || pos == path.size() - 1) {
61+
return {};
62+
}
63+
return path.substr(pos + 1);
64+
}
65+
66+
5767
void warmup_parallel_stl()
5868
{
5969
static std::once_flag once;
@@ -66,6 +76,7 @@ void warmup_parallel_stl()
6676
QNN_WAR("warmup_parallel_stl");
6777
}
6878

79+
6980
std::unique_ptr<sample_app::QnnSampleApp> initQnnSampleApp(std::string cachedBinaryPath, std::string backEndPath, std::string systemLibraryPath,
7081
bool loadFromCachedBinary, std::vector<LoraAdapter>& lora_adapters,
7182
const std::string& input_data_type, const std::string& output_data_type) {
@@ -74,6 +85,10 @@ std::unique_ptr<sample_app::QnnSampleApp> initQnnSampleApp(std::string cachedBin
7485
std::string cachedBinaryPath2;
7586
std::string opPackagePaths;
7687
std::string saveBinaryName;
88+
if (!cachedBinaryPath.empty()){
89+
saveBinaryName = getFileNameFromPath(cachedBinaryPath);
90+
QNN_DEBUG("initQnnSampleApp saveBinaryName=%s\n", saveBinaryName.c_str());
91+
}
7792

7893
if (loadFromCachedBinary) { // *.bin
7994
cachedBinaryPath2 = cachedBinaryPath;
@@ -123,7 +138,7 @@ std::unique_ptr<sample_app::QnnSampleApp> initQnnSampleApp(std::string cachedBin
123138
sg_qnnInterface = qnnFunctionPointers.qnnInterface;
124139
std::unique_ptr<sample_app::QnnSampleApp> app(new sample_app::QnnSampleApp(qnnFunctionPointers, "null", opPackagePaths, sg_backendHandle, "null",
125140
debug, parsedOutputDataType, parsedInputDataType, sg_parsedProfilingLevel,
126-
dumpOutputs, cachedBinaryPath2, saveBinaryName, lora_adapters));
141+
dumpOutputs, cachedBinaryPath2, saveBinaryName, lora_adapters, cachedBinaryPath));
127142
return app;
128143
}
129144

@@ -307,6 +322,10 @@ bool DeleteShareMemory(std::string share_memory_name) {
307322
#endif
308323
}
309324

325+
bool fileExists(const std::string& path) {
326+
std::ifstream f(path.c_str());
327+
return f.good();
328+
}
310329
bool ModelInitializeEx(const std::string& model_name, const std::string& proc_name, const std::string& model_path,
311330
const std::string& backend_lib_path, const std::string& system_lib_path,
312331
std::vector<LoraAdapter>& lora_adapters,
@@ -333,8 +352,14 @@ bool ModelInitializeEx(const std::string& model_name, const std::string& proc_na
333352
std::string suffix_mode_path = cachedBinaryPath.substr(cachedBinaryPath.find_last_of('.') + 1);
334353
if (suffix_mode_path == "bin") { // *.bin
335354
QNN_INFO("cachedBinaryPath: %s", cachedBinaryPath.c_str());
336-
}
337-
else { // *.dll
355+
} else if (suffix_mode_path == "dlc"){
356+
std::string dlcBinPath = cachedBinaryPath + ".bin";
357+
if (fileExists(dlcBinPath)) {
358+
cachedBinaryPath = dlcBinPath;
359+
suffix_mode_path = "bin";
360+
QNN_INFO("Found dlc.bin, updated cachedBinaryPath: %s\n", cachedBinaryPath.c_str());
361+
}
362+
} else { // *.dll
338363
loadFromCachedBinary = false;
339364
QNN_INFO("modelPath: %s", cachedBinaryPath.c_str());
340365
}
@@ -382,7 +407,7 @@ bool ModelInitializeEx(const std::string& model_name, const std::string& proc_na
382407
return false;
383408
}
384409

385-
if (!loadFromCachedBinary) {
410+
if (!loadFromCachedBinary || (suffix_mode_path == "dlc")) { //issue#23
386411
if (sample_app::StatusCode::SUCCESS != app->createContext()) {
387412
app->reportError("Context Creation failure");
388413
return false;

src/PAL/include/PAL/DynamicLoading.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ enum {
2626
DL_NOW = 0x0001,
2727
DL_LOCAL = 0x0002,
2828
DL_GLOBAL = 0x0004,
29+
DL_NOLOAD = 0x0008
2930
};
3031

3132
// specify this address to distingiush from NULL pointer

src/PAL/src/windows/DynamicLoading.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,18 @@ void *pal::dynamicloading::dlOpen(const char *filename, int flags) {
4646
// that would be too costly. SNPE didn't use this feature now
4747
// , wait until we really need it. keep the flexibility here
4848
// ask caller MUST pass DL_NOW
49-
sg_lastErrMsg = "flags must include DL_NOW";
49+
sg_lastErrMsg = "flags must include DL_NOW or only specify DL_NOLOAD";
5050
return NULL;
5151
}
5252

53+
// Only test if the specified library is loaded or not
54+
// Return its handle if loaded, otherwise, return NULL
55+
if (flags & DL_NOLOAD) {
56+
// If the library is loaded, it would be a handle to this library
57+
// If the library is not loaded, it would be a NULL
58+
mod = GetModuleHandleA(filename);
59+
return static_cast<void *>(mod);
60+
}
5361
cur_proc = GetCurrentProcess();
5462

5563
if (EnumProcessModules(cur_proc, NULL, 0, &as_is) == 0) {

src/QnnSampleApp.cpp

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "PAL/FileOp.hpp"
1919
#include "PAL/Path.hpp"
2020
#include "PAL/StringOp.hpp"
21+
#include "QnnDlcUtils.hpp"
2122
#include "QnnSampleApp.hpp"
2223
#include "QnnSampleAppUtils.hpp"
2324
#include "QnnWrapperUtils.hpp"
@@ -192,7 +193,8 @@ sample_app::QnnSampleApp::QnnSampleApp(QnnFunctionPointers qnnFunctionPointers,
192193
bool dumpOutputs,
193194
std::string cachedBinaryPath,
194195
std::string saveBinaryName,
195-
const std::vector<LoraAdapter>& lora_adapters)
196+
const std::vector<LoraAdapter>& lora_adapters,
197+
std::string dlcPath)
196198
: m_qnnFunctionPointers(qnnFunctionPointers),
197199
m_outputPath(outputPath),
198200
m_saveBinaryName(saveBinaryName),
@@ -204,9 +206,17 @@ sample_app::QnnSampleApp::QnnSampleApp(QnnFunctionPointers qnnFunctionPointers,
204206
m_profilingLevel(profilingLevel),
205207
m_dumpOutputs(dumpOutputs),
206208
m_isBackendInitialized(false),
207-
m_isContextCreated(false) {
209+
m_isContextCreated(false),
210+
m_dlcPath(dlcPath)
211+
{
212+
208213
split(m_inputListPaths, inputListPaths, ',');
209214
split(m_opPackagePaths, opPackagePaths, ',');
215+
if(!dlcPath.empty()){
216+
size_t pos = dlcPath.find_last_of("\\/");
217+
m_outputPath = dlcPath.substr(0, pos);
218+
//printf("m_outputPath=%s\n", m_outputPath.c_str());
219+
}
210220
if (m_outputPath.empty()) {
211221
m_outputPath = s_defaultOutputPath;
212222
}
@@ -220,6 +230,10 @@ sample_app::QnnSampleApp::QnnSampleApp(QnnFunctionPointers qnnFunctionPointers,
220230
}
221231

222232
sample_app::QnnSampleApp::~QnnSampleApp() {
233+
// Free DLC resources using utility function
234+
dlc_utils::freeDlcResources(m_qnnFunctionPointers.qnnSystemInterfaceHandle,
235+
m_dlcHandle,
236+
m_dlcLogHandle);
223237
// Free Profiling object if it was created
224238
if (nullptr != m_profileBackendHandle) {
225239
QNN_DEBUG("Freeing backend profile object.");
@@ -448,20 +462,30 @@ sample_app::StatusCode sample_app::QnnSampleApp::freeContext() {
448462
// are expected to be read by the app.
449463
sample_app::StatusCode sample_app::QnnSampleApp::composeGraphs() {
450464
auto returnStatus = StatusCode::SUCCESS;
451-
if (qnn_wrapper_api::ModelError_t::MODEL_NO_ERROR !=
452-
m_qnnFunctionPointers.composeGraphsFnHandle(
453-
m_backendHandle,
454-
m_qnnFunctionPointers.qnnInterface,
455-
m_context,
456-
(const qnn_wrapper_api::GraphConfigInfo_t**)m_graphConfigsInfo,
457-
m_graphConfigsInfoCount,
458-
&m_graphsInfo,
459-
&m_graphsCount,
460-
m_debug,
461-
log::getLogCallback(),
462-
log::getLogLevel())) {
463-
QNN_ERROR("Failed in composeGraphs()");
464-
returnStatus = StatusCode::FAILURE;
465+
// If DLC path is provided, use DLC-based composition
466+
if (!m_dlcPath.empty()) {
467+
printf("DLC path provided, using DLC-based graph composition\n");
468+
returnStatus = composeGraphsFromDlc();
469+
return returnStatus;
470+
} else{
471+
// Default: compose with QNN's model.so
472+
// Default path: use model.so
473+
QNN_INFO("Using model.so for graph composition");
474+
if (qnn_wrapper_api::ModelError_t::MODEL_NO_ERROR !=
475+
m_qnnFunctionPointers.composeGraphsFnHandle(
476+
m_backendHandle,
477+
m_qnnFunctionPointers.qnnInterface,
478+
m_context,
479+
(const qnn_wrapper_api::GraphConfigInfo_t**)m_graphConfigsInfo,
480+
m_graphConfigsInfoCount,
481+
&m_graphsInfo,
482+
&m_graphsCount,
483+
m_debug,
484+
log::getLogCallback(),
485+
log::getLogLevel())) {
486+
QNN_ERROR("Failed in composeGraphs()");
487+
returnStatus = StatusCode::FAILURE;
488+
}
465489
}
466490
return returnStatus;
467491
}
@@ -983,6 +1007,38 @@ sample_app::StatusCode sample_app::QnnSampleApp::saveBinary() {
9831007

9841008
// C:\Qualcomm\AIStack\QNN\<version>\include\QNN\QnnProfile.h
9851009
// C:\Qualcomm\AIStack\QNN\<version>\include\QNN\HTP\QnnHtpProfile.h
1010+
sample_app::StatusCode sample_app::QnnSampleApp::composeGraphsFromDlc() {
1011+
QNN_DEBUG("Composing graphs from DLC\n");
1012+
// Create DLC handle using utility function
1013+
auto dlcStatus = dlc_utils::createDlcHandle(m_qnnFunctionPointers.qnnSystemInterfaceHandle,
1014+
m_dlcPath,
1015+
log::getLogCallback(),
1016+
log::getLogLevel(),
1017+
m_dlcLogHandle,
1018+
m_dlcHandle);
1019+
1020+
if (dlc_utils::StatusCode::SUCCESS != dlcStatus) {
1021+
QNN_ERROR("Failed to create DLC handle");
1022+
return StatusCode::FAILURE;
1023+
}
1024+
1025+
// Compose graphs from DLC using utility function
1026+
dlcStatus = dlc_utils::composeGraphsFromDlc(m_qnnFunctionPointers.qnnSystemInterfaceHandle,
1027+
m_dlcHandle,
1028+
m_backendHandle,
1029+
m_context,
1030+
m_qnnFunctionPointers.qnnInterfaceHandle,
1031+
m_graphsInfo,
1032+
m_graphsCount);
1033+
1034+
if (dlc_utils::StatusCode::SUCCESS != dlcStatus) {
1035+
QNN_ERROR("Failed to compose graphs from DLC");
1036+
return StatusCode::FAILURE;
1037+
}
1038+
1039+
QNN_INFO("Successfully composed %d graphs from DLC", m_graphsCount);
1040+
return StatusCode::SUCCESS;
1041+
}
9861042
sample_app::StatusCode sample_app::QnnSampleApp::extractBackendProfilingInfo(
9871043
Qnn_ProfileHandle_t profileHandle) {
9881044
if (nullptr == m_profileBackendHandle) {

src/QnnSampleApp.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ class QnnSampleApp {
6060
bool dumpOutputs = false,
6161
std::string cachedBinaryPath = "",
6262
std::string saveBinaryName = "",
63-
const std::vector<LoraAdapter>& lora_adapters = std::vector<LoraAdapter>());
63+
const std::vector<LoraAdapter>& lora_adapters = std::vector<LoraAdapter>(),
64+
std::string dlcPath = "");
6465

6566
// @brief Print a message to STDERR then return a nonzero
6667
// exit status.
@@ -169,6 +170,7 @@ class QnnSampleApp {
169170

170171
StatusCode extractProfilingEvent(QnnProfile_EventId_t profileEventId);
171172

173+
StatusCode composeGraphsFromDlc();
172174
static const std::string s_defaultOutputPath;
173175

174176
QnnFunctionPointers m_qnnFunctionPointers;
@@ -220,6 +222,10 @@ class QnnSampleApp {
220222
std::string m_graphName;
221223
std::vector<std::string> m_inputName;
222224
std::vector<std::string> m_outputName;
225+
226+
std::string m_dlcPath;
227+
QnnSystemDlc_Handle_t m_dlcHandle = nullptr;
228+
Qnn_LogHandle_t m_dlcLogHandle = nullptr;
223229
};
224230
} // namespace sample_app
225231
} // namespace tools

src/SampleApp.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ typedef struct QnnFunctionPointers {
3636
FreeGraphInfoFnHandleType_t freeGraphInfoFnHandle;
3737
QNN_INTERFACE_VER_TYPE qnnInterface;
3838
QNN_SYSTEM_INTERFACE_VER_TYPE qnnSystemInterface;
39+
QnnInterface_t qnnInterfaceHandle;
40+
QnnSystemInterface_t qnnSystemInterfaceHandle;
3941
} QnnFunctionPointers;
4042

4143
} // namespace sample_app

src/Utils/BuildId.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
namespace qnn {
1212
namespace tools {
1313

14-
inline std::string getBuildId() { return std::string("v2.38.0.250901140452_125126"); }
14+
inline std::string getBuildId() { return std::string("v2.42.0.251225"); }
1515

1616
} // namespace tools
1717
} // namespace qnn

src/Utils/DynamicLoadUtil.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ dynamicloadutil::StatusCode dynamicloadutil::getQnnFunctionPointers(
7777
QNN_API_VERSION_MINOR <= interfaceProviders[pIdx]->apiVersion.coreApiVersion.minor) {
7878
foundValidInterface = true;
7979
qnnFunctionPointers->qnnInterface = interfaceProviders[pIdx]->QNN_INTERFACE_VER_NAME;
80+
qnnFunctionPointers->qnnInterfaceHandle = *interfaceProviders[pIdx];
8081
break;
8182
}
8283
}
@@ -166,6 +167,7 @@ dynamicloadutil::StatusCode dynamicloadutil::getQnnSystemFunctionPointers(
166167
foundValidSystemInterface = true;
167168
qnnFunctionPointers->qnnSystemInterface =
168169
systemInterfaceProviders[pIdx]->QNN_SYSTEM_INTERFACE_VER_NAME;
170+
qnnFunctionPointers->qnnSystemInterfaceHandle = *systemInterfaceProviders[pIdx];
169171
break;
170172
}
171173
}

0 commit comments

Comments
 (0)