• 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,Version version)77 void spirvTestsRegistry::addTestClass(baseTestClass *test, const char *testName,
78                                       Version version)
79 {
80 
81     testClasses.push_back(test);
82     test_definition testDef;
83     testDef.func = test->getFunction();
84     testDef.name = testName;
85     testDef.min_version = version;
86     testDefinitions.push_back(testDef);
87 }
88 
getInstance()89 spirvTestsRegistry& spirvTestsRegistry::getInstance()
90 {
91     static spirvTestsRegistry instance;
92     return instance;
93 }
94 
offline_get_program_with_il(clProgramWrapper & prog,const cl_device_id deviceID,const cl_context context,const char * prog_name)95 static int offline_get_program_with_il(clProgramWrapper &prog,
96                                        const cl_device_id deviceID,
97                                        const cl_context context,
98                                        const char *prog_name)
99 {
100     cl_int err = 0;
101     std::string outputTypeStr = "binary";
102     std::string defaultScript = std::string("..") + slash + std::string("spv_to_binary.py");
103     std::string outputFilename = spvBinariesPath + slash + std::string(prog_name);
104     std::string sourceFilename = outputFilename +  spvExt;
105 
106     std::string scriptArgs =
107         sourceFilename + " " +
108         outputFilename + " " +
109         gAddrWidth + " " +
110         outputTypeStr + " " +
111         "-cl-std=CL2.0";
112 
113     std::string scriptToRunString = defaultScript + scriptArgs;
114 
115     // execute script
116     log_info("Executing command: %s\n", scriptToRunString.c_str());
117     fflush(stdout);
118     int returnCode = system(scriptToRunString.c_str());
119     if (returnCode != 0) {
120         log_error("Command finished with error: 0x%x\n", returnCode);
121         return CL_COMPILE_PROGRAM_FAILURE;
122     }
123 
124     // read output file
125     std::vector<unsigned char> buffer_vec = readBinary(outputFilename.c_str());
126     size_t file_bytes = buffer_vec.size();
127     if (file_bytes == 0) {
128         log_error("OfflinerCompiler: Failed to open binary file: %s", outputFilename.c_str());
129         return -1;
130     }
131 
132     const unsigned char *buffer = &buffer_vec[0];
133     cl_int status = 0;
134     prog = clCreateProgramWithBinary(context, 1, &deviceID, &file_bytes, &buffer, &status, &err);
135     SPIRV_CHECK_ERROR((err || status), "Failed to create program with clCreateProgramWithBinary");
136     return err;
137 }
138 
get_program_with_il(clProgramWrapper & prog,const cl_device_id deviceID,const cl_context context,const char * prog_name,spec_const spec_const_def)139 int get_program_with_il(clProgramWrapper &prog, const cl_device_id deviceID,
140                         const cl_context context, const char *prog_name,
141                         spec_const spec_const_def)
142 {
143     cl_int err = 0;
144     if (gCompilationMode == kBinary)
145     {
146         return offline_get_program_with_il(prog, deviceID, context, prog_name);
147     }
148 
149     std::vector<unsigned char> buffer_vec = readSPIRV(prog_name);
150 
151     int file_bytes = buffer_vec.size();
152     if (file_bytes == 0)
153     {
154         log_error("File %s not found\n", prog_name);
155         return -1;
156     }
157 
158     unsigned char *buffer = &buffer_vec[0];
159     if (gCoreILProgram)
160     {
161         prog = clCreateProgramWithIL(context, buffer, file_bytes, &err);
162         SPIRV_CHECK_ERROR(
163             err, "Failed to create program with clCreateProgramWithIL");
164 
165         if (spec_const_def.spec_value != NULL)
166         {
167             err = clSetProgramSpecializationConstant(
168                 prog, spec_const_def.spec_id, spec_const_def.spec_size,
169                 spec_const_def.spec_value);
170             SPIRV_CHECK_ERROR(
171                 err, "Failed to run clSetProgramSpecializationConstant");
172         }
173     }
174     else
175     {
176         cl_platform_id platform;
177         err = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM,
178                               sizeof(cl_platform_id), &platform, NULL);
179         SPIRV_CHECK_ERROR(err,
180                           "Failed to get platform info with clGetDeviceInfo");
181         clCreateProgramWithILKHR_fn clCreateProgramWithILKHR = NULL;
182 
183         clCreateProgramWithILKHR = (clCreateProgramWithILKHR_fn)
184             clGetExtensionFunctionAddressForPlatform(
185                 platform, "clCreateProgramWithILKHR");
186         if (clCreateProgramWithILKHR == NULL)
187         {
188             log_error(
189                 "ERROR: clGetExtensionFunctionAddressForPlatform failed\n");
190             return -1;
191         }
192         prog = clCreateProgramWithILKHR(context, buffer, file_bytes, &err);
193         SPIRV_CHECK_ERROR(
194             err, "Failed to create program with clCreateProgramWithILKHR");
195     }
196 
197     err = clBuildProgram(prog, 1, &deviceID, NULL, NULL, NULL);
198     SPIRV_CHECK_ERROR(err, "Failed to build program");
199 
200     return err;
201 }
202 
InitCL(cl_device_id id)203 test_status InitCL(cl_device_id id)
204 {
205     test_status spirv_status;
206     bool force = true;
207     spirv_status = check_spirv_compilation_readiness(id);
208     if (spirv_status != TEST_PASS)
209     {
210         return spirv_status;
211     }
212 
213     cl_uint address_bits;
214     cl_uint err = clGetDeviceInfo(id, CL_DEVICE_ADDRESS_BITS, sizeof(cl_uint),
215                                   &address_bits, NULL);
216     if (err != CL_SUCCESS)
217     {
218         log_error("clGetDeviceInfo failed to get address bits!");
219         return TEST_FAIL;
220     }
221 
222     gAddrWidth = address_bits == 32 ? "32" : "64";
223     return TEST_PASS;
224 }
225 
printUsage()226 void printUsage() {
227     log_info("Reading SPIR-V files from default '%s' path.\n", spvBinariesPath.c_str());
228     log_info("In case you want to set other directory use '%s' argument.\n", spvBinariesPathArg.c_str());
229 }
230 
main(int argc,const char * argv[])231 int main(int argc, const char *argv[])
232 {
233     gReSeed = 1;
234     bool modifiedSpvBinariesPath = false;
235     for (int i = 0; i < argc; ++i) {
236         int argsRemoveNum = 0;
237         if (argv[i] == spvBinariesPathArg) {
238             if (i + 1 == argc) {
239                 log_error("Missing value for '%s' argument.\n", spvBinariesPathArg.c_str());
240                 return TEST_FAIL;
241             } else {
242                 spvBinariesPath = std::string(argv[i + 1]);
243                 argsRemoveNum += 2;
244                 modifiedSpvBinariesPath = true;
245             }
246         }
247 
248         if (argsRemoveNum > 0) {
249             for (int j = i; j < (argc - argsRemoveNum); ++j)
250                 argv[j] = argv[j + argsRemoveNum];
251 
252             argc -= argsRemoveNum;
253             --i;
254         }
255     }
256     if (modifiedSpvBinariesPath == false) {
257        printUsage();
258     }
259 
260     return runTestHarnessWithCheck(
261         argc, argv, spirvTestsRegistry::getInstance().getNumTests(),
262         spirvTestsRegistry::getInstance().getTestDefinitions(), false, 0,
263         InitCL);
264 }
265