Line data Source code
1 : //
2 : // Copyright (c) 2016 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 : // TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL
7 : // output. Some of the implementations are straightforward and just call the HLSL equivalent of the
8 : // ESSL texture function, others do more work to emulate ESSL texture sampling or size query
9 : // behavior.
10 : //
11 :
12 : #include "compiler/translator/TextureFunctionHLSL.h"
13 :
14 : #include "compiler/translator/UtilsHLSL.h"
15 :
16 : namespace sh
17 : {
18 :
19 : namespace
20 : {
21 :
22 0 : void OutputIntTexCoordWrap(TInfoSinkBase &out,
23 : const char *wrapMode,
24 : const char *size,
25 : const TString &texCoord,
26 : const TString &texCoordOffset,
27 : const char *texCoordOutName)
28 : {
29 : // GLES 3.0.4 table 3.22 specifies how the wrap modes work. We don't use the formulas verbatim
30 : // but rather use equivalent formulas that map better to HLSL.
31 0 : out << "int " << texCoordOutName << ";\n";
32 0 : out << "float " << texCoordOutName << "Offset = " << texCoord << " + float(" << texCoordOffset
33 0 : << ") / " << size << ";\n";
34 :
35 : // CLAMP_TO_EDGE
36 0 : out << "if (" << wrapMode << " == 1)\n";
37 0 : out << "{\n";
38 0 : out << " " << texCoordOutName << " = clamp(int(floor(" << size << " * " << texCoordOutName
39 0 : << "Offset)), 0, int(" << size << ") - 1);\n";
40 0 : out << "}\n";
41 :
42 : // MIRRORED_REPEAT
43 0 : out << "else if (" << wrapMode << " == 3)\n";
44 0 : out << "{\n";
45 0 : out << " float coordWrapped = 1.0 - abs(frac(abs(" << texCoordOutName
46 0 : << "Offset) * 0.5) * 2.0 - 1.0);\n";
47 0 : out << " " << texCoordOutName << " = int(floor(" << size << " * coordWrapped));\n";
48 0 : out << "}\n";
49 :
50 : // REPEAT
51 0 : out << "else\n";
52 0 : out << "{\n";
53 0 : out << " " << texCoordOutName << " = int(floor(" << size << " * frac(" << texCoordOutName
54 0 : << "Offset)));\n";
55 0 : out << "}\n";
56 0 : }
57 :
58 0 : void OutputIntTexCoordWraps(TInfoSinkBase &out,
59 : const TextureFunctionHLSL::TextureFunction &textureFunction,
60 : TString *texCoordX,
61 : TString *texCoordY,
62 : TString *texCoordZ)
63 : {
64 : // Convert from normalized floating-point to integer
65 0 : out << "int wrapS = samplerMetadata[samplerIndex].wrapModes & 0x3;\n";
66 0 : if (textureFunction.offset)
67 : {
68 0 : OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "offset.x", "tix");
69 : }
70 : else
71 : {
72 0 : OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "0", "tix");
73 : }
74 0 : *texCoordX = "tix";
75 0 : out << "int wrapT = (samplerMetadata[samplerIndex].wrapModes >> 2) & 0x3;\n";
76 0 : if (textureFunction.offset)
77 : {
78 0 : OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "offset.y", "tiy");
79 : }
80 : else
81 : {
82 0 : OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "0", "tiy");
83 : }
84 0 : *texCoordY = "tiy";
85 :
86 0 : if (IsSamplerArray(textureFunction.sampler))
87 : {
88 0 : *texCoordZ = "int(max(0, min(layers - 1, floor(0.5 + t.z))))";
89 : }
90 0 : else if (!IsSamplerCube(textureFunction.sampler) && !IsSampler2D(textureFunction.sampler))
91 : {
92 0 : out << "int wrapR = (samplerMetadata[samplerIndex].wrapModes >> 4) & 0x3;\n";
93 0 : if (textureFunction.offset)
94 : {
95 0 : OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "offset.z", "tiz");
96 : }
97 : else
98 : {
99 0 : OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "0", "tiz");
100 : }
101 0 : *texCoordZ = "tiz";
102 : }
103 0 : }
104 :
105 0 : void OutputHLSL4SampleFunctionPrefix(TInfoSinkBase &out,
106 : const TextureFunctionHLSL::TextureFunction &textureFunction,
107 : const TString &textureReference,
108 : const TString &samplerReference)
109 : {
110 0 : out << textureReference;
111 0 : if (IsIntegerSampler(textureFunction.sampler) ||
112 0 : textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
113 : {
114 0 : out << ".Load(";
115 0 : return;
116 : }
117 :
118 0 : if (IsShadowSampler(textureFunction.sampler))
119 : {
120 0 : switch (textureFunction.method)
121 : {
122 : case TextureFunctionHLSL::TextureFunction::IMPLICIT:
123 : case TextureFunctionHLSL::TextureFunction::BIAS:
124 : case TextureFunctionHLSL::TextureFunction::LOD:
125 0 : out << ".SampleCmp(";
126 0 : break;
127 : case TextureFunctionHLSL::TextureFunction::LOD0:
128 : case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
129 : case TextureFunctionHLSL::TextureFunction::GRAD:
130 0 : out << ".SampleCmpLevelZero(";
131 0 : break;
132 : default:
133 0 : UNREACHABLE();
134 : }
135 : }
136 : else
137 : {
138 0 : switch (textureFunction.method)
139 : {
140 : case TextureFunctionHLSL::TextureFunction::IMPLICIT:
141 0 : out << ".Sample(";
142 0 : break;
143 : case TextureFunctionHLSL::TextureFunction::BIAS:
144 0 : out << ".SampleBias(";
145 0 : break;
146 : case TextureFunctionHLSL::TextureFunction::LOD:
147 : case TextureFunctionHLSL::TextureFunction::LOD0:
148 : case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
149 0 : out << ".SampleLevel(";
150 0 : break;
151 : case TextureFunctionHLSL::TextureFunction::GRAD:
152 0 : out << ".SampleGrad(";
153 0 : break;
154 : default:
155 0 : UNREACHABLE();
156 : }
157 : }
158 0 : out << samplerReference << ", ";
159 : }
160 :
161 0 : const char *GetSamplerCoordinateTypeString(
162 : const TextureFunctionHLSL::TextureFunction &textureFunction,
163 : int hlslCoords)
164 : {
165 0 : if (IsIntegerSampler(textureFunction.sampler) ||
166 0 : textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
167 : {
168 0 : switch (hlslCoords)
169 : {
170 : case 2:
171 0 : return "int3";
172 : case 3:
173 0 : return "int4";
174 : default:
175 0 : UNREACHABLE();
176 : }
177 : }
178 : else
179 : {
180 0 : switch (hlslCoords)
181 : {
182 : case 2:
183 0 : return "float2";
184 : case 3:
185 0 : return "float3";
186 : case 4:
187 0 : return "float4";
188 : default:
189 0 : UNREACHABLE();
190 : }
191 : }
192 : return "";
193 : }
194 :
195 0 : int GetHLSLCoordCount(const TextureFunctionHLSL::TextureFunction &textureFunction,
196 : ShShaderOutput outputType)
197 : {
198 0 : if (outputType == SH_HLSL_3_0_OUTPUT)
199 : {
200 0 : int hlslCoords = 2;
201 0 : switch (textureFunction.sampler)
202 : {
203 : case EbtSampler2D:
204 : case EbtSamplerExternalOES:
205 0 : hlslCoords = 2;
206 0 : break;
207 : case EbtSamplerCube:
208 0 : hlslCoords = 3;
209 0 : break;
210 : default:
211 0 : UNREACHABLE();
212 : }
213 :
214 0 : switch (textureFunction.method)
215 : {
216 : case TextureFunctionHLSL::TextureFunction::IMPLICIT:
217 0 : return hlslCoords;
218 : case TextureFunctionHLSL::TextureFunction::BIAS:
219 : case TextureFunctionHLSL::TextureFunction::LOD:
220 : case TextureFunctionHLSL::TextureFunction::LOD0:
221 : case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
222 0 : return 4;
223 : default:
224 0 : UNREACHABLE();
225 : }
226 : }
227 : else
228 : {
229 0 : switch (textureFunction.sampler)
230 : {
231 : case EbtSampler2D:
232 0 : return 2;
233 : case EbtSampler3D:
234 0 : return 3;
235 : case EbtSamplerCube:
236 0 : return 3;
237 : case EbtSampler2DArray:
238 0 : return 3;
239 : case EbtSamplerExternalOES:
240 0 : return 2;
241 : case EbtISampler2D:
242 0 : return 2;
243 : case EbtISampler3D:
244 0 : return 3;
245 : case EbtISamplerCube:
246 0 : return 3;
247 : case EbtISampler2DArray:
248 0 : return 3;
249 : case EbtUSampler2D:
250 0 : return 2;
251 : case EbtUSampler3D:
252 0 : return 3;
253 : case EbtUSamplerCube:
254 0 : return 3;
255 : case EbtUSampler2DArray:
256 0 : return 3;
257 : case EbtSampler2DShadow:
258 0 : return 2;
259 : case EbtSamplerCubeShadow:
260 0 : return 3;
261 : case EbtSampler2DArrayShadow:
262 0 : return 3;
263 : default:
264 0 : UNREACHABLE();
265 : }
266 : }
267 : return 0;
268 : }
269 :
270 0 : void OutputTextureFunctionArgumentList(TInfoSinkBase &out,
271 : const TextureFunctionHLSL::TextureFunction &textureFunction,
272 : const ShShaderOutput outputType)
273 : {
274 0 : if (outputType == SH_HLSL_3_0_OUTPUT)
275 : {
276 0 : switch (textureFunction.sampler)
277 : {
278 : case EbtSampler2D:
279 : case EbtSamplerExternalOES:
280 0 : out << "sampler2D s";
281 0 : break;
282 : case EbtSamplerCube:
283 0 : out << "samplerCUBE s";
284 0 : break;
285 : default:
286 0 : UNREACHABLE();
287 : }
288 : }
289 : else
290 : {
291 0 : if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
292 : {
293 0 : out << TextureString(textureFunction.sampler) << " x, "
294 0 : << SamplerString(textureFunction.sampler) << " s";
295 : }
296 : else
297 : {
298 0 : ASSERT(outputType == SH_HLSL_4_1_OUTPUT);
299 0 : out << "const uint samplerIndex";
300 : }
301 : }
302 :
303 0 : if (textureFunction.method ==
304 : TextureFunctionHLSL::TextureFunction::FETCH) // Integer coordinates
305 : {
306 0 : switch (textureFunction.coords)
307 : {
308 : case 2:
309 0 : out << ", int2 t";
310 0 : break;
311 : case 3:
312 0 : out << ", int3 t";
313 0 : break;
314 : default:
315 0 : UNREACHABLE();
316 : }
317 : }
318 : else // Floating-point coordinates (except textureSize)
319 : {
320 0 : switch (textureFunction.coords)
321 : {
322 : case 1:
323 0 : out << ", int lod";
324 0 : break; // textureSize()
325 : case 2:
326 0 : out << ", float2 t";
327 0 : break;
328 : case 3:
329 0 : out << ", float3 t";
330 0 : break;
331 : case 4:
332 0 : out << ", float4 t";
333 0 : break;
334 : default:
335 0 : UNREACHABLE();
336 : }
337 : }
338 :
339 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
340 : {
341 0 : switch (textureFunction.sampler)
342 : {
343 : case EbtSampler2D:
344 : case EbtISampler2D:
345 : case EbtUSampler2D:
346 : case EbtSampler2DArray:
347 : case EbtISampler2DArray:
348 : case EbtUSampler2DArray:
349 : case EbtSampler2DShadow:
350 : case EbtSampler2DArrayShadow:
351 : case EbtSamplerExternalOES:
352 0 : out << ", float2 ddx, float2 ddy";
353 0 : break;
354 : case EbtSampler3D:
355 : case EbtISampler3D:
356 : case EbtUSampler3D:
357 : case EbtSamplerCube:
358 : case EbtISamplerCube:
359 : case EbtUSamplerCube:
360 : case EbtSamplerCubeShadow:
361 0 : out << ", float3 ddx, float3 ddy";
362 0 : break;
363 : default:
364 0 : UNREACHABLE();
365 : }
366 : }
367 :
368 0 : switch (textureFunction.method)
369 : {
370 : case TextureFunctionHLSL::TextureFunction::IMPLICIT:
371 0 : break;
372 : case TextureFunctionHLSL::TextureFunction::BIAS:
373 0 : break; // Comes after the offset parameter
374 : case TextureFunctionHLSL::TextureFunction::LOD:
375 0 : out << ", float lod";
376 0 : break;
377 : case TextureFunctionHLSL::TextureFunction::LOD0:
378 0 : break;
379 : case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
380 0 : break; // Comes after the offset parameter
381 : case TextureFunctionHLSL::TextureFunction::SIZE:
382 0 : break;
383 : case TextureFunctionHLSL::TextureFunction::FETCH:
384 0 : out << ", int mip";
385 0 : break;
386 : case TextureFunctionHLSL::TextureFunction::GRAD:
387 0 : break;
388 : default:
389 0 : UNREACHABLE();
390 : }
391 :
392 0 : if (textureFunction.offset)
393 : {
394 0 : switch (textureFunction.sampler)
395 : {
396 : case EbtSampler3D:
397 : case EbtISampler3D:
398 : case EbtUSampler3D:
399 0 : out << ", int3 offset";
400 0 : break;
401 : case EbtSampler2D:
402 : case EbtSampler2DArray:
403 : case EbtISampler2D:
404 : case EbtISampler2DArray:
405 : case EbtUSampler2D:
406 : case EbtUSampler2DArray:
407 : case EbtSampler2DShadow:
408 : case EbtSampler2DArrayShadow:
409 : case EbtSamplerExternalOES:
410 0 : out << ", int2 offset";
411 0 : break;
412 : default:
413 0 : UNREACHABLE();
414 : }
415 : }
416 :
417 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS ||
418 0 : textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
419 : {
420 0 : out << ", float bias";
421 : }
422 0 : }
423 :
424 0 : void GetTextureReference(TInfoSinkBase &out,
425 : const TextureFunctionHLSL::TextureFunction &textureFunction,
426 : const ShShaderOutput outputType,
427 : TString *textureReference,
428 : TString *samplerReference)
429 : {
430 0 : if (outputType == SH_HLSL_4_1_OUTPUT)
431 : {
432 0 : TString suffix = TextureGroupSuffix(textureFunction.sampler);
433 0 : if (TextureGroup(textureFunction.sampler) == HLSL_TEXTURE_2D)
434 : {
435 0 : *textureReference = TString("textures") + suffix + "[samplerIndex]";
436 0 : *samplerReference = TString("samplers") + suffix + "[samplerIndex]";
437 : }
438 : else
439 : {
440 0 : out << " const uint textureIndex = samplerIndex - textureIndexOffset" << suffix
441 0 : << ";\n";
442 0 : *textureReference = TString("textures") + suffix + "[textureIndex]";
443 0 : out << " const uint samplerArrayIndex = samplerIndex - samplerIndexOffset" << suffix
444 0 : << ";\n";
445 0 : *samplerReference = TString("samplers") + suffix + "[samplerArrayIndex]";
446 : }
447 : }
448 : else
449 : {
450 0 : *textureReference = "x";
451 0 : *samplerReference = "s";
452 : }
453 0 : }
454 :
455 0 : void OutputTextureSizeFunctionBody(TInfoSinkBase &out,
456 : const TextureFunctionHLSL::TextureFunction &textureFunction,
457 : const TString &textureReference,
458 : bool getDimensionsIgnoresBaseLevel)
459 : {
460 0 : if (getDimensionsIgnoresBaseLevel)
461 : {
462 0 : out << "int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n";
463 : }
464 : else
465 : {
466 0 : out << "int baseLevel = 0;\n";
467 : }
468 :
469 0 : if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) ||
470 0 : (IsIntegerSampler(textureFunction.sampler) && IsSamplerCube(textureFunction.sampler)))
471 : {
472 : // "depth" stores either the number of layers in an array texture or 3D depth
473 0 : out << " uint width; uint height; uint depth; uint numberOfLevels;\n"
474 0 : << " " << textureReference
475 0 : << ".GetDimensions(baseLevel, width, height, depth, numberOfLevels);\n"
476 0 : << " width = max(width >> lod, 1);\n"
477 0 : << " height = max(height >> lod, 1);\n";
478 :
479 0 : if (!IsSamplerArray(textureFunction.sampler))
480 : {
481 0 : out << " depth = max(depth >> lod, 1);\n";
482 : }
483 : }
484 0 : else if (IsSampler2D(textureFunction.sampler) || IsSamplerCube(textureFunction.sampler))
485 : {
486 0 : out << " uint width; uint height; uint numberOfLevels;\n"
487 0 : << " " << textureReference
488 0 : << ".GetDimensions(baseLevel, width, height, numberOfLevels);\n"
489 0 : << " width = max(width >> lod, 1);\n"
490 0 : << " height = max(height >> lod, 1);\n";
491 : }
492 : else
493 0 : UNREACHABLE();
494 :
495 0 : if (strcmp(textureFunction.getReturnType(), "int3") == 0)
496 : {
497 0 : out << " return int3(width, height, depth);";
498 : }
499 : else
500 : {
501 0 : out << " return int2(width, height);";
502 : }
503 0 : }
504 :
505 0 : void ProjectTextureCoordinates(const TextureFunctionHLSL::TextureFunction &textureFunction,
506 : TString *texCoordX,
507 : TString *texCoordY,
508 : TString *texCoordZ)
509 : {
510 0 : if (textureFunction.proj)
511 : {
512 0 : TString proj("");
513 0 : switch (textureFunction.coords)
514 : {
515 : case 3:
516 0 : proj = " / t.z";
517 0 : break;
518 : case 4:
519 0 : proj = " / t.w";
520 0 : break;
521 : default:
522 0 : UNREACHABLE();
523 : }
524 0 : *texCoordX = "(" + *texCoordX + proj + ")";
525 0 : *texCoordY = "(" + *texCoordY + proj + ")";
526 0 : *texCoordZ = "(" + *texCoordZ + proj + ")";
527 : }
528 0 : }
529 :
530 0 : void OutputIntegerTextureSampleFunctionComputations(
531 : TInfoSinkBase &out,
532 : const TextureFunctionHLSL::TextureFunction &textureFunction,
533 : const ShShaderOutput outputType,
534 : const TString &textureReference,
535 : TString *texCoordX,
536 : TString *texCoordY,
537 : TString *texCoordZ)
538 : {
539 0 : if (!IsIntegerSampler(textureFunction.sampler))
540 : {
541 0 : return;
542 : }
543 0 : if (IsSamplerCube(textureFunction.sampler))
544 : {
545 0 : out << " float width; float height; float layers; float levels;\n";
546 :
547 0 : out << " uint mip = 0;\n";
548 :
549 0 : out << " " << textureReference
550 0 : << ".GetDimensions(mip, width, height, layers, levels);\n";
551 :
552 0 : out << " bool xMajor = abs(t.x) > abs(t.y) && abs(t.x) > abs(t.z);\n";
553 0 : out << " bool yMajor = abs(t.y) > abs(t.z) && abs(t.y) > abs(t.x);\n";
554 0 : out << " bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n";
555 : out << " bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || "
556 0 : "(zMajor && t.z < 0.0f);\n";
557 :
558 : // FACE_POSITIVE_X = 000b
559 : // FACE_NEGATIVE_X = 001b
560 : // FACE_POSITIVE_Y = 010b
561 : // FACE_NEGATIVE_Y = 011b
562 : // FACE_POSITIVE_Z = 100b
563 : // FACE_NEGATIVE_Z = 101b
564 0 : out << " int face = (int)negative + (int)yMajor * 2 + (int)zMajor * 4;\n";
565 :
566 0 : out << " float u = xMajor ? -t.z : (yMajor && t.y < 0.0f ? -t.x : t.x);\n";
567 0 : out << " float v = yMajor ? t.z : (negative ? t.y : -t.y);\n";
568 0 : out << " float m = xMajor ? t.x : (yMajor ? t.y : t.z);\n";
569 :
570 0 : out << " t.x = (u * 0.5f / m) + 0.5f;\n";
571 0 : out << " t.y = (v * 0.5f / m) + 0.5f;\n";
572 :
573 : // Mip level computation.
574 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
575 0 : textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD ||
576 0 : textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
577 : {
578 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT)
579 : {
580 : out << " float2 tSized = float2(t.x * width, t.y * height);\n"
581 : " float2 dx = ddx(tSized);\n"
582 : " float2 dy = ddy(tSized);\n"
583 0 : " float lod = 0.5f * log2(max(dot(dx, dx), dot(dy, dy)));\n";
584 : }
585 0 : else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
586 : {
587 : // ESSL 3.00.6 spec section 8.8: "For the cube version, the partial
588 : // derivatives of P are assumed to be in the coordinate system used before
589 : // texture coordinates are projected onto the appropriate cube face."
590 : // ddx[0] and ddy[0] are the derivatives of t.x passed into the function
591 : // ddx[1] and ddy[1] are the derivatives of t.y passed into the function
592 : // ddx[2] and ddy[2] are the derivatives of t.z passed into the function
593 : // Determine the derivatives of u, v and m
594 : out << " float dudx = xMajor ? ddx[2] : (yMajor && t.y < 0.0f ? -ddx[0] "
595 : ": ddx[0]);\n"
596 : " float dudy = xMajor ? ddy[2] : (yMajor && t.y < 0.0f ? -ddy[0] "
597 : ": ddy[0]);\n"
598 : " float dvdx = yMajor ? ddx[2] : (negative ? ddx[1] : -ddx[1]);\n"
599 : " float dvdy = yMajor ? ddy[2] : (negative ? ddy[1] : -ddy[1]);\n"
600 : " float dmdx = xMajor ? ddx[0] : (yMajor ? ddx[1] : ddx[2]);\n"
601 0 : " float dmdy = xMajor ? ddy[0] : (yMajor ? ddy[1] : ddy[2]);\n";
602 : // Now determine the derivatives of the face coordinates, using the
603 : // derivatives calculated above.
604 : // d / dx (u(x) * 0.5 / m(x) + 0.5)
605 : // = 0.5 * (m(x) * u'(x) - u(x) * m'(x)) / m(x)^2
606 : out << " float dfacexdx = 0.5f * (m * dudx - u * dmdx) / (m * m);\n"
607 : " float dfaceydx = 0.5f * (m * dvdx - v * dmdx) / (m * m);\n"
608 : " float dfacexdy = 0.5f * (m * dudy - u * dmdy) / (m * m);\n"
609 : " float dfaceydy = 0.5f * (m * dvdy - v * dmdy) / (m * m);\n"
610 : " float2 sizeVec = float2(width, height);\n"
611 : " float2 faceddx = float2(dfacexdx, dfaceydx) * sizeVec;\n"
612 0 : " float2 faceddy = float2(dfacexdy, dfaceydy) * sizeVec;\n";
613 : // Optimization: instead of: log2(max(length(faceddx), length(faceddy)))
614 : // we compute: log2(max(length(faceddx)^2, length(faceddy)^2)) / 2
615 : out << " float lengthfaceddx2 = dot(faceddx, faceddx);\n"
616 : " float lengthfaceddy2 = dot(faceddy, faceddy);\n"
617 0 : " float lod = log2(max(lengthfaceddx2, lengthfaceddy2)) * 0.5f;\n";
618 : }
619 0 : out << " mip = uint(min(max(round(lod), 0), levels - 1));\n"
620 0 : << " " << textureReference
621 0 : << ".GetDimensions(mip, width, height, layers, levels);\n";
622 : }
623 :
624 : // Convert from normalized floating-point to integer
625 0 : *texCoordX = "int(floor(width * frac(" + *texCoordX + ")))";
626 0 : *texCoordY = "int(floor(height * frac(" + *texCoordY + ")))";
627 0 : *texCoordZ = "face";
628 : }
629 0 : else if (textureFunction.method != TextureFunctionHLSL::TextureFunction::FETCH)
630 : {
631 0 : if (IsSampler2D(textureFunction.sampler))
632 : {
633 0 : if (IsSamplerArray(textureFunction.sampler))
634 : {
635 0 : out << " float width; float height; float layers; float levels;\n";
636 :
637 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
638 : {
639 0 : out << " uint mip = 0;\n";
640 : }
641 0 : else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
642 : {
643 0 : out << " uint mip = bias;\n";
644 : }
645 : else
646 : {
647 :
648 0 : out << " " << textureReference
649 0 : << ".GetDimensions(0, width, height, layers, levels);\n";
650 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
651 0 : textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
652 : {
653 : out << " float2 tSized = float2(t.x * width, t.y * height);\n"
654 : " float dx = length(ddx(tSized));\n"
655 : " float dy = length(ddy(tSized));\n"
656 0 : " float lod = log2(max(dx, dy));\n";
657 :
658 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
659 : {
660 0 : out << " lod += bias;\n";
661 : }
662 : }
663 0 : else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
664 : {
665 : out << " float2 sizeVec = float2(width, height);\n"
666 : " float2 sizeDdx = ddx * sizeVec;\n"
667 : " float2 sizeDdy = ddy * sizeVec;\n"
668 : " float lod = log2(max(dot(sizeDdx, sizeDdx), "
669 0 : "dot(sizeDdy, sizeDdy))) * 0.5f;\n";
670 : }
671 :
672 0 : out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
673 : }
674 :
675 0 : out << " " << textureReference
676 0 : << ".GetDimensions(mip, width, height, layers, levels);\n";
677 : }
678 : else
679 : {
680 0 : out << " float width; float height; float levels;\n";
681 :
682 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
683 : {
684 0 : out << " uint mip = 0;\n";
685 : }
686 0 : else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
687 : {
688 0 : out << " uint mip = bias;\n";
689 : }
690 : else
691 : {
692 0 : out << " " << textureReference
693 0 : << ".GetDimensions(0, width, height, levels);\n";
694 :
695 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
696 0 : textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
697 : {
698 : out << " float2 tSized = float2(t.x * width, t.y * height);\n"
699 : " float dx = length(ddx(tSized));\n"
700 : " float dy = length(ddy(tSized));\n"
701 0 : " float lod = log2(max(dx, dy));\n";
702 :
703 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
704 : {
705 0 : out << " lod += bias;\n";
706 : }
707 : }
708 0 : else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
709 : {
710 : out << " float2 sizeVec = float2(width, height);\n"
711 : " float2 sizeDdx = ddx * sizeVec;\n"
712 : " float2 sizeDdy = ddy * sizeVec;\n"
713 : " float lod = log2(max(dot(sizeDdx, sizeDdx), "
714 0 : "dot(sizeDdy, sizeDdy))) * 0.5f;\n";
715 : }
716 :
717 0 : out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
718 : }
719 :
720 0 : out << " " << textureReference
721 0 : << ".GetDimensions(mip, width, height, levels);\n";
722 : }
723 : }
724 0 : else if (IsSampler3D(textureFunction.sampler))
725 : {
726 0 : out << " float width; float height; float depth; float levels;\n";
727 :
728 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
729 : {
730 0 : out << " uint mip = 0;\n";
731 : }
732 0 : else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
733 : {
734 0 : out << " uint mip = bias;\n";
735 : }
736 : else
737 : {
738 0 : out << " " << textureReference
739 0 : << ".GetDimensions(0, width, height, depth, levels);\n";
740 :
741 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
742 0 : textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
743 : {
744 : out << " float3 tSized = float3(t.x * width, t.y * height, t.z * depth);\n"
745 : " float dx = length(ddx(tSized));\n"
746 : " float dy = length(ddy(tSized));\n"
747 0 : " float lod = log2(max(dx, dy));\n";
748 :
749 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
750 : {
751 0 : out << " lod += bias;\n";
752 : }
753 : }
754 0 : else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
755 : {
756 : out << " float3 sizeVec = float3(width, height, depth);\n"
757 : " float3 sizeDdx = ddx * sizeVec;\n"
758 : " float3 sizeDdy = ddy * sizeVec;\n"
759 : " float lod = log2(max(dot(sizeDdx, sizeDdx), dot(sizeDdy, "
760 0 : "sizeDdy))) * 0.5f;\n";
761 : }
762 :
763 0 : out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
764 : }
765 :
766 0 : out << " " << textureReference
767 0 : << ".GetDimensions(mip, width, height, depth, levels);\n";
768 : }
769 : else
770 0 : UNREACHABLE();
771 :
772 0 : OutputIntTexCoordWraps(out, textureFunction, texCoordX, texCoordY, texCoordZ);
773 : }
774 : }
775 :
776 0 : void OutputTextureSampleFunctionReturnStatement(
777 : TInfoSinkBase &out,
778 : const TextureFunctionHLSL::TextureFunction &textureFunction,
779 : const ShShaderOutput outputType,
780 : const TString &textureReference,
781 : const TString &samplerReference,
782 : const TString &texCoordX,
783 : const TString &texCoordY,
784 : const TString &texCoordZ)
785 : {
786 0 : out << " return ";
787 :
788 : // HLSL intrinsic
789 0 : if (outputType == SH_HLSL_3_0_OUTPUT)
790 : {
791 0 : switch (textureFunction.sampler)
792 : {
793 : case EbtSampler2D:
794 : case EbtSamplerExternalOES:
795 0 : out << "tex2D";
796 0 : break;
797 : case EbtSamplerCube:
798 0 : out << "texCUBE";
799 0 : break;
800 : default:
801 0 : UNREACHABLE();
802 : }
803 :
804 0 : switch (textureFunction.method)
805 : {
806 : case TextureFunctionHLSL::TextureFunction::IMPLICIT:
807 0 : out << "(" << samplerReference << ", ";
808 0 : break;
809 : case TextureFunctionHLSL::TextureFunction::BIAS:
810 0 : out << "bias(" << samplerReference << ", ";
811 0 : break;
812 : case TextureFunctionHLSL::TextureFunction::LOD:
813 0 : out << "lod(" << samplerReference << ", ";
814 0 : break;
815 : case TextureFunctionHLSL::TextureFunction::LOD0:
816 0 : out << "lod(" << samplerReference << ", ";
817 0 : break;
818 : case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
819 0 : out << "lod(" << samplerReference << ", ";
820 0 : break;
821 : default:
822 0 : UNREACHABLE();
823 : }
824 : }
825 0 : else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
826 : {
827 0 : OutputHLSL4SampleFunctionPrefix(out, textureFunction, textureReference, samplerReference);
828 : }
829 : else
830 0 : UNREACHABLE();
831 :
832 0 : const int hlslCoords = GetHLSLCoordCount(textureFunction, outputType);
833 :
834 0 : out << GetSamplerCoordinateTypeString(textureFunction, hlslCoords) << "(" << texCoordX << ", "
835 0 : << texCoordY;
836 :
837 0 : if (outputType == SH_HLSL_3_0_OUTPUT)
838 : {
839 0 : if (hlslCoords >= 3)
840 : {
841 0 : if (textureFunction.coords < 3)
842 : {
843 0 : out << ", 0";
844 : }
845 : else
846 : {
847 0 : out << ", " << texCoordZ;
848 : }
849 : }
850 :
851 0 : if (hlslCoords == 4)
852 : {
853 0 : switch (textureFunction.method)
854 : {
855 : case TextureFunctionHLSL::TextureFunction::BIAS:
856 0 : out << ", bias";
857 0 : break;
858 : case TextureFunctionHLSL::TextureFunction::LOD:
859 0 : out << ", lod";
860 0 : break;
861 : case TextureFunctionHLSL::TextureFunction::LOD0:
862 0 : out << ", 0";
863 0 : break;
864 : case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
865 0 : out << ", bias";
866 0 : break;
867 : default:
868 0 : UNREACHABLE();
869 : }
870 : }
871 :
872 0 : out << ")";
873 : }
874 0 : else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
875 : {
876 0 : if (hlslCoords >= 3)
877 : {
878 0 : ASSERT(!IsIntegerSampler(textureFunction.sampler) ||
879 : !IsSamplerCube(textureFunction.sampler) || texCoordZ == "face");
880 0 : out << ", " << texCoordZ;
881 : }
882 :
883 0 : if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
884 : {
885 0 : if (IsIntegerSampler(textureFunction.sampler))
886 : {
887 0 : out << ", mip)";
888 : }
889 0 : else if (IsShadowSampler(textureFunction.sampler))
890 : {
891 : // Compare value
892 0 : if (textureFunction.proj)
893 : {
894 : // According to ESSL 3.00.4 sec 8.8 p95 on textureProj:
895 : // The resulting third component of P' in the shadow forms is used as
896 : // Dref
897 0 : out << "), " << texCoordZ;
898 : }
899 : else
900 : {
901 0 : switch (textureFunction.coords)
902 : {
903 : case 3:
904 0 : out << "), t.z";
905 0 : break;
906 : case 4:
907 0 : out << "), t.w";
908 0 : break;
909 : default:
910 0 : UNREACHABLE();
911 : }
912 : }
913 : }
914 : else
915 : {
916 0 : out << "), ddx, ddy";
917 : }
918 : }
919 0 : else if (IsIntegerSampler(textureFunction.sampler) ||
920 0 : textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
921 : {
922 0 : out << ", mip)";
923 : }
924 0 : else if (IsShadowSampler(textureFunction.sampler))
925 : {
926 : // Compare value
927 0 : if (textureFunction.proj)
928 : {
929 : // According to ESSL 3.00.4 sec 8.8 p95 on textureProj:
930 : // The resulting third component of P' in the shadow forms is used as Dref
931 0 : out << "), " << texCoordZ;
932 : }
933 : else
934 : {
935 0 : switch (textureFunction.coords)
936 : {
937 : case 3:
938 0 : out << "), t.z";
939 0 : break;
940 : case 4:
941 0 : out << "), t.w";
942 0 : break;
943 : default:
944 0 : UNREACHABLE();
945 : }
946 : }
947 : }
948 : else
949 : {
950 0 : switch (textureFunction.method)
951 : {
952 : case TextureFunctionHLSL::TextureFunction::IMPLICIT:
953 0 : out << ")";
954 0 : break;
955 : case TextureFunctionHLSL::TextureFunction::BIAS:
956 0 : out << "), bias";
957 0 : break;
958 : case TextureFunctionHLSL::TextureFunction::LOD:
959 0 : out << "), lod";
960 0 : break;
961 : case TextureFunctionHLSL::TextureFunction::LOD0:
962 0 : out << "), 0";
963 0 : break;
964 : case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
965 0 : out << "), bias";
966 0 : break;
967 : default:
968 0 : UNREACHABLE();
969 : }
970 : }
971 :
972 0 : if (textureFunction.offset &&
973 0 : (!IsIntegerSampler(textureFunction.sampler) ||
974 0 : textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH))
975 : {
976 0 : out << ", offset";
977 : }
978 : }
979 : else
980 0 : UNREACHABLE();
981 :
982 0 : out << ");\n"; // Close the sample function call and return statement
983 0 : }
984 :
985 : } // Anonymous namespace
986 :
987 0 : TString TextureFunctionHLSL::TextureFunction::name() const
988 : {
989 0 : TString name = "gl_texture";
990 :
991 : // We need to include full the sampler type in the function name to make the signature unique
992 : // on D3D11, where samplers are passed to texture functions as indices.
993 0 : name += TextureTypeSuffix(this->sampler);
994 :
995 0 : if (proj)
996 : {
997 0 : name += "Proj";
998 : }
999 :
1000 0 : if (offset)
1001 : {
1002 0 : name += "Offset";
1003 : }
1004 :
1005 0 : switch (method)
1006 : {
1007 : case IMPLICIT:
1008 0 : break;
1009 : case BIAS:
1010 0 : break; // Extra parameter makes the signature unique
1011 : case LOD:
1012 0 : name += "Lod";
1013 0 : break;
1014 : case LOD0:
1015 0 : name += "Lod0";
1016 0 : break;
1017 : case LOD0BIAS:
1018 0 : name += "Lod0";
1019 0 : break; // Extra parameter makes the signature unique
1020 : case SIZE:
1021 0 : name += "Size";
1022 0 : break;
1023 : case FETCH:
1024 0 : name += "Fetch";
1025 0 : break;
1026 : case GRAD:
1027 0 : name += "Grad";
1028 0 : break;
1029 : default:
1030 0 : UNREACHABLE();
1031 : }
1032 :
1033 0 : return name;
1034 : }
1035 :
1036 0 : const char *TextureFunctionHLSL::TextureFunction::getReturnType() const
1037 : {
1038 0 : if (method == TextureFunction::SIZE)
1039 : {
1040 0 : switch (sampler)
1041 : {
1042 : case EbtSampler2D:
1043 : case EbtISampler2D:
1044 : case EbtUSampler2D:
1045 : case EbtSampler2DShadow:
1046 : case EbtSamplerCube:
1047 : case EbtISamplerCube:
1048 : case EbtUSamplerCube:
1049 : case EbtSamplerCubeShadow:
1050 : case EbtSamplerExternalOES:
1051 0 : return "int2";
1052 : case EbtSampler3D:
1053 : case EbtISampler3D:
1054 : case EbtUSampler3D:
1055 : case EbtSampler2DArray:
1056 : case EbtISampler2DArray:
1057 : case EbtUSampler2DArray:
1058 : case EbtSampler2DArrayShadow:
1059 0 : return "int3";
1060 : default:
1061 0 : UNREACHABLE();
1062 : }
1063 : }
1064 : else // Sampling function
1065 : {
1066 0 : switch (sampler)
1067 : {
1068 : case EbtSampler2D:
1069 : case EbtSampler3D:
1070 : case EbtSamplerCube:
1071 : case EbtSampler2DArray:
1072 : case EbtSamplerExternalOES:
1073 0 : return "float4";
1074 : case EbtISampler2D:
1075 : case EbtISampler3D:
1076 : case EbtISamplerCube:
1077 : case EbtISampler2DArray:
1078 0 : return "int4";
1079 : case EbtUSampler2D:
1080 : case EbtUSampler3D:
1081 : case EbtUSamplerCube:
1082 : case EbtUSampler2DArray:
1083 0 : return "uint4";
1084 : case EbtSampler2DShadow:
1085 : case EbtSamplerCubeShadow:
1086 : case EbtSampler2DArrayShadow:
1087 0 : return "float";
1088 : default:
1089 0 : UNREACHABLE();
1090 : }
1091 : }
1092 : return "";
1093 : }
1094 :
1095 0 : bool TextureFunctionHLSL::TextureFunction::operator<(const TextureFunction &rhs) const
1096 : {
1097 0 : return std::tie(sampler, coords, proj, offset, method) <
1098 0 : std::tie(rhs.sampler, rhs.coords, rhs.proj, rhs.offset, rhs.method);
1099 : }
1100 :
1101 0 : TString TextureFunctionHLSL::useTextureFunction(const TString &name,
1102 : TBasicType samplerType,
1103 : int coords,
1104 : size_t argumentCount,
1105 : bool lod0,
1106 : sh::GLenum shaderType)
1107 : {
1108 : TextureFunction textureFunction;
1109 0 : textureFunction.sampler = samplerType;
1110 0 : textureFunction.coords = coords;
1111 0 : textureFunction.method = TextureFunction::IMPLICIT;
1112 0 : textureFunction.proj = false;
1113 0 : textureFunction.offset = false;
1114 :
1115 0 : if (name == "texture2D" || name == "textureCube" || name == "texture")
1116 : {
1117 0 : textureFunction.method = TextureFunction::IMPLICIT;
1118 : }
1119 0 : else if (name == "texture2DProj" || name == "textureProj")
1120 : {
1121 0 : textureFunction.method = TextureFunction::IMPLICIT;
1122 0 : textureFunction.proj = true;
1123 : }
1124 0 : else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod" ||
1125 0 : name == "texture2DLodEXT" || name == "textureCubeLodEXT")
1126 : {
1127 0 : textureFunction.method = TextureFunction::LOD;
1128 : }
1129 0 : else if (name == "texture2DProjLod" || name == "textureProjLod" ||
1130 0 : name == "texture2DProjLodEXT")
1131 : {
1132 0 : textureFunction.method = TextureFunction::LOD;
1133 0 : textureFunction.proj = true;
1134 : }
1135 0 : else if (name == "textureSize")
1136 : {
1137 0 : textureFunction.method = TextureFunction::SIZE;
1138 : }
1139 0 : else if (name == "textureOffset")
1140 : {
1141 0 : textureFunction.method = TextureFunction::IMPLICIT;
1142 0 : textureFunction.offset = true;
1143 : }
1144 0 : else if (name == "textureProjOffset")
1145 : {
1146 0 : textureFunction.method = TextureFunction::IMPLICIT;
1147 0 : textureFunction.offset = true;
1148 0 : textureFunction.proj = true;
1149 : }
1150 0 : else if (name == "textureLodOffset")
1151 : {
1152 0 : textureFunction.method = TextureFunction::LOD;
1153 0 : textureFunction.offset = true;
1154 : }
1155 0 : else if (name == "textureProjLodOffset")
1156 : {
1157 0 : textureFunction.method = TextureFunction::LOD;
1158 0 : textureFunction.proj = true;
1159 0 : textureFunction.offset = true;
1160 : }
1161 0 : else if (name == "texelFetch")
1162 : {
1163 0 : textureFunction.method = TextureFunction::FETCH;
1164 : }
1165 0 : else if (name == "texelFetchOffset")
1166 : {
1167 0 : textureFunction.method = TextureFunction::FETCH;
1168 0 : textureFunction.offset = true;
1169 : }
1170 0 : else if (name == "textureGrad" || name == "texture2DGradEXT")
1171 : {
1172 0 : textureFunction.method = TextureFunction::GRAD;
1173 : }
1174 0 : else if (name == "textureGradOffset")
1175 : {
1176 0 : textureFunction.method = TextureFunction::GRAD;
1177 0 : textureFunction.offset = true;
1178 : }
1179 0 : else if (name == "textureProjGrad" || name == "texture2DProjGradEXT" ||
1180 0 : name == "textureCubeGradEXT")
1181 : {
1182 0 : textureFunction.method = TextureFunction::GRAD;
1183 0 : textureFunction.proj = true;
1184 : }
1185 0 : else if (name == "textureProjGradOffset")
1186 : {
1187 0 : textureFunction.method = TextureFunction::GRAD;
1188 0 : textureFunction.proj = true;
1189 0 : textureFunction.offset = true;
1190 : }
1191 : else
1192 0 : UNREACHABLE();
1193 :
1194 0 : if (textureFunction.method ==
1195 : TextureFunction::IMPLICIT) // Could require lod 0 or have a bias argument
1196 : {
1197 0 : size_t mandatoryArgumentCount = 2; // All functions have sampler and coordinate arguments
1198 :
1199 0 : if (textureFunction.offset)
1200 : {
1201 0 : mandatoryArgumentCount++;
1202 : }
1203 :
1204 0 : bool bias = (argumentCount > mandatoryArgumentCount); // Bias argument is optional
1205 :
1206 0 : if (lod0 || shaderType == GL_VERTEX_SHADER)
1207 : {
1208 0 : if (bias)
1209 : {
1210 0 : textureFunction.method = TextureFunction::LOD0BIAS;
1211 : }
1212 : else
1213 : {
1214 0 : textureFunction.method = TextureFunction::LOD0;
1215 : }
1216 : }
1217 0 : else if (bias)
1218 : {
1219 0 : textureFunction.method = TextureFunction::BIAS;
1220 : }
1221 : }
1222 :
1223 0 : mUsesTexture.insert(textureFunction);
1224 0 : return textureFunction.name();
1225 : }
1226 :
1227 0 : void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out,
1228 : const ShShaderOutput outputType,
1229 : bool getDimensionsIgnoresBaseLevel)
1230 : {
1231 0 : for (const TextureFunction &textureFunction : mUsesTexture)
1232 : {
1233 : // Function header
1234 0 : out << textureFunction.getReturnType() << " " << textureFunction.name() << "(";
1235 :
1236 0 : OutputTextureFunctionArgumentList(out, textureFunction, outputType);
1237 :
1238 : out << ")\n"
1239 0 : "{\n";
1240 :
1241 : // In some cases we use a variable to store the texture/sampler objects, but to work around
1242 : // a D3D11 compiler bug related to discard inside a loop that is conditional on texture
1243 : // sampling we need to call the function directly on references to the texture and sampler
1244 : // arrays. The bug was found using dEQP-GLES3.functional.shaders.discard*loop_texture*
1245 : // tests.
1246 0 : TString textureReference;
1247 0 : TString samplerReference;
1248 0 : GetTextureReference(out, textureFunction, outputType, &textureReference, &samplerReference);
1249 :
1250 0 : if (textureFunction.method == TextureFunction::SIZE)
1251 : {
1252 0 : OutputTextureSizeFunctionBody(out, textureFunction, textureReference,
1253 0 : getDimensionsIgnoresBaseLevel);
1254 : }
1255 : else
1256 : {
1257 0 : TString texCoordX("t.x");
1258 0 : TString texCoordY("t.y");
1259 0 : TString texCoordZ("t.z");
1260 0 : ProjectTextureCoordinates(textureFunction, &texCoordX, &texCoordY, &texCoordZ);
1261 : OutputIntegerTextureSampleFunctionComputations(out, textureFunction, outputType,
1262 : textureReference, &texCoordX, &texCoordY,
1263 0 : &texCoordZ);
1264 : OutputTextureSampleFunctionReturnStatement(out, textureFunction, outputType,
1265 : textureReference, samplerReference,
1266 0 : texCoordX, texCoordY, texCoordZ);
1267 : }
1268 :
1269 : out << "}\n"
1270 0 : "\n";
1271 : }
1272 0 : }
1273 :
1274 : } // namespace sh
|