blob: 02d4c566c837353bd691f83eba3079431dfdd212 [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
Alexis Hetuc6a57cb2016-04-07 10:48:31 -040061 PixelProcessor::UniformBufferInfo::UniformBufferInfo()
62 {
63 buffer = nullptr;
64 offset = 0;
65 }
66
John Bauman89401822014-05-06 15:04:28 -040067 PixelProcessor::PixelProcessor(Context *context) : context(context)
68 {
69 setGlobalMipmapBias(0.0f); // Round to highest LOD [0.5, 1.0]: -0.5
70 // Round to nearest LOD [0.7, 1.4]: 0.0
71 // Round to lowest LOD [1.0, 2.0]: 0.5
72
73 routineCache = 0;
74 setRoutineCacheSize(1024);
75 }
76
77 PixelProcessor::~PixelProcessor()
78 {
79 delete routineCache;
80 routineCache = 0;
81 }
82
83 void PixelProcessor::setFloatConstant(unsigned int index, const float value[4])
84 {
Alexis Hetu04c967a2015-07-08 15:56:17 -040085 if(index < FRAGMENT_UNIFORM_VECTORS)
John Bauman89401822014-05-06 15:04:28 -040086 {
87 c[index][0] = value[0];
88 c[index][1] = value[1];
89 c[index][2] = value[2];
90 c[index][3] = value[3];
91 }
92 else ASSERT(false);
93
94 if(index < 8) // ps_1_x constants
95 {
96 // FIXME: Compact into generic function
97 short x = iround(4095 * clamp(value[0], -1.0f, 1.0f));
98 short y = iround(4095 * clamp(value[1], -1.0f, 1.0f));
99 short z = iround(4095 * clamp(value[2], -1.0f, 1.0f));
100 short w = iround(4095 * clamp(value[3], -1.0f, 1.0f));
101
102 cW[index][0][0] = x;
103 cW[index][0][1] = x;
104 cW[index][0][2] = x;
105 cW[index][0][3] = x;
106
107 cW[index][1][0] = y;
108 cW[index][1][1] = y;
109 cW[index][1][2] = y;
110 cW[index][1][3] = y;
111
112 cW[index][2][0] = z;
113 cW[index][2][1] = z;
114 cW[index][2][2] = z;
115 cW[index][2][3] = z;
116
117 cW[index][3][0] = w;
118 cW[index][3][1] = w;
119 cW[index][3][2] = w;
120 cW[index][3][3] = w;
121 }
122 }
123
124 void PixelProcessor::setIntegerConstant(unsigned int index, const int value[4])
125 {
126 if(index < 16)
127 {
128 i[index][0] = value[0];
129 i[index][1] = value[1];
130 i[index][2] = value[2];
131 i[index][3] = value[3];
132 }
133 else ASSERT(false);
134 }
135
136 void PixelProcessor::setBooleanConstant(unsigned int index, int boolean)
137 {
138 if(index < 16)
139 {
140 b[index] = boolean != 0;
141 }
142 else ASSERT(false);
143 }
144
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400145 void PixelProcessor::setUniformBuffer(int index, sw::Resource* buffer, int offset)
146 {
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400147 uniformBufferInfo[index].buffer = buffer;
148 uniformBufferInfo[index].offset = offset;
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400149 }
150
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400151 void PixelProcessor::lockUniformBuffers(byte** u, sw::Resource* uniformBuffers[])
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400152 {
153 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i)
154 {
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400155 u[i] = uniformBufferInfo[i].buffer ? static_cast<byte*>(uniformBufferInfo[i].buffer->lock(PUBLIC, PRIVATE)) + uniformBufferInfo[i].offset : nullptr;
156 uniformBuffers[i] = uniformBufferInfo[i].buffer;
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400157 }
158 }
159
John Bauman89401822014-05-06 15:04:28 -0400160 void PixelProcessor::setRenderTarget(int index, Surface *renderTarget)
161 {
162 context->renderTarget[index] = renderTarget;
163 }
164
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400165 void PixelProcessor::setDepthBuffer(Surface *depthBuffer)
John Bauman89401822014-05-06 15:04:28 -0400166 {
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400167 context->depthBuffer = depthBuffer;
168 }
169
170 void PixelProcessor::setStencilBuffer(Surface *stencilBuffer)
171 {
172 context->stencilBuffer = stencilBuffer;
John Bauman89401822014-05-06 15:04:28 -0400173 }
174
175 void PixelProcessor::setTexCoordIndex(unsigned int stage, int texCoordIndex)
176 {
177 if(stage < 8)
178 {
179 context->textureStage[stage].setTexCoordIndex(texCoordIndex);
180 }
181 else ASSERT(false);
182 }
183
184 void PixelProcessor::setStageOperation(unsigned int stage, TextureStage::StageOperation stageOperation)
185 {
186 if(stage < 8)
187 {
188 context->textureStage[stage].setStageOperation(stageOperation);
189 }
190 else ASSERT(false);
191 }
192
193 void PixelProcessor::setFirstArgument(unsigned int stage, TextureStage::SourceArgument firstArgument)
194 {
195 if(stage < 8)
196 {
197 context->textureStage[stage].setFirstArgument(firstArgument);
198 }
199 else ASSERT(false);
200 }
201
202 void PixelProcessor::setSecondArgument(unsigned int stage, TextureStage::SourceArgument secondArgument)
203 {
204 if(stage < 8)
205 {
206 context->textureStage[stage].setSecondArgument(secondArgument);
207 }
208 else ASSERT(false);
209 }
210
211 void PixelProcessor::setThirdArgument(unsigned int stage, TextureStage::SourceArgument thirdArgument)
212 {
213 if(stage < 8)
214 {
215 context->textureStage[stage].setThirdArgument(thirdArgument);
216 }
217 else ASSERT(false);
218 }
219
220 void PixelProcessor::setStageOperationAlpha(unsigned int stage, TextureStage::StageOperation stageOperationAlpha)
221 {
222 if(stage < 8)
223 {
224 context->textureStage[stage].setStageOperationAlpha(stageOperationAlpha);
225 }
226 else ASSERT(false);
227 }
228
229 void PixelProcessor::setFirstArgumentAlpha(unsigned int stage, TextureStage::SourceArgument firstArgumentAlpha)
230 {
231 if(stage < 8)
232 {
233 context->textureStage[stage].setFirstArgumentAlpha(firstArgumentAlpha);
234 }
235 else ASSERT(false);
236 }
237
238 void PixelProcessor::setSecondArgumentAlpha(unsigned int stage, TextureStage::SourceArgument secondArgumentAlpha)
239 {
240 if(stage < 8)
241 {
242 context->textureStage[stage].setSecondArgumentAlpha(secondArgumentAlpha);
243 }
244 else ASSERT(false);
245 }
246
247 void PixelProcessor::setThirdArgumentAlpha(unsigned int stage, TextureStage::SourceArgument thirdArgumentAlpha)
248 {
249 if(stage < 8)
250 {
251 context->textureStage[stage].setThirdArgumentAlpha(thirdArgumentAlpha);
252 }
253 else ASSERT(false);
254 }
255
256 void PixelProcessor::setFirstModifier(unsigned int stage, TextureStage::ArgumentModifier firstModifier)
257 {
258 if(stage < 8)
259 {
260 context->textureStage[stage].setFirstModifier(firstModifier);
261 }
262 else ASSERT(false);
263 }
264
265 void PixelProcessor::setSecondModifier(unsigned int stage, TextureStage::ArgumentModifier secondModifier)
266 {
267 if(stage < 8)
268 {
269 context->textureStage[stage].setSecondModifier(secondModifier);
270 }
271 else ASSERT(false);
272 }
273
274 void PixelProcessor::setThirdModifier(unsigned int stage, TextureStage::ArgumentModifier thirdModifier)
275 {
276 if(stage < 8)
277 {
278 context->textureStage[stage].setThirdModifier(thirdModifier);
279 }
280 else ASSERT(false);
281 }
282
283 void PixelProcessor::setFirstModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier firstModifierAlpha)
284 {
285 if(stage < 8)
286 {
287 context->textureStage[stage].setFirstModifierAlpha(firstModifierAlpha);
288 }
289 else ASSERT(false);
290 }
291
292 void PixelProcessor::setSecondModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier secondModifierAlpha)
293 {
294 if(stage < 8)
295 {
296 context->textureStage[stage].setSecondModifierAlpha(secondModifierAlpha);
297 }
298 else ASSERT(false);
299 }
300
301 void PixelProcessor::setThirdModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier thirdModifierAlpha)
302 {
303 if(stage < 8)
304 {
305 context->textureStage[stage].setThirdModifierAlpha(thirdModifierAlpha);
306 }
307 else ASSERT(false);
308 }
309
310 void PixelProcessor::setDestinationArgument(unsigned int stage, TextureStage::DestinationArgument destinationArgument)
311 {
312 if(stage < 8)
313 {
314 context->textureStage[stage].setDestinationArgument(destinationArgument);
315 }
316 else ASSERT(false);
317 }
318
319 void PixelProcessor::setConstantColor(unsigned int stage, const Color<float> &constantColor)
320 {
321 if(stage < 8)
322 {
323 context->textureStage[stage].setConstantColor(constantColor);
324 }
325 else ASSERT(false);
326 }
327
328 void PixelProcessor::setBumpmapMatrix(unsigned int stage, int element, float value)
329 {
330 if(stage < 8)
331 {
332 context->textureStage[stage].setBumpmapMatrix(element, value);
333 }
334 else ASSERT(false);
335 }
336
337 void PixelProcessor::setLuminanceScale(unsigned int stage, float value)
338 {
339 if(stage < 8)
340 {
341 context->textureStage[stage].setLuminanceScale(value);
342 }
343 else ASSERT(false);
344 }
345
346 void PixelProcessor::setLuminanceOffset(unsigned int stage, float value)
347 {
348 if(stage < 8)
349 {
350 context->textureStage[stage].setLuminanceOffset(value);
351 }
352 else ASSERT(false);
353 }
354
355 void PixelProcessor::setTextureFilter(unsigned int sampler, FilterType textureFilter)
356 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400357 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400358 {
359 context->sampler[sampler].setTextureFilter(textureFilter);
360 }
361 else ASSERT(false);
362 }
363
364 void PixelProcessor::setMipmapFilter(unsigned int sampler, MipmapType mipmapFilter)
365 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400366 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400367 {
368 context->sampler[sampler].setMipmapFilter(mipmapFilter);
369 }
370 else ASSERT(false);
371 }
372
373 void PixelProcessor::setGatherEnable(unsigned int sampler, bool enable)
374 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400375 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400376 {
377 context->sampler[sampler].setGatherEnable(enable);
378 }
379 else ASSERT(false);
380 }
381
382 void PixelProcessor::setAddressingModeU(unsigned int sampler, AddressingMode addressMode)
383 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400384 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400385 {
386 context->sampler[sampler].setAddressingModeU(addressMode);
387 }
388 else ASSERT(false);
389 }
390
391 void PixelProcessor::setAddressingModeV(unsigned int sampler, AddressingMode addressMode)
392 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400393 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400394 {
395 context->sampler[sampler].setAddressingModeV(addressMode);
396 }
397 else ASSERT(false);
398 }
399
400 void PixelProcessor::setAddressingModeW(unsigned int sampler, AddressingMode addressMode)
401 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400402 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400403 {
404 context->sampler[sampler].setAddressingModeW(addressMode);
405 }
406 else ASSERT(false);
407 }
408
409 void PixelProcessor::setReadSRGB(unsigned int sampler, bool sRGB)
410 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400411 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400412 {
413 context->sampler[sampler].setReadSRGB(sRGB);
414 }
415 else ASSERT(false);
416 }
417
418 void PixelProcessor::setMipmapLOD(unsigned int sampler, float bias)
419 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400420 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400421 {
422 context->sampler[sampler].setMipmapLOD(bias);
423 }
424 else ASSERT(false);
425 }
426
427 void PixelProcessor::setBorderColor(unsigned int sampler, const Color<float> &borderColor)
428 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400429 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400430 {
431 context->sampler[sampler].setBorderColor(borderColor);
432 }
433 else ASSERT(false);
434 }
435
Alexis Hetu617a5d52014-11-13 10:56:20 -0500436 void PixelProcessor::setMaxAnisotropy(unsigned int sampler, float maxAnisotropy)
John Bauman89401822014-05-06 15:04:28 -0400437 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400438 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400439 {
440 context->sampler[sampler].setMaxAnisotropy(maxAnisotropy);
441 }
442 else ASSERT(false);
443 }
444
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400445 void PixelProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR)
446 {
447 if(sampler < TEXTURE_IMAGE_UNITS)
448 {
449 context->sampler[sampler].setSwizzleR(swizzleR);
450 }
451 else ASSERT(false);
452 }
453
454 void PixelProcessor::setSwizzleG(unsigned int sampler, SwizzleType swizzleG)
455 {
456 if(sampler < TEXTURE_IMAGE_UNITS)
457 {
458 context->sampler[sampler].setSwizzleG(swizzleG);
459 }
460 else ASSERT(false);
461 }
462
463 void PixelProcessor::setSwizzleB(unsigned int sampler, SwizzleType swizzleB)
464 {
465 if(sampler < TEXTURE_IMAGE_UNITS)
466 {
467 context->sampler[sampler].setSwizzleB(swizzleB);
468 }
469 else ASSERT(false);
470 }
471
472 void PixelProcessor::setSwizzleA(unsigned int sampler, SwizzleType swizzleA)
473 {
474 if(sampler < TEXTURE_IMAGE_UNITS)
475 {
476 context->sampler[sampler].setSwizzleA(swizzleA);
477 }
478 else ASSERT(false);
479 }
480
John Bauman89401822014-05-06 15:04:28 -0400481 void PixelProcessor::setWriteSRGB(bool sRGB)
482 {
483 context->setWriteSRGB(sRGB);
484 }
485
Maxime Grégoired9762742015-07-08 16:43:48 -0400486 void PixelProcessor::setColorLogicOpEnabled(bool colorLogicOpEnabled)
487 {
488 context->setColorLogicOpEnabled(colorLogicOpEnabled);
489 }
490
491 void PixelProcessor::setLogicalOperation(LogicalOperation logicalOperation)
492 {
493 context->setLogicalOperation(logicalOperation);
494 }
495
John Bauman89401822014-05-06 15:04:28 -0400496 void PixelProcessor::setDepthBufferEnable(bool depthBufferEnable)
497 {
498 context->setDepthBufferEnable(depthBufferEnable);
499 }
500
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400501 void PixelProcessor::setDepthCompare(DepthCompareMode depthCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400502 {
503 context->depthCompareMode = depthCompareMode;
504 }
505
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400506 void PixelProcessor::setAlphaCompare(AlphaCompareMode alphaCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400507 {
508 context->alphaCompareMode = alphaCompareMode;
509 }
510
511 void PixelProcessor::setDepthWriteEnable(bool depthWriteEnable)
512 {
513 context->depthWriteEnable = depthWriteEnable;
514 }
515
516 void PixelProcessor::setAlphaTestEnable(bool alphaTestEnable)
517 {
518 context->alphaTestEnable = alphaTestEnable;
519 }
520
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400521 void PixelProcessor::setCullMode(CullMode cullMode)
John Bauman89401822014-05-06 15:04:28 -0400522 {
523 context->cullMode = cullMode;
524 }
525
526 void PixelProcessor::setColorWriteMask(int index, int rgbaMask)
527 {
528 context->setColorWriteMask(index, rgbaMask);
529 }
530
531 void PixelProcessor::setStencilEnable(bool stencilEnable)
532 {
533 context->stencilEnable = stencilEnable;
534 }
535
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400536 void PixelProcessor::setStencilCompare(StencilCompareMode stencilCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400537 {
538 context->stencilCompareMode = stencilCompareMode;
539 }
540
541 void PixelProcessor::setStencilReference(int stencilReference)
542 {
543 context->stencilReference = stencilReference;
544 stencil.set(stencilReference, context->stencilMask, context->stencilWriteMask);
545 }
546
547 void PixelProcessor::setStencilReferenceCCW(int stencilReferenceCCW)
548 {
549 context->stencilReferenceCCW = stencilReferenceCCW;
550 stencilCCW.set(stencilReferenceCCW, context->stencilMaskCCW, context->stencilWriteMaskCCW);
551 }
552
553 void PixelProcessor::setStencilMask(int stencilMask)
554 {
555 context->stencilMask = stencilMask;
556 stencil.set(context->stencilReference, stencilMask, context->stencilWriteMask);
557 }
558
559 void PixelProcessor::setStencilMaskCCW(int stencilMaskCCW)
560 {
561 context->stencilMaskCCW = stencilMaskCCW;
562 stencilCCW.set(context->stencilReferenceCCW, stencilMaskCCW, context->stencilWriteMaskCCW);
563 }
564
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400565 void PixelProcessor::setStencilFailOperation(StencilOperation stencilFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400566 {
567 context->stencilFailOperation = stencilFailOperation;
568 }
569
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400570 void PixelProcessor::setStencilPassOperation(StencilOperation stencilPassOperation)
John Bauman89401822014-05-06 15:04:28 -0400571 {
572 context->stencilPassOperation = stencilPassOperation;
573 }
574
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400575 void PixelProcessor::setStencilZFailOperation(StencilOperation stencilZFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400576 {
577 context->stencilZFailOperation = stencilZFailOperation;
578 }
579
580 void PixelProcessor::setStencilWriteMask(int stencilWriteMask)
581 {
582 context->stencilWriteMask = stencilWriteMask;
583 stencil.set(context->stencilReference, context->stencilMask, stencilWriteMask);
584 }
585
586 void PixelProcessor::setStencilWriteMaskCCW(int stencilWriteMaskCCW)
587 {
588 context->stencilWriteMaskCCW = stencilWriteMaskCCW;
589 stencilCCW.set(context->stencilReferenceCCW, context->stencilMaskCCW, stencilWriteMaskCCW);
590 }
591
592 void PixelProcessor::setTwoSidedStencil(bool enable)
593 {
594 context->twoSidedStencil = enable;
595 }
596
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400597 void PixelProcessor::setStencilCompareCCW(StencilCompareMode stencilCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400598 {
599 context->stencilCompareModeCCW = stencilCompareMode;
600 }
601
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400602 void PixelProcessor::setStencilFailOperationCCW(StencilOperation stencilFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400603 {
604 context->stencilFailOperationCCW = stencilFailOperation;
605 }
606
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400607 void PixelProcessor::setStencilPassOperationCCW(StencilOperation stencilPassOperation)
John Bauman89401822014-05-06 15:04:28 -0400608 {
609 context->stencilPassOperationCCW = stencilPassOperation;
610 }
611
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400612 void PixelProcessor::setStencilZFailOperationCCW(StencilOperation stencilZFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400613 {
614 context->stencilZFailOperationCCW = stencilZFailOperation;
615 }
616
617 void PixelProcessor::setTextureFactor(const Color<float> &textureFactor)
618 {
619 // FIXME: Compact into generic function // FIXME: Clamp
620 short textureFactorR = iround(4095 * textureFactor.r);
621 short textureFactorG = iround(4095 * textureFactor.g);
622 short textureFactorB = iround(4095 * textureFactor.b);
623 short textureFactorA = iround(4095 * textureFactor.a);
624
625 factor.textureFactor4[0][0] = textureFactorR;
626 factor.textureFactor4[0][1] = textureFactorR;
627 factor.textureFactor4[0][2] = textureFactorR;
628 factor.textureFactor4[0][3] = textureFactorR;
629
630 factor.textureFactor4[1][0] = textureFactorG;
631 factor.textureFactor4[1][1] = textureFactorG;
632 factor.textureFactor4[1][2] = textureFactorG;
633 factor.textureFactor4[1][3] = textureFactorG;
634
635 factor.textureFactor4[2][0] = textureFactorB;
636 factor.textureFactor4[2][1] = textureFactorB;
637 factor.textureFactor4[2][2] = textureFactorB;
638 factor.textureFactor4[2][3] = textureFactorB;
639
640 factor.textureFactor4[3][0] = textureFactorA;
641 factor.textureFactor4[3][1] = textureFactorA;
642 factor.textureFactor4[3][2] = textureFactorA;
643 factor.textureFactor4[3][3] = textureFactorA;
644 }
645
646 void PixelProcessor::setBlendConstant(const Color<float> &blendConstant)
647 {
648 // FIXME: Compact into generic function // FIXME: Clamp
649 short blendConstantR = iround(65535 * blendConstant.r);
650 short blendConstantG = iround(65535 * blendConstant.g);
651 short blendConstantB = iround(65535 * blendConstant.b);
652 short blendConstantA = iround(65535 * blendConstant.a);
653
654 factor.blendConstant4W[0][0] = blendConstantR;
655 factor.blendConstant4W[0][1] = blendConstantR;
656 factor.blendConstant4W[0][2] = blendConstantR;
657 factor.blendConstant4W[0][3] = blendConstantR;
658
659 factor.blendConstant4W[1][0] = blendConstantG;
660 factor.blendConstant4W[1][1] = blendConstantG;
661 factor.blendConstant4W[1][2] = blendConstantG;
662 factor.blendConstant4W[1][3] = blendConstantG;
663
664 factor.blendConstant4W[2][0] = blendConstantB;
665 factor.blendConstant4W[2][1] = blendConstantB;
666 factor.blendConstant4W[2][2] = blendConstantB;
667 factor.blendConstant4W[2][3] = blendConstantB;
668
669 factor.blendConstant4W[3][0] = blendConstantA;
670 factor.blendConstant4W[3][1] = blendConstantA;
671 factor.blendConstant4W[3][2] = blendConstantA;
672 factor.blendConstant4W[3][3] = blendConstantA;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500673
John Bauman89401822014-05-06 15:04:28 -0400674 // FIXME: Compact into generic function // FIXME: Clamp
675 short invBlendConstantR = iround(65535 * (1 - blendConstant.r));
676 short invBlendConstantG = iround(65535 * (1 - blendConstant.g));
677 short invBlendConstantB = iround(65535 * (1 - blendConstant.b));
678 short invBlendConstantA = iround(65535 * (1 - blendConstant.a));
679
680 factor.invBlendConstant4W[0][0] = invBlendConstantR;
681 factor.invBlendConstant4W[0][1] = invBlendConstantR;
682 factor.invBlendConstant4W[0][2] = invBlendConstantR;
683 factor.invBlendConstant4W[0][3] = invBlendConstantR;
684
685 factor.invBlendConstant4W[1][0] = invBlendConstantG;
686 factor.invBlendConstant4W[1][1] = invBlendConstantG;
687 factor.invBlendConstant4W[1][2] = invBlendConstantG;
688 factor.invBlendConstant4W[1][3] = invBlendConstantG;
689
690 factor.invBlendConstant4W[2][0] = invBlendConstantB;
691 factor.invBlendConstant4W[2][1] = invBlendConstantB;
692 factor.invBlendConstant4W[2][2] = invBlendConstantB;
693 factor.invBlendConstant4W[2][3] = invBlendConstantB;
694
695 factor.invBlendConstant4W[3][0] = invBlendConstantA;
696 factor.invBlendConstant4W[3][1] = invBlendConstantA;
697 factor.invBlendConstant4W[3][2] = invBlendConstantA;
698 factor.invBlendConstant4W[3][3] = invBlendConstantA;
699
700 factor.blendConstant4F[0][0] = blendConstant.r;
701 factor.blendConstant4F[0][1] = blendConstant.r;
702 factor.blendConstant4F[0][2] = blendConstant.r;
703 factor.blendConstant4F[0][3] = blendConstant.r;
704
705 factor.blendConstant4F[1][0] = blendConstant.g;
706 factor.blendConstant4F[1][1] = blendConstant.g;
707 factor.blendConstant4F[1][2] = blendConstant.g;
708 factor.blendConstant4F[1][3] = blendConstant.g;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500709
John Bauman89401822014-05-06 15:04:28 -0400710 factor.blendConstant4F[2][0] = blendConstant.b;
711 factor.blendConstant4F[2][1] = blendConstant.b;
712 factor.blendConstant4F[2][2] = blendConstant.b;
713 factor.blendConstant4F[2][3] = blendConstant.b;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500714
John Bauman89401822014-05-06 15:04:28 -0400715 factor.blendConstant4F[3][0] = blendConstant.a;
716 factor.blendConstant4F[3][1] = blendConstant.a;
717 factor.blendConstant4F[3][2] = blendConstant.a;
718 factor.blendConstant4F[3][3] = blendConstant.a;
719
720 factor.invBlendConstant4F[0][0] = 1 - blendConstant.r;
721 factor.invBlendConstant4F[0][1] = 1 - blendConstant.r;
722 factor.invBlendConstant4F[0][2] = 1 - blendConstant.r;
723 factor.invBlendConstant4F[0][3] = 1 - blendConstant.r;
724
725 factor.invBlendConstant4F[1][0] = 1 - blendConstant.g;
726 factor.invBlendConstant4F[1][1] = 1 - blendConstant.g;
727 factor.invBlendConstant4F[1][2] = 1 - blendConstant.g;
728 factor.invBlendConstant4F[1][3] = 1 - blendConstant.g;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500729
John Bauman89401822014-05-06 15:04:28 -0400730 factor.invBlendConstant4F[2][0] = 1 - blendConstant.b;
731 factor.invBlendConstant4F[2][1] = 1 - blendConstant.b;
732 factor.invBlendConstant4F[2][2] = 1 - blendConstant.b;
733 factor.invBlendConstant4F[2][3] = 1 - blendConstant.b;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500734
John Bauman89401822014-05-06 15:04:28 -0400735 factor.invBlendConstant4F[3][0] = 1 - blendConstant.a;
736 factor.invBlendConstant4F[3][1] = 1 - blendConstant.a;
737 factor.invBlendConstant4F[3][2] = 1 - blendConstant.a;
738 factor.invBlendConstant4F[3][3] = 1 - blendConstant.a;
739 }
740
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400741 void PixelProcessor::setFillMode(FillMode fillMode)
John Bauman89401822014-05-06 15:04:28 -0400742 {
743 context->fillMode = fillMode;
744 }
745
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400746 void PixelProcessor::setShadingMode(ShadingMode shadingMode)
John Bauman89401822014-05-06 15:04:28 -0400747 {
748 context->shadingMode = shadingMode;
749 }
750
751 void PixelProcessor::setAlphaBlendEnable(bool alphaBlendEnable)
752 {
753 context->setAlphaBlendEnable(alphaBlendEnable);
754 }
755
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400756 void PixelProcessor::setSourceBlendFactor(BlendFactor sourceBlendFactor)
John Bauman89401822014-05-06 15:04:28 -0400757 {
758 context->setSourceBlendFactor(sourceBlendFactor);
759 }
760
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400761 void PixelProcessor::setDestBlendFactor(BlendFactor destBlendFactor)
John Bauman89401822014-05-06 15:04:28 -0400762 {
763 context->setDestBlendFactor(destBlendFactor);
764 }
765
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400766 void PixelProcessor::setBlendOperation(BlendOperation blendOperation)
John Bauman89401822014-05-06 15:04:28 -0400767 {
768 context->setBlendOperation(blendOperation);
769 }
770
771 void PixelProcessor::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)
772 {
773 context->setSeparateAlphaBlendEnable(separateAlphaBlendEnable);
774 }
775
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400776 void PixelProcessor::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)
John Bauman89401822014-05-06 15:04:28 -0400777 {
778 context->setSourceBlendFactorAlpha(sourceBlendFactorAlpha);
779 }
780
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400781 void PixelProcessor::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)
John Bauman89401822014-05-06 15:04:28 -0400782 {
783 context->setDestBlendFactorAlpha(destBlendFactorAlpha);
784 }
785
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400786 void PixelProcessor::setBlendOperationAlpha(BlendOperation blendOperationAlpha)
John Bauman89401822014-05-06 15:04:28 -0400787 {
788 context->setBlendOperationAlpha(blendOperationAlpha);
789 }
790
Alexis Hetua818c452015-06-11 13:06:58 -0400791 void PixelProcessor::setAlphaReference(float alphaReference)
John Bauman89401822014-05-06 15:04:28 -0400792 {
793 context->alphaReference = alphaReference;
794
Alexis Hetua818c452015-06-11 13:06:58 -0400795 factor.alphaReference4[0] = (word)iround(alphaReference * 0x1000 / 0xFF);
796 factor.alphaReference4[1] = (word)iround(alphaReference * 0x1000 / 0xFF);
797 factor.alphaReference4[2] = (word)iround(alphaReference * 0x1000 / 0xFF);
798 factor.alphaReference4[3] = (word)iround(alphaReference * 0x1000 / 0xFF);
John Bauman89401822014-05-06 15:04:28 -0400799 }
800
801 void PixelProcessor::setGlobalMipmapBias(float bias)
802 {
803 context->setGlobalMipmapBias(bias);
804 }
805
806 void PixelProcessor::setFogStart(float start)
807 {
808 setFogRanges(start, context->fogEnd);
809 }
810
811 void PixelProcessor::setFogEnd(float end)
812 {
813 setFogRanges(context->fogStart, end);
814 }
815
816 void PixelProcessor::setFogColor(Color<float> fogColor)
817 {
818 // TODO: Compact into generic function
819 word fogR = (unsigned short)(65535 * fogColor.r);
820 word fogG = (unsigned short)(65535 * fogColor.g);
821 word fogB = (unsigned short)(65535 * fogColor.b);
822
823 fog.color4[0][0] = fogR;
824 fog.color4[0][1] = fogR;
825 fog.color4[0][2] = fogR;
826 fog.color4[0][3] = fogR;
827
828 fog.color4[1][0] = fogG;
829 fog.color4[1][1] = fogG;
830 fog.color4[1][2] = fogG;
831 fog.color4[1][3] = fogG;
832
833 fog.color4[2][0] = fogB;
834 fog.color4[2][1] = fogB;
835 fog.color4[2][2] = fogB;
836 fog.color4[2][3] = fogB;
837
838 fog.colorF[0] = replicate(fogColor.r);
839 fog.colorF[1] = replicate(fogColor.g);
840 fog.colorF[2] = replicate(fogColor.b);
841 }
842
843 void PixelProcessor::setFogDensity(float fogDensity)
844 {
845 fog.densityE = replicate(-fogDensity * 1.442695f); // 1/e^x = 2^(-x*1.44)
Nicolas Capensa36f3f92015-08-04 15:34:26 -0400846 fog.density2E = replicate(-fogDensity * fogDensity * 1.442695f);
John Bauman89401822014-05-06 15:04:28 -0400847 }
848
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400849 void PixelProcessor::setPixelFogMode(FogMode fogMode)
John Bauman89401822014-05-06 15:04:28 -0400850 {
851 context->pixelFogMode = fogMode;
852 }
853
854 void PixelProcessor::setPerspectiveCorrection(bool perspectiveEnable)
855 {
856 perspectiveCorrection = perspectiveEnable;
857 }
858
859 void PixelProcessor::setOcclusionEnabled(bool enable)
860 {
861 context->occlusionEnabled = enable;
862 }
863
864 void PixelProcessor::setRoutineCacheSize(int cacheSize)
865 {
866 delete routineCache;
John Bauman66b8ab22014-05-06 15:57:45 -0400867 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precachePixel ? "sw-pixel" : 0);
John Bauman89401822014-05-06 15:04:28 -0400868 }
869
870 void PixelProcessor::setFogRanges(float start, float end)
871 {
872 context->fogStart = start;
873 context->fogEnd = end;
874
875 if(start == end)
876 {
877 end += 0.001f; // Hack: ensure there is a small range
878 }
879
880 float fogScale = -1.0f / (end - start);
881 float fogOffset = end * -fogScale;
882
883 fog.scale = replicate(fogScale);
884 fog.offset = replicate(fogOffset);
885 }
886
887 const PixelProcessor::State PixelProcessor::update() const
888 {
889 State state;
890
891 if(context->pixelShader)
892 {
John Bauman19bac1e2014-05-06 15:23:49 -0400893 state.shaderID = context->pixelShader->getSerialID();
John Bauman89401822014-05-06 15:04:28 -0400894 }
895 else
896 {
John Bauman19bac1e2014-05-06 15:23:49 -0400897 state.shaderID = 0;
John Bauman89401822014-05-06 15:04:28 -0400898 }
899
900 state.depthOverride = context->pixelShader && context->pixelShader->depthOverride();
John Bauman19bac1e2014-05-06 15:23:49 -0400901 state.shaderContainsKill = context->pixelShader ? context->pixelShader->containsKill() : false;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500902
John Bauman89401822014-05-06 15:04:28 -0400903 if(context->alphaTestActive())
904 {
905 state.alphaCompareMode = context->alphaCompareMode;
906
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400907 state.transparencyAntialiasing = context->getMultiSampleCount() > 1 ? transparencyAntialiasing : TRANSPARENCY_NONE;
John Bauman89401822014-05-06 15:04:28 -0400908 }
909
910 state.depthWriteEnable = context->depthWriteActive();
911
912 if(context->stencilActive())
913 {
914 state.stencilActive = true;
915 state.stencilCompareMode = context->stencilCompareMode;
916 state.stencilFailOperation = context->stencilFailOperation;
917 state.stencilPassOperation = context->stencilPassOperation;
918 state.stencilZFailOperation = context->stencilZFailOperation;
919 state.noStencilMask = (context->stencilMask == 0xFF);
920 state.noStencilWriteMask = (context->stencilWriteMask == 0xFF);
921 state.stencilWriteMasked = (context->stencilWriteMask == 0x00);
922
923 state.twoSidedStencil = context->twoSidedStencil;
924 state.stencilCompareModeCCW = context->twoSidedStencil ? context->stencilCompareModeCCW : state.stencilCompareMode;
925 state.stencilFailOperationCCW = context->twoSidedStencil ? context->stencilFailOperationCCW : state.stencilFailOperation;
926 state.stencilPassOperationCCW = context->twoSidedStencil ? context->stencilPassOperationCCW : state.stencilPassOperation;
927 state.stencilZFailOperationCCW = context->twoSidedStencil ? context->stencilZFailOperationCCW : state.stencilZFailOperation;
928 state.noStencilMaskCCW = context->twoSidedStencil ? (context->stencilMaskCCW == 0xFF) : state.noStencilMask;
929 state.noStencilWriteMaskCCW = context->twoSidedStencil ? (context->stencilWriteMaskCCW == 0xFF) : state.noStencilWriteMask;
930 state.stencilWriteMaskedCCW = context->twoSidedStencil ? (context->stencilWriteMaskCCW == 0x00) : state.stencilWriteMasked;
931 }
932
933 if(context->depthBufferActive())
934 {
935 state.depthTestActive = true;
936 state.depthCompareMode = context->depthCompareMode;
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400937 state.quadLayoutDepthBuffer = context->depthBuffer->getInternalFormat() != FORMAT_D32F_LOCKABLE &&
938 context->depthBuffer->getInternalFormat() != FORMAT_D32FS8_TEXTURE &&
939 context->depthBuffer->getInternalFormat() != FORMAT_D32FS8_SHADOW;
John Bauman89401822014-05-06 15:04:28 -0400940 }
941
942 state.occlusionEnabled = context->occlusionEnabled;
943
944 state.fogActive = context->fogActive();
945 state.pixelFogMode = context->pixelFogActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400946 state.wBasedFog = context->wBasedFog && context->pixelFogActive() != FOG_NONE;
John Bauman89401822014-05-06 15:04:28 -0400947 state.perspective = context->perspectiveActive();
948
949 if(context->alphaBlendActive())
950 {
951 state.alphaBlendActive = true;
952 state.sourceBlendFactor = context->sourceBlendFactor();
953 state.destBlendFactor = context->destBlendFactor();
954 state.blendOperation = context->blendOperation();
955 state.sourceBlendFactorAlpha = context->sourceBlendFactorAlpha();
956 state.destBlendFactorAlpha = context->destBlendFactorAlpha();
957 state.blendOperationAlpha = context->blendOperationAlpha();
958 }
Maxime Grégoired9762742015-07-08 16:43:48 -0400959
960 state.logicalOperation = context->colorLogicOp();
961
John Bauman89401822014-05-06 15:04:28 -0400962 state.colorWriteMask = (context->colorWriteActive(0) << 0) |
963 (context->colorWriteActive(1) << 4) |
964 (context->colorWriteActive(2) << 8) |
965 (context->colorWriteActive(3) << 12);
966
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500967 for(int i = 0; i < RENDERTARGETS; i++)
John Bauman89401822014-05-06 15:04:28 -0400968 {
969 state.targetFormat[i] = context->renderTargetInternalFormat(i);
970 }
971
John Bauman66b8ab22014-05-06 15:57:45 -0400972 state.writeSRGB = context->writeSRGB && context->renderTarget[0] && Surface::isSRGBwritable(context->renderTarget[0]->getExternalFormat());
973 state.multiSample = context->getMultiSampleCount();
John Bauman89401822014-05-06 15:04:28 -0400974 state.multiSampleMask = context->multiSampleMask;
975
976 if(state.multiSample > 1 && context->pixelShader)
977 {
978 state.centroid = context->pixelShader->containsCentroid();
979 }
980
981 if(!context->pixelShader)
982 {
983 for(unsigned int i = 0; i < 8; i++)
984 {
985 state.textureStage[i] = context->textureStage[i].textureStageState();
986 }
987
988 state.specularAdd = context->specularActive() && context->specularEnable;
989 }
990
991 for(unsigned int i = 0; i < 16; i++)
992 {
993 if(context->pixelShader)
994 {
995 if(context->pixelShader->usesSampler(i))
996 {
997 state.sampler[i] = context->sampler[i].samplerState();
998 }
999 }
1000 else
1001 {
1002 if(i < 8 && state.textureStage[i].stageOperation != TextureStage::STAGE_DISABLE)
1003 {
1004 state.sampler[i] = context->sampler[i].samplerState();
1005 }
1006 else break;
1007 }
1008 }
1009
1010 const bool point = context->isDrawPoint(true);
1011 const bool sprite = context->pointSpriteActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001012 const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
John Bauman89401822014-05-06 15:04:28 -04001013
1014 if(context->pixelShaderVersion() < 0x0300)
1015 {
1016 for(int coordinate = 0; coordinate < 8; coordinate++)
1017 {
1018 for(int component = 0; component < 4; component++)
1019 {
1020 if(context->textureActive(coordinate, component))
1021 {
1022 state.texture[coordinate].component |= 1 << component;
1023
1024 if(point && !sprite)
1025 {
1026 state.texture[coordinate].flat |= 1 << component;
1027 }
1028 }
1029 }
1030
1031 if(context->textureTransformProject[coordinate] && context->pixelShaderVersion() <= 0x0103)
1032 {
1033 if(context->textureTransformCount[coordinate] == 2)
1034 {
1035 state.texture[coordinate].project = 1;
1036 }
1037 else if(context->textureTransformCount[coordinate] == 3)
1038 {
1039 state.texture[coordinate].project = 2;
1040 }
1041 else if(context->textureTransformCount[coordinate] == 4 || context->textureTransformCount[coordinate] == 0)
1042 {
1043 state.texture[coordinate].project = 3;
1044 }
1045 }
1046 }
1047
1048 for(int color = 0; color < 2; color++)
1049 {
1050 for(int component = 0; component < 4; component++)
1051 {
1052 if(context->colorActive(color, component))
1053 {
1054 state.color[color].component |= 1 << component;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001055
John Bauman89401822014-05-06 15:04:28 -04001056 if(point || flatShading)
1057 {
1058 state.color[color].flat |= 1 << component;
1059 }
1060 }
1061 }
1062 }
1063
1064 if(context->fogActive())
1065 {
1066 state.fog.component = true;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001067
John Bauman89401822014-05-06 15:04:28 -04001068 if(point)
1069 {
1070 state.fog.flat = true;
1071 }
1072 }
1073 }
1074 else
1075 {
1076 for(int interpolant = 0; interpolant < 10; interpolant++)
1077 {
1078 for(int component = 0; component < 4; component++)
1079 {
1080 if(context->pixelShader->semantic[interpolant][component].active())
1081 {
1082 bool flat = point;
1083
1084 switch(context->pixelShader->semantic[interpolant][component].usage)
1085 {
John Bauman19bac1e2014-05-06 15:23:49 -04001086 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
1087 case Shader::USAGE_COLOR: flat = flatShading; break;
John Bauman89401822014-05-06 15:04:28 -04001088 }
1089
1090 state.interpolant[interpolant].component |= 1 << component;
1091
1092 if(flat)
1093 {
1094 state.interpolant[interpolant].flat |= 1 << component;
1095 }
1096 }
1097 }
1098 }
1099 }
1100
1101 if(state.centroid)
1102 {
1103 for(int interpolant = 0; interpolant < 10; interpolant++)
1104 {
1105 for(int component = 0; component < 4; component++)
1106 {
1107 state.interpolant[interpolant].centroid = context->pixelShader->semantic[interpolant][0].centroid;
1108 }
1109 }
1110 }
1111
1112 state.hash = state.computeHash();
1113
1114 return state;
1115 }
1116
1117 Routine *PixelProcessor::routine(const State &state)
1118 {
1119 Routine *routine = routineCache->query(state);
1120
1121 if(!routine)
1122 {
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001123 const bool integerPipeline = (context->pixelShaderVersion() <= 0x0104);
Nicolas Capensba53fbf2016-01-14 13:43:42 -05001124 QuadRasterizer *generator = nullptr;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001125
Alexis Hetuf2a8c372015-07-13 11:08:41 -04001126 if(integerPipeline)
1127 {
1128 generator = new PixelPipeline(state, context->pixelShader);
1129 }
1130 else
1131 {
1132 generator = new PixelProgram(state, context->pixelShader);
1133 }
Nicolas Capens4f172c72016-01-13 08:34:30 -05001134
John Bauman89401822014-05-06 15:04:28 -04001135 generator->generate();
Nicolas Capens4f172c72016-01-13 08:34:30 -05001136 routine = (*generator)(L"PixelRoutine_%0.8X", state.shaderID);
John Bauman89401822014-05-06 15:04:28 -04001137 delete generator;
1138
1139 routineCache->add(state, routine);
1140 }
1141
1142 return routine;
1143 }
1144}