• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************
2 Copyright (c) 2016 The Khronos Group Inc. All Rights Reserved.
3 
4 This code is protected by copyright laws and contains material proprietary to the Khronos Group, Inc.
5 This is UNPUBLISHED PROPRIETARY SOURCE CODE that may not be disclosed in whole or in part to
6 third parties, and may not be reproduced, republished, distributed, transmitted, displayed,
7 broadcast or otherwise exploited in any manner without the express prior written permission
8 of Khronos Group. The receipt or possession of this code does not convey any rights to reproduce,
9 disclose, or distribute its contents, or to manufacture, use, or sell anything that it may describe,
10 in whole or in part other than under the terms of the Khronos Adopters Agreement
11 or Khronos Conformance Test Source License Agreement as executed between Khronos and the recipient.
12 ******************************************************************/
13 
14 #include <stdio.h>
15 #include <string.h>
16 #include "procs.h"
17 #if !defined(_WIN32)
18 #include <unistd.h>
19 #endif
20 
21 #include <iostream>
22 #include <fstream>
23 #include <string>
24 #include <sstream>
25 
26 #if defined(_WIN32)
27 const std::string slash = "\\";
28 #else
29 const std::string slash = "/";
30 #endif
31 
32 const std::string spvExt = ".spv";
33 std::string gAddrWidth = "";
34 std::string spvBinariesPath = "spirv_bin";
35 std::string spvBinariesPathArg = "--spirv-binaries-path";
36 
readBinary(const char * file_name)37 std::vector<unsigned char> readBinary(const char *file_name)
38 {
39     using namespace std;
40 
41     ifstream file(file_name, ios::in | ios::binary | ios::ate);
42 
43     std::vector<char> tmpBuffer(0);
44 
45     if (file.is_open()) {
46         size_t size = file.tellg();
47         tmpBuffer.resize(size);
48         file.seekg(0, ios::beg);
49         file.read(&tmpBuffer[0], size);
50         file.close();
51     } else {
52         log_error("File %s not found\n", file_name);
53     }
54 
55     std::vector<unsigned char> result(tmpBuffer.begin(), tmpBuffer.end());
56 
57     return result;
58 }
59 
60 
readSPIRV(const char * file_name)61 std::vector<unsigned char> readSPIRV(const char *file_name)
62 {
63     std::string full_name_str = spvBinariesPath + slash + file_name + spvExt + gAddrWidth;
64     return readBinary(full_name_str.c_str());
65 }
66 
getTestDefinitions()67 test_definition *spirvTestsRegistry::getTestDefinitions()
68 {
69     return &testDefinitions[0];
70 }
71 
getNumTests()72 size_t spirvTestsRegistry::getNumTests()
73 {
74     return testDefinitions.size();
75 }
76 
addTestClass(baseTestClass * test,const char * testName)77 void spirvTestsRegistry::addTestClass(baseTestClass *test, const char *testName)
78 {
79 
80     testClasses.push_back(test);
81     test_definition testDef;
82     testDef.func = test->getFunction();
83     testDef.name = testName;
84     testDef.min_version = Version(2, 1);
85     testDefinitions.push_back(testDef);
86 }
87 
getInstance()88 spirvTestsRegistry& spirvTestsRegistry::getInstance()
89 {
90     static spirvTestsRegistry instance;
91     return instance;
92 }
93 
offline_get_program_with_il(clProgramWrapper & prog,const cl_device_id deviceID,const cl_context context,const char * prog_name)94 static int offline_get_program_with_il(clProgramWrapper &prog,
95                                        const cl_device_id deviceID,
96                                        const cl_context context,
97                                        const char *prog_name)
98 {
99     cl_int err = 0;
100     std::string outputTypeStr = "binary";
101     std::string defaultScript = std::string("..") + slash + std::string("spv_to_binary.py");
102     std::string outputFilename = spvBinariesPath + slash + std::string(prog_name);
103     std::string sourceFilename = outputFilename +  spvExt;
104 
105     std::string scriptArgs =
106         sourceFilename + " " +
107         outputFilename + " " +
108         gAddrWidth + " " +
109         outputTypeStr + " " +
110         "-cl-std=CL2.0";
111 
112     std::string scriptToRunString = defaultScript + scriptArgs;
113 
114     // execute script
115     log_info("Executing command: %s\n", scriptToRunString.c_str());
116     fflush(stdout);
117     int returnCode = system(scriptToRunString.c_str());
118     if (returnCode != 0) {
119         log_error("Command finished with error: 0x%x\n", returnCode);
120         return CL_COMPILE_PROGRAM_FAILURE;
121     }
122 
123     // read output file
124     std::vector<unsigned char> buffer_vec = readBinary(outputFilename.c_str());
125     size_t file_bytes = buffer_vec.size();
126     if (file_bytes == 0) {
127         log_error("OfflinerCompiler: Failed to open binary file: %s", outputFilename.c_str());
128         return -1;
129     }
130 
131     const unsigned char *buffer = &buffer_vec[0];
132     cl_int status = 0;
133     prog = clCreateProgramWithBinary(context, 1, &deviceID, &file_bytes, &buffer, &status, &err);
134     SPIRV_CHECK_ERROR((err || status), "Failed to create program with clCreateProgramWithBinary");
135     return err;
136 }
137 
get_program_with_il(clProgramWrapper & prog,const cl_device_id deviceID,const cl_context context,const char * prog_name)138 int get_program_with_il(clProgramWrapper &prog,
139                         const cl_device_id deviceID,
140                         const cl_context context,
141                         const char *prog_name)
142 {
143     cl_int err = 0;
144     if (gCompilationMode == kBinary) {
145         return offline_get_program_with_il(prog, deviceID, context, prog_name);
146     }
147 
148     std::vector<unsigned char> buffer_vec = readSPIRV(prog_name);
149 
150     int file_bytes = buffer_vec.size();
151     if (file_bytes == 0) {
152         log_error("File %s not found\n", prog_name);
153         return -1;
154     }
155 
156     unsigned char *buffer = &buffer_vec[0];
157     prog = clCreateProgramWithIL(context, buffer, file_bytes, &err);
158     SPIRV_CHECK_ERROR(err, "Failed to create program with clCreateProgramWithIL");
159 
160     err = clBuildProgram(prog, 1, &deviceID, NULL, NULL, NULL);
161     SPIRV_CHECK_ERROR(err, "Failed to build program");
162 
163     return err;
164 }
165 
checkAddressWidth(cl_device_id id)166 test_status checkAddressWidth(cl_device_id id)
167 {
168   cl_uint address_bits;
169   cl_uint err = clGetDeviceInfo(id, CL_DEVICE_ADDRESS_BITS, sizeof(cl_uint), &address_bits, NULL);
170   if(err != CL_SUCCESS){
171     log_error("clGetDeviceInfo failed to get address bits!");
172     return TEST_FAIL;
173   }
174 
175   gAddrWidth = address_bits == 32 ? "32" : "64";
176   return TEST_PASS;
177 }
178 
printUsage()179 void printUsage() {
180     log_info("Reading SPIR-V files from default '%s' path.\n", spvBinariesPath.c_str());
181     log_info("In case you want to set other directory use '%s' argument.\n", spvBinariesPathArg.c_str());
182 }
183 
main(int argc,const char * argv[])184 int main(int argc, const char *argv[])
185 {
186     gReSeed = 1;
187     bool modifiedSpvBinariesPath = false;
188     for (int i = 0; i < argc; ++i) {
189         int argsRemoveNum = 0;
190         if (argv[i] == spvBinariesPathArg) {
191             if (i + 1 == argc) {
192                 log_error("Missing value for '%s' argument.\n", spvBinariesPathArg.c_str());
193                 return TEST_FAIL;
194             } else {
195                 spvBinariesPath = std::string(argv[i + 1]);
196                 argsRemoveNum += 2;
197                 modifiedSpvBinariesPath = true;
198             }
199         }
200 
201         if (argsRemoveNum > 0) {
202             for (int j = i; j < (argc - argsRemoveNum); ++j)
203                 argv[j] = argv[j + argsRemoveNum];
204 
205             argc -= argsRemoveNum;
206             --i;
207         }
208     }
209     if (modifiedSpvBinariesPath == false) {
210        printUsage();
211     }
212 
213     return runTestHarnessWithCheck(argc, argv,
214                           spirvTestsRegistry::getInstance().getNumTests(),
215                           spirvTestsRegistry::getInstance().getTestDefinitions(),
216                           false, 0, checkAddressWidth);
217 }
218