11#include < iostream>
22
33#include < RunAsGPU/Shared/Shared.hpp>
4- #include < RunAsGPU/Shared/HelpPage.hpp>
54#include < RunAsGPU/Shared/Runner.hpp>
65
76namespace fs = std::filesystem;
87
9- void list () {
10- std::vector<GraphicalUnit> gpu_list = Runner::ListGraphicalUnits ();
8+ enum FindBy {
9+ Name = 0 ,
10+ Vendor = 1 ,
11+ Product = 2 ,
12+ Global = 3
13+ };
14+
15+ int findUnit (const std::vector<GraphicalUnit> &gpuList, const std::string &name, const FindBy &by) {
16+ for (int i = 0 ; i < gpuList.size (); i++) {
17+ switch (by) {
18+ case Name:
19+ if (StringContains (gpuList[i].fullName , name))
20+ return i;
21+
22+ break ;
23+ case Vendor:
24+ if (StringContains (gpuList[i].vendorName , name))
25+ return i;
26+
27+ if (name.find_first_not_of (" 0123456789ABCDEFabcdef" ) == std::string::npos) {
28+ try {
29+ int ven = std::stoi (name, nullptr , 16 );
30+ if (gpuList[i].vendor == ven)
31+ return i;
32+ } catch (const std::exception &e) {
33+ std::cerr << " Error: Invalid Vendor ID: " << name << std::endl;
34+ return -1 ;
35+ }
36+ }
37+
38+ break ;
39+ case Product:
40+ if (StringContains (gpuList[i].productName , name))
41+ return i;
42+
43+ if (name.find_first_not_of (" 0123456789ABCDEFabcdef" ) == std::string::npos) {
44+ try {
45+ int prod = std::stoi (name, nullptr , 16 );
46+ if (gpuList[i].product == prod)
47+ return i;
48+ } catch (const std::exception &e) {
49+ std::cerr << " Error: Invalid Product ID: " << name << std::endl;
50+ return -1 ;
51+ }
52+ }
53+
54+ break ;
55+ case Global:
56+ if (int res = findUnit (gpuList, name, Name); res != -1 ) return res;
57+ if (int res = findUnit (gpuList, name, Vendor); res != -1 ) return res;
58+ if (int res = findUnit (gpuList, name, Product); res != -1 ) return res;
59+ return -1 ;
60+ }
61+ }
62+
63+ return -1 ;
64+ }
65+
66+ void list (const std::vector<GraphicalUnit> &gpu_list) {
1167 for (int i = 0 ; i < gpu_list.size (); i++) {
12- const GraphicalUnit& unit = gpu_list[i];
68+ const GraphicalUnit & unit = gpu_list[i];
1369
1470 std::cout << " GPU - " << unit.vendorName << " (" << std::hex << unit.vendor << " )\n " ;
1571 std::cout << " \t Name = " << unit.productName << " (" << std::hex << unit.product << " )\n " ;
@@ -20,45 +76,135 @@ void list() {
2076 }
2177}
2278
79+ void printHelp (const std::string &exeName) {
80+ std::cout << " RunAsGPU v1.0" << std::endl;
81+ std::cout << " Usage: " << exeName << " [action] [options] [exec [..args]]\n " << std::endl;
82+ std::cout << " Actions:" << std::endl;
83+ std::cout << " list - List all active GPUs" << std::endl;
84+ std::cout << " run <command> - Run an application with GPU selection\n " << std::endl;
85+ std::cout << " Options:" << std::endl;
86+ std::cout << " -ui, --unit-id <ID> - Select a specific GPU by its given ID" << std::endl;
87+ std::cout << " -fu, --find-unit <GPU> - Find a GPU by identification" << std::endl;
88+ std::cout << " -fnu, --find-unit-name <N> - Find a GPU by name" << std::endl;
89+ std::cout << " -fvu, --find-unit-vendor <V> - Find a GPU by vendor name/ID" << std::endl;
90+ std::cout << " -fpu, --find-unit-product <P> - Find a GPU by product name/ID" << std::endl;
91+ }
92+
2393int main (int argc, char **argv) {
24- if (argc == 1 || (argc == 2 && (std::string (argv[1 ]) == " --help" || std::string (argv[1 ]) == " -h" ))) {
25- std::string fn = GetExecutablePath ().filename ().string ();
26-
27- std::cout << " RunAsGPU v1.0" << std::endl;
28- std::cout << " usage: ./" << fn << " [action] [options] [exec [..args]]" << std::endl << std::endl;
29- std::cout << " actions:" << std::endl;
30-
31- HelpPage actions;
32- actions.setStartSpaceWidth (4 );
33- actions.setDescSeparator (" " );
34- actions.addArg (" run" , " " , " Run an executable" );
35- actions.addArg (" list" , " " , " List all active GPUs" );
36- actions.display (std::cout);
37-
38- std::cout << std::endl;
39- std::cout << " options:" << std::endl;
40-
41- HelpPage options;
42- options.setStartSpaceWidth (4 );
43- options.setSpaceWidth (3 );
44- options.setDescSeparator (" =" );
45- options.addArg (" -ui | --unit-id" , " ID" , " Select a specific GPU by its given ID" );
46- options.addArg (" -fu | --find-unit" , " [GPU]" , " Find a GPU by its identification (Vendor ID, Device / Product ID, Name)" );
47- options.addArg (" -fnu | --find-unit-name" , " [Name]" , " Find a GPU by the name" );
48- options.addArg (" -fvu | --find-unit-vendor" , " [Vendor]" , " Find a GPU by the name or ID of the Vendor (e.g. NVIDIA)" );
49- options.addArg (" -fpu | --find-unit-product" , " [Product]" , " Find a GPU by the name or ID of the Product (e.g. GeForce 6800 XT)" );
50- options.addArg (" -ni | --non-interactive" , " " , " Will not prompt for GPU selection (e.g. running as a script)" );
51- options.display (std::cout);
94+ if (argc < 2 ) {
95+ printHelp (argv[0 ]);
96+ return 1 ;
97+ }
98+
99+ std::string action = argv[1 ];
52100
101+ if (action == " --help" || action == " -h" ) {
102+ printHelp (argv[0 ]);
53103 return 0 ;
54104 }
55105
56- std::vector<std::string> args;
57- std::string action = argv[1 ];
106+ std::vector<GraphicalUnit> gpu_list = Runner::ListGraphicalUnits ();
107+ int unit = 0 ;
108+
58109 if (action == " list" ) {
59- list ();
110+ list (gpu_list );
60111 return 0 ;
61112 }
62113
63- return 0 ;
114+ if (action == " run" ) {
115+ std::vector<std::string> args;
116+ for (int i = 2 ; i < argc; i++) {
117+ std::string arg = argv[i];
118+
119+ if (arg == " -ui" || arg == " --unit-id" ) {
120+ if (i + 1 < argc) {
121+ std::string unitStr = argv[++i];
122+ if (unitStr.find_first_not_of (" 0123456789" ) == std::string::npos)
123+ unit = std::stoi (unitStr);
124+ else {
125+ std::cerr << " Invalid GPU ID: " << unitStr << " \n " ;
126+ return 1 ;
127+ }
128+ } else {
129+ std::cerr << " Missing value for " << arg << " \n " ;
130+ return 1 ;
131+ }
132+ } else if (arg == " -fu" || arg == " --find-unit" ) {
133+ if (i + 1 < argc) {
134+ std::string data = argv[++i];
135+ unit = findUnit (gpu_list, data, Global);
136+
137+ if (unit == -1 ) {
138+ std::cerr << " Invalid data given: " << data << std::endl;
139+ return 1 ;
140+ }
141+ } else {
142+ std::cerr << " Missing value for " << arg << " \n " ;
143+ return 1 ;
144+ }
145+ } else if (arg == " -fnu" || arg == " --find-unit-name" ) {
146+ if (i + 1 < argc) {
147+ std::string data = argv[++i];
148+ unit = findUnit (gpu_list, data, Name);
149+
150+ if (unit == -1 ) {
151+ std::cerr << " Invalid name: " << data << std::endl;
152+ return 1 ;
153+ }
154+ } else {
155+ std::cerr << " Missing value for " << arg << " \n " ;
156+ return 1 ;
157+ }
158+ } else if (arg == " -fvu" || arg == " --find-unit-vendor" ) {
159+ if (i + 1 < argc) {
160+ std::string data = argv[++i];
161+ unit = findUnit (gpu_list, argv[++i], Vendor);
162+
163+ if (unit == -1 ) {
164+ std::cerr << " Invalid vendor name/ID: " << argv[i] << " \n " ;
165+ return 1 ;
166+ }
167+ } else {
168+ std::cerr << " Missing value for " << arg << " \n " ;
169+ return 1 ;
170+ }
171+ } else if (arg == " -fpu" || arg == " --find-unit-product" ) {
172+ if (i + 1 < argc) {
173+ std::string data = argv[++i];
174+ unit = findUnit (gpu_list, data, Product);
175+
176+ if (unit == -1 ) {
177+ std::cerr << " Invalid product name/ID: " << data << " \n " ;
178+ return 1 ;
179+ }
180+ } else {
181+ std::cerr << " Missing value for " << arg << " \n " ;
182+ return 1 ;
183+ }
184+ } else
185+ args.push_back (arg);
186+ }
187+
188+ if (args.empty ()) {
189+ std::cerr << " No executable specified.\n " ;
190+ return 1 ;
191+ }
192+
193+ std::string execPath = args[0 ];
194+ args.erase (args.begin ());
195+
196+ std::string command = " DRI_PRIME=" + std::to_string (unit) + " " + execPath;
197+ for (const auto & arg : args) {
198+ command += " " + arg;
199+ }
200+
201+ std::cout << " Running: " << command << " \n " ;
202+ int result = std::system (command.c_str ());
203+
204+ return result == 0 ? 0 : 1 ;
205+ }
206+
207+ std::cerr << " Unknown command: " << action << " \n " ;
208+ printHelp (argv[0 ]);
209+ return 1 ;
64210}
0 commit comments