blob: f0ad980e59fe56c8d2d32bd3bf48795401e31d67 [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001// SwiftShader Software Renderer
2//
John Bauman66b8ab22014-05-06 15:57:45 -04003// Copyright(c) 2005-2013 TransGaming Inc.
John Bauman89401822014-05-06 15:04:28 -04004//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#include "PixelProcessor.hpp"
13
Alexis Hetuf2a8c372015-07-13 11:08:41 -040014#include "PixelPipeline.hpp"
15#include "PixelProgram.hpp"
John Bauman89401822014-05-06 15:04:28 -040016#include "PixelShader.hpp"
17#include "MetaMacro.hpp"
18#include "Surface.hpp"
19#include "Primitive.hpp"
20#include "Constants.hpp"
21#include "Debug.hpp"
22
John Bauman66b8ab22014-05-06 15:57:45 -040023#include <string.h>
24
John Bauman89401822014-05-06 15:04:28 -040025namespace sw
26{
27 extern bool complementaryDepthBuffer;
Nicolas Capensa0f4be82014-10-22 14:35:30 -040028 extern TransparencyAntialiasing transparencyAntialiasing;
John Bauman89401822014-05-06 15:04:28 -040029 extern bool perspectiveCorrection;
30
John Bauman66b8ab22014-05-06 15:57:45 -040031 bool precachePixel = false;
32
John Bauman89401822014-05-06 15:04:28 -040033 unsigned int PixelProcessor::States::computeHash()
34 {
35 unsigned int *state = (unsigned int*)this;
36 unsigned int hash = 0;
37
Nicolas Capens5d961882016-01-01 23:18:14 -050038 for(unsigned int i = 0; i < sizeof(States) / 4; i++)
John Bauman89401822014-05-06 15:04:28 -040039 {
40 hash ^= state[i];
41 }
42
43 return hash;
44 }
45
46 PixelProcessor::State::State()
47 {
48 memset(this, 0, sizeof(State));
49 }
50
51 bool PixelProcessor::State::operator==(const State &state) const
52 {
53 if(hash != state.hash)
54 {
55 return false;
56 }
57
58 return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
59 }
60
61 PixelProcessor::PixelProcessor(Context *context) : context(context)
62 {
63 setGlobalMipmapBias(0.0f); // Round to highest LOD [0.5, 1.0]: -0.5
64 // Round to nearest LOD [0.7, 1.4]: 0.0
65 // Round to lowest LOD [1.0, 2.0]: 0.5
66
67 routineCache = 0;
68 setRoutineCacheSize(1024);
Nicolas Capens3d7be4e2016-02-07 22:47:00 -050069
70 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
71 {
72 uniformBuffer[i] = nullptr;
73 }
John Bauman89401822014-05-06 15:04:28 -040074 }
75
76 PixelProcessor::~PixelProcessor()
77 {
78 delete routineCache;
79 routineCache = 0;
80 }
81
82 void PixelProcessor::setFloatConstant(unsigned int index, const float value[4])
83 {
Alexis Hetu04c967a2015-07-08 15:56:17 -040084 if(index < FRAGMENT_UNIFORM_VECTORS)
John Bauman89401822014-05-06 15:04:28 -040085 {
86 c[index][0] = value[0];
87 c[index][1] = value[1];
88 c[index][2] = value[2];
89 c[index][3] = value[3];
90 }
91 else ASSERT(false);
92
93 if(index < 8) // ps_1_x constants
94 {
95 // FIXME: Compact into generic function
96 short x = iround(4095 * clamp(value[0], -1.0f, 1.0f));
97 short y = iround(4095 * clamp(value[1], -1.0f, 1.0f));
98 short z = iround(4095 * clamp(value[2], -1.0f, 1.0f));
99 short w = iround(4095 * clamp(value[3], -1.0f, 1.0f));
100
101 cW[index][0][0] = x;
102 cW[index][0][1] = x;
103 cW[index][0][2] = x;
104 cW[index][0][3] = x;
105
106 cW[index][1][0] = y;
107 cW[index][1][1] = y;
108 cW[index][1][2] = y;
109 cW[index][1][3] = y;
110
111 cW[index][2][0] = z;
112 cW[index][2][1] = z;
113 cW[index][2][2] = z;
114 cW[index][2][3] = z;
115
116 cW[index][3][0] = w;
117 cW[index][3][1] = w;
118 cW[index][3][2] = w;
119 cW[index][3][3] = w;
120 }
121 }
122
123 void PixelProcessor::setIntegerConstant(unsigned int index, const int value[4])
124 {
125 if(index < 16)
126 {
127 i[index][0] = value[0];
128 i[index][1] = value[1];
129 i[index][2] = value[2];
130 i[index][3] = value[3];
131 }
132 else ASSERT(false);
133 }
134
135 void PixelProcessor::setBooleanConstant(unsigned int index, int boolean)
136 {
137 if(index < 16)
138 {
139 b[index] = boolean != 0;
140 }
141 else ASSERT(false);
142 }
143
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400144 void PixelProcessor::setUniformBuffer(int index, sw::Resource* buffer, int offset)
145 {
146 uniformBuffer[index] = buffer;
147 uniformBufferOffset[index] = offset;
148 }
149
150 void PixelProcessor::lockUniformBuffers(byte** u)
151 {
152 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i)
153 {
154 u[i] = uniformBuffer[i] ? static_cast<byte*>(uniformBuffer[i]->lock(PUBLIC, PRIVATE)) + uniformBufferOffset[i] : nullptr;
155 }
156 }
157
158 void PixelProcessor::unlockUniformBuffers()
159 {
160 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i)
161 {
162 if(uniformBuffer[i])
163 {
164 uniformBuffer[i]->unlock();
165 uniformBuffer[i] = nullptr;
166 }
167 }
168 }
169
John Bauman89401822014-05-06 15:04:28 -0400170 void PixelProcessor::setRenderTarget(int index, Surface *renderTarget)
171 {
172 context->renderTarget[index] = renderTarget;
173 }
174
175 void PixelProcessor::setDepthStencil(Surface *depthStencil)
176 {
177 context->depthStencil = depthStencil;
178 }
179
180 void PixelProcessor::setTexCoordIndex(unsigned int stage, int texCoordIndex)
181 {
182 if(stage < 8)
183 {
184 context->textureStage[stage].setTexCoordIndex(texCoordIndex);
185 }
186 else ASSERT(false);
187 }
188
189 void PixelProcessor::setStageOperation(unsigned int stage, TextureStage::StageOperation stageOperation)
190 {
191 if(stage < 8)
192 {
193 context->textureStage[stage].setStageOperation(stageOperation);
194 }
195 else ASSERT(false);
196 }
197
198 void PixelProcessor::setFirstArgument(unsigned int stage, TextureStage::SourceArgument firstArgument)
199 {
200 if(stage < 8)
201 {
202 context->textureStage[stage].setFirstArgument(firstArgument);
203 }
204 else ASSERT(false);
205 }
206
207 void PixelProcessor::setSecondArgument(unsigned int stage, TextureStage::SourceArgument secondArgument)
208 {
209 if(stage < 8)
210 {
211 context->textureStage[stage].setSecondArgument(secondArgument);
212 }
213 else ASSERT(false);
214 }
215
216 void PixelProcessor::setThirdArgument(unsigned int stage, TextureStage::SourceArgument thirdArgument)
217 {
218 if(stage < 8)
219 {
220 context->textureStage[stage].setThirdArgument(thirdArgument);
221 }
222 else ASSERT(false);
223 }
224
225 void PixelProcessor::setStageOperationAlpha(unsigned int stage, TextureStage::StageOperation stageOperationAlpha)
226 {
227 if(stage < 8)
228 {
229 context->textureStage[stage].setStageOperationAlpha(stageOperationAlpha);
230 }
231 else ASSERT(false);
232 }
233
234 void PixelProcessor::setFirstArgumentAlpha(unsigned int stage, TextureStage::SourceArgument firstArgumentAlpha)
235 {
236 if(stage < 8)
237 {
238 context->textureStage[stage].setFirstArgumentAlpha(firstArgumentAlpha);
239 }
240 else ASSERT(false);
241 }
242
243 void PixelProcessor::setSecondArgumentAlpha(unsigned int stage, TextureStage::SourceArgument secondArgumentAlpha)
244 {
245 if(stage < 8)
246 {
247 context->textureStage[stage].setSecondArgumentAlpha(secondArgumentAlpha);
248 }
249 else ASSERT(false);
250 }
251
252 void PixelProcessor::setThirdArgumentAlpha(unsigned int stage, TextureStage::SourceArgument thirdArgumentAlpha)
253 {
254 if(stage < 8)
255 {
256 context->textureStage[stage].setThirdArgumentAlpha(thirdArgumentAlpha);
257 }
258 else ASSERT(false);
259 }
260
261 void PixelProcessor::setFirstModifier(unsigned int stage, TextureStage::ArgumentModifier firstModifier)
262 {
263 if(stage < 8)
264 {
265 context->textureStage[stage].setFirstModifier(firstModifier);
266 }
267 else ASSERT(false);
268 }
269
270 void PixelProcessor::setSecondModifier(unsigned int stage, TextureStage::ArgumentModifier secondModifier)
271 {
272 if(stage < 8)
273 {
274 context->textureStage[stage].setSecondModifier(secondModifier);
275 }
276 else ASSERT(false);
277 }
278
279 void PixelProcessor::setThirdModifier(unsigned int stage, TextureStage::ArgumentModifier thirdModifier)
280 {
281 if(stage < 8)
282 {
283 context->textureStage[stage].setThirdModifier(thirdModifier);
284 }
285 else ASSERT(false);
286 }
287
288 void PixelProcessor::setFirstModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier firstModifierAlpha)
289 {
290 if(stage < 8)
291 {
292 context->textureStage[stage].setFirstModifierAlpha(firstModifierAlpha);
293 }
294 else ASSERT(false);
295 }
296
297 void PixelProcessor::setSecondModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier secondModifierAlpha)
298 {
299 if(stage < 8)
300 {
301 context->textureStage[stage].setSecondModifierAlpha(secondModifierAlpha);
302 }
303 else ASSERT(false);
304 }
305
306 void PixelProcessor::setThirdModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier thirdModifierAlpha)
307 {
308 if(stage < 8)
309 {
310 context->textureStage[stage].setThirdModifierAlpha(thirdModifierAlpha);
311 }
312 else ASSERT(false);
313 }
314
315 void PixelProcessor::setDestinationArgument(unsigned int stage, TextureStage::DestinationArgument destinationArgument)
316 {
317 if(stage < 8)
318 {
319 context->textureStage[stage].setDestinationArgument(destinationArgument);
320 }
321 else ASSERT(false);
322 }
323
324 void PixelProcessor::setConstantColor(unsigned int stage, const Color<float> &constantColor)
325 {
326 if(stage < 8)
327 {
328 context->textureStage[stage].setConstantColor(constantColor);
329 }
330 else ASSERT(false);
331 }
332
333 void PixelProcessor::setBumpmapMatrix(unsigned int stage, int element, float value)
334 {
335 if(stage < 8)
336 {
337 context->textureStage[stage].setBumpmapMatrix(element, value);
338 }
339 else ASSERT(false);
340 }
341
342 void PixelProcessor::setLuminanceScale(unsigned int stage, float value)
343 {
344 if(stage < 8)
345 {
346 context->textureStage[stage].setLuminanceScale(value);
347 }
348 else ASSERT(false);
349 }
350
351 void PixelProcessor::setLuminanceOffset(unsigned int stage, float value)
352 {
353 if(stage < 8)
354 {
355 context->textureStage[stage].setLuminanceOffset(value);
356 }
357 else ASSERT(false);
358 }
359
360 void PixelProcessor::setTextureFilter(unsigned int sampler, FilterType textureFilter)
361 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400362 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400363 {
364 context->sampler[sampler].setTextureFilter(textureFilter);
365 }
366 else ASSERT(false);
367 }
368
369 void PixelProcessor::setMipmapFilter(unsigned int sampler, MipmapType mipmapFilter)
370 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400371 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400372 {
373 context->sampler[sampler].setMipmapFilter(mipmapFilter);
374 }
375 else ASSERT(false);
376 }
377
378 void PixelProcessor::setGatherEnable(unsigned int sampler, bool enable)
379 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400380 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400381 {
382 context->sampler[sampler].setGatherEnable(enable);
383 }
384 else ASSERT(false);
385 }
386
387 void PixelProcessor::setAddressingModeU(unsigned int sampler, AddressingMode addressMode)
388 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400389 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400390 {
391 context->sampler[sampler].setAddressingModeU(addressMode);
392 }
393 else ASSERT(false);
394 }
395
396 void PixelProcessor::setAddressingModeV(unsigned int sampler, AddressingMode addressMode)
397 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400398 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400399 {
400 context->sampler[sampler].setAddressingModeV(addressMode);
401 }
402 else ASSERT(false);
403 }
404
405 void PixelProcessor::setAddressingModeW(unsigned int sampler, AddressingMode addressMode)
406 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400407 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400408 {
409 context->sampler[sampler].setAddressingModeW(addressMode);
410 }
411 else ASSERT(false);
412 }
413
414 void PixelProcessor::setReadSRGB(unsigned int sampler, bool sRGB)
415 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400416 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400417 {
418 context->sampler[sampler].setReadSRGB(sRGB);
419 }
420 else ASSERT(false);
421 }
422
423 void PixelProcessor::setMipmapLOD(unsigned int sampler, float bias)
424 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400425 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400426 {
427 context->sampler[sampler].setMipmapLOD(bias);
428 }
429 else ASSERT(false);
430 }
431
432 void PixelProcessor::setBorderColor(unsigned int sampler, const Color<float> &borderColor)
433 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400434 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400435 {
436 context->sampler[sampler].setBorderColor(borderColor);
437 }
438 else ASSERT(false);
439 }
440
Alexis Hetu617a5d52014-11-13 10:56:20 -0500441 void PixelProcessor::setMaxAnisotropy(unsigned int sampler, float maxAnisotropy)
John Bauman89401822014-05-06 15:04:28 -0400442 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400443 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400444 {
445 context->sampler[sampler].setMaxAnisotropy(maxAnisotropy);
446 }
447 else ASSERT(false);
448 }
449
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400450 void PixelProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR)
451 {
452 if(sampler < TEXTURE_IMAGE_UNITS)
453 {
454 context->sampler[sampler].setSwizzleR(swizzleR);
455 }
456 else ASSERT(false);
457 }
458
459 void PixelProcessor::setSwizzleG(unsigned int sampler, SwizzleType swizzleG)
460 {
461 if(sampler < TEXTURE_IMAGE_UNITS)
462 {
463 context->sampler[sampler].setSwizzleG(swizzleG);
464 }
465 else ASSERT(false);
466 }
467
468 void PixelProcessor::setSwizzleB(unsigned int sampler, SwizzleType swizzleB)
469 {
470 if(sampler < TEXTURE_IMAGE_UNITS)
471 {
472 context->sampler[sampler].setSwizzleB(swizzleB);
473 }
474 else ASSERT(false);
475 }
476
477 void PixelProcessor::setSwizzleA(unsigned int sampler, SwizzleType swizzleA)
478 {
479 if(sampler < TEXTURE_IMAGE_UNITS)
480 {
481 context->sampler[sampler].setSwizzleA(swizzleA);
482 }
483 else ASSERT(false);
484 }
485
John Bauman89401822014-05-06 15:04:28 -0400486 void PixelProcessor::setWriteSRGB(bool sRGB)
487 {
488 context->setWriteSRGB(sRGB);
489 }
490
Maxime Grégoired9762742015-07-08 16:43:48 -0400491 void PixelProcessor::setColorLogicOpEnabled(bool colorLogicOpEnabled)
492 {
493 context->setColorLogicOpEnabled(colorLogicOpEnabled);
494 }
495
496 void PixelProcessor::setLogicalOperation(LogicalOperation logicalOperation)
497 {
498 context->setLogicalOperation(logicalOperation);
499 }
500
John Bauman89401822014-05-06 15:04:28 -0400501 void PixelProcessor::setDepthBufferEnable(bool depthBufferEnable)
502 {
503 context->setDepthBufferEnable(depthBufferEnable);
504 }
505
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400506 void PixelProcessor::setDepthCompare(DepthCompareMode depthCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400507 {
508 context->depthCompareMode = depthCompareMode;
509 }
510
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400511 void PixelProcessor::setAlphaCompare(AlphaCompareMode alphaCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400512 {
513 context->alphaCompareMode = alphaCompareMode;
514 }
515
516 void PixelProcessor::setDepthWriteEnable(bool depthWriteEnable)
517 {
518 context->depthWriteEnable = depthWriteEnable;
519 }
520
521 void PixelProcessor::setAlphaTestEnable(bool alphaTestEnable)
522 {
523 context->alphaTestEnable = alphaTestEnable;
524 }
525
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400526 void PixelProcessor::setCullMode(CullMode cullMode)
John Bauman89401822014-05-06 15:04:28 -0400527 {
528 context->cullMode = cullMode;
529 }
530
531 void PixelProcessor::setColorWriteMask(int index, int rgbaMask)
532 {
533 context->setColorWriteMask(index, rgbaMask);
534 }
535
536 void PixelProcessor::setStencilEnable(bool stencilEnable)
537 {
538 context->stencilEnable = stencilEnable;
539 }
540
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400541 void PixelProcessor::setStencilCompare(StencilCompareMode stencilCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400542 {
543 context->stencilCompareMode = stencilCompareMode;
544 }
545
546 void PixelProcessor::setStencilReference(int stencilReference)
547 {
548 context->stencilReference = stencilReference;
549 stencil.set(stencilReference, context->stencilMask, context->stencilWriteMask);
550 }
551
552 void PixelProcessor::setStencilReferenceCCW(int stencilReferenceCCW)
553 {
554 context->stencilReferenceCCW = stencilReferenceCCW;
555 stencilCCW.set(stencilReferenceCCW, context->stencilMaskCCW, context->stencilWriteMaskCCW);
556 }
557
558 void PixelProcessor::setStencilMask(int stencilMask)
559 {
560 context->stencilMask = stencilMask;
561 stencil.set(context->stencilReference, stencilMask, context->stencilWriteMask);
562 }
563
564 void PixelProcessor::setStencilMaskCCW(int stencilMaskCCW)
565 {
566 context->stencilMaskCCW = stencilMaskCCW;
567 stencilCCW.set(context->stencilReferenceCCW, stencilMaskCCW, context->stencilWriteMaskCCW);
568 }
569
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400570 void PixelProcessor::setStencilFailOperation(StencilOperation stencilFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400571 {
572 context->stencilFailOperation = stencilFailOperation;
573 }
574
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400575 void PixelProcessor::setStencilPassOperation(StencilOperation stencilPassOperation)
John Bauman89401822014-05-06 15:04:28 -0400576 {
577 context->stencilPassOperation = stencilPassOperation;
578 }
579
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400580 void PixelProcessor::setStencilZFailOperation(StencilOperation stencilZFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400581 {
582 context->stencilZFailOperation = stencilZFailOperation;
583 }
584
585 void PixelProcessor::setStencilWriteMask(int stencilWriteMask)
586 {
587 context->stencilWriteMask = stencilWriteMask;
588 stencil.set(context->stencilReference, context->stencilMask, stencilWriteMask);
589 }
590
591 void PixelProcessor::setStencilWriteMaskCCW(int stencilWriteMaskCCW)
592 {
593 context->stencilWriteMaskCCW = stencilWriteMaskCCW;
594 stencilCCW.set(context->stencilReferenceCCW, context->stencilMaskCCW, stencilWriteMaskCCW);
595 }
596
597 void PixelProcessor::setTwoSidedStencil(bool enable)
598 {
599 context->twoSidedStencil = enable;
600 }
601
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400602 void PixelProcessor::setStencilCompareCCW(StencilCompareMode stencilCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400603 {
604 context->stencilCompareModeCCW = stencilCompareMode;
605 }
606
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400607 void PixelProcessor::setStencilFailOperationCCW(StencilOperation stencilFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400608 {
609 context->stencilFailOperationCCW = stencilFailOperation;
610 }
611
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400612 void PixelProcessor::setStencilPassOperationCCW(StencilOperation stencilPassOperation)
John Bauman89401822014-05-06 15:04:28 -0400613 {
614 context->stencilPassOperationCCW = stencilPassOperation;
615 }
616
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400617 void PixelProcessor::setStencilZFailOperationCCW(StencilOperation stencilZFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400618 {
619 context->stencilZFailOperationCCW = stencilZFailOperation;
620 }
621
622 void PixelProcessor::setTextureFactor(const Color<float> &textureFactor)
623 {
624 // FIXME: Compact into generic function // FIXME: Clamp
625 short textureFactorR = iround(4095 * textureFactor.r);
626 short textureFactorG = iround(4095 * textureFactor.g);
627 short textureFactorB = iround(4095 * textureFactor.b);
628 short textureFactorA = iround(4095 * textureFactor.a);
629
630 factor.textureFactor4[0][0] = textureFactorR;
631 factor.textureFactor4[0][1] = textureFactorR;
632 factor.textureFactor4[0][2] = textureFactorR;
633 factor.textureFactor4[0][3] = textureFactorR;
634
635 factor.textureFactor4[1][0] = textureFactorG;
636 factor.textureFactor4[1][1] = textureFactorG;
637 factor.textureFactor4[1][2] = textureFactorG;
638 factor.textureFactor4[1][3] = textureFactorG;
639
640 factor.textureFactor4[2][0] = textureFactorB;
641 factor.textureFactor4[2][1] = textureFactorB;
642 factor.textureFactor4[2][2] = textureFactorB;
643 factor.textureFactor4[2][3] = textureFactorB;
644
645 factor.textureFactor4[3][0] = textureFactorA;
646 factor.textureFactor4[3][1] = textureFactorA;
647 factor.textureFactor4[3][2] = textureFactorA;
648 factor.textureFactor4[3][3] = textureFactorA;
649 }
650
651 void PixelProcessor::setBlendConstant(const Color<float> &blendConstant)
652 {
653 // FIXME: Compact into generic function // FIXME: Clamp
654 short blendConstantR = iround(65535 * blendConstant.r);
655 short blendConstantG = iround(65535 * blendConstant.g);
656 short blendConstantB = iround(65535 * blendConstant.b);
657 short blendConstantA = iround(65535 * blendConstant.a);
658
659 factor.blendConstant4W[0][0] = blendConstantR;
660 factor.blendConstant4W[0][1] = blendConstantR;
661 factor.blendConstant4W[0][2] = blendConstantR;
662 factor.blendConstant4W[0][3] = blendConstantR;
663
664 factor.blendConstant4W[1][0] = blendConstantG;
665 factor.blendConstant4W[1][1] = blendConstantG;
666 factor.blendConstant4W[1][2] = blendConstantG;
667 factor.blendConstant4W[1][3] = blendConstantG;
668
669 factor.blendConstant4W[2][0] = blendConstantB;
670 factor.blendConstant4W[2][1] = blendConstantB;
671 factor.blendConstant4W[2][2] = blendConstantB;
672 factor.blendConstant4W[2][3] = blendConstantB;
673
674 factor.blendConstant4W[3][0] = blendConstantA;
675 factor.blendConstant4W[3][1] = blendConstantA;
676 factor.blendConstant4W[3][2] = blendConstantA;
677 factor.blendConstant4W[3][3] = blendConstantA;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500678
John Bauman89401822014-05-06 15:04:28 -0400679 // FIXME: Compact into generic function // FIXME: Clamp
680 short invBlendConstantR = iround(65535 * (1 - blendConstant.r));
681 short invBlendConstantG = iround(65535 * (1 - blendConstant.g));
682 short invBlendConstantB = iround(65535 * (1 - blendConstant.b));
683 short invBlendConstantA = iround(65535 * (1 - blendConstant.a));
684
685 factor.invBlendConstant4W[0][0] = invBlendConstantR;
686 factor.invBlendConstant4W[0][1] = invBlendConstantR;
687 factor.invBlendConstant4W[0][2] = invBlendConstantR;
688 factor.invBlendConstant4W[0][3] = invBlendConstantR;
689
690 factor.invBlendConstant4W[1][0] = invBlendConstantG;
691 factor.invBlendConstant4W[1][1] = invBlendConstantG;
692 factor.invBlendConstant4W[1][2] = invBlendConstantG;
693 factor.invBlendConstant4W[1][3] = invBlendConstantG;
694
695 factor.invBlendConstant4W[2][0] = invBlendConstantB;
696 factor.invBlendConstant4W[2][1] = invBlendConstantB;
697 factor.invBlendConstant4W[2][2] = invBlendConstantB;
698 factor.invBlendConstant4W[2][3] = invBlendConstantB;
699
700 factor.invBlendConstant4W[3][0] = invBlendConstantA;
701 factor.invBlendConstant4W[3][1] = invBlendConstantA;
702 factor.invBlendConstant4W[3][2] = invBlendConstantA;
703 factor.invBlendConstant4W[3][3] = invBlendConstantA;
704
705 factor.blendConstant4F[0][0] = blendConstant.r;
706 factor.blendConstant4F[0][1] = blendConstant.r;
707 factor.blendConstant4F[0][2] = blendConstant.r;
708 factor.blendConstant4F[0][3] = blendConstant.r;
709
710 factor.blendConstant4F[1][0] = blendConstant.g;
711 factor.blendConstant4F[1][1] = blendConstant.g;
712 factor.blendConstant4F[1][2] = blendConstant.g;
713 factor.blendConstant4F[1][3] = blendConstant.g;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500714
John Bauman89401822014-05-06 15:04:28 -0400715 factor.blendConstant4F[2][0] = blendConstant.b;
716 factor.blendConstant4F[2][1] = blendConstant.b;
717 factor.blendConstant4F[2][2] = blendConstant.b;
718 factor.blendConstant4F[2][3] = blendConstant.b;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500719
John Bauman89401822014-05-06 15:04:28 -0400720 factor.blendConstant4F[3][0] = blendConstant.a;
721 factor.blendConstant4F[3][1] = blendConstant.a;
722 factor.blendConstant4F[3][2] = blendConstant.a;
723 factor.blendConstant4F[3][3] = blendConstant.a;
724
725 factor.invBlendConstant4F[0][0] = 1 - blendConstant.r;
726 factor.invBlendConstant4F[0][1] = 1 - blendConstant.r;
727 factor.invBlendConstant4F[0][2] = 1 - blendConstant.r;
728 factor.invBlendConstant4F[0][3] = 1 - blendConstant.r;
729
730 factor.invBlendConstant4F[1][0] = 1 - blendConstant.g;
731 factor.invBlendConstant4F[1][1] = 1 - blendConstant.g;
732 factor.invBlendConstant4F[1][2] = 1 - blendConstant.g;
733 factor.invBlendConstant4F[1][3] = 1 - blendConstant.g;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500734
John Bauman89401822014-05-06 15:04:28 -0400735 factor.invBlendConstant4F[2][0] = 1 - blendConstant.b;
736 factor.invBlendConstant4F[2][1] = 1 - blendConstant.b;
737 factor.invBlendConstant4F[2][2] = 1 - blendConstant.b;
738 factor.invBlendConstant4F[2][3] = 1 - blendConstant.b;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500739
John Bauman89401822014-05-06 15:04:28 -0400740 factor.invBlendConstant4F[3][0] = 1 - blendConstant.a;
741 factor.invBlendConstant4F[3][1] = 1 - blendConstant.a;
742 factor.invBlendConstant4F[3][2] = 1 - blendConstant.a;
743 factor.invBlendConstant4F[3][3] = 1 - blendConstant.a;
744 }
745
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400746 void PixelProcessor::setFillMode(FillMode fillMode)
John Bauman89401822014-05-06 15:04:28 -0400747 {
748 context->fillMode = fillMode;
749 }
750
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400751 void PixelProcessor::setShadingMode(ShadingMode shadingMode)
John Bauman89401822014-05-06 15:04:28 -0400752 {
753 context->shadingMode = shadingMode;
754 }
755
756 void PixelProcessor::setAlphaBlendEnable(bool alphaBlendEnable)
757 {
758 context->setAlphaBlendEnable(alphaBlendEnable);
759 }
760
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400761 void PixelProcessor::setSourceBlendFactor(BlendFactor sourceBlendFactor)
John Bauman89401822014-05-06 15:04:28 -0400762 {
763 context->setSourceBlendFactor(sourceBlendFactor);
764 }
765
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400766 void PixelProcessor::setDestBlendFactor(BlendFactor destBlendFactor)
John Bauman89401822014-05-06 15:04:28 -0400767 {
768 context->setDestBlendFactor(destBlendFactor);
769 }
770
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400771 void PixelProcessor::setBlendOperation(BlendOperation blendOperation)
John Bauman89401822014-05-06 15:04:28 -0400772 {
773 context->setBlendOperation(blendOperation);
774 }
775
776 void PixelProcessor::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)
777 {
778 context->setSeparateAlphaBlendEnable(separateAlphaBlendEnable);
779 }
780
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400781 void PixelProcessor::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)
John Bauman89401822014-05-06 15:04:28 -0400782 {
783 context->setSourceBlendFactorAlpha(sourceBlendFactorAlpha);
784 }
785
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400786 void PixelProcessor::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)
John Bauman89401822014-05-06 15:04:28 -0400787 {
788 context->setDestBlendFactorAlpha(destBlendFactorAlpha);
789 }
790
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400791 void PixelProcessor::setBlendOperationAlpha(BlendOperation blendOperationAlpha)
John Bauman89401822014-05-06 15:04:28 -0400792 {
793 context->setBlendOperationAlpha(blendOperationAlpha);
794 }
795
Alexis Hetua818c452015-06-11 13:06:58 -0400796 void PixelProcessor::setAlphaReference(float alphaReference)
John Bauman89401822014-05-06 15:04:28 -0400797 {
798 context->alphaReference = alphaReference;
799
Alexis Hetua818c452015-06-11 13:06:58 -0400800 factor.alphaReference4[0] = (word)iround(alphaReference * 0x1000 / 0xFF);
801 factor.alphaReference4[1] = (word)iround(alphaReference * 0x1000 / 0xFF);
802 factor.alphaReference4[2] = (word)iround(alphaReference * 0x1000 / 0xFF);
803 factor.alphaReference4[3] = (word)iround(alphaReference * 0x1000 / 0xFF);
John Bauman89401822014-05-06 15:04:28 -0400804 }
805
806 void PixelProcessor::setGlobalMipmapBias(float bias)
807 {
808 context->setGlobalMipmapBias(bias);
809 }
810
811 void PixelProcessor::setFogStart(float start)
812 {
813 setFogRanges(start, context->fogEnd);
814 }
815
816 void PixelProcessor::setFogEnd(float end)
817 {
818 setFogRanges(context->fogStart, end);
819 }
820
821 void PixelProcessor::setFogColor(Color<float> fogColor)
822 {
823 // TODO: Compact into generic function
824 word fogR = (unsigned short)(65535 * fogColor.r);
825 word fogG = (unsigned short)(65535 * fogColor.g);
826 word fogB = (unsigned short)(65535 * fogColor.b);
827
828 fog.color4[0][0] = fogR;
829 fog.color4[0][1] = fogR;
830 fog.color4[0][2] = fogR;
831 fog.color4[0][3] = fogR;
832
833 fog.color4[1][0] = fogG;
834 fog.color4[1][1] = fogG;
835 fog.color4[1][2] = fogG;
836 fog.color4[1][3] = fogG;
837
838 fog.color4[2][0] = fogB;
839 fog.color4[2][1] = fogB;
840 fog.color4[2][2] = fogB;
841 fog.color4[2][3] = fogB;
842
843 fog.colorF[0] = replicate(fogColor.r);
844 fog.colorF[1] = replicate(fogColor.g);
845 fog.colorF[2] = replicate(fogColor.b);
846 }
847
848 void PixelProcessor::setFogDensity(float fogDensity)
849 {
850 fog.densityE = replicate(-fogDensity * 1.442695f); // 1/e^x = 2^(-x*1.44)
Nicolas Capensa36f3f92015-08-04 15:34:26 -0400851 fog.density2E = replicate(-fogDensity * fogDensity * 1.442695f);
John Bauman89401822014-05-06 15:04:28 -0400852 }
853
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400854 void PixelProcessor::setPixelFogMode(FogMode fogMode)
John Bauman89401822014-05-06 15:04:28 -0400855 {
856 context->pixelFogMode = fogMode;
857 }
858
859 void PixelProcessor::setPerspectiveCorrection(bool perspectiveEnable)
860 {
861 perspectiveCorrection = perspectiveEnable;
862 }
863
864 void PixelProcessor::setOcclusionEnabled(bool enable)
865 {
866 context->occlusionEnabled = enable;
867 }
868
869 void PixelProcessor::setRoutineCacheSize(int cacheSize)
870 {
871 delete routineCache;
John Bauman66b8ab22014-05-06 15:57:45 -0400872 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precachePixel ? "sw-pixel" : 0);
John Bauman89401822014-05-06 15:04:28 -0400873 }
874
875 void PixelProcessor::setFogRanges(float start, float end)
876 {
877 context->fogStart = start;
878 context->fogEnd = end;
879
880 if(start == end)
881 {
882 end += 0.001f; // Hack: ensure there is a small range
883 }
884
885 float fogScale = -1.0f / (end - start);
886 float fogOffset = end * -fogScale;
887
888 fog.scale = replicate(fogScale);
889 fog.offset = replicate(fogOffset);
890 }
891
892 const PixelProcessor::State PixelProcessor::update() const
893 {
894 State state;
895
896 if(context->pixelShader)
897 {
John Bauman19bac1e2014-05-06 15:23:49 -0400898 state.shaderID = context->pixelShader->getSerialID();
John Bauman89401822014-05-06 15:04:28 -0400899 }
900 else
901 {
John Bauman19bac1e2014-05-06 15:23:49 -0400902 state.shaderID = 0;
John Bauman89401822014-05-06 15:04:28 -0400903 }
904
905 state.depthOverride = context->pixelShader && context->pixelShader->depthOverride();
John Bauman19bac1e2014-05-06 15:23:49 -0400906 state.shaderContainsKill = context->pixelShader ? context->pixelShader->containsKill() : false;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500907
John Bauman89401822014-05-06 15:04:28 -0400908 if(context->alphaTestActive())
909 {
910 state.alphaCompareMode = context->alphaCompareMode;
911
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400912 state.transparencyAntialiasing = context->getMultiSampleCount() > 1 ? transparencyAntialiasing : TRANSPARENCY_NONE;
John Bauman89401822014-05-06 15:04:28 -0400913 }
914
915 state.depthWriteEnable = context->depthWriteActive();
916
917 if(context->stencilActive())
918 {
919 state.stencilActive = true;
920 state.stencilCompareMode = context->stencilCompareMode;
921 state.stencilFailOperation = context->stencilFailOperation;
922 state.stencilPassOperation = context->stencilPassOperation;
923 state.stencilZFailOperation = context->stencilZFailOperation;
924 state.noStencilMask = (context->stencilMask == 0xFF);
925 state.noStencilWriteMask = (context->stencilWriteMask == 0xFF);
926 state.stencilWriteMasked = (context->stencilWriteMask == 0x00);
927
928 state.twoSidedStencil = context->twoSidedStencil;
929 state.stencilCompareModeCCW = context->twoSidedStencil ? context->stencilCompareModeCCW : state.stencilCompareMode;
930 state.stencilFailOperationCCW = context->twoSidedStencil ? context->stencilFailOperationCCW : state.stencilFailOperation;
931 state.stencilPassOperationCCW = context->twoSidedStencil ? context->stencilPassOperationCCW : state.stencilPassOperation;
932 state.stencilZFailOperationCCW = context->twoSidedStencil ? context->stencilZFailOperationCCW : state.stencilZFailOperation;
933 state.noStencilMaskCCW = context->twoSidedStencil ? (context->stencilMaskCCW == 0xFF) : state.noStencilMask;
934 state.noStencilWriteMaskCCW = context->twoSidedStencil ? (context->stencilWriteMaskCCW == 0xFF) : state.noStencilWriteMask;
935 state.stencilWriteMaskedCCW = context->twoSidedStencil ? (context->stencilWriteMaskCCW == 0x00) : state.stencilWriteMasked;
936 }
937
938 if(context->depthBufferActive())
939 {
940 state.depthTestActive = true;
941 state.depthCompareMode = context->depthCompareMode;
942 state.quadLayoutDepthBuffer = context->depthStencil->getInternalFormat() != FORMAT_D32F_LOCKABLE &&
John Bauman66b8ab22014-05-06 15:57:45 -0400943 context->depthStencil->getInternalFormat() != FORMAT_D32FS8_TEXTURE &&
944 context->depthStencil->getInternalFormat() != FORMAT_D32FS8_SHADOW;
John Bauman89401822014-05-06 15:04:28 -0400945 }
946
947 state.occlusionEnabled = context->occlusionEnabled;
948
949 state.fogActive = context->fogActive();
950 state.pixelFogMode = context->pixelFogActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400951 state.wBasedFog = context->wBasedFog && context->pixelFogActive() != FOG_NONE;
John Bauman89401822014-05-06 15:04:28 -0400952 state.perspective = context->perspectiveActive();
953
954 if(context->alphaBlendActive())
955 {
956 state.alphaBlendActive = true;
957 state.sourceBlendFactor = context->sourceBlendFactor();
958 state.destBlendFactor = context->destBlendFactor();
959 state.blendOperation = context->blendOperation();
960 state.sourceBlendFactorAlpha = context->sourceBlendFactorAlpha();
961 state.destBlendFactorAlpha = context->destBlendFactorAlpha();
962 state.blendOperationAlpha = context->blendOperationAlpha();
963 }
Maxime Grégoired9762742015-07-08 16:43:48 -0400964
965 state.logicalOperation = context->colorLogicOp();
966
John Bauman89401822014-05-06 15:04:28 -0400967 state.colorWriteMask = (context->colorWriteActive(0) << 0) |
968 (context->colorWriteActive(1) << 4) |
969 (context->colorWriteActive(2) << 8) |
970 (context->colorWriteActive(3) << 12);
971
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500972 for(int i = 0; i < RENDERTARGETS; i++)
John Bauman89401822014-05-06 15:04:28 -0400973 {
974 state.targetFormat[i] = context->renderTargetInternalFormat(i);
975 }
976
John Bauman66b8ab22014-05-06 15:57:45 -0400977 state.writeSRGB = context->writeSRGB && context->renderTarget[0] && Surface::isSRGBwritable(context->renderTarget[0]->getExternalFormat());
978 state.multiSample = context->getMultiSampleCount();
John Bauman89401822014-05-06 15:04:28 -0400979 state.multiSampleMask = context->multiSampleMask;
980
981 if(state.multiSample > 1 && context->pixelShader)
982 {
983 state.centroid = context->pixelShader->containsCentroid();
984 }
985
986 if(!context->pixelShader)
987 {
988 for(unsigned int i = 0; i < 8; i++)
989 {
990 state.textureStage[i] = context->textureStage[i].textureStageState();
991 }
992
993 state.specularAdd = context->specularActive() && context->specularEnable;
994 }
995
996 for(unsigned int i = 0; i < 16; i++)
997 {
998 if(context->pixelShader)
999 {
1000 if(context->pixelShader->usesSampler(i))
1001 {
1002 state.sampler[i] = context->sampler[i].samplerState();
1003 }
1004 }
1005 else
1006 {
1007 if(i < 8 && state.textureStage[i].stageOperation != TextureStage::STAGE_DISABLE)
1008 {
1009 state.sampler[i] = context->sampler[i].samplerState();
1010 }
1011 else break;
1012 }
1013 }
1014
1015 const bool point = context->isDrawPoint(true);
1016 const bool sprite = context->pointSpriteActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001017 const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
John Bauman89401822014-05-06 15:04:28 -04001018
1019 if(context->pixelShaderVersion() < 0x0300)
1020 {
1021 for(int coordinate = 0; coordinate < 8; coordinate++)
1022 {
1023 for(int component = 0; component < 4; component++)
1024 {
1025 if(context->textureActive(coordinate, component))
1026 {
1027 state.texture[coordinate].component |= 1 << component;
1028
1029 if(point && !sprite)
1030 {
1031 state.texture[coordinate].flat |= 1 << component;
1032 }
1033 }
1034 }
1035
1036 if(context->textureTransformProject[coordinate] && context->pixelShaderVersion() <= 0x0103)
1037 {
1038 if(context->textureTransformCount[coordinate] == 2)
1039 {
1040 state.texture[coordinate].project = 1;
1041 }
1042 else if(context->textureTransformCount[coordinate] == 3)
1043 {
1044 state.texture[coordinate].project = 2;
1045 }
1046 else if(context->textureTransformCount[coordinate] == 4 || context->textureTransformCount[coordinate] == 0)
1047 {
1048 state.texture[coordinate].project = 3;
1049 }
1050 }
1051 }
1052
1053 for(int color = 0; color < 2; color++)
1054 {
1055 for(int component = 0; component < 4; component++)
1056 {
1057 if(context->colorActive(color, component))
1058 {
1059 state.color[color].component |= 1 << component;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001060
John Bauman89401822014-05-06 15:04:28 -04001061 if(point || flatShading)
1062 {
1063 state.color[color].flat |= 1 << component;
1064 }
1065 }
1066 }
1067 }
1068
1069 if(context->fogActive())
1070 {
1071 state.fog.component = true;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001072
John Bauman89401822014-05-06 15:04:28 -04001073 if(point)
1074 {
1075 state.fog.flat = true;
1076 }
1077 }
1078 }
1079 else
1080 {
1081 for(int interpolant = 0; interpolant < 10; interpolant++)
1082 {
1083 for(int component = 0; component < 4; component++)
1084 {
1085 if(context->pixelShader->semantic[interpolant][component].active())
1086 {
1087 bool flat = point;
1088
1089 switch(context->pixelShader->semantic[interpolant][component].usage)
1090 {
John Bauman19bac1e2014-05-06 15:23:49 -04001091 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
1092 case Shader::USAGE_COLOR: flat = flatShading; break;
John Bauman89401822014-05-06 15:04:28 -04001093 }
1094
1095 state.interpolant[interpolant].component |= 1 << component;
1096
1097 if(flat)
1098 {
1099 state.interpolant[interpolant].flat |= 1 << component;
1100 }
1101 }
1102 }
1103 }
1104 }
1105
1106 if(state.centroid)
1107 {
1108 for(int interpolant = 0; interpolant < 10; interpolant++)
1109 {
1110 for(int component = 0; component < 4; component++)
1111 {
1112 state.interpolant[interpolant].centroid = context->pixelShader->semantic[interpolant][0].centroid;
1113 }
1114 }
1115 }
1116
1117 state.hash = state.computeHash();
1118
1119 return state;
1120 }
1121
1122 Routine *PixelProcessor::routine(const State &state)
1123 {
1124 Routine *routine = routineCache->query(state);
1125
1126 if(!routine)
1127 {
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001128 const bool integerPipeline = (context->pixelShaderVersion() <= 0x0104);
Nicolas Capensba53fbf2016-01-14 13:43:42 -05001129 QuadRasterizer *generator = nullptr;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001130
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001131 if(integerPipeline)
1132 {
1133 generator = new PixelPipeline(state, context->pixelShader);
1134 }
1135 else
1136 {
1137 generator = new PixelProgram(state, context->pixelShader);
1138 }
Nicolas Capens4f172c72016-01-13 08:34:30 -05001139
John Bauman89401822014-05-06 15:04:28 -04001140 generator->generate();
Nicolas Capens4f172c72016-01-13 08:34:30 -05001141 routine = (*generator)(L"PixelRoutine_%0.8X", state.shaderID);
John Bauman89401822014-05-06 15:04:28 -04001142 delete generator;
1143
1144 routineCache->add(state, routine);
1145 }
1146
1147 return routine;
1148 }
1149}