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 "core/device.hpp" 24 #include "core/platform.hpp" 25 #include "pipe/p_screen.h" 26 #include "pipe/p_state.h" 27 28 using namespace clover; 29 30 namespace { 31 template<typename T> 32 std::vector<T> 33 get_compute_param(pipe_screen *pipe, pipe_shader_ir ir_format, 34 pipe_compute_cap cap) { 35 int sz = pipe->get_compute_param(pipe, ir_format, cap, NULL); 36 std::vector<T> v(sz / sizeof(T)); 37 38 pipe->get_compute_param(pipe, ir_format, cap, &v.front()); 39 return v; 40 } 41 } 42 43 device::device(clover::platform &platform, pipe_loader_device *ldev) : 44 platform(platform), ldev(ldev) { 45 pipe = pipe_loader_create_screen(ldev); 46 if (!pipe || !pipe->get_param(pipe, PIPE_CAP_COMPUTE)) { 47 if (pipe) 48 pipe->destroy(pipe); 49 throw error(CL_INVALID_DEVICE); 50 } 51 } 52 53 device::~device() { 54 if (pipe) 55 pipe->destroy(pipe); 56 if (ldev) 57 pipe_loader_release(&ldev, 1); 58 } 59 60 bool 61 device::operator==(const device &dev) const { 62 return this == &dev; 63 } 64 65 cl_device_type 66 device::type() const { 67 switch (ldev->type) { 68 case PIPE_LOADER_DEVICE_SOFTWARE: 69 return CL_DEVICE_TYPE_CPU; 70 case PIPE_LOADER_DEVICE_PCI: 71 case PIPE_LOADER_DEVICE_PLATFORM: 72 return CL_DEVICE_TYPE_GPU; 73 default: 74 unreachable("Unknown device type."); 75 } 76 } 77 78 cl_uint 79 device::vendor_id() const { 80 switch (ldev->type) { 81 case PIPE_LOADER_DEVICE_SOFTWARE: 82 case PIPE_LOADER_DEVICE_PLATFORM: 83 return 0; 84 case PIPE_LOADER_DEVICE_PCI: 85 return ldev->u.pci.vendor_id; 86 default: 87 unreachable("Unknown device type."); 88 } 89 } 90 91 size_t 92 device::max_images_read() const { 93 return PIPE_MAX_SHADER_IMAGES; 94 } 95 96 size_t 97 device::max_images_write() const { 98 return PIPE_MAX_SHADER_IMAGES; 99 } 100 101 size_t 102 device::max_image_buffer_size() const { 103 return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE); 104 } 105 106 cl_uint 107 device::max_image_levels_2d() const { 108 return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); 109 } 110 111 cl_uint 112 device::max_image_levels_3d() const { 113 return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_3D_LEVELS); 114 } 115 116 size_t 117 device::max_image_array_number() const { 118 return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS); 119 } 120 121 cl_uint 122 device::max_samplers() const { 123 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, 124 PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS); 125 } 126 127 cl_ulong 128 device::max_mem_global() const { 129 return get_compute_param<uint64_t>(pipe, ir_format(), 130 PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE)[0]; 131 } 132 133 cl_ulong 134 device::max_mem_local() const { 135 return get_compute_param<uint64_t>(pipe, ir_format(), 136 PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE)[0]; 137 } 138 139 cl_ulong 140 device::max_mem_input() const { 141 return get_compute_param<uint64_t>(pipe, ir_format(), 142 PIPE_COMPUTE_CAP_MAX_INPUT_SIZE)[0]; 143 } 144 145 cl_ulong 146 device::max_const_buffer_size() const { 147 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, 148 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE); 149 } 150 151 cl_uint 152 device::max_const_buffers() const { 153 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, 154 PIPE_SHADER_CAP_MAX_CONST_BUFFERS); 155 } 156 157 size_t 158 device::max_threads_per_block() const { 159 return get_compute_param<uint64_t>( 160 pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK)[0]; 161 } 162 163 cl_ulong 164 device::max_mem_alloc_size() const { 165 return get_compute_param<uint64_t>(pipe, ir_format(), 166 PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE)[0]; 167 } 168 169 cl_uint 170 device::max_clock_frequency() const { 171 return get_compute_param<uint32_t>(pipe, ir_format(), 172 PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY)[0]; 173 } 174 175 cl_uint 176 device::max_compute_units() const { 177 return get_compute_param<uint32_t>(pipe, ir_format(), 178 PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS)[0]; 179 } 180 181 bool 182 device::image_support() const { 183 return get_compute_param<uint32_t>(pipe, ir_format(), 184 PIPE_COMPUTE_CAP_IMAGES_SUPPORTED)[0]; 185 } 186 187 bool 188 device::has_doubles() const { 189 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, 190 PIPE_SHADER_CAP_DOUBLES); 191 } 192 193 std::vector<size_t> 194 device::max_block_size() const { 195 auto v = get_compute_param<uint64_t>(pipe, ir_format(), 196 PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE); 197 return { v.begin(), v.end() }; 198 } 199 200 cl_uint 201 device::subgroup_size() const { 202 return get_compute_param<uint32_t>(pipe, ir_format(), 203 PIPE_COMPUTE_CAP_SUBGROUP_SIZE)[0]; 204 } 205 206 cl_uint 207 device::address_bits() const { 208 return get_compute_param<uint32_t>(pipe, ir_format(), 209 PIPE_COMPUTE_CAP_ADDRESS_BITS)[0]; 210 } 211 212 std::string 213 device::device_name() const { 214 return pipe->get_name(pipe); 215 } 216 217 std::string 218 device::vendor_name() const { 219 return pipe->get_device_vendor(pipe); 220 } 221 222 enum pipe_shader_ir 223 device::ir_format() const { 224 return (enum pipe_shader_ir) pipe->get_shader_param( 225 pipe, PIPE_SHADER_COMPUTE, PIPE_SHADER_CAP_PREFERRED_IR); 226 } 227 228 std::string 229 device::ir_target() const { 230 std::vector<char> target = get_compute_param<char>( 231 pipe, ir_format(), PIPE_COMPUTE_CAP_IR_TARGET); 232 return { target.data() }; 233 } 234 235 enum pipe_endian 236 device::endianness() const { 237 return (enum pipe_endian)pipe->get_param(pipe, PIPE_CAP_ENDIANNESS); 238 } 239