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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 // SOFTWARE.
21 //
22
23 #include "core/device.hpp"
24 #include "pipe/p_screen.h"
25 #include "pipe/p_state.h"
26
27 using namespace clover;
28
29 namespace {
30 template<typename T>
31 std::vector<T>
get_compute_param(pipe_screen * pipe,pipe_compute_cap cap)32 get_compute_param(pipe_screen *pipe, pipe_compute_cap cap) {
33 int sz = pipe->get_compute_param(pipe, cap, NULL);
34 std::vector<T> v(sz / sizeof(T));
35
36 pipe->get_compute_param(pipe, cap, &v.front());
37 return v;
38 }
39 }
40
_cl_device_id(pipe_loader_device * ldev)41 _cl_device_id::_cl_device_id(pipe_loader_device *ldev) : ldev(ldev) {
42 pipe = pipe_loader_create_screen(ldev, PIPE_SEARCH_DIR);
43 if (!pipe || !pipe->get_param(pipe, PIPE_CAP_COMPUTE))
44 throw error(CL_INVALID_DEVICE);
45 }
46
_cl_device_id(_cl_device_id && dev)47 _cl_device_id::_cl_device_id(_cl_device_id &&dev) : pipe(dev.pipe), ldev(dev.ldev) {
48 dev.ldev = NULL;
49 dev.pipe = NULL;
50 }
51
~_cl_device_id()52 _cl_device_id::~_cl_device_id() {
53 if (pipe)
54 pipe->destroy(pipe);
55 if (ldev)
56 pipe_loader_release(&ldev, 1);
57 }
58
59 cl_device_type
type() const60 _cl_device_id::type() const {
61 switch (ldev->type) {
62 case PIPE_LOADER_DEVICE_SOFTWARE:
63 return CL_DEVICE_TYPE_CPU;
64 case PIPE_LOADER_DEVICE_PCI:
65 return CL_DEVICE_TYPE_GPU;
66 default:
67 assert(0);
68 return 0;
69 }
70 }
71
72 cl_uint
vendor_id() const73 _cl_device_id::vendor_id() const {
74 switch (ldev->type) {
75 case PIPE_LOADER_DEVICE_SOFTWARE:
76 return 0;
77 case PIPE_LOADER_DEVICE_PCI:
78 return ldev->u.pci.vendor_id;
79 default:
80 assert(0);
81 return 0;
82 }
83 }
84
85 size_t
max_images_read() const86 _cl_device_id::max_images_read() const {
87 return PIPE_MAX_SHADER_RESOURCES;
88 }
89
90 size_t
max_images_write() const91 _cl_device_id::max_images_write() const {
92 return PIPE_MAX_SHADER_RESOURCES;
93 }
94
95 cl_uint
max_image_levels_2d() const96 _cl_device_id::max_image_levels_2d() const {
97 return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
98 }
99
100 cl_uint
max_image_levels_3d() const101 _cl_device_id::max_image_levels_3d() const {
102 return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_3D_LEVELS);
103 }
104
105 cl_uint
max_samplers() const106 _cl_device_id::max_samplers() const {
107 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE,
108 PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS);
109 }
110
111 cl_ulong
max_mem_global() const112 _cl_device_id::max_mem_global() const {
113 return get_compute_param<uint64_t>(pipe,
114 PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE)[0];
115 }
116
117 cl_ulong
max_mem_local() const118 _cl_device_id::max_mem_local() const {
119 return get_compute_param<uint64_t>(pipe,
120 PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE)[0];
121 }
122
123 cl_ulong
max_mem_input() const124 _cl_device_id::max_mem_input() const {
125 return get_compute_param<uint64_t>(pipe,
126 PIPE_COMPUTE_CAP_MAX_INPUT_SIZE)[0];
127 }
128
129 cl_ulong
max_const_buffer_size() const130 _cl_device_id::max_const_buffer_size() const {
131 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE,
132 PIPE_SHADER_CAP_MAX_CONSTS) * 16;
133 }
134
135 cl_uint
max_const_buffers() const136 _cl_device_id::max_const_buffers() const {
137 return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE,
138 PIPE_SHADER_CAP_MAX_CONST_BUFFERS);
139 }
140
141 size_t
max_threads_per_block() const142 _cl_device_id::max_threads_per_block() const {
143 return get_compute_param<uint64_t>(
144 pipe, PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK)[0];
145 }
146
147 std::vector<size_t>
max_block_size() const148 _cl_device_id::max_block_size() const {
149 auto v = get_compute_param<uint64_t>(pipe, PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE);
150 return { v.begin(), v.end() };
151 }
152
153 std::string
device_name() const154 _cl_device_id::device_name() const {
155 return pipe->get_name(pipe);
156 }
157
158 std::string
vendor_name() const159 _cl_device_id::vendor_name() const {
160 return pipe->get_vendor(pipe);
161 }
162
163 enum pipe_shader_ir
ir_format() const164 _cl_device_id::ir_format() const {
165 return (enum pipe_shader_ir) pipe->get_shader_param(pipe,
166 PIPE_SHADER_COMPUTE,
167 PIPE_SHADER_CAP_PREFERRED_IR);
168 }
169
170 std::string
ir_target() const171 _cl_device_id::ir_target() const {
172 std::vector<char> target = get_compute_param<char>(pipe,
173 PIPE_COMPUTE_CAP_IR_TARGET);
174 return { target.data() };
175 }
176
device_registry()177 device_registry::device_registry() {
178 int n = pipe_loader_probe(NULL, 0);
179 std::vector<pipe_loader_device *> ldevs(n);
180
181 pipe_loader_probe(&ldevs.front(), n);
182
183 for (pipe_loader_device *ldev : ldevs) {
184 try {
185 devs.emplace_back(ldev);
186 } catch (error &) {}
187 }
188 }
189