• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 The ANGLE Project Authors. 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 // ShaderStorageBlockFunctionHLSL: Wrapper functions for RWByteAddressBuffer Load/Store functions.
7 //
8 
9 #include "compiler/translator/ShaderStorageBlockFunctionHLSL.h"
10 
11 #include "common/utilities.h"
12 #include "compiler/translator/UtilsHLSL.h"
13 #include "compiler/translator/blocklayout.h"
14 #include "compiler/translator/blocklayoutHLSL.h"
15 #include "compiler/translator/util.h"
16 
17 namespace sh
18 {
19 
20 // static
OutputSSBOLoadFunctionBody(TInfoSinkBase & out,const ShaderStorageBlockFunction & ssboFunction)21 void ShaderStorageBlockFunctionHLSL::OutputSSBOLoadFunctionBody(
22     TInfoSinkBase &out,
23     const ShaderStorageBlockFunction &ssboFunction)
24 {
25     const char *convertString;
26     switch (ssboFunction.type.getBasicType())
27     {
28         case EbtFloat:
29             convertString = "asfloat(";
30             break;
31         case EbtInt:
32             convertString = "asint(";
33             break;
34         case EbtUInt:
35             convertString = "asuint(";
36             break;
37         case EbtBool:
38             convertString = "asint(";
39             break;
40         default:
41             UNREACHABLE();
42             return;
43     }
44 
45     size_t bytesPerComponent =
46         gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type)));
47     out << "    " << ssboFunction.typeString << " result";
48     if (ssboFunction.type.isScalar())
49     {
50         size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent;
51         out << " = " << convertString << "buffer.Load(loc + " << offset << "));\n ";
52     }
53     else if (ssboFunction.type.isVector())
54     {
55         if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle)
56         {
57             size_t componentStride = bytesPerComponent;
58             if (ssboFunction.rowMajor)
59             {
60                 componentStride = ssboFunction.matrixStride;
61             }
62 
63             out << " = {";
64             for (const int offset : ssboFunction.swizzleOffsets)
65             {
66                 size_t offsetInBytes = offset * componentStride;
67                 out << convertString << "buffer.Load(loc + " << offsetInBytes << ")),";
68             }
69             out << "};\n";
70         }
71         else
72         {
73             out << " = " << convertString << "buffer.Load"
74                 << static_cast<uint32_t>(ssboFunction.type.getNominalSize()) << "(loc));\n";
75         }
76     }
77     else if (ssboFunction.type.isMatrix())
78     {
79         if (ssboFunction.rowMajor)
80         {
81             out << ";";
82             out << "    float" << static_cast<uint32_t>(ssboFunction.type.getRows()) << "x"
83                 << static_cast<uint32_t>(ssboFunction.type.getCols()) << " tmp_ = {";
84             for (uint8_t rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++)
85             {
86                 out << "asfloat(buffer.Load" << static_cast<uint32_t>(ssboFunction.type.getCols())
87                     << "(loc + " << rowIndex * ssboFunction.matrixStride << ")), ";
88             }
89             out << "};\n";
90             out << "    result = transpose(tmp_);\n";
91         }
92         else
93         {
94             out << " = {";
95             for (uint8_t columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++)
96             {
97                 out << "asfloat(buffer.Load" << static_cast<uint32_t>(ssboFunction.type.getRows())
98                     << "(loc + " << columnIndex * ssboFunction.matrixStride << ")), ";
99             }
100             out << "};\n";
101         }
102     }
103     else
104     {
105         // TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951
106         out << ";\n";
107     }
108 
109     out << "    return result;\n";
110     return;
111 }
112 
113 // static
OutputSSBOStoreFunctionBody(TInfoSinkBase & out,const ShaderStorageBlockFunction & ssboFunction)114 void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody(
115     TInfoSinkBase &out,
116     const ShaderStorageBlockFunction &ssboFunction)
117 {
118     size_t bytesPerComponent =
119         gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type)));
120     if (ssboFunction.type.isScalar())
121     {
122         size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent;
123         if (ssboFunction.type.getBasicType() == EbtBool)
124         {
125             out << "    buffer.Store(loc + " << offset << ", uint(value));\n";
126         }
127         else
128         {
129             out << "    buffer.Store(loc + " << offset << ", asuint(value));\n";
130         }
131     }
132     else if (ssboFunction.type.isVector())
133     {
134         out << "    uint" << static_cast<uint32_t>(ssboFunction.type.getNominalSize())
135             << " _value;\n";
136         if (ssboFunction.type.getBasicType() == EbtBool)
137         {
138             out << "    _value = uint" << static_cast<uint32_t>(ssboFunction.type.getNominalSize())
139                 << "(value);\n";
140         }
141         else
142         {
143             out << "    _value = asuint(value);\n";
144         }
145 
146         if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle)
147         {
148             size_t componentStride = bytesPerComponent;
149             if (ssboFunction.rowMajor)
150             {
151                 componentStride = ssboFunction.matrixStride;
152             }
153             const TVector<int> &swizzleOffsets = ssboFunction.swizzleOffsets;
154             for (int index = 0; index < static_cast<int>(swizzleOffsets.size()); index++)
155             {
156                 size_t offsetInBytes = swizzleOffsets[index] * componentStride;
157                 out << "buffer.Store(loc + " << offsetInBytes << ", _value[" << index << "]);\n";
158             }
159         }
160         else
161         {
162             out << "    buffer.Store" << static_cast<uint32_t>(ssboFunction.type.getNominalSize())
163                 << "(loc, _value);\n";
164         }
165     }
166     else if (ssboFunction.type.isMatrix())
167     {
168         if (ssboFunction.rowMajor)
169         {
170             out << "    float" << static_cast<uint32_t>(ssboFunction.type.getRows()) << "x"
171                 << static_cast<uint32_t>(ssboFunction.type.getCols())
172                 << " tmp_ = transpose(value);\n";
173             for (uint8_t rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++)
174             {
175                 out << "    buffer.Store" << static_cast<uint32_t>(ssboFunction.type.getCols())
176                     << "(loc + " << rowIndex * ssboFunction.matrixStride << ", asuint(tmp_["
177                     << static_cast<uint32_t>(rowIndex) << "]));\n";
178             }
179         }
180         else
181         {
182             for (uint8_t columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++)
183             {
184                 out << "    buffer.Store" << static_cast<uint32_t>(ssboFunction.type.getRows())
185                     << "(loc + " << columnIndex * ssboFunction.matrixStride << ", asuint(value["
186                     << static_cast<uint32_t>(columnIndex) << "]));\n";
187             }
188         }
189     }
190     else
191     {
192         // TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951
193     }
194 }
195 
196 // static
OutputSSBOLengthFunctionBody(TInfoSinkBase & out,int unsizedArrayStride)197 void ShaderStorageBlockFunctionHLSL::OutputSSBOLengthFunctionBody(TInfoSinkBase &out,
198                                                                   int unsizedArrayStride)
199 {
200     out << "    uint dim = 0;\n";
201     out << "    buffer.GetDimensions(dim);\n";
202     out << "    return int((dim - loc)/uint(" << unsizedArrayStride << "));\n";
203 }
204 
205 // static
OutputSSBOAtomicMemoryFunctionBody(TInfoSinkBase & out,const ShaderStorageBlockFunction & ssboFunction)206 void ShaderStorageBlockFunctionHLSL::OutputSSBOAtomicMemoryFunctionBody(
207     TInfoSinkBase &out,
208     const ShaderStorageBlockFunction &ssboFunction)
209 {
210     out << "    " << ssboFunction.typeString << " original_value;\n";
211     switch (ssboFunction.method)
212     {
213         case SSBOMethod::ATOMIC_ADD:
214             out << "    buffer.InterlockedAdd(loc, value, original_value);\n";
215             break;
216         case SSBOMethod::ATOMIC_MIN:
217             out << "    buffer.InterlockedMin(loc, value, original_value);\n";
218             break;
219         case SSBOMethod::ATOMIC_MAX:
220             out << "    buffer.InterlockedMax(loc, value, original_value);\n";
221             break;
222         case SSBOMethod::ATOMIC_AND:
223             out << "    buffer.InterlockedAnd(loc, value, original_value);\n";
224             break;
225         case SSBOMethod::ATOMIC_OR:
226             out << "    buffer.InterlockedOr(loc, value, original_value);\n";
227             break;
228         case SSBOMethod::ATOMIC_XOR:
229             out << "    buffer.InterlockedXor(loc, value, original_value);\n";
230             break;
231         case SSBOMethod::ATOMIC_EXCHANGE:
232             out << "    buffer.InterlockedExchange(loc, value, original_value);\n";
233             break;
234         case SSBOMethod::ATOMIC_COMPSWAP:
235             out << "    buffer.InterlockedCompareExchange(loc, compare_value, value, "
236                    "original_value);\n";
237             break;
238         default:
239             UNREACHABLE();
240     }
241     out << "    return original_value;\n";
242 }
243 
operator <(const ShaderStorageBlockFunction & rhs) const244 bool ShaderStorageBlockFunctionHLSL::ShaderStorageBlockFunction::operator<(
245     const ShaderStorageBlockFunction &rhs) const
246 {
247     return functionName < rhs.functionName;
248 }
249 
registerShaderStorageBlockFunction(const TType & type,SSBOMethod method,TLayoutBlockStorage storage,bool rowMajor,int matrixStride,int unsizedArrayStride,TIntermSwizzle * swizzleNode)250 TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction(
251     const TType &type,
252     SSBOMethod method,
253     TLayoutBlockStorage storage,
254     bool rowMajor,
255     int matrixStride,
256     int unsizedArrayStride,
257     TIntermSwizzle *swizzleNode)
258 {
259     ShaderStorageBlockFunction ssboFunction;
260     ssboFunction.typeString = TypeString(type);
261     ssboFunction.method     = method;
262     switch (method)
263     {
264         case SSBOMethod::LOAD:
265             ssboFunction.functionName = "_Load_";
266             break;
267         case SSBOMethod::STORE:
268             ssboFunction.functionName = "_Store_";
269             break;
270         case SSBOMethod::LENGTH:
271             ssboFunction.unsizedArrayStride = unsizedArrayStride;
272             ssboFunction.functionName       = "_Length_" + str(unsizedArrayStride);
273             mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
274             return ssboFunction.functionName;
275         case SSBOMethod::ATOMIC_ADD:
276             ssboFunction.functionName = "_ssbo_atomicAdd_" + ssboFunction.typeString;
277             mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
278             return ssboFunction.functionName;
279         case SSBOMethod::ATOMIC_MIN:
280             ssboFunction.functionName = "_ssbo_atomicMin_" + ssboFunction.typeString;
281             mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
282             return ssboFunction.functionName;
283         case SSBOMethod::ATOMIC_MAX:
284             ssboFunction.functionName = "_ssbo_atomicMax_" + ssboFunction.typeString;
285             mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
286             return ssboFunction.functionName;
287         case SSBOMethod::ATOMIC_AND:
288             ssboFunction.functionName = "_ssbo_atomicAnd_" + ssboFunction.typeString;
289             mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
290             return ssboFunction.functionName;
291         case SSBOMethod::ATOMIC_OR:
292             ssboFunction.functionName = "_ssbo_atomicOr_" + ssboFunction.typeString;
293             mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
294             return ssboFunction.functionName;
295         case SSBOMethod::ATOMIC_XOR:
296             ssboFunction.functionName = "_ssbo_atomicXor_" + ssboFunction.typeString;
297             mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
298             return ssboFunction.functionName;
299         case SSBOMethod::ATOMIC_EXCHANGE:
300             ssboFunction.functionName = "_ssbo_atomicExchange_" + ssboFunction.typeString;
301             mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
302             return ssboFunction.functionName;
303         case SSBOMethod::ATOMIC_COMPSWAP:
304             ssboFunction.functionName = "_ssbo_atomicCompSwap_" + ssboFunction.typeString;
305             mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
306             return ssboFunction.functionName;
307         default:
308             UNREACHABLE();
309     }
310 
311     ssboFunction.functionName += ssboFunction.typeString;
312     ssboFunction.type = type;
313     if (swizzleNode != nullptr)
314     {
315         ssboFunction.swizzleOffsets   = swizzleNode->getSwizzleOffsets();
316         ssboFunction.isDefaultSwizzle = false;
317     }
318     else
319     {
320         if (ssboFunction.type.getNominalSize() > 1)
321         {
322             for (uint8_t index = 0; index < ssboFunction.type.getNominalSize(); index++)
323             {
324                 ssboFunction.swizzleOffsets.push_back(index);
325             }
326         }
327         else
328         {
329             ssboFunction.swizzleOffsets.push_back(0);
330         }
331 
332         ssboFunction.isDefaultSwizzle = true;
333     }
334     ssboFunction.rowMajor     = rowMajor;
335     ssboFunction.matrixStride = matrixStride;
336     ssboFunction.functionName += "_" + TString(getBlockStorageString(storage));
337 
338     if (rowMajor)
339     {
340         ssboFunction.functionName += "_rm_";
341     }
342     else
343     {
344         ssboFunction.functionName += "_cm_";
345     }
346 
347     for (const int offset : ssboFunction.swizzleOffsets)
348     {
349         switch (offset)
350         {
351             case 0:
352                 ssboFunction.functionName += "x";
353                 break;
354             case 1:
355                 ssboFunction.functionName += "y";
356                 break;
357             case 2:
358                 ssboFunction.functionName += "z";
359                 break;
360             case 3:
361                 ssboFunction.functionName += "w";
362                 break;
363             default:
364                 UNREACHABLE();
365         }
366     }
367 
368     mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
369     return ssboFunction.functionName;
370 }
371 
shaderStorageBlockFunctionHeader(TInfoSinkBase & out)372 void ShaderStorageBlockFunctionHLSL::shaderStorageBlockFunctionHeader(TInfoSinkBase &out)
373 {
374     for (const ShaderStorageBlockFunction &ssboFunction : mRegisteredShaderStorageBlockFunctions)
375     {
376         switch (ssboFunction.method)
377         {
378             case SSBOMethod::LOAD:
379             {
380                 // Function header
381                 out << ssboFunction.typeString << " " << ssboFunction.functionName
382                     << "(RWByteAddressBuffer buffer, uint loc)\n";
383                 out << "{\n";
384                 OutputSSBOLoadFunctionBody(out, ssboFunction);
385                 break;
386             }
387             case SSBOMethod::STORE:
388             {
389                 // Function header
390                 out << "void " << ssboFunction.functionName
391                     << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString
392                     << " value)\n";
393                 out << "{\n";
394                 OutputSSBOStoreFunctionBody(out, ssboFunction);
395                 break;
396             }
397             case SSBOMethod::LENGTH:
398             {
399                 out << "int " << ssboFunction.functionName
400                     << "(RWByteAddressBuffer buffer, uint loc)\n";
401                 out << "{\n";
402                 OutputSSBOLengthFunctionBody(out, ssboFunction.unsizedArrayStride);
403                 break;
404             }
405             case SSBOMethod::ATOMIC_ADD:
406             case SSBOMethod::ATOMIC_MIN:
407             case SSBOMethod::ATOMIC_MAX:
408             case SSBOMethod::ATOMIC_AND:
409             case SSBOMethod::ATOMIC_OR:
410             case SSBOMethod::ATOMIC_XOR:
411             case SSBOMethod::ATOMIC_EXCHANGE:
412             {
413                 out << ssboFunction.typeString << " " << ssboFunction.functionName
414                     << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString
415                     << " value)\n";
416                 out << "{\n";
417 
418                 OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction);
419                 break;
420             }
421             case SSBOMethod::ATOMIC_COMPSWAP:
422             {
423                 out << ssboFunction.typeString << " " << ssboFunction.functionName
424                     << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString
425                     << " compare_value, " << ssboFunction.typeString << " value)\n";
426                 out << "{\n";
427                 OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction);
428                 break;
429             }
430             default:
431                 UNREACHABLE();
432         }
433 
434         out << "}\n"
435                "\n";
436     }
437 }
438 
439 }  // namespace sh
440