1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #include "PixelProcessor.hpp" |
16 | |
17 | #include "Surface.hpp" |
18 | #include "Primitive.hpp" |
19 | #include "Shader/PixelPipeline.hpp" |
20 | #include "Shader/PixelProgram.hpp" |
21 | #include "Shader/PixelShader.hpp" |
22 | #include "Shader/Constants.hpp" |
23 | #include "Common/Debug.hpp" |
24 | |
25 | #include <cstring> |
26 | |
27 | namespace sw |
28 | { |
29 | extern bool complementaryDepthBuffer; |
30 | extern TransparencyAntialiasing transparencyAntialiasing; |
31 | extern bool perspectiveCorrection; |
32 | |
33 | bool precachePixel = false; |
34 | |
35 | uint32_t PixelProcessor::States::computeHash() |
36 | { |
37 | uint32_t *state = reinterpret_cast<uint32_t*>(this); |
38 | uint32_t hash = 0; |
39 | |
40 | for(unsigned int i = 0; i < sizeof(States) / sizeof(uint32_t); i++) |
41 | { |
42 | hash ^= state[i]; |
43 | } |
44 | |
45 | return hash; |
46 | } |
47 | |
48 | bool PixelProcessor::State::operator==(const State &state) const |
49 | { |
50 | if(hash != state.hash) |
51 | { |
52 | return false; |
53 | } |
54 | |
55 | static_assert(is_memcmparable<State>::value, "Cannot memcmp State" ); |
56 | return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0; |
57 | } |
58 | |
59 | PixelProcessor::UniformBufferInfo::UniformBufferInfo() |
60 | { |
61 | buffer = nullptr; |
62 | offset = 0; |
63 | } |
64 | |
65 | PixelProcessor::PixelProcessor(Context *context) : context(context) |
66 | { |
67 | setGlobalMipmapBias(0.0f); // Round to highest LOD [0.5, 1.0]: -0.5 |
68 | // Round to nearest LOD [0.7, 1.4]: 0.0 |
69 | // Round to lowest LOD [1.0, 2.0]: 0.5 |
70 | |
71 | routineCache = 0; |
72 | setRoutineCacheSize(1024); |
73 | } |
74 | |
75 | PixelProcessor::~PixelProcessor() |
76 | { |
77 | delete routineCache; |
78 | routineCache = nullptr; |
79 | } |
80 | |
81 | void PixelProcessor::setFloatConstant(unsigned int index, const float value[4]) |
82 | { |
83 | if(index < FRAGMENT_UNIFORM_VECTORS) |
84 | { |
85 | c[index][0] = value[0]; |
86 | c[index][1] = value[1]; |
87 | c[index][2] = value[2]; |
88 | c[index][3] = value[3]; |
89 | } |
90 | else ASSERT(false); |
91 | |
92 | if(index < 8) // ps_1_x constants |
93 | { |
94 | // TODO: Compact into generic function |
95 | short x = iround(4095 * clamp_s(value[0], -1.0f, 1.0f)); |
96 | short y = iround(4095 * clamp_s(value[1], -1.0f, 1.0f)); |
97 | short z = iround(4095 * clamp_s(value[2], -1.0f, 1.0f)); |
98 | short w = iround(4095 * clamp_s(value[3], -1.0f, 1.0f)); |
99 | |
100 | cW[index][0][0] = x; |
101 | cW[index][0][1] = x; |
102 | cW[index][0][2] = x; |
103 | cW[index][0][3] = x; |
104 | |
105 | cW[index][1][0] = y; |
106 | cW[index][1][1] = y; |
107 | cW[index][1][2] = y; |
108 | cW[index][1][3] = y; |
109 | |
110 | cW[index][2][0] = z; |
111 | cW[index][2][1] = z; |
112 | cW[index][2][2] = z; |
113 | cW[index][2][3] = z; |
114 | |
115 | cW[index][3][0] = w; |
116 | cW[index][3][1] = w; |
117 | cW[index][3][2] = w; |
118 | cW[index][3][3] = w; |
119 | } |
120 | } |
121 | |
122 | void PixelProcessor::setIntegerConstant(unsigned int index, const int value[4]) |
123 | { |
124 | if(index < 16) |
125 | { |
126 | i[index][0] = value[0]; |
127 | i[index][1] = value[1]; |
128 | i[index][2] = value[2]; |
129 | i[index][3] = value[3]; |
130 | } |
131 | else ASSERT(false); |
132 | } |
133 | |
134 | void PixelProcessor::setBooleanConstant(unsigned int index, int boolean) |
135 | { |
136 | if(index < 16) |
137 | { |
138 | b[index] = boolean != 0; |
139 | } |
140 | else ASSERT(false); |
141 | } |
142 | |
143 | void PixelProcessor::setUniformBuffer(int index, sw::Resource* buffer, int offset) |
144 | { |
145 | uniformBufferInfo[index].buffer = buffer; |
146 | uniformBufferInfo[index].offset = offset; |
147 | } |
148 | |
149 | void PixelProcessor::lockUniformBuffers(byte** u, sw::Resource* uniformBuffers[]) |
150 | { |
151 | for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i) |
152 | { |
153 | u[i] = uniformBufferInfo[i].buffer ? static_cast<byte*>(uniformBufferInfo[i].buffer->lock(PUBLIC, PRIVATE)) + uniformBufferInfo[i].offset : nullptr; |
154 | uniformBuffers[i] = uniformBufferInfo[i].buffer; |
155 | } |
156 | } |
157 | |
158 | void PixelProcessor::setRenderTarget(int index, Surface *renderTarget, unsigned int layer) |
159 | { |
160 | context->renderTarget[index] = renderTarget; |
161 | context->renderTargetLayer[index] = layer; |
162 | } |
163 | |
164 | void PixelProcessor::setDepthBuffer(Surface *depthBuffer, unsigned int layer) |
165 | { |
166 | context->depthBuffer = depthBuffer; |
167 | context->depthBufferLayer = layer; |
168 | } |
169 | |
170 | void PixelProcessor::setStencilBuffer(Surface *stencilBuffer, unsigned int layer) |
171 | { |
172 | context->stencilBuffer = stencilBuffer; |
173 | context->stencilBufferLayer = layer; |
174 | } |
175 | |
176 | void PixelProcessor::setTexCoordIndex(unsigned int stage, int texCoordIndex) |
177 | { |
178 | if(stage < 8) |
179 | { |
180 | context->textureStage[stage].setTexCoordIndex(texCoordIndex); |
181 | } |
182 | else ASSERT(false); |
183 | } |
184 | |
185 | void PixelProcessor::setStageOperation(unsigned int stage, TextureStage::StageOperation stageOperation) |
186 | { |
187 | if(stage < 8) |
188 | { |
189 | context->textureStage[stage].setStageOperation(stageOperation); |
190 | } |
191 | else ASSERT(false); |
192 | } |
193 | |
194 | void PixelProcessor::setFirstArgument(unsigned int stage, TextureStage::SourceArgument firstArgument) |
195 | { |
196 | if(stage < 8) |
197 | { |
198 | context->textureStage[stage].setFirstArgument(firstArgument); |
199 | } |
200 | else ASSERT(false); |
201 | } |
202 | |
203 | void PixelProcessor::setSecondArgument(unsigned int stage, TextureStage::SourceArgument secondArgument) |
204 | { |
205 | if(stage < 8) |
206 | { |
207 | context->textureStage[stage].setSecondArgument(secondArgument); |
208 | } |
209 | else ASSERT(false); |
210 | } |
211 | |
212 | void PixelProcessor::setThirdArgument(unsigned int stage, TextureStage::SourceArgument thirdArgument) |
213 | { |
214 | if(stage < 8) |
215 | { |
216 | context->textureStage[stage].setThirdArgument(thirdArgument); |
217 | } |
218 | else ASSERT(false); |
219 | } |
220 | |
221 | void PixelProcessor::setStageOperationAlpha(unsigned int stage, TextureStage::StageOperation stageOperationAlpha) |
222 | { |
223 | if(stage < 8) |
224 | { |
225 | context->textureStage[stage].setStageOperationAlpha(stageOperationAlpha); |
226 | } |
227 | else ASSERT(false); |
228 | } |
229 | |
230 | void PixelProcessor::setFirstArgumentAlpha(unsigned int stage, TextureStage::SourceArgument firstArgumentAlpha) |
231 | { |
232 | if(stage < 8) |
233 | { |
234 | context->textureStage[stage].setFirstArgumentAlpha(firstArgumentAlpha); |
235 | } |
236 | else ASSERT(false); |
237 | } |
238 | |
239 | void PixelProcessor::setSecondArgumentAlpha(unsigned int stage, TextureStage::SourceArgument secondArgumentAlpha) |
240 | { |
241 | if(stage < 8) |
242 | { |
243 | context->textureStage[stage].setSecondArgumentAlpha(secondArgumentAlpha); |
244 | } |
245 | else ASSERT(false); |
246 | } |
247 | |
248 | void PixelProcessor::setThirdArgumentAlpha(unsigned int stage, TextureStage::SourceArgument thirdArgumentAlpha) |
249 | { |
250 | if(stage < 8) |
251 | { |
252 | context->textureStage[stage].setThirdArgumentAlpha(thirdArgumentAlpha); |
253 | } |
254 | else ASSERT(false); |
255 | } |
256 | |
257 | void PixelProcessor::setFirstModifier(unsigned int stage, TextureStage::ArgumentModifier firstModifier) |
258 | { |
259 | if(stage < 8) |
260 | { |
261 | context->textureStage[stage].setFirstModifier(firstModifier); |
262 | } |
263 | else ASSERT(false); |
264 | } |
265 | |
266 | void PixelProcessor::setSecondModifier(unsigned int stage, TextureStage::ArgumentModifier secondModifier) |
267 | { |
268 | if(stage < 8) |
269 | { |
270 | context->textureStage[stage].setSecondModifier(secondModifier); |
271 | } |
272 | else ASSERT(false); |
273 | } |
274 | |
275 | void PixelProcessor::setThirdModifier(unsigned int stage, TextureStage::ArgumentModifier thirdModifier) |
276 | { |
277 | if(stage < 8) |
278 | { |
279 | context->textureStage[stage].setThirdModifier(thirdModifier); |
280 | } |
281 | else ASSERT(false); |
282 | } |
283 | |
284 | void PixelProcessor::setFirstModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier firstModifierAlpha) |
285 | { |
286 | if(stage < 8) |
287 | { |
288 | context->textureStage[stage].setFirstModifierAlpha(firstModifierAlpha); |
289 | } |
290 | else ASSERT(false); |
291 | } |
292 | |
293 | void PixelProcessor::setSecondModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier secondModifierAlpha) |
294 | { |
295 | if(stage < 8) |
296 | { |
297 | context->textureStage[stage].setSecondModifierAlpha(secondModifierAlpha); |
298 | } |
299 | else ASSERT(false); |
300 | } |
301 | |
302 | void PixelProcessor::setThirdModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier thirdModifierAlpha) |
303 | { |
304 | if(stage < 8) |
305 | { |
306 | context->textureStage[stage].setThirdModifierAlpha(thirdModifierAlpha); |
307 | } |
308 | else ASSERT(false); |
309 | } |
310 | |
311 | void PixelProcessor::setDestinationArgument(unsigned int stage, TextureStage::DestinationArgument destinationArgument) |
312 | { |
313 | if(stage < 8) |
314 | { |
315 | context->textureStage[stage].setDestinationArgument(destinationArgument); |
316 | } |
317 | else ASSERT(false); |
318 | } |
319 | |
320 | void PixelProcessor::setConstantColor(unsigned int stage, const Color<float> &constantColor) |
321 | { |
322 | if(stage < 8) |
323 | { |
324 | context->textureStage[stage].setConstantColor(constantColor); |
325 | } |
326 | else ASSERT(false); |
327 | } |
328 | |
329 | void PixelProcessor::setBumpmapMatrix(unsigned int stage, int element, float value) |
330 | { |
331 | if(stage < 8) |
332 | { |
333 | context->textureStage[stage].setBumpmapMatrix(element, value); |
334 | } |
335 | else ASSERT(false); |
336 | } |
337 | |
338 | void PixelProcessor::setLuminanceScale(unsigned int stage, float value) |
339 | { |
340 | if(stage < 8) |
341 | { |
342 | context->textureStage[stage].setLuminanceScale(value); |
343 | } |
344 | else ASSERT(false); |
345 | } |
346 | |
347 | void PixelProcessor::setLuminanceOffset(unsigned int stage, float value) |
348 | { |
349 | if(stage < 8) |
350 | { |
351 | context->textureStage[stage].setLuminanceOffset(value); |
352 | } |
353 | else ASSERT(false); |
354 | } |
355 | |
356 | void PixelProcessor::setTextureFilter(unsigned int sampler, FilterType textureFilter) |
357 | { |
358 | if(sampler < TEXTURE_IMAGE_UNITS) |
359 | { |
360 | context->sampler[sampler].setTextureFilter(textureFilter); |
361 | } |
362 | else ASSERT(false); |
363 | } |
364 | |
365 | void PixelProcessor::setMipmapFilter(unsigned int sampler, MipmapType mipmapFilter) |
366 | { |
367 | if(sampler < TEXTURE_IMAGE_UNITS) |
368 | { |
369 | context->sampler[sampler].setMipmapFilter(mipmapFilter); |
370 | } |
371 | else ASSERT(false); |
372 | } |
373 | |
374 | void PixelProcessor::setGatherEnable(unsigned int sampler, bool enable) |
375 | { |
376 | if(sampler < TEXTURE_IMAGE_UNITS) |
377 | { |
378 | context->sampler[sampler].setGatherEnable(enable); |
379 | } |
380 | else ASSERT(false); |
381 | } |
382 | |
383 | void PixelProcessor::setAddressingModeU(unsigned int sampler, AddressingMode addressMode) |
384 | { |
385 | if(sampler < TEXTURE_IMAGE_UNITS) |
386 | { |
387 | context->sampler[sampler].setAddressingModeU(addressMode); |
388 | } |
389 | else ASSERT(false); |
390 | } |
391 | |
392 | void PixelProcessor::setAddressingModeV(unsigned int sampler, AddressingMode addressMode) |
393 | { |
394 | if(sampler < TEXTURE_IMAGE_UNITS) |
395 | { |
396 | context->sampler[sampler].setAddressingModeV(addressMode); |
397 | } |
398 | else ASSERT(false); |
399 | } |
400 | |
401 | void PixelProcessor::setAddressingModeW(unsigned int sampler, AddressingMode addressMode) |
402 | { |
403 | if(sampler < TEXTURE_IMAGE_UNITS) |
404 | { |
405 | context->sampler[sampler].setAddressingModeW(addressMode); |
406 | } |
407 | else ASSERT(false); |
408 | } |
409 | |
410 | void PixelProcessor::setReadSRGB(unsigned int sampler, bool sRGB) |
411 | { |
412 | if(sampler < TEXTURE_IMAGE_UNITS) |
413 | { |
414 | context->sampler[sampler].setReadSRGB(sRGB); |
415 | } |
416 | else ASSERT(false); |
417 | } |
418 | |
419 | void PixelProcessor::setMipmapLOD(unsigned int sampler, float bias) |
420 | { |
421 | if(sampler < TEXTURE_IMAGE_UNITS) |
422 | { |
423 | context->sampler[sampler].setMipmapLOD(bias); |
424 | } |
425 | else ASSERT(false); |
426 | } |
427 | |
428 | void PixelProcessor::setBorderColor(unsigned int sampler, const Color<float> &borderColor) |
429 | { |
430 | if(sampler < TEXTURE_IMAGE_UNITS) |
431 | { |
432 | context->sampler[sampler].setBorderColor(borderColor); |
433 | } |
434 | else ASSERT(false); |
435 | } |
436 | |
437 | void PixelProcessor::setMaxAnisotropy(unsigned int sampler, float maxAnisotropy) |
438 | { |
439 | if(sampler < TEXTURE_IMAGE_UNITS) |
440 | { |
441 | context->sampler[sampler].setMaxAnisotropy(maxAnisotropy); |
442 | } |
443 | else ASSERT(false); |
444 | } |
445 | |
446 | void PixelProcessor::setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering) |
447 | { |
448 | if(sampler < TEXTURE_IMAGE_UNITS) |
449 | { |
450 | context->sampler[sampler].setHighPrecisionFiltering(highPrecisionFiltering); |
451 | } |
452 | else ASSERT(false); |
453 | } |
454 | |
455 | void PixelProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR) |
456 | { |
457 | if(sampler < TEXTURE_IMAGE_UNITS) |
458 | { |
459 | context->sampler[sampler].setSwizzleR(swizzleR); |
460 | } |
461 | else ASSERT(false); |
462 | } |
463 | |
464 | void PixelProcessor::setSwizzleG(unsigned int sampler, SwizzleType swizzleG) |
465 | { |
466 | if(sampler < TEXTURE_IMAGE_UNITS) |
467 | { |
468 | context->sampler[sampler].setSwizzleG(swizzleG); |
469 | } |
470 | else ASSERT(false); |
471 | } |
472 | |
473 | void PixelProcessor::setSwizzleB(unsigned int sampler, SwizzleType swizzleB) |
474 | { |
475 | if(sampler < TEXTURE_IMAGE_UNITS) |
476 | { |
477 | context->sampler[sampler].setSwizzleB(swizzleB); |
478 | } |
479 | else ASSERT(false); |
480 | } |
481 | |
482 | void PixelProcessor::setSwizzleA(unsigned int sampler, SwizzleType swizzleA) |
483 | { |
484 | if(sampler < TEXTURE_IMAGE_UNITS) |
485 | { |
486 | context->sampler[sampler].setSwizzleA(swizzleA); |
487 | } |
488 | else ASSERT(false); |
489 | } |
490 | |
491 | void PixelProcessor::setCompareFunc(unsigned int sampler, CompareFunc compFunc) |
492 | { |
493 | if(sampler < TEXTURE_IMAGE_UNITS) |
494 | { |
495 | context->sampler[sampler].setCompareFunc(compFunc); |
496 | } |
497 | else ASSERT(false); |
498 | } |
499 | |
500 | void PixelProcessor::setBaseLevel(unsigned int sampler, int baseLevel) |
501 | { |
502 | if(sampler < TEXTURE_IMAGE_UNITS) |
503 | { |
504 | context->sampler[sampler].setBaseLevel(baseLevel); |
505 | } |
506 | else ASSERT(false); |
507 | } |
508 | |
509 | void PixelProcessor::setMaxLevel(unsigned int sampler, int maxLevel) |
510 | { |
511 | if(sampler < TEXTURE_IMAGE_UNITS) |
512 | { |
513 | context->sampler[sampler].setMaxLevel(maxLevel); |
514 | } |
515 | else ASSERT(false); |
516 | } |
517 | |
518 | void PixelProcessor::setMinLod(unsigned int sampler, float minLod) |
519 | { |
520 | if(sampler < TEXTURE_IMAGE_UNITS) |
521 | { |
522 | context->sampler[sampler].setMinLod(minLod); |
523 | } |
524 | else ASSERT(false); |
525 | } |
526 | |
527 | void PixelProcessor::setMaxLod(unsigned int sampler, float maxLod) |
528 | { |
529 | if(sampler < TEXTURE_IMAGE_UNITS) |
530 | { |
531 | context->sampler[sampler].setMaxLod(maxLod); |
532 | } |
533 | else ASSERT(false); |
534 | } |
535 | |
536 | void PixelProcessor::setSyncRequired(unsigned int sampler, bool isSincRequired) |
537 | { |
538 | if(sampler < TEXTURE_IMAGE_UNITS) |
539 | { |
540 | context->sampler[sampler].setSyncRequired(isSincRequired); |
541 | } |
542 | else ASSERT(false); |
543 | } |
544 | |
545 | void PixelProcessor::setWriteSRGB(bool sRGB) |
546 | { |
547 | context->setWriteSRGB(sRGB); |
548 | } |
549 | |
550 | void PixelProcessor::setColorLogicOpEnabled(bool colorLogicOpEnabled) |
551 | { |
552 | context->setColorLogicOpEnabled(colorLogicOpEnabled); |
553 | } |
554 | |
555 | void PixelProcessor::setLogicalOperation(LogicalOperation logicalOperation) |
556 | { |
557 | context->setLogicalOperation(logicalOperation); |
558 | } |
559 | |
560 | void PixelProcessor::setDepthBufferEnable(bool depthBufferEnable) |
561 | { |
562 | context->setDepthBufferEnable(depthBufferEnable); |
563 | } |
564 | |
565 | void PixelProcessor::setDepthCompare(DepthCompareMode depthCompareMode) |
566 | { |
567 | context->depthCompareMode = depthCompareMode; |
568 | } |
569 | |
570 | void PixelProcessor::setAlphaCompare(AlphaCompareMode alphaCompareMode) |
571 | { |
572 | context->alphaCompareMode = alphaCompareMode; |
573 | } |
574 | |
575 | void PixelProcessor::setDepthWriteEnable(bool depthWriteEnable) |
576 | { |
577 | context->depthWriteEnable = depthWriteEnable; |
578 | } |
579 | |
580 | void PixelProcessor::setAlphaTestEnable(bool alphaTestEnable) |
581 | { |
582 | context->alphaTestEnable = alphaTestEnable; |
583 | } |
584 | |
585 | void PixelProcessor::setCullMode(CullMode cullMode, bool frontFacingCCW) |
586 | { |
587 | context->cullMode = cullMode; |
588 | context->frontFacingCCW = frontFacingCCW; |
589 | } |
590 | |
591 | void PixelProcessor::setColorWriteMask(int index, int rgbaMask) |
592 | { |
593 | context->setColorWriteMask(index, rgbaMask); |
594 | } |
595 | |
596 | void PixelProcessor::setStencilEnable(bool stencilEnable) |
597 | { |
598 | context->stencilEnable = stencilEnable; |
599 | } |
600 | |
601 | void PixelProcessor::setStencilCompare(StencilCompareMode stencilCompareMode) |
602 | { |
603 | context->stencilCompareMode = stencilCompareMode; |
604 | } |
605 | |
606 | void PixelProcessor::setStencilReference(int stencilReference) |
607 | { |
608 | context->stencilReference = stencilReference; |
609 | stencil.set(stencilReference, context->stencilMask, context->stencilWriteMask); |
610 | } |
611 | |
612 | void PixelProcessor::setStencilReferenceCCW(int stencilReferenceCCW) |
613 | { |
614 | context->stencilReferenceCCW = stencilReferenceCCW; |
615 | stencilCCW.set(stencilReferenceCCW, context->stencilMaskCCW, context->stencilWriteMaskCCW); |
616 | } |
617 | |
618 | void PixelProcessor::setStencilMask(int stencilMask) |
619 | { |
620 | context->stencilMask = stencilMask; |
621 | stencil.set(context->stencilReference, stencilMask, context->stencilWriteMask); |
622 | } |
623 | |
624 | void PixelProcessor::setStencilMaskCCW(int stencilMaskCCW) |
625 | { |
626 | context->stencilMaskCCW = stencilMaskCCW; |
627 | stencilCCW.set(context->stencilReferenceCCW, stencilMaskCCW, context->stencilWriteMaskCCW); |
628 | } |
629 | |
630 | void PixelProcessor::setStencilFailOperation(StencilOperation stencilFailOperation) |
631 | { |
632 | context->stencilFailOperation = stencilFailOperation; |
633 | } |
634 | |
635 | void PixelProcessor::setStencilPassOperation(StencilOperation stencilPassOperation) |
636 | { |
637 | context->stencilPassOperation = stencilPassOperation; |
638 | } |
639 | |
640 | void PixelProcessor::setStencilZFailOperation(StencilOperation stencilZFailOperation) |
641 | { |
642 | context->stencilZFailOperation = stencilZFailOperation; |
643 | } |
644 | |
645 | void PixelProcessor::setStencilWriteMask(int stencilWriteMask) |
646 | { |
647 | context->stencilWriteMask = stencilWriteMask; |
648 | stencil.set(context->stencilReference, context->stencilMask, stencilWriteMask); |
649 | } |
650 | |
651 | void PixelProcessor::setStencilWriteMaskCCW(int stencilWriteMaskCCW) |
652 | { |
653 | context->stencilWriteMaskCCW = stencilWriteMaskCCW; |
654 | stencilCCW.set(context->stencilReferenceCCW, context->stencilMaskCCW, stencilWriteMaskCCW); |
655 | } |
656 | |
657 | void PixelProcessor::setTwoSidedStencil(bool enable) |
658 | { |
659 | context->twoSidedStencil = enable; |
660 | } |
661 | |
662 | void PixelProcessor::setStencilCompareCCW(StencilCompareMode stencilCompareMode) |
663 | { |
664 | context->stencilCompareModeCCW = stencilCompareMode; |
665 | } |
666 | |
667 | void PixelProcessor::setStencilFailOperationCCW(StencilOperation stencilFailOperation) |
668 | { |
669 | context->stencilFailOperationCCW = stencilFailOperation; |
670 | } |
671 | |
672 | void PixelProcessor::setStencilPassOperationCCW(StencilOperation stencilPassOperation) |
673 | { |
674 | context->stencilPassOperationCCW = stencilPassOperation; |
675 | } |
676 | |
677 | void PixelProcessor::setStencilZFailOperationCCW(StencilOperation stencilZFailOperation) |
678 | { |
679 | context->stencilZFailOperationCCW = stencilZFailOperation; |
680 | } |
681 | |
682 | void PixelProcessor::setTextureFactor(const Color<float> &textureFactor) |
683 | { |
684 | // FIXME: Compact into generic function // FIXME: Clamp |
685 | short textureFactorR = iround(4095 * textureFactor.r); |
686 | short textureFactorG = iround(4095 * textureFactor.g); |
687 | short textureFactorB = iround(4095 * textureFactor.b); |
688 | short textureFactorA = iround(4095 * textureFactor.a); |
689 | |
690 | factor.textureFactor4[0][0] = textureFactorR; |
691 | factor.textureFactor4[0][1] = textureFactorR; |
692 | factor.textureFactor4[0][2] = textureFactorR; |
693 | factor.textureFactor4[0][3] = textureFactorR; |
694 | |
695 | factor.textureFactor4[1][0] = textureFactorG; |
696 | factor.textureFactor4[1][1] = textureFactorG; |
697 | factor.textureFactor4[1][2] = textureFactorG; |
698 | factor.textureFactor4[1][3] = textureFactorG; |
699 | |
700 | factor.textureFactor4[2][0] = textureFactorB; |
701 | factor.textureFactor4[2][1] = textureFactorB; |
702 | factor.textureFactor4[2][2] = textureFactorB; |
703 | factor.textureFactor4[2][3] = textureFactorB; |
704 | |
705 | factor.textureFactor4[3][0] = textureFactorA; |
706 | factor.textureFactor4[3][1] = textureFactorA; |
707 | factor.textureFactor4[3][2] = textureFactorA; |
708 | factor.textureFactor4[3][3] = textureFactorA; |
709 | } |
710 | |
711 | void PixelProcessor::setBlendConstant(const Color<float> &blendConstant) |
712 | { |
713 | // FIXME: Compact into generic function // FIXME: Clamp |
714 | short blendConstantR = iround(65535 * blendConstant.r); |
715 | short blendConstantG = iround(65535 * blendConstant.g); |
716 | short blendConstantB = iround(65535 * blendConstant.b); |
717 | short blendConstantA = iround(65535 * blendConstant.a); |
718 | |
719 | factor.blendConstant4W[0][0] = blendConstantR; |
720 | factor.blendConstant4W[0][1] = blendConstantR; |
721 | factor.blendConstant4W[0][2] = blendConstantR; |
722 | factor.blendConstant4W[0][3] = blendConstantR; |
723 | |
724 | factor.blendConstant4W[1][0] = blendConstantG; |
725 | factor.blendConstant4W[1][1] = blendConstantG; |
726 | factor.blendConstant4W[1][2] = blendConstantG; |
727 | factor.blendConstant4W[1][3] = blendConstantG; |
728 | |
729 | factor.blendConstant4W[2][0] = blendConstantB; |
730 | factor.blendConstant4W[2][1] = blendConstantB; |
731 | factor.blendConstant4W[2][2] = blendConstantB; |
732 | factor.blendConstant4W[2][3] = blendConstantB; |
733 | |
734 | factor.blendConstant4W[3][0] = blendConstantA; |
735 | factor.blendConstant4W[3][1] = blendConstantA; |
736 | factor.blendConstant4W[3][2] = blendConstantA; |
737 | factor.blendConstant4W[3][3] = blendConstantA; |
738 | |
739 | // FIXME: Compact into generic function // FIXME: Clamp |
740 | short invBlendConstantR = iround(65535 * (1 - blendConstant.r)); |
741 | short invBlendConstantG = iround(65535 * (1 - blendConstant.g)); |
742 | short invBlendConstantB = iround(65535 * (1 - blendConstant.b)); |
743 | short invBlendConstantA = iround(65535 * (1 - blendConstant.a)); |
744 | |
745 | factor.invBlendConstant4W[0][0] = invBlendConstantR; |
746 | factor.invBlendConstant4W[0][1] = invBlendConstantR; |
747 | factor.invBlendConstant4W[0][2] = invBlendConstantR; |
748 | factor.invBlendConstant4W[0][3] = invBlendConstantR; |
749 | |
750 | factor.invBlendConstant4W[1][0] = invBlendConstantG; |
751 | factor.invBlendConstant4W[1][1] = invBlendConstantG; |
752 | factor.invBlendConstant4W[1][2] = invBlendConstantG; |
753 | factor.invBlendConstant4W[1][3] = invBlendConstantG; |
754 | |
755 | factor.invBlendConstant4W[2][0] = invBlendConstantB; |
756 | factor.invBlendConstant4W[2][1] = invBlendConstantB; |
757 | factor.invBlendConstant4W[2][2] = invBlendConstantB; |
758 | factor.invBlendConstant4W[2][3] = invBlendConstantB; |
759 | |
760 | factor.invBlendConstant4W[3][0] = invBlendConstantA; |
761 | factor.invBlendConstant4W[3][1] = invBlendConstantA; |
762 | factor.invBlendConstant4W[3][2] = invBlendConstantA; |
763 | factor.invBlendConstant4W[3][3] = invBlendConstantA; |
764 | |
765 | factor.blendConstant4F[0][0] = blendConstant.r; |
766 | factor.blendConstant4F[0][1] = blendConstant.r; |
767 | factor.blendConstant4F[0][2] = blendConstant.r; |
768 | factor.blendConstant4F[0][3] = blendConstant.r; |
769 | |
770 | factor.blendConstant4F[1][0] = blendConstant.g; |
771 | factor.blendConstant4F[1][1] = blendConstant.g; |
772 | factor.blendConstant4F[1][2] = blendConstant.g; |
773 | factor.blendConstant4F[1][3] = blendConstant.g; |
774 | |
775 | factor.blendConstant4F[2][0] = blendConstant.b; |
776 | factor.blendConstant4F[2][1] = blendConstant.b; |
777 | factor.blendConstant4F[2][2] = blendConstant.b; |
778 | factor.blendConstant4F[2][3] = blendConstant.b; |
779 | |
780 | factor.blendConstant4F[3][0] = blendConstant.a; |
781 | factor.blendConstant4F[3][1] = blendConstant.a; |
782 | factor.blendConstant4F[3][2] = blendConstant.a; |
783 | factor.blendConstant4F[3][3] = blendConstant.a; |
784 | |
785 | factor.invBlendConstant4F[0][0] = 1 - blendConstant.r; |
786 | factor.invBlendConstant4F[0][1] = 1 - blendConstant.r; |
787 | factor.invBlendConstant4F[0][2] = 1 - blendConstant.r; |
788 | factor.invBlendConstant4F[0][3] = 1 - blendConstant.r; |
789 | |
790 | factor.invBlendConstant4F[1][0] = 1 - blendConstant.g; |
791 | factor.invBlendConstant4F[1][1] = 1 - blendConstant.g; |
792 | factor.invBlendConstant4F[1][2] = 1 - blendConstant.g; |
793 | factor.invBlendConstant4F[1][3] = 1 - blendConstant.g; |
794 | |
795 | factor.invBlendConstant4F[2][0] = 1 - blendConstant.b; |
796 | factor.invBlendConstant4F[2][1] = 1 - blendConstant.b; |
797 | factor.invBlendConstant4F[2][2] = 1 - blendConstant.b; |
798 | factor.invBlendConstant4F[2][3] = 1 - blendConstant.b; |
799 | |
800 | factor.invBlendConstant4F[3][0] = 1 - blendConstant.a; |
801 | factor.invBlendConstant4F[3][1] = 1 - blendConstant.a; |
802 | factor.invBlendConstant4F[3][2] = 1 - blendConstant.a; |
803 | factor.invBlendConstant4F[3][3] = 1 - blendConstant.a; |
804 | } |
805 | |
806 | void PixelProcessor::setFillMode(FillMode fillMode) |
807 | { |
808 | context->fillMode = fillMode; |
809 | } |
810 | |
811 | void PixelProcessor::setShadingMode(ShadingMode shadingMode) |
812 | { |
813 | context->shadingMode = shadingMode; |
814 | } |
815 | |
816 | void PixelProcessor::setAlphaBlendEnable(bool alphaBlendEnable) |
817 | { |
818 | context->setAlphaBlendEnable(alphaBlendEnable); |
819 | } |
820 | |
821 | void PixelProcessor::setSourceBlendFactor(BlendFactor sourceBlendFactor) |
822 | { |
823 | context->setSourceBlendFactor(sourceBlendFactor); |
824 | } |
825 | |
826 | void PixelProcessor::setDestBlendFactor(BlendFactor destBlendFactor) |
827 | { |
828 | context->setDestBlendFactor(destBlendFactor); |
829 | } |
830 | |
831 | void PixelProcessor::setBlendOperation(BlendOperation blendOperation) |
832 | { |
833 | context->setBlendOperation(blendOperation); |
834 | } |
835 | |
836 | void PixelProcessor::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable) |
837 | { |
838 | context->setSeparateAlphaBlendEnable(separateAlphaBlendEnable); |
839 | } |
840 | |
841 | void PixelProcessor::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha) |
842 | { |
843 | context->setSourceBlendFactorAlpha(sourceBlendFactorAlpha); |
844 | } |
845 | |
846 | void PixelProcessor::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha) |
847 | { |
848 | context->setDestBlendFactorAlpha(destBlendFactorAlpha); |
849 | } |
850 | |
851 | void PixelProcessor::setBlendOperationAlpha(BlendOperation blendOperationAlpha) |
852 | { |
853 | context->setBlendOperationAlpha(blendOperationAlpha); |
854 | } |
855 | |
856 | void PixelProcessor::setAlphaReference(float alphaReference) |
857 | { |
858 | context->alphaReference = alphaReference; |
859 | |
860 | factor.alphaReference4[0] = (word)iround(alphaReference * 0x1000 / 0xFF); |
861 | factor.alphaReference4[1] = (word)iround(alphaReference * 0x1000 / 0xFF); |
862 | factor.alphaReference4[2] = (word)iround(alphaReference * 0x1000 / 0xFF); |
863 | factor.alphaReference4[3] = (word)iround(alphaReference * 0x1000 / 0xFF); |
864 | } |
865 | |
866 | void PixelProcessor::setGlobalMipmapBias(float bias) |
867 | { |
868 | context->setGlobalMipmapBias(bias); |
869 | } |
870 | |
871 | void PixelProcessor::setFogStart(float start) |
872 | { |
873 | setFogRanges(start, context->fogEnd); |
874 | } |
875 | |
876 | void PixelProcessor::setFogEnd(float end) |
877 | { |
878 | setFogRanges(context->fogStart, end); |
879 | } |
880 | |
881 | void PixelProcessor::setFogColor(Color<float> fogColor) |
882 | { |
883 | // TODO: Compact into generic function |
884 | word fogR = (unsigned short)(65535 * fogColor.r); |
885 | word fogG = (unsigned short)(65535 * fogColor.g); |
886 | word fogB = (unsigned short)(65535 * fogColor.b); |
887 | |
888 | fog.color4[0][0] = fogR; |
889 | fog.color4[0][1] = fogR; |
890 | fog.color4[0][2] = fogR; |
891 | fog.color4[0][3] = fogR; |
892 | |
893 | fog.color4[1][0] = fogG; |
894 | fog.color4[1][1] = fogG; |
895 | fog.color4[1][2] = fogG; |
896 | fog.color4[1][3] = fogG; |
897 | |
898 | fog.color4[2][0] = fogB; |
899 | fog.color4[2][1] = fogB; |
900 | fog.color4[2][2] = fogB; |
901 | fog.color4[2][3] = fogB; |
902 | |
903 | fog.colorF[0] = replicate(fogColor.r); |
904 | fog.colorF[1] = replicate(fogColor.g); |
905 | fog.colorF[2] = replicate(fogColor.b); |
906 | } |
907 | |
908 | void PixelProcessor::setFogDensity(float fogDensity) |
909 | { |
910 | fog.densityE = replicate(-fogDensity * 1.442695f); // 1/e^x = 2^(-x*1.44) |
911 | fog.density2E = replicate(-fogDensity * fogDensity * 1.442695f); |
912 | } |
913 | |
914 | void PixelProcessor::setPixelFogMode(FogMode fogMode) |
915 | { |
916 | context->pixelFogMode = fogMode; |
917 | } |
918 | |
919 | void PixelProcessor::setPerspectiveCorrection(bool perspectiveEnable) |
920 | { |
921 | perspectiveCorrection = perspectiveEnable; |
922 | } |
923 | |
924 | void PixelProcessor::setOcclusionEnabled(bool enable) |
925 | { |
926 | context->occlusionEnabled = enable; |
927 | } |
928 | |
929 | void PixelProcessor::setRoutineCacheSize(int cacheSize) |
930 | { |
931 | delete routineCache; |
932 | routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536)); |
933 | } |
934 | |
935 | void PixelProcessor::setFogRanges(float start, float end) |
936 | { |
937 | context->fogStart = start; |
938 | context->fogEnd = end; |
939 | |
940 | if(start == end) |
941 | { |
942 | end += 0.001f; // Hack: ensure there is a small range |
943 | } |
944 | |
945 | float fogScale = -1.0f / (end - start); |
946 | float fogOffset = end * -fogScale; |
947 | |
948 | fog.scale = replicate(fogScale); |
949 | fog.offset = replicate(fogOffset); |
950 | } |
951 | |
952 | const PixelProcessor::State PixelProcessor::update() const |
953 | { |
954 | State state; |
955 | |
956 | if(context->pixelShader) |
957 | { |
958 | state.shaderID = context->pixelShader->getSerialID(); |
959 | } |
960 | else |
961 | { |
962 | state.shaderID = 0; |
963 | } |
964 | |
965 | state.depthOverride = context->pixelShader && context->pixelShader->depthOverride(); |
966 | state.shaderContainsKill = context->pixelShader ? context->pixelShader->containsKill() : false; |
967 | |
968 | if(context->alphaTestActive()) |
969 | { |
970 | state.alphaCompareMode = context->alphaCompareMode; |
971 | |
972 | state.transparencyAntialiasing = context->getMultiSampleCount() > 1 ? transparencyAntialiasing : TRANSPARENCY_NONE; |
973 | } |
974 | |
975 | state.depthWriteEnable = context->depthWriteActive(); |
976 | |
977 | if(context->stencilActive()) |
978 | { |
979 | state.stencilActive = true; |
980 | state.stencilCompareMode = context->stencilCompareMode; |
981 | state.stencilFailOperation = context->stencilFailOperation; |
982 | state.stencilPassOperation = context->stencilPassOperation; |
983 | state.stencilZFailOperation = context->stencilZFailOperation; |
984 | state.noStencilMask = (context->stencilMask == 0xFF); |
985 | state.noStencilWriteMask = (context->stencilWriteMask == 0xFF); |
986 | state.stencilWriteMasked = (context->stencilWriteMask == 0x00); |
987 | |
988 | state.twoSidedStencil = context->twoSidedStencil; |
989 | state.stencilCompareModeCCW = context->twoSidedStencil ? context->stencilCompareModeCCW : state.stencilCompareMode; |
990 | state.stencilFailOperationCCW = context->twoSidedStencil ? context->stencilFailOperationCCW : state.stencilFailOperation; |
991 | state.stencilPassOperationCCW = context->twoSidedStencil ? context->stencilPassOperationCCW : state.stencilPassOperation; |
992 | state.stencilZFailOperationCCW = context->twoSidedStencil ? context->stencilZFailOperationCCW : state.stencilZFailOperation; |
993 | state.noStencilMaskCCW = context->twoSidedStencil ? (context->stencilMaskCCW == 0xFF) : state.noStencilMask; |
994 | state.noStencilWriteMaskCCW = context->twoSidedStencil ? (context->stencilWriteMaskCCW == 0xFF) : state.noStencilWriteMask; |
995 | state.stencilWriteMaskedCCW = context->twoSidedStencil ? (context->stencilWriteMaskCCW == 0x00) : state.stencilWriteMasked; |
996 | } |
997 | |
998 | if(context->depthBufferActive()) |
999 | { |
1000 | state.depthTestActive = true; |
1001 | state.depthCompareMode = context->depthCompareMode; |
1002 | state.quadLayoutDepthBuffer = Surface::hasQuadLayout(context->depthBuffer->getInternalFormat()); |
1003 | } |
1004 | |
1005 | state.occlusionEnabled = context->occlusionEnabled; |
1006 | |
1007 | state.fogActive = context->fogActive(); |
1008 | state.pixelFogMode = context->pixelFogActive(); |
1009 | state.wBasedFog = context->wBasedFog && context->pixelFogActive() != FOG_NONE; |
1010 | state.perspective = context->perspectiveActive(); |
1011 | state.depthClamp = (context->depthBias != 0.0f) || (context->slopeDepthBias != 0.0f); |
1012 | |
1013 | if(context->alphaBlendActive()) |
1014 | { |
1015 | state.alphaBlendActive = true; |
1016 | state.sourceBlendFactor = context->sourceBlendFactor(); |
1017 | state.destBlendFactor = context->destBlendFactor(); |
1018 | state.blendOperation = context->blendOperation(); |
1019 | state.sourceBlendFactorAlpha = context->sourceBlendFactorAlpha(); |
1020 | state.destBlendFactorAlpha = context->destBlendFactorAlpha(); |
1021 | state.blendOperationAlpha = context->blendOperationAlpha(); |
1022 | } |
1023 | |
1024 | state.logicalOperation = context->colorLogicOp(); |
1025 | |
1026 | for(int i = 0; i < RENDERTARGETS; i++) |
1027 | { |
1028 | state.colorWriteMask |= context->colorWriteActive(i) << (4 * i); |
1029 | state.targetFormat[i] = context->renderTargetInternalFormat(i); |
1030 | } |
1031 | |
1032 | state.writeSRGB = context->writeSRGB && context->renderTarget[0] && Surface::isSRGBwritable(context->renderTarget[0]->getExternalFormat()); |
1033 | state.multiSample = context->getMultiSampleCount(); |
1034 | state.multiSampleMask = context->multiSampleMask; |
1035 | |
1036 | if(state.multiSample > 1 && context->pixelShader) |
1037 | { |
1038 | state.centroid = context->pixelShader->containsCentroid(); |
1039 | } |
1040 | |
1041 | state.frontFaceCCW = context->frontFacingCCW; |
1042 | |
1043 | if(!context->pixelShader) |
1044 | { |
1045 | for(unsigned int i = 0; i < 8; i++) |
1046 | { |
1047 | state.textureStage[i] = context->textureStage[i].textureStageState(); |
1048 | } |
1049 | |
1050 | state.specularAdd = context->specularActive() && context->specularEnable; |
1051 | } |
1052 | |
1053 | for(unsigned int i = 0; i < 16; i++) |
1054 | { |
1055 | if(context->pixelShader) |
1056 | { |
1057 | if(context->pixelShader->usesSampler(i)) |
1058 | { |
1059 | state.sampler[i] = context->sampler[i].samplerState(); |
1060 | } |
1061 | } |
1062 | else |
1063 | { |
1064 | if(i < 8 && state.textureStage[i].stageOperation != TextureStage::STAGE_DISABLE) |
1065 | { |
1066 | state.sampler[i] = context->sampler[i].samplerState(); |
1067 | } |
1068 | else break; |
1069 | } |
1070 | } |
1071 | |
1072 | const bool point = context->isDrawPoint(true); |
1073 | const bool sprite = context->pointSpriteActive(); |
1074 | const bool flatShading = (context->shadingMode == SHADING_FLAT) || point; |
1075 | |
1076 | if(context->pixelShaderModel() < 0x0300) |
1077 | { |
1078 | for(int coordinate = 0; coordinate < 8; coordinate++) |
1079 | { |
1080 | for(int component = 0; component < 4; component++) |
1081 | { |
1082 | if(context->textureActive(coordinate, component)) |
1083 | { |
1084 | state.texture[coordinate].component |= 1 << component; |
1085 | |
1086 | if(point && !sprite) |
1087 | { |
1088 | state.texture[coordinate].flat |= 1 << component; |
1089 | } |
1090 | } |
1091 | } |
1092 | |
1093 | if(context->textureTransformProject[coordinate] && context->pixelShaderModel() <= 0x0103) |
1094 | { |
1095 | if(context->textureTransformCount[coordinate] == 2) |
1096 | { |
1097 | state.texture[coordinate].project = 1; |
1098 | } |
1099 | else if(context->textureTransformCount[coordinate] == 3) |
1100 | { |
1101 | state.texture[coordinate].project = 2; |
1102 | } |
1103 | else if(context->textureTransformCount[coordinate] == 4 || context->textureTransformCount[coordinate] == 0) |
1104 | { |
1105 | state.texture[coordinate].project = 3; |
1106 | } |
1107 | } |
1108 | } |
1109 | |
1110 | for(int color = 0; color < 2; color++) |
1111 | { |
1112 | for(int component = 0; component < 4; component++) |
1113 | { |
1114 | if(context->colorActive(color, component)) |
1115 | { |
1116 | state.color[color].component |= 1 << component; |
1117 | |
1118 | if(point || flatShading) |
1119 | { |
1120 | state.color[color].flat |= 1 << component; |
1121 | } |
1122 | } |
1123 | } |
1124 | } |
1125 | |
1126 | if(context->fogActive()) |
1127 | { |
1128 | state.fog.component = true; |
1129 | |
1130 | if(point) |
1131 | { |
1132 | state.fog.flat = true; |
1133 | } |
1134 | } |
1135 | } |
1136 | else |
1137 | { |
1138 | for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) |
1139 | { |
1140 | for(int component = 0; component < 4; component++) |
1141 | { |
1142 | const Shader::Semantic &semantic = context->pixelShader->getInput(interpolant, component); |
1143 | |
1144 | if(semantic.active()) |
1145 | { |
1146 | bool flat = point; |
1147 | |
1148 | switch(semantic.usage) |
1149 | { |
1150 | case Shader::USAGE_TEXCOORD: flat = point && !sprite; break; |
1151 | case Shader::USAGE_COLOR: flat = semantic.flat || flatShading; break; |
1152 | } |
1153 | |
1154 | state.interpolant[interpolant].component |= 1 << component; |
1155 | |
1156 | if(flat) |
1157 | { |
1158 | state.interpolant[interpolant].flat |= 1 << component; |
1159 | } |
1160 | } |
1161 | } |
1162 | } |
1163 | } |
1164 | |
1165 | if(state.centroid) |
1166 | { |
1167 | for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) |
1168 | { |
1169 | for(int component = 0; component < 4; component++) |
1170 | { |
1171 | state.interpolant[interpolant].centroid = context->pixelShader->getInput(interpolant, 0).centroid; |
1172 | } |
1173 | } |
1174 | } |
1175 | |
1176 | state.hash = state.computeHash(); |
1177 | |
1178 | return state; |
1179 | } |
1180 | |
1181 | std::shared_ptr<Routine> PixelProcessor::routine(const State &state) |
1182 | { |
1183 | auto routine = routineCache->query(state); |
1184 | |
1185 | if(!routine) |
1186 | { |
1187 | const bool integerPipeline = (context->pixelShaderModel() <= 0x0104); |
1188 | QuadRasterizer *generator = nullptr; |
1189 | |
1190 | if(integerPipeline) |
1191 | { |
1192 | generator = new PixelPipeline(state, context->pixelShader); |
1193 | } |
1194 | else |
1195 | { |
1196 | generator = new PixelProgram(state, context->pixelShader); |
1197 | } |
1198 | |
1199 | generator->generate(); |
1200 | routine = (*generator)("PixelRoutine_%0.8X" , state.shaderID); |
1201 | delete generator; |
1202 | |
1203 | routineCache->add(state, routine); |
1204 | } |
1205 | |
1206 | return routine; |
1207 | } |
1208 | } |
1209 | |