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 <algorithm>
24
25#include "core/format.hpp"
26#include "core/memory.hpp"
27#include "pipe/p_screen.h"
28#include "pipe/p_context.h"
29
30namespace clover {
31   static const std::map<cl_image_format, pipe_format> formats {
32      { { CL_BGRA, CL_UNORM_INT8 }, PIPE_FORMAT_B8G8R8A8_UNORM },
33      { { CL_ARGB, CL_UNORM_INT8 }, PIPE_FORMAT_A8R8G8B8_UNORM },
34      { { CL_RGB, CL_UNORM_SHORT_565 }, PIPE_FORMAT_B5G6R5_UNORM },
35      { { CL_LUMINANCE, CL_UNORM_INT8 }, PIPE_FORMAT_L8_UNORM },
36      { { CL_A, CL_UNORM_INT8 }, PIPE_FORMAT_A8_UNORM },
37      { { CL_INTENSITY, CL_UNORM_INT8 }, PIPE_FORMAT_I8_UNORM },
38      { { CL_LUMINANCE, CL_UNORM_INT16 }, PIPE_FORMAT_L16_UNORM },
39      { { CL_R, CL_FLOAT }, PIPE_FORMAT_R32_FLOAT },
40      { { CL_RG, CL_FLOAT }, PIPE_FORMAT_R32G32_FLOAT },
41      { { CL_RGB, CL_FLOAT }, PIPE_FORMAT_R32G32B32_FLOAT },
42      { { CL_RGBA, CL_FLOAT }, PIPE_FORMAT_R32G32B32A32_FLOAT },
43      { { CL_R, CL_UNORM_INT16 }, PIPE_FORMAT_R16_UNORM },
44      { { CL_RG, CL_UNORM_INT16 }, PIPE_FORMAT_R16G16_UNORM },
45      { { CL_RGB, CL_UNORM_INT16 }, PIPE_FORMAT_R16G16B16_UNORM },
46      { { CL_RGBA, CL_UNORM_INT16 }, PIPE_FORMAT_R16G16B16A16_UNORM },
47      { { CL_R, CL_SNORM_INT16 }, PIPE_FORMAT_R16_SNORM },
48      { { CL_RG, CL_SNORM_INT16 }, PIPE_FORMAT_R16G16_SNORM },
49      { { CL_RGB, CL_SNORM_INT16 }, PIPE_FORMAT_R16G16B16_SNORM },
50      { { CL_RGBA, CL_SNORM_INT16 }, PIPE_FORMAT_R16G16B16A16_SNORM },
51      { { CL_R, CL_UNORM_INT8 }, PIPE_FORMAT_R8_UNORM },
52      { { CL_RG, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8_UNORM },
53      { { CL_RGB, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8B8_UNORM },
54      { { CL_RGBA, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8B8A8_UNORM },
55      { { CL_R, CL_SNORM_INT8 }, PIPE_FORMAT_R8_SNORM },
56      { { CL_RG, CL_SNORM_INT8 }, PIPE_FORMAT_R8G8_SNORM },
57      { { CL_RGB, CL_SNORM_INT8 }, PIPE_FORMAT_R8G8B8_SNORM },
58      { { CL_RGBA, CL_SNORM_INT8 }, PIPE_FORMAT_R8G8B8A8_SNORM },
59      { { CL_R, CL_HALF_FLOAT }, PIPE_FORMAT_R16_FLOAT },
60      { { CL_RG, CL_HALF_FLOAT }, PIPE_FORMAT_R16G16_FLOAT },
61      { { CL_RGB, CL_HALF_FLOAT }, PIPE_FORMAT_R16G16B16_FLOAT },
62      { { CL_RGBA, CL_HALF_FLOAT }, PIPE_FORMAT_R16G16B16A16_FLOAT },
63      { { CL_RGBx, CL_UNORM_SHORT_555 }, PIPE_FORMAT_B5G5R5X1_UNORM },
64      { { CL_RGBx, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8B8X8_UNORM },
65      { { CL_A, CL_UNORM_INT16 }, PIPE_FORMAT_A16_UNORM },
66      { { CL_INTENSITY, CL_UNORM_INT16 }, PIPE_FORMAT_I16_UNORM },
67      { { CL_LUMINANCE, CL_SNORM_INT8 }, PIPE_FORMAT_L8_SNORM },
68      { { CL_INTENSITY, CL_SNORM_INT8 }, PIPE_FORMAT_I8_SNORM },
69      { { CL_A, CL_SNORM_INT16 }, PIPE_FORMAT_A16_SNORM },
70      { { CL_LUMINANCE, CL_SNORM_INT16 }, PIPE_FORMAT_L16_SNORM },
71      { { CL_INTENSITY, CL_SNORM_INT16 }, PIPE_FORMAT_I16_SNORM },
72      { { CL_A, CL_HALF_FLOAT }, PIPE_FORMAT_A16_FLOAT },
73      { { CL_LUMINANCE, CL_HALF_FLOAT }, PIPE_FORMAT_L16_FLOAT },
74      { { CL_INTENSITY, CL_HALF_FLOAT }, PIPE_FORMAT_I16_FLOAT },
75      { { CL_A, CL_FLOAT }, PIPE_FORMAT_A32_FLOAT },
76      { { CL_LUMINANCE, CL_FLOAT }, PIPE_FORMAT_L32_FLOAT },
77      { { CL_INTENSITY, CL_FLOAT }, PIPE_FORMAT_I32_FLOAT },
78      { { CL_RA, CL_UNORM_INT8 }, PIPE_FORMAT_R8A8_UNORM },
79      { { CL_R, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8_UINT },
80      { { CL_RG, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8G8_UINT },
81      { { CL_RGB, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8G8B8_UINT },
82      { { CL_RGBA, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8G8B8A8_UINT },
83      { { CL_R, CL_SIGNED_INT8 }, PIPE_FORMAT_R8_SINT },
84      { { CL_RG, CL_SIGNED_INT8 }, PIPE_FORMAT_R8G8_SINT },
85      { { CL_RGB, CL_SIGNED_INT8 }, PIPE_FORMAT_R8G8B8_SINT },
86      { { CL_RGBA, CL_SIGNED_INT8 }, PIPE_FORMAT_R8G8B8A8_SINT },
87      { { CL_R, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16_UINT },
88      { { CL_RG, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16G16_UINT },
89      { { CL_RGB, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16G16B16_UINT },
90      { { CL_RGBA, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16G16B16A16_UINT },
91      { { CL_R, CL_SIGNED_INT16 }, PIPE_FORMAT_R16_SINT },
92      { { CL_RG, CL_SIGNED_INT16 }, PIPE_FORMAT_R16G16_SINT },
93      { { CL_RGB, CL_SIGNED_INT16 }, PIPE_FORMAT_R16G16B16_SINT },
94      { { CL_RGBA, CL_SIGNED_INT16 }, PIPE_FORMAT_R16G16B16A16_SINT },
95      { { CL_R, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32_UINT },
96      { { CL_RG, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32G32_UINT },
97      { { CL_RGB, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32G32B32_UINT },
98      { { CL_RGBA, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32G32B32A32_UINT },
99      { { CL_R, CL_SIGNED_INT32 }, PIPE_FORMAT_R32_SINT },
100      { { CL_RG, CL_SIGNED_INT32 }, PIPE_FORMAT_R32G32_SINT },
101      { { CL_RGB, CL_SIGNED_INT32 }, PIPE_FORMAT_R32G32B32_SINT },
102      { { CL_RGBA, CL_SIGNED_INT32 }, PIPE_FORMAT_R32G32B32A32_SINT },
103      { { CL_A, CL_UNSIGNED_INT8 }, PIPE_FORMAT_A8_UINT },
104      { { CL_INTENSITY, CL_UNSIGNED_INT8 }, PIPE_FORMAT_I8_UINT },
105      { { CL_LUMINANCE, CL_UNSIGNED_INT8 }, PIPE_FORMAT_L8_UINT },
106      { { CL_A, CL_SIGNED_INT8 }, PIPE_FORMAT_A8_SINT },
107      { { CL_INTENSITY, CL_SIGNED_INT8 }, PIPE_FORMAT_I8_SINT },
108      { { CL_LUMINANCE, CL_SIGNED_INT8 }, PIPE_FORMAT_L8_SINT },
109      { { CL_A, CL_UNSIGNED_INT16 }, PIPE_FORMAT_A16_UINT },
110      { { CL_INTENSITY, CL_UNSIGNED_INT16 }, PIPE_FORMAT_I16_UINT },
111      { { CL_LUMINANCE, CL_UNSIGNED_INT16 }, PIPE_FORMAT_L16_UINT },
112      { { CL_A, CL_SIGNED_INT16 }, PIPE_FORMAT_A16_SINT },
113      { { CL_INTENSITY, CL_SIGNED_INT16 }, PIPE_FORMAT_I16_SINT },
114      { { CL_LUMINANCE, CL_SIGNED_INT16 }, PIPE_FORMAT_L16_SINT },
115      { { CL_A, CL_UNSIGNED_INT32 }, PIPE_FORMAT_A32_UINT },
116      { { CL_INTENSITY, CL_UNSIGNED_INT32 }, PIPE_FORMAT_I32_UINT },
117      { { CL_LUMINANCE, CL_UNSIGNED_INT32 }, PIPE_FORMAT_L32_UINT },
118      { { CL_A, CL_SIGNED_INT32 }, PIPE_FORMAT_A32_SINT },
119      { { CL_INTENSITY, CL_SIGNED_INT32 }, PIPE_FORMAT_I32_SINT },
120      { { CL_LUMINANCE, CL_SIGNED_INT32 }, PIPE_FORMAT_L32_SINT }
121   };
122
123   pipe_texture_target
124   translate_target(cl_mem_object_type type) {
125      switch (type) {
126      case CL_MEM_OBJECT_BUFFER:
127         return PIPE_BUFFER;
128      case CL_MEM_OBJECT_IMAGE2D:
129         return PIPE_TEXTURE_2D;
130      case CL_MEM_OBJECT_IMAGE3D:
131         return PIPE_TEXTURE_3D;
132      default:
133         throw error(CL_INVALID_VALUE);
134      }
135   }
136
137   pipe_format
138   translate_format(const cl_image_format &format) {
139      auto it = formats.find(format);
140
141      if (it == formats.end())
142         throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
143
144      return it->second;
145   }
146
147   std::set<cl_image_format>
148   supported_formats(cl_context ctx, cl_mem_object_type type) {
149      std::set<cl_image_format> s;
150      pipe_texture_target target = translate_target(type);
151      unsigned bindings = (PIPE_BIND_SAMPLER_VIEW |
152                           PIPE_BIND_COMPUTE_RESOURCE |
153                           PIPE_BIND_TRANSFER_READ |
154                           PIPE_BIND_TRANSFER_WRITE);
155
156      for (auto f : formats) {
157         if (std::all_of(ctx->devs.begin(), ctx->devs.end(),
158                         [=](const device *dev) {
159                            return dev->pipe->is_format_supported(
160                               dev->pipe, f.second, target, 1, bindings);
161                         }))
162            s.insert(f.first);
163      }
164
165      return s;
166   }
167}
168