diff --git a/Modules/OpenCL/mitkOclResourceService.h b/Modules/OpenCL/mitkOclResourceService.h index 1f79449be2..be547466f3 100644 --- a/Modules/OpenCL/mitkOclResourceService.h +++ b/Modules/OpenCL/mitkOclResourceService.h @@ -1,83 +1,83 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkOclResourceService_h #define __mitkOclResourceService_h #include #include /** * @brief Declaration of the OpenCL Resources micro-service * * The OclResourceService defines an service interface for providing access to the * essential OpenCL-related variables. In addition the service can also store compiled * OpenCL Programs in order to avoid multiple compiling of a single program source */ class OclResourceService { public: /** @brief Returns a valid OpenCL Context (if applicable) or NULL if none present */ - virtual cl_context GetContext() const = 0; + virtual cl_context GetContext() = 0; /** @brief Returns a valid cl_command_queue related to the (one) OpenCL context */ virtual cl_command_queue GetCommandQueue() const = 0; /** @brief Returns the identifier of an OpenCL device related to the current context */ virtual cl_device_id GetCurrentDevice() const = 0; /** @brief Checks if an OpenCL image format passed in is supported on current device */ virtual bool GetIsFormatSupported( cl_image_format* format ) = 0; /** @brief Puts the OpenCL Context info in std::cout */ virtual void PrintContextInfo() = 0; /** @brief Insert program into the internal program storage * * @param program A cl_program object. * @param string Text identifier of the inserted program. Used for getting the program. * @param todo: what is the flag? */ virtual void InsertProgram(cl_program program, std::string string, bool flag) = 0; /** @brief Get the cl_program by name * @param name Text identifier of the program. * @throws an mitk::Exception in case the program cannot be found */ virtual cl_program GetProgram(const std::string& name) const = 0; /** @brief Remove all invalid (=do not compile) programs from the internal storage */ virtual void InvalidateStorage() = 0; /** @brief Remove given program from storage * @param name Text identifier of the program. */ virtual void RemoveProgram(const std::string& name) = 0; /** @brief Get the maximum size of an image * * @param dimension (unsigned int) identifier of the image diemsion in {0,1,2} * @param image object type, either CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE3D */ virtual unsigned int GetMaximumImageSize( unsigned int , cl_mem_object_type) = 0; virtual ~OclResourceService() = 0; }; US_DECLARE_SERVICE_INTERFACE(OclResourceService, "OpenCLResourceService/1.0") #endif // __mitkOclResourceService_h diff --git a/Modules/OpenCL/mitkOclResourceServiceImpl_Private.cpp b/Modules/OpenCL/mitkOclResourceServiceImpl_Private.cpp index 9d0e999741..18c26e7f52 100644 --- a/Modules/OpenCL/mitkOclResourceServiceImpl_Private.cpp +++ b/Modules/OpenCL/mitkOclResourceServiceImpl_Private.cpp @@ -1,254 +1,277 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkOclResourceServiceImpl_p.h" OclResourceService::~OclResourceService() { } OclResourceServiceImpl::OclResourceServiceImpl() : m_Context(NULL), m_Devices(NULL), m_ProgramStorage() { - this->CreateContext(); } OclResourceServiceImpl::~OclResourceServiceImpl() { // if map non-empty, release all remaining if( m_ProgramStorage.size() ) { ProgramMapType::iterator it = m_ProgramStorage.begin(); while(it != m_ProgramStorage.end() ) { clReleaseProgram( it->second ); m_ProgramStorage.erase( it++ ); } } // if devices were allocated, delete if(m_Devices) { // TODO: Available first in OpenCL 1.2 : query the device for CL_PLATFORM_VERSION // through clGetPlatformInfo // clReleaseDevice(m_Devices[0]); delete [] m_Devices; } // if context was created release it - if(m_Context) + if( m_Context ) clReleaseContext( this->m_Context ); } -cl_context OclResourceServiceImpl::GetContext() const +cl_context OclResourceServiceImpl::GetContext() { + if( !this->CreateContext() ) + { + MITK_ERROR("OclResourceService.GetContext") << "No context was created. Returning NULL."; + } + return m_Context; } cl_command_queue OclResourceServiceImpl::GetCommandQueue() const { // check if queue valid - cl_int clErr = clGetCommandQueueInfo( m_CommandQueue, CL_QUEUE_CONTEXT, NULL, NULL, NULL ); - if( clErr != CL_SUCCESS ) + cl_context clQueueContext; + + cl_int clErr = clGetCommandQueueInfo( m_CommandQueue, CL_QUEUE_CONTEXT, sizeof(clQueueContext), &clQueueContext, NULL ); + if( clErr != CL_SUCCESS || clQueueContext != this->m_Context ) { MITK_WARN << "Have no valid command queue. Query returned : " << GetOclErrorAsString( clErr ); return NULL; } return this->m_CommandQueue; } cl_device_id OclResourceServiceImpl::GetCurrentDevice() const { return m_Devices[0]; } bool OclResourceServiceImpl::GetIsFormatSupported(cl_image_format *fmt) { cl_image_format temp; temp.image_channel_data_type = fmt->image_channel_data_type; temp.image_channel_order = fmt->image_channel_order; return (this->m_ImageFormats->GetNearestSupported(&temp, fmt)); } void OclResourceServiceImpl::PrintContextInfo() { - if( m_Context == NULL){ - MITK_ERROR("OpenCL.ResourceService") << "No OpenCL Context available "; - } - else + // context and devices available + if( this->CreateContext() && m_Devices ) { oclPrintDeviceInfo( m_Devices[0] ); } } void OclResourceServiceImpl::InsertProgram(cl_program _program_in, std::string name, bool forceOverride) { std::pair< ProgramMapType::iterator, bool> retValue; typedef std::pair< std::string, cl_program > MapElemPair; retValue = m_ProgramStorage.insert( MapElemPair(name, _program_in) ); // insertion failed, i.e. a program with same name exists if( !retValue.second ) { std::string overrideMsg(""); if( forceOverride ) { // overwrite old instance m_ProgramStorage[name] = _program_in; overrideMsg +=" The old program was overwritten!"; } MITK_WARN("OpenCL.ResourceService") << "The program " << name << " already exists." << overrideMsg; } } cl_program OclResourceServiceImpl::GetProgram(const std::string &name) const { ProgramMapType::const_iterator it; it = m_ProgramStorage.find(name); if( it != m_ProgramStorage.end() ) { return it->second; } mitkThrow() << "Requested OpenCL Program (" << name <<") not found."; } void OclResourceServiceImpl::InvalidateStorage() { - // do nothing if no context present - if(m_Context == NULL) + // do nothing if no context present, there is also no storage + if( !this->CreateContext() ) return; // query the map ProgramMapType::iterator it = m_ProgramStorage.begin(); while(it != m_ProgramStorage.end() ) { // query the program build status cl_build_status status; unsigned int query = clGetProgramBuildInfo( it->second, m_Devices[0], CL_PROGRAM_BUILD_STATUS, sizeof(cl_int), &status, NULL ); + CHECK_OCL_ERR( query ) MITK_DEBUG << "Quering status for " << it->first << std::endl; // remove program if no succesfull build // we need to pay attention to the increment of the iterator when erasing current element if( status != CL_BUILD_SUCCESS ) { MITK_DEBUG << " +-- Build failed " << std::endl; m_ProgramStorage.erase( it++ ); } else { ++it; } } } void OclResourceServiceImpl::RemoveProgram(const std::string& name) { ProgramMapType::iterator it = m_ProgramStorage.find(name); if( it != m_ProgramStorage.end() ) { m_ProgramStorage.erase(it); } else { MITK_WARN("OpenCL.ResourceService") << "Program name [" <CreateContext() ) return 0; unsigned int retValue = 0; switch(dimension) { case 0: if ( _imagetype == CL_MEM_OBJECT_IMAGE2D) clGetDeviceInfo( m_Devices[0], CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( cl_uint ), &retValue, NULL ); else clGetDeviceInfo( m_Devices[0], CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof( cl_uint ), &retValue, NULL ); break; case 1: if ( _imagetype == CL_MEM_OBJECT_IMAGE2D) clGetDeviceInfo( m_Devices[0], CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( cl_uint ), &retValue, NULL ); else clGetDeviceInfo( m_Devices[0], CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof( cl_uint ), &retValue, NULL ); break; case 2: if ( _imagetype == CL_MEM_OBJECT_IMAGE3D) clGetDeviceInfo( m_Devices[0], CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof( cl_uint ), &retValue, NULL); break; default: MITK_WARN << "Could not recieve info. Desired dimension or object type does not exist. "; break; } return retValue; } -void OclResourceServiceImpl::CreateContext() +bool OclResourceServiceImpl::CreateContext() { cl_int clErr = 0; size_t szParmDataBytes; cl_platform_id cpPlatform; cl_device_id m_cdDevice; - try{ - clErr = oclGetPlatformID( &cpPlatform); - CHECK_OCL_ERR( clErr ); + static bool CreateContextFailed = false; + + if( m_Context != NULL ) + return true; + + if( CreateContextFailed ) + { + MITK_ERROR("OpenCL.ResourceService") << "No OpenCL Context available "; + return false; + } + else if( m_Context == NULL ) + { + + try{ + clErr = oclGetPlatformID( &cpPlatform); + CHECK_OCL_ERR( clErr ); - clErr = clGetDeviceIDs( cpPlatform, CL_DEVICE_TYPE_GPU, 1, &m_cdDevice, NULL); - CHECK_OCL_ERR( clErr ); + clErr = clGetDeviceIDs( cpPlatform, CL_DEVICE_TYPE_GPU, 1, &m_cdDevice, NULL); + CHECK_OCL_ERR( clErr ); - this->m_Context = clCreateContext( 0, 1, &m_cdDevice, NULL, NULL, &clErr); - CHECK_OCL_ERR( clErr ); + this->m_Context = clCreateContext( 0, 1, &m_cdDevice, NULL, NULL, &clErr); + CreateContextFailed = (clErr != CL_SUCCESS); - // get the info size - clErr = clGetContextInfo(m_Context, CL_CONTEXT_DEVICES, 0,NULL, &szParmDataBytes ); - this->m_Devices = (cl_device_id*) malloc(szParmDataBytes); + // get the info size + clErr = clGetContextInfo(m_Context, CL_CONTEXT_DEVICES, 0,NULL, &szParmDataBytes ); + this->m_Devices = (cl_device_id*) malloc(szParmDataBytes); - // get device info - clErr = clGetContextInfo(m_Context, CL_CONTEXT_DEVICES, szParmDataBytes, m_Devices, NULL); - CHECK_OCL_ERR( clErr ); + // get device info + clErr = clGetContextInfo(m_Context, CL_CONTEXT_DEVICES, szParmDataBytes, m_Devices, NULL); + CHECK_OCL_ERR( clErr ); - // create command queue - m_CommandQueue = clCreateCommandQueue(m_Context, m_Devices[0], 0, &clErr); - CHECK_OCL_ERR( clErr ); + // create command queue + m_CommandQueue = clCreateCommandQueue(m_Context, m_Devices[0], 0, &clErr); + CHECK_OCL_ERR( clErr ); - this->PrintContextInfo( ); + this->PrintContextInfo( ); + + // collect available image formats for current context + this->m_ImageFormats = mitk::OclImageFormats::New(); + this->m_ImageFormats->SetGPUContext(m_Context); + } + catch( std::exception& e) + { + MITK_ERROR("OpenCL.ResourceService") << "Exception while creating context: \n" << e.what(); + } - // collect available image formats for current context - this->m_ImageFormats = mitk::OclImageFormats::New(); - this->m_ImageFormats->SetGPUContext(m_Context); - } - catch( std::exception& e) - { - MITK_ERROR("OpenCL.ResourceService") << "Exception while creating context: \n" << e.what(); } + + return true; + } diff --git a/Modules/OpenCL/mitkOclResourceServiceImpl_p.h b/Modules/OpenCL/mitkOclResourceServiceImpl_p.h index bd1ef9ed77..b476bf28c4 100644 --- a/Modules/OpenCL/mitkOclResourceServiceImpl_p.h +++ b/Modules/OpenCL/mitkOclResourceServiceImpl_p.h @@ -1,85 +1,85 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkOclResourceServiceImpl_h #define __mitkOclResourceServiceImpl_h #include //Micro Services #include #include #include #include //ocl #include "mitkOclResourceService.h" #include "mitkOclUtils.h" #include "mitkOclImageFormats.h" //todo add docu! class OclResourceServiceImpl : public US_BASECLASS_NAME, public OclResourceService { public: typedef std::map< std::string, cl_program > ProgramMapType; OclResourceServiceImpl(); ~OclResourceServiceImpl(); - cl_context GetContext() const; + cl_context GetContext(); cl_command_queue GetCommandQueue() const; cl_device_id GetCurrentDevice() const; bool GetIsFormatSupported(cl_image_format *); void PrintContextInfo(); void InsertProgram(cl_program _program_in, std::string name, bool forceOverride=true); cl_program GetProgram(const std::string&name) const; void InvalidateStorage(); void RemoveProgram(const std::string&name); unsigned int GetMaximumImageSize(unsigned int dimension, cl_mem_object_type _imagetype); private: - void CreateContext(); + bool CreateContext(); /** The context */ cl_context m_Context; /** Available OpenCL devices */ cl_device_id* m_Devices; /** Class for handling (un)supported GPU image formats **/ mitk::OclImageFormats::Pointer m_ImageFormats; /** The command queue*/ cl_command_queue m_CommandQueue; /** Map containing all available (allready compiled) OpenCL Programs */ ProgramMapType m_ProgramStorage; }; #endif // __mitkOclResourceServiceImpl_h