• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 The ANGLE Project. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // common.h: Common header for other metal source code.
7 
8 #ifndef LIBANGLE_RENDERER_METAL_SHADERS_COMMON_H_
9 #define LIBANGLE_RENDERER_METAL_SHADERS_COMMON_H_
10 
11 // clang-format off
12 #ifndef SKIP_STD_HEADERS
13 @@#    include <simd/simd.h>
14 @@#    include <metal_stdlib>
15 #endif
16 
17 #include "constants.h"
18 
19 #define ANGLE_KERNEL_GUARD(IDX, MAX_COUNT) \
20     if (IDX >= MAX_COUNT)                  \
21     {                                      \
22         return;                            \
23     }
24 
25 using namespace metal;
26 // clang-format on
27 
28 // Common constant defined number of color outputs
29 constant uint32_t kNumColorOutputs [[function_constant(0)]];
30 constant bool kColorOutputAvailable0 = kNumColorOutputs > 0;
31 constant bool kColorOutputAvailable1 = kNumColorOutputs > 1;
32 constant bool kColorOutputAvailable2 = kNumColorOutputs > 2;
33 constant bool kColorOutputAvailable3 = kNumColorOutputs > 3;
34 constant bool kColorOutputAvailable4 = kNumColorOutputs > 4;
35 constant bool kColorOutputAvailable5 = kNumColorOutputs > 5;
36 constant bool kColorOutputAvailable6 = kNumColorOutputs > 6;
37 constant bool kColorOutputAvailable7 = kNumColorOutputs > 7;
38 
39 namespace rx
40 {
41 namespace mtl_shader
42 {
43 
44 // Full screen triangle's vertices
45 constant float2 gCorners[3] = {float2(-1.0f, -1.0f), float2(3.0f, -1.0f), float2(-1.0f, 3.0f)};
46 
47 template <typename T>
48 struct MultipleColorOutputs
49 {
50     vec<T, 4> color0 [[color(0), function_constant(kColorOutputAvailable0)]];
51     vec<T, 4> color1 [[color(1), function_constant(kColorOutputAvailable1)]];
52     vec<T, 4> color2 [[color(2), function_constant(kColorOutputAvailable2)]];
53     vec<T, 4> color3 [[color(3), function_constant(kColorOutputAvailable3)]];
54     vec<T, 4> color4 [[color(4), function_constant(kColorOutputAvailable4)]];
55     vec<T, 4> color5 [[color(5), function_constant(kColorOutputAvailable5)]];
56     vec<T, 4> color6 [[color(6), function_constant(kColorOutputAvailable6)]];
57     vec<T, 4> color7 [[color(7), function_constant(kColorOutputAvailable7)]];
58 };
59 
60 #define ANGLE_ASSIGN_COLOR_OUPUT(STRUCT_VARIABLE, COLOR_INDEX, VALUE) \
61     do                                                                \
62     {                                                                 \
63         if (kColorOutputAvailable##COLOR_INDEX)                       \
64         {                                                             \
65             STRUCT_VARIABLE.color##COLOR_INDEX = VALUE;               \
66         }                                                             \
67     } while (0)
68 
69 template <typename T>
toMultipleColorOutputs(vec<T,4> color)70 static inline MultipleColorOutputs<T> toMultipleColorOutputs(vec<T, 4> color)
71 {
72     MultipleColorOutputs<T> re;
73 
74     ANGLE_ASSIGN_COLOR_OUPUT(re, 0, color);
75     ANGLE_ASSIGN_COLOR_OUPUT(re, 1, color);
76     ANGLE_ASSIGN_COLOR_OUPUT(re, 2, color);
77     ANGLE_ASSIGN_COLOR_OUPUT(re, 3, color);
78     ANGLE_ASSIGN_COLOR_OUPUT(re, 4, color);
79     ANGLE_ASSIGN_COLOR_OUPUT(re, 5, color);
80     ANGLE_ASSIGN_COLOR_OUPUT(re, 6, color);
81     ANGLE_ASSIGN_COLOR_OUPUT(re, 7, color);
82 
83     return re;
84 }
85 
cubeTexcoords(float2 texcoords,int face)86 static inline float3 cubeTexcoords(float2 texcoords, int face)
87 {
88     texcoords = 2.0 * texcoords - 1.0;
89     switch (face)
90     {
91         case 0:
92             return float3(1.0, -texcoords.y, -texcoords.x);
93         case 1:
94             return float3(-1.0, -texcoords.y, texcoords.x);
95         case 2:
96             return float3(texcoords.x, 1.0, texcoords.y);
97         case 3:
98             return float3(texcoords.x, -1.0, -texcoords.y);
99         case 4:
100             return float3(texcoords.x, -texcoords.y, 1.0);
101         case 5:
102             return float3(-texcoords.x, -texcoords.y, -1.0);
103     }
104     return float3(texcoords, 0);
105 }
106 
107 template <typename T>
resolveTextureMS(texture2d_ms<T> srcTexture,uint2 coords)108 static inline vec<T, 4> resolveTextureMS(texture2d_ms<T> srcTexture, uint2 coords)
109 {
110     uint samples = srcTexture.get_num_samples();
111 
112     vec<T, 4> output(0);
113 
114     for (uint sample = 0; sample < samples; ++sample)
115     {
116         output += srcTexture.read(coords, sample);
117     }
118 
119     output = output / samples;
120 
121     return output;
122 }
123 
sRGBtoLinear(float4 color)124 static inline float4 sRGBtoLinear(float4 color)
125 {
126     float3 linear1 = color.rgb / 12.92;
127     float3 linear2 = pow((color.rgb + float3(0.055)) / 1.055, 2.4);
128     float3 factor  = float3(color.rgb <= float3(0.04045));
129     float4 linear  = float4(factor * linear1 + float3(1.0 - factor) * linear2, color.a);
130 
131     return linear;
132 }
133 
linearToSRGB(float color)134 static inline float linearToSRGB(float color)
135 {
136     if (color <= 0.0f)
137         return 0.0f;
138     else if (color < 0.0031308f)
139         return 12.92f * color;
140     else if (color < 1.0f)
141         return 1.055f * pow(color, 0.41666f) - 0.055f;
142     else
143         return 1.0f;
144 }
145 
linearToSRGB(float4 color)146 static inline float4 linearToSRGB(float4 color)
147 {
148     return float4(linearToSRGB(color.r), linearToSRGB(color.g), linearToSRGB(color.b), color.a);
149 }
150 
151 template <typename Short>
bytesToShort(constant uchar * input,uint offset)152 static inline Short bytesToShort(constant uchar *input, uint offset)
153 {
154     Short inputLo = input[offset];
155     Short inputHi = input[offset + 1];
156     // Little endian conversion:
157     return inputLo | (inputHi << 8);
158 }
159 
160 template <typename Int>
bytesToInt(constant uchar * input,uint offset)161 static inline Int bytesToInt(constant uchar *input, uint offset)
162 {
163     Int input0 = input[offset];
164     Int input1 = input[offset + 1];
165     Int input2 = input[offset + 2];
166     Int input3 = input[offset + 3];
167     // Little endian conversion:
168     return input0 | (input1 << 8) | (input2 << 16) | (input3 << 24);
169 }
170 
171 template <typename Short>
shortToBytes(Short val,uint offset,device uchar * output)172 static inline void shortToBytes(Short val, uint offset, device uchar *output)
173 {
174     ushort valUnsigned = as_type<ushort>(val);
175     output[offset]     = valUnsigned & 0xff;
176     output[offset + 1] = (valUnsigned >> 8) & 0xff;
177 }
178 
179 template <typename Int>
intToBytes(Int val,uint offset,device uchar * output)180 static inline void intToBytes(Int val, uint offset, device uchar *output)
181 {
182     uint valUnsigned   = as_type<uint>(val);
183     output[offset]     = valUnsigned & 0xff;
184     output[offset + 1] = (valUnsigned >> 8) & 0xff;
185     output[offset + 2] = (valUnsigned >> 16) & 0xff;
186     output[offset + 3] = (valUnsigned >> 24) & 0xff;
187 }
188 
floatToBytes(float val,uint offset,device uchar * output)189 static inline void floatToBytes(float val, uint offset, device uchar *output)
190 {
191     intToBytes(as_type<uint>(val), offset, output);
192 }
193 
int24bitToBytes(uint val,uint offset,device uchar * output)194 static inline void int24bitToBytes(uint val, uint offset, device uchar *output)
195 {
196     output[offset]     = val & 0xff;
197     output[offset + 1] = (val >> 8) & 0xff;
198     output[offset + 2] = (val >> 16) & 0xff;
199 }
200 
201 template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
getShiftedData(T input)202 static inline T getShiftedData(T input)
203 {
204     static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
205                   "T must have at least as many bits as inputBitCount + inputBitStart.");
206     const T mask = (1 << inputBitCount) - 1;
207     return (input >> inputBitStart) & mask;
208 }
209 
210 template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
shiftData(T input)211 static inline T shiftData(T input)
212 {
213     static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
214                   "T must have at least as many bits as inputBitCount + inputBitStart.");
215     const T mask = (1 << inputBitCount) - 1;
216     return (input & mask) << inputBitStart;
217 }
218 
219 template <unsigned int inputBitCount, typename T>
normalizedToFloat(T input)220 static inline float normalizedToFloat(T input)
221 {
222     static_assert(inputBitCount <= (sizeof(T) * 8),
223                   "T must have more bits than or same bits as inputBitCount.");
224     static_assert(inputBitCount <= 23, "Only single precision is supported");
225 
226     constexpr float inverseMax = 1.0f / ((1 << inputBitCount) - 1);
227     return input * inverseMax;
228 }
229 
230 template <typename T>
normalizedToFloat(T input)231 static inline float normalizedToFloat(T input)
232 {
233     return normalizedToFloat<sizeof(T) * 8, T>(input);
234 }
235 
236 template <>
normalizedToFloat(short input)237 inline float normalizedToFloat(short input)
238 {
239     constexpr float inverseMax = 1.0f / 0x7fff;
240     return static_cast<float>(input) * inverseMax;
241 }
242 
243 template <>
normalizedToFloat(int input)244 inline float normalizedToFloat(int input)
245 {
246     constexpr float inverseMax = 1.0f / 0x7fffffff;
247     return static_cast<float>(input) * inverseMax;
248 }
249 
250 template <>
normalizedToFloat(uint input)251 inline float normalizedToFloat(uint input)
252 {
253     constexpr float inverseMax = 1.0f / 0xffffffff;
254     return static_cast<float>(input) * inverseMax;
255 }
256 
257 template <unsigned int outputBitCount, typename T>
floatToNormalized(float input)258 static inline T floatToNormalized(float input)
259 {
260     static_assert(outputBitCount <= (sizeof(T) * 8),
261                   "T must have more bits than or same bits as inputBitCount.");
262     static_assert(outputBitCount <= 23, "Only single precision is supported");
263 
264     return static_cast<T>(((1 << outputBitCount) - 1) * input + 0.5f);
265 }
266 
267 template <typename T>
floatToNormalized(float input)268 static inline T floatToNormalized(float input)
269 {
270     return floatToNormalized<sizeof(T) * 8, T>(input);
271 }
272 
273 }  // namespace mtl_shader
274 }  // namespace rx
275 
276 #endif /* LIBANGLE_RENDERER_METAL_SHADERS_COMMON_H_ */
277