1 // 2 // Copyright 2012 Francisco Jerez 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 // OTHER DEALINGS IN THE SOFTWARE. 21 // 22 23 #include <unistd.h> 24 #include "core/device.hpp" 25 #include "core/platform.hpp" 26 #include "pipe/p_screen.h" 27 #include "pipe/p_state.h" 28 29 using namespace clover; 30 31 namespace { 32 template<typename T> 33 std::vector<T> 34 get_compute_param(pipe_screen *pipe, pipe_shader_ir ir_format, 35 pipe_compute_cap cap) { 36 int sz = pipe->get_compute_param(pipe, ir_format, cap, NULL); 37 std::vector<T> v(sz / sizeof(T)); 38 39 pipe->get_compute_param(pipe, ir_format, cap, &v.front()); 40 return v; 41 } 42 } 43 44 device::device(clover::platform &platform, pipe_loader_device *ldev) : 45 platform(platform), ldev(ldev) { 46 pipe = pipe_loader_create_screen(ldev); 47 if (!pipe || !pipe->get_param(pipe, PIPE_CAP_COMPUTE)) { 48 if (pipe) 49 pipe->destroy(pipe); 50 throw error(CL_INVALID_DEVICE); 51 } 52 } 53 54 device::~device() { 55 if (pipe) 56 pipe->destroy(pipe); 57 if (ldev) 58 pipe_loader_release(&ldev, 1); 59 } 60 61 bool 62 device::operator==(const device &dev) const { 63 return this == &dev; 64 } 65 66 cl_device_type 67 device::type() const { 68 switch (ldev->type) { 69 case PIPE_LOADER_DEVICE_SOFTWARE: 70 return CL_DEVICE_TYPE_CPU; 71 case PIPE_LOADER_DEVICE_PCI: 72 case PIPE_LOADER_DEVICE_PLATFORM: 73 return CL_DEVICE_TYPE_GPU; 74 default: 75 unreachable("Unknown device type."); 76 } 77 } 78 79 cl_uint 80 device::vendor_id() const { 81 switch (ldev->type) { 82 case PIPE_LOADER_DEVICE_SOFTWARE: 83 case PIPE_LOADER_DEVICE_PLATFORM: 84 return 0; 85 case PIPE_LOADER_DEVICE_PCI: 86 return ldev->u.pci.vendor_id; 87 default: 88 unreachable("Unknown device type."); 89 } 90 } 91 92 size_t 93 device::max_images_read() const { 94 return PIPE_MAX_SHADER_IMAGES; 95 } 96 97 size_t 98 device::max_images_write() const { 99 return PIPE_MAX_SHADER_IMAGES; 100 } 101 102 size_t 103 device::max_image_buffer_size() const { 104 return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE); 105 } 106 107 cl_uint 108 device::max_image_levels_2d() const { 109 return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); 110 } 111 112 cl_uint 113 device::max_image_levels_3d() const { 114 return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_3D_LEVELS); 115 } 116 117 size_t 118 device::max_image_array_number() const { 119 return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS); 120 } 121 122 cl_uint 123 device::max_samplers() const { 124 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, 125 PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS); 126 } 127 128 cl_ulong 129 device::max_mem_global() const { 130 return get_compute_param<uint64_t>(pipe, ir_format(), 131 PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE)[0]; 132 } 133 134 cl_ulong 135 device::max_mem_local() const { 136 return get_compute_param<uint64_t>(pipe, ir_format(), 137 PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE)[0]; 138 } 139 140 cl_ulong 141 device::max_mem_input() const { 142 return get_compute_param<uint64_t>(pipe, ir_format(), 143 PIPE_COMPUTE_CAP_MAX_INPUT_SIZE)[0]; 144 } 145 146 cl_ulong 147 device::max_const_buffer_size() const { 148 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, 149 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE); 150 } 151 152 cl_uint 153 device::max_const_buffers() const { 154 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, 155 PIPE_SHADER_CAP_MAX_CONST_BUFFERS); 156 } 157 158 size_t 159 device::max_threads_per_block() const { 160 return get_compute_param<uint64_t>( 161 pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK)[0]; 162 } 163 164 cl_ulong 165 device::max_mem_alloc_size() const { 166 return get_compute_param<uint64_t>(pipe, ir_format(), 167 PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE)[0]; 168 } 169 170 cl_uint 171 device::max_clock_frequency() const { 172 return get_compute_param<uint32_t>(pipe, ir_format(), 173 PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY)[0]; 174 } 175 176 cl_uint 177 device::max_compute_units() const { 178 return get_compute_param<uint32_t>(pipe, ir_format(), 179 PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS)[0]; 180 } 181 182 bool 183 device::image_support() const { 184 return get_compute_param<uint32_t>(pipe, ir_format(), 185 PIPE_COMPUTE_CAP_IMAGES_SUPPORTED)[0]; 186 } 187 188 bool 189 device::has_doubles() const { 190 return pipe->get_param(pipe, PIPE_CAP_DOUBLES); 191 } 192 193 bool 194 device::has_halves() const { 195 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, 196 PIPE_SHADER_CAP_FP16); 197 } 198 199 bool 200 device::has_int64_atomics() const { 201 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, 202 PIPE_SHADER_CAP_INT64_ATOMICS); 203 } 204 205 bool 206 device::has_unified_memory() const { 207 return pipe->get_param(pipe, PIPE_CAP_UMA); 208 } 209 210 cl_uint 211 device::mem_base_addr_align() const { 212 return sysconf(_SC_PAGESIZE); 213 } 214 215 std::vector<size_t> 216 device::max_block_size() const { 217 auto v = get_compute_param<uint64_t>(pipe, ir_format(), 218 PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE); 219 return { v.begin(), v.end() }; 220 } 221 222 cl_uint 223 device::subgroup_size() const { 224 return get_compute_param<uint32_t>(pipe, ir_format(), 225 PIPE_COMPUTE_CAP_SUBGROUP_SIZE)[0]; 226 } 227 228 cl_uint 229 device::address_bits() const { 230 return get_compute_param<uint32_t>(pipe, ir_format(), 231 PIPE_COMPUTE_CAP_ADDRESS_BITS)[0]; 232 } 233 234 std::string 235 device::device_name() const { 236 return pipe->get_name(pipe); 237 } 238 239 std::string 240 device::vendor_name() const { 241 return pipe->get_device_vendor(pipe); 242 } 243 244 enum pipe_shader_ir 245 device::ir_format() const { 246 return (enum pipe_shader_ir) pipe->get_shader_param( 247 pipe, PIPE_SHADER_COMPUTE, PIPE_SHADER_CAP_PREFERRED_IR); 248 } 249 250 std::string 251 device::ir_target() const { 252 std::vector<char> target = get_compute_param<char>( 253 pipe, ir_format(), PIPE_COMPUTE_CAP_IR_TARGET); 254 return { target.data() }; 255 } 256 257 enum pipe_endian 258 device::endianness() const { 259 return (enum pipe_endian)pipe->get_param(pipe, PIPE_CAP_ENDIANNESS); 260 } 261 262 std::string 263 device::device_version() const { 264 return "1.1"; 265 } 266 267 std::string 268 device::device_clc_version() const { 269 return "1.1"; 270 } 271