Changeset 3450 in CLRX


Ignore:
Timestamp:
Sep 29, 2017, 8:19:51 PM (23 months ago)
Author:
matszpk
Message:

CLRadeonExtender: Add new library: CLRXCLHelper that facilitate creating binary/program for OpenCL. Use CLRXCLHelper in samples.

Location:
CLRadeonExtender/trunk
Files:
6 added
5 edited

Legend:

Unmodified
Added
Removed
  • CLRadeonExtender/trunk/CMakeLists.txt

    r3395 r3450  
    391391ADD_SUBDIRECTORY(amdbin)
    392392ADD_SUBDIRECTORY(amdasm)
     393IF(HAVE_OPENCL)
     394    ADD_SUBDIRECTORY(clhelper)
     395ENDIF(HAVE_OPENCL)
    393396IF (BUILD_TESTS)
    394397    ADD_SUBDIRECTORY(tests)
  • CLRadeonExtender/trunk/pkgconfig/CMakeLists.txt

    r3268 r3450  
    2626CONFIGURE_FILE("${PROJECT_SOURCE_DIR}/pkgconfig/clrxutils.pc.in"
    2727        "${PROJECT_BINARY_DIR}/pkgconfig/clrxutils.pc" @ONLY)
     28CONFIGURE_FILE("${PROJECT_SOURCE_DIR}/pkgconfig/clrxclhelper.pc.in"
     29        "${PROJECT_BINARY_DIR}/pkgconfig/clrxclhelper.pc" @ONLY)
    2830
    2931SET(PKGCONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/pkgconfig)
    3032INSTALL(FILES "${PROJECT_BINARY_DIR}/pkgconfig/clrxamdasm.pc"
    3133              "${PROJECT_BINARY_DIR}/pkgconfig/clrxamdbin.pc"
    32               "${PROJECT_BINARY_DIR}/pkgconfig/clrxutils.pc" 
     34              "${PROJECT_BINARY_DIR}/pkgconfig/clrxutils.pc"
     35              "${PROJECT_BINARY_DIR}/pkgconfig/clrxclhelper.pc"
    3336              DESTINATION "${PKGCONFIG_INSTALL_DIR}")
  • CLRadeonExtender/trunk/samples/CLUtils.cpp

    r3437 r3450  
    2929#include <CL/cl.h>
    3030#include <CLRX/amdasm/Assembler.h>
     31#include <CLRX/clhelper/CLHelper.h>
    3132#include "CLUtils.h"
    3233
    3334using namespace CLRX;
    34 
    35 static char* stripCString(char* str)
    36 {
    37     while (*str==' ') str++;
    38     char* last = str+::strlen(str);
    39     while (last!=str && (*last==0||*last==' '))
    40         last--;
    41     if (*last!=0) last[1] = 0;
    42     return str;
    43 }
    4435
    4536/* parse args from command line and handle options:
     
    6051    }
    6152   
    62     cl_uint platformsNum;
    63     std::unique_ptr<cl_platform_id[]> platforms;
    64     cl_int error = 0;
    65     error = clGetPlatformIDs(0, nullptr, &platformsNum);
    66     if (error != CL_SUCCESS)
    67         throw CLError(error, "clGetPlatformIDs");
    68     platforms.reset(new cl_platform_id[platformsNum]);
    69     error = clGetPlatformIDs(platformsNum, platforms.get(), nullptr);
    70     if (error != CL_SUCCESS)
    71         throw CLError(error, "clGetPlatformIDs");
    72    
    73     cl_platform_id choosenPlatform = nullptr;
    74     /// find platform with AMD or GalliumCompute devices
    75     for (cl_uint i = 0; i < platformsNum; i++)
    76     {
    77         size_t platformNameSize;
    78         std::unique_ptr<char[]> platformName;
    79         error = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 0, nullptr,
    80                            &platformNameSize);
    81         if (error != CL_SUCCESS)
    82             throw CLError(error, "clGetPlatformInfo");
    83         platformName.reset(new char[platformNameSize]);
    84         error = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, platformNameSize,
    85                    platformName.get(), nullptr);
    86         if (error != CL_SUCCESS)
    87             throw CLError(error, "clGetPlatformInfo");
    88        
    89         // find correct platform (supported GalliumCompute and AMD APP)
    90         const char* splatformName = stripCString(platformName.get());
    91         if (::strcmp(splatformName, "AMD Accelerated Parallel Processing")==0 ||
    92             ::strcmp(splatformName, "Clover")==0)
    93         {
    94             choosenPlatform = platforms[i];
    95             break;
    96         }
    97     }
    98    
    99     if (choosenPlatform==nullptr)
    100         throw Exception("PlatformNotFound");
     53    cl_int error = CL_SUCCESS;
     54    cl_platform_id choosenPlatform = chooseCLPlatformForCLRX();
    10155   
    10256    if (argc >= 2 && ::strcmp(argv[1], "-L")==0)
     
    159113{
    160114    context = nullptr;
     115    device = nullptr;
    161116    queue = nullptr;
    162117    program = nullptr;
    163118   
    164     cl_uint platformsNum;
    165     std::unique_ptr<cl_platform_id[]> platforms;
    166     cl_int error = 0;
    167     error = clGetPlatformIDs(0, nullptr, &platformsNum);
    168     if (error != CL_SUCCESS)
    169         throw CLError(error, "clGetPlatformIDs");
    170     platforms.reset(new cl_platform_id[platformsNum]);
    171     error = clGetPlatformIDs(platformsNum, platforms.get(), nullptr);
    172     if (error != CL_SUCCESS)
    173         throw CLError(error, "clGetPlatformIDs");
    174    
    175     cxuint amdappVersion = 0;
    176    
    177     BinaryFormat binaryFormat = BinaryFormat::GALLIUM;
    178     cl_platform_id choosenPlatform = nullptr;
    179     bool defaultCL2ForDriver = false;
    180     /// find platform with AMD devices
    181     for (cl_uint i = 0; i < platformsNum; i++)
    182     {
    183         size_t platformNameSize;
    184         std::unique_ptr<char[]> platformName;
    185         error = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 0, nullptr,
    186                            &platformNameSize);
    187         if (error != CL_SUCCESS)
    188             throw CLError(error, "clGetPlatformInfo");
    189         platformName.reset(new char[platformNameSize]);
    190         error = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, platformNameSize,
    191                    platformName.get(), nullptr);
    192         if (error != CL_SUCCESS)
    193             throw CLError(error, "clGetPlatformInfo");
    194        
    195         const char* splatformName = stripCString(platformName.get());
    196         if (::strcmp(splatformName, "AMD Accelerated Parallel Processing")==0 ||
    197             ::strcmp(splatformName, "Clover")==0)
    198         {
    199             choosenPlatform = platforms[i];
    200             binaryFormat = ::strcmp(platformName.get(), "Clover")==0 ?
    201                     BinaryFormat::GALLIUM : BinaryFormat::AMD;
    202            
    203             if (binaryFormat == BinaryFormat::AMD)
    204             {
    205                 // get amdappVersion
    206                 size_t platformVersionSize;
    207                 std::unique_ptr<char[]> platformVersion;
    208                 error = clGetPlatformInfo(choosenPlatform, CL_PLATFORM_VERSION, 0, nullptr,
    209                                         &platformVersionSize);
    210                 if (error != CL_SUCCESS)
    211                     throw CLError(error, "clGetPlatformInfoVersion");
    212                 platformVersion.reset(new char[platformVersionSize]);
    213                 error = clGetPlatformInfo(choosenPlatform, CL_PLATFORM_VERSION,
    214                                 platformVersionSize, platformVersion.get(), nullptr);
    215                 if (error != CL_SUCCESS)
    216                     throw CLError(error, "clGetPlatformInfoVersion");
    217                
    218                 const char* amdappPart = strstr(platformVersion.get(), "AMD-APP (");
    219                 if (amdappPart!=nullptr)
    220                 {
    221                     // parse AMDAPP version
    222                     try
    223                     {
    224                         const char* majorVerPart = amdappPart+9;
    225                         const char* minorVerPart;
    226                         const char* end;
    227                         cxuint majorVersion = cstrtoui(majorVerPart, nullptr,
    228                                         minorVerPart);
    229                        
    230                         if (*minorVerPart!=0)
    231                         {
    232                             minorVerPart++; // skip '.'
    233                             cxuint minorVersion = cstrtoui(minorVerPart, nullptr, end);
    234                             amdappVersion = majorVersion*100U + minorVersion;
    235                         }
    236                     }
    237                     catch(const ParseException& ex)
    238                     { } // ignore error
    239                 }
    240             }
    241            
    242             if (binaryFormat == BinaryFormat::AMD && useCL==2)
    243                 binaryFormat = BinaryFormat::AMDCL2;
    244             // for driver 2004.6 OpenCL 2.0 binary format is default
    245             if (binaryFormat == BinaryFormat::AMD && amdappVersion >= 200406)
    246                 defaultCL2ForDriver = true;
    247             break;
    248         }
    249     }
    250    
    251     if (choosenPlatform==nullptr)
    252         throw Exception("PlatformNotFound");
     119    cl_int error = CL_SUCCESS;
     120    const cl_platform_id choosenPlatform = chooseCLPlatformForCLRX();
    253121   
    254122    // find device
     
    270138    device = devices[deviceIndex];
    271139   
    272     cl_uint bits = 32;
    273     if (binaryFormat != BinaryFormat::GALLIUM)
    274     {
    275         // get address Bits from device info (for AMDAPP)
    276         error = clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(cl_uint),
    277                                  &bits, nullptr);
    278         if (error != CL_SUCCESS)
    279             throw CLError(error, "clGetDeviceAddressBits");
    280     }
     140    const CLAsmSetup asmSetup = assemblerSetupForCLDevice(device, useCL==1 ?
     141            CLHELPER_USEAMDLEGACY : useCL==2 ? CLHELPER_USEAMDCL2 : 0);
    281142   
    282143    // get workGroupSize and Compute Units of device
     
    308169    std::cout << "Device: " << deviceIndex << " - " << deviceName.get() << std::endl;
    309170   
    310     // get device version - used for getting Mesa3D version and LLVM version
    311     size_t deviceVersionSize;
    312     std::unique_ptr<char[]> deviceVersion;
    313     error = clGetDeviceInfo(device, CL_DEVICE_VERSION, 0, nullptr, &deviceVersionSize);
    314     if (error != CL_SUCCESS)
    315         throw CLError(error, "clGetDeviceInfoVersion");
    316     deviceVersion.reset(new char[deviceVersionSize]);
    317     error = clGetDeviceInfo(device, CL_DEVICE_VERSION, deviceVersionSize,
    318                             deviceVersion.get(), nullptr);
    319     if (error != CL_SUCCESS)
    320         throw CLError(error, "clGetDeviceInfoVersion");
    321    
    322     // get bits from device name (LLVM version)
    323     cxuint llvmVersion = 0;
    324     cxuint mesaVersion = 0;
    325    
    326     if (binaryFormat == BinaryFormat::GALLIUM)
    327     {
    328         const char* llvmPart = strstr(deviceName.get(), "LLVM ");
    329         if (llvmPart!=nullptr)
    330         {
    331             try
    332             {
    333                 // parse LLVM version
    334                 const char* majorVerPart = llvmPart+5;
    335                 const char* minorVerPart;
    336                 const char* end;
    337                 cxuint majorVersion = cstrtoui(majorVerPart, nullptr, minorVerPart);
    338                 if (*minorVerPart!=0)
    339                 {
    340                     minorVerPart++; // skip '.'
    341                     cxuint minorVersion = cstrtoui(minorVerPart, nullptr, end);
    342                     llvmVersion = majorVersion*10000U + minorVersion*100U;
    343 #if HAVE_64BIT
    344                     if (majorVersion*10000U + minorVersion*100U >= 30900U)
    345                         bits = 64; // use 64-bit
    346 #endif
    347                 }
    348             }
    349             catch(const ParseException& ex)
    350             { } // ignore error
    351         }
    352        
    353         const char* mesaPart = strstr(deviceVersion.get(), "Mesa ");
    354         if (mesaPart==nullptr)
    355             mesaPart = strstr(deviceVersion.get(), "MESA ");
    356         if (mesaPart!=nullptr)
    357         {
    358             try
    359             {
    360                 // parse Mesa3D version
    361                 const char* majorVerPart = mesaPart+5;
    362                 const char* minorVerPart;
    363                 const char* end;
    364                 cxuint majorVersion = cstrtoui(majorVerPart, nullptr, minorVerPart);
    365                 if (*minorVerPart!=0)
    366                 {
    367                     minorVerPart++; // skip '.'
    368                     cxuint minorVersion = cstrtoui(minorVerPart, nullptr, end);
    369                     mesaVersion = majorVersion*10000U + minorVersion*100U;
    370                 }
    371             }
    372             catch(const ParseException& ex)
    373             { } // ignore error
    374         }
    375     }
    376     /* assemble source code */
    377     /// determine device type
    378     char* sdeviceName = stripCString(deviceName.get());
    379     char* devNamePtr = sdeviceName;
    380     if (binaryFormat==BinaryFormat::GALLIUM)
    381     {
    382         char* sptr = ::strstr(sdeviceName, "(AMD ");
    383         // if form 'AMD Radeon xxx (AMD CODENAME /...)
    384         if (sptr != nullptr) // if found 'AMD ';
    385             devNamePtr = sptr+5;
    386         else
    387         {
    388             // if form 'AMD CODENAME (....
    389             sptr = ::strstr(sdeviceName, "AMD ");
    390             if (sptr != nullptr) // if found 'AMD ';
    391                 devNamePtr = sptr+4;
    392         }
    393     }
    394     char* devNameEnd = devNamePtr;
    395     while (isAlnum(*devNameEnd)) devNameEnd++;
    396     *devNameEnd = 0; // finish at first word
    397     const GPUDeviceType devType = getGPUDeviceTypeFromName(devNamePtr);
    398     /* change binary format to AMDCL2 if default for this driver version and
    399      * architecture >= GCN 1.1 */
    400     bool useLegacy = false;
    401     if (defaultCL2ForDriver &&
    402         getGPUArchitectureFromDeviceType(devType) >= GPUArchitecture::GCN1_1)
    403     {
    404         if (useCL!=1) // if not cl1/old
    405             binaryFormat = BinaryFormat::AMDCL2;
    406         else // use legacy
    407             useLegacy = true;
    408     }
    409 
    410     std::cout << "BinaryFormat: " << binaryFormatNamesTbl[cxuint(binaryFormat)] << "\n"
    411         "Bitness: " << bits << std::endl;
     171    std::cout << "BinaryFormat: " <<
     172        binaryFormatNamesTbl[cxuint(asmSetup.binaryFormat)] << "\n"
     173        "Bitness: " << (asmSetup.is64Bit ? 64U : 32U) << std::endl;
    412174   
    413175    /// create command queue
     
    416178        throw CLError(error, "clCreateCommandQueue");
    417179   
    418     Array<cxbyte> binary;
    419     {
    420         /* assemble source code */
    421         /// determine device type
    422         ArrayIStream astream(::strlen(sourceCode), sourceCode);
    423         // by default assembler put logs to stderr
    424         Assembler assembler("", astream, 0, binaryFormat, devType);
    425         assembler.set64Bit(bits==64);
    426         // setting version (LLVM and driverVersion)
    427         if (binaryFormat == BinaryFormat::GALLIUM && llvmVersion != 0)
    428             assembler.setLLVMVersion(llvmVersion);
    429         if (binaryFormat == BinaryFormat::GALLIUM && mesaVersion != 0)
    430             assembler.setDriverVersion(mesaVersion);
    431         else if ((binaryFormat == BinaryFormat::AMD ||
    432                 binaryFormat == BinaryFormat::AMDCL2) && amdappVersion != 0)
    433             assembler.setDriverVersion(amdappVersion);
    434         assembler.assemble();
    435         assembler.writeBinary(binary);
    436     }
    437    
    438     size_t binarySize = binary.size();
    439     const cxbyte* binaryContent = binary.data();
    440     program = clCreateProgramWithBinary(context, 1, &device, &binarySize,
    441                         &binaryContent, nullptr, &error);
    442     if (program==nullptr)
    443         throw CLError(error, "clCreateProgramWithBinary");
    444     // build program
    445     error = clBuildProgram(program, 1, &device,
    446                (binaryFormat==BinaryFormat::AMDCL2) ? "-cl-std=CL2.0" :
    447                (useLegacy ? "-legacy" : ""),
    448                nullptr, nullptr);
    449     if (error != CL_SUCCESS)
    450     {
    451         /* get build logs */
    452         size_t buildLogSize;
    453         std::unique_ptr<char[]> buildLog;
    454         cl_int lerror = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,
    455                            0, nullptr, &buildLogSize);
    456         if (lerror == CL_SUCCESS)
    457         {
    458             buildLog.reset(new char[buildLogSize]);
    459             lerror = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,
    460                            buildLogSize, buildLog.get(), nullptr);
    461             if (lerror == CL_SUCCESS) // print build log
    462                 std::cerr << "BuildLog:\n" << buildLog.get() << std::endl;
    463         }
    464         throw CLError(error, "clBuildProgram");
     180    CString buildLog;
     181    try
     182    { program = createProgramForCLDevice(context, device,
     183                    asmSetup, sourceCode, 0, &buildLog); }
     184    // function throw exception when fail
     185    catch(const CLError& error)
     186    {
     187        std::cerr << "BuildLog:\n" << buildLog << std::endl;
     188        throw;
    465189    }
    466190   
  • CLRadeonExtender/trunk/samples/CLUtils.h

    r3411 r3450  
    2525#include <vector>
    2626#include <exception>
     27#include <CLRX/clhelper/CLHelper.h>
    2728#include <CL/cl.h>
    28 
    29 /// error class based on std::exception
    30 class CLError: public std::exception
    31 {
    32 private:
    33     cl_int error;
    34     std::string description;
    35 public:
    36     /// empty constructor
    37     CLError() : error(0)
    38     { }
    39     explicit CLError(const char* _description) : error(0), description(_description)
    40     { }
    41     CLError(cl_int _error, const char* _description) : error(_error)
    42     {
    43         char buf[20];
    44         ::snprintf(buf, 20, "%d", _error);
    45         description = "Error code: ";
    46         description += buf;
    47         description += ", Desc: ";
    48         description += _description;
    49     }
    50     virtual ~CLError() noexcept
    51     { }
    52     const char* what() const noexcept
    53     { return (!description.empty()) ? description.c_str() : "No error!"; }
    54     int code() const
    55     { return error; }
    56 };
    5729
    5830class CLFacade
  • CLRadeonExtender/trunk/samples/CMakeLists.txt

    r2682 r3450  
    2222ADD_LIBRARY(SamplesCLUtils STATIC CLUtils.cpp)
    2323
    24 SET(LINK_LIBRARIES SamplesCLUtils OpenCL CLRXAmdAsm${PROGRAM_LIB_SUFFIX}
     24SET(LINK_LIBRARIES SamplesCLUtils OpenCL CLRXCLHelper${PROGRAM_LIB_SUFFIX}
     25        CLRXAmdAsm${PROGRAM_LIB_SUFFIX}
    2526        CLRXAmdBin${PROGRAM_LIB_SUFFIX} CLRXUtils${PROGRAM_LIB_SUFFIX}
    2627        ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS})
Note: See TracChangeset for help on using the changeset viewer.