device.cpp revision 613323b2564babc1ecaac25a6cfd786b8c839315
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
27using namespace clover;
28
29namespace {
30   template<typename T>
31   std::vector<T>
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
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
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
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
59cl_device_type
60_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
72cl_uint
73_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
85size_t
86_cl_device_id::max_images_read() const {
87   return PIPE_MAX_SHADER_RESOURCES;
88}
89
90size_t
91_cl_device_id::max_images_write() const {
92   return PIPE_MAX_SHADER_RESOURCES;
93}
94
95cl_uint
96_cl_device_id::max_image_levels_2d() const {
97   return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
98}
99
100cl_uint
101_cl_device_id::max_image_levels_3d() const {
102   return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_3D_LEVELS);
103}
104
105cl_uint
106_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
111cl_ulong
112_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
117cl_ulong
118_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
123cl_ulong
124_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
129cl_ulong
130_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
135cl_uint
136_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
141size_t
142_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
147std::vector<size_t>
148_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
153std::string
154_cl_device_id::device_name() const {
155   return pipe->get_name(pipe);
156}
157
158std::string
159_cl_device_id::vendor_name() const {
160   return pipe->get_vendor(pipe);
161}
162
163enum pipe_shader_ir
164_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
170std::string
171_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
177device_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