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 "Context.hpp"
16
17#include "Primitive.hpp"
18#include "System/Memory.hpp"
19#include "Vulkan/VkDebug.hpp"
20#include "Vulkan/VkImageView.hpp"
21#include "Pipeline/SpirvShader.hpp"
22
23#include <string.h>
24
25namespace sw
26{
27 Context::Context()
28 {
29 init();
30 }
31
32 bool Context::isDrawPoint(bool polygonModeAware) const
33 {
34 switch(topology)
35 {
36 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
37 return true;
38 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
39 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
40 return false;
41 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
42 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
43 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
44 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_POINT) : false;
45 default:
46 UNIMPLEMENTED("topology %d", int(topology));
47 }
48 return false;
49 }
50
51 bool Context::isDrawLine(bool polygonModeAware) const
52 {
53 switch(topology)
54 {
55 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
56 return false;
57 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
58 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
59 return true;
60 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
61 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
62 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
63 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_LINE) : false;
64 default:
65 UNIMPLEMENTED("topology %d", int(topology));
66 }
67 return false;
68 }
69
70 bool Context::isDrawTriangle(bool polygonModeAware) const
71 {
72 switch(topology)
73 {
74 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
75 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
76 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
77 return false;
78 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
79 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
80 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
81 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_FILL) : true;
82 default:
83 UNIMPLEMENTED("topology %d", int(topology));
84 }
85 return false;
86 }
87
88 void Context::init()
89 {
90 for(int i = 0; i < RENDERTARGETS; ++i)
91 {
92 renderTarget[i] = nullptr;
93 }
94
95 depthBuffer = nullptr;
96 stencilBuffer = nullptr;
97
98 stencilEnable = false;
99 frontStencil = {};
100 backStencil = {};
101
102 robustBufferAccess = false;
103
104 rasterizerDiscard = false;
105
106 depthCompareMode = VK_COMPARE_OP_LESS;
107 depthBoundsTestEnable = false;
108 depthBufferEnable = false;
109 depthWriteEnable = false;
110
111 cullMode = VK_CULL_MODE_FRONT_BIT;
112 frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
113 provokingVertexMode = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
114 lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
115
116 depthBias = 0.0f;
117 slopeDepthBias = 0.0f;
118
119 for(int i = 0; i < RENDERTARGETS; i++)
120 {
121 colorWriteMask[i] = 0x0000000F;
122 }
123
124 pipelineLayout = nullptr;
125
126 pixelShader = nullptr;
127 vertexShader = nullptr;
128
129 occlusionEnabled = false;
130
131 lineWidth = 1.0f;
132
133 sampleMask = 0xFFFFFFFF;
134 alphaToCoverage = false;
135 }
136
137 bool Context::depthWriteActive() const
138 {
139 if(!depthBufferActive()) return false;
140
141 return depthWriteEnable;
142 }
143
144 bool Context::depthBufferActive() const
145 {
146 return depthBuffer && depthBufferEnable;
147 }
148
149 bool Context::stencilActive() const
150 {
151 return stencilBuffer && stencilEnable;
152 }
153
154 void Context::setBlendState(int index, BlendState state)
155 {
156 ASSERT((index >= 0) && (index < RENDERTARGETS));
157
158 blendState[index] = state;
159 }
160
161 BlendState Context::getBlendState(int index) const
162 {
163 ASSERT((index >= 0) && (index < RENDERTARGETS));
164
165 BlendState activeBlendState;
166 activeBlendState.alphaBlendEnable = alphaBlendActive(index);
167 activeBlendState.sourceBlendFactor = sourceBlendFactor(index);
168 activeBlendState.destBlendFactor = destBlendFactor(index);
169 activeBlendState.blendOperation = blendOperation(index);
170 activeBlendState.sourceBlendFactorAlpha = sourceBlendFactorAlpha(index);
171 activeBlendState.destBlendFactorAlpha = destBlendFactorAlpha(index);
172 activeBlendState.blendOperationAlpha = blendOperationAlpha(index);
173 return activeBlendState;
174 }
175
176 bool Context::alphaBlendActive(int index) const
177 {
178 ASSERT((index >= 0) && (index < RENDERTARGETS));
179
180 if(!blendState[index].alphaBlendEnable)
181 {
182 return false;
183 }
184
185 if(!colorUsed())
186 {
187 return false;
188 }
189
190 bool colorBlend = !(blendOperation(index) == VK_BLEND_OP_SRC_EXT && sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE);
191 bool alphaBlend = !(blendOperationAlpha(index) == VK_BLEND_OP_SRC_EXT && sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE);
192
193 return colorBlend || alphaBlend;
194 }
195
196 VkBlendFactor Context::sourceBlendFactor(int index) const
197 {
198 ASSERT((index >= 0) && (index < RENDERTARGETS));
199
200 if(!blendState[index].alphaBlendEnable) return VK_BLEND_FACTOR_ONE;
201
202 switch(blendState[index].blendOperation)
203 {
204 case VK_BLEND_OP_ADD:
205 case VK_BLEND_OP_SUBTRACT:
206 case VK_BLEND_OP_REVERSE_SUBTRACT:
207 return blendState[index].sourceBlendFactor;
208 case VK_BLEND_OP_MIN:
209 return VK_BLEND_FACTOR_ONE;
210 case VK_BLEND_OP_MAX:
211 return VK_BLEND_FACTOR_ONE;
212 default:
213 ASSERT(false);
214 }
215
216 return blendState[index].sourceBlendFactor;
217 }
218
219 VkBlendFactor Context::destBlendFactor(int index) const
220 {
221 ASSERT((index >= 0) && (index < RENDERTARGETS));
222
223 if(!blendState[index].alphaBlendEnable) return VK_BLEND_FACTOR_ONE;
224
225 switch(blendState[index].blendOperation)
226 {
227 case VK_BLEND_OP_ADD:
228 case VK_BLEND_OP_SUBTRACT:
229 case VK_BLEND_OP_REVERSE_SUBTRACT:
230 return blendState[index].destBlendFactor;
231 case VK_BLEND_OP_MIN:
232 return VK_BLEND_FACTOR_ONE;
233 case VK_BLEND_OP_MAX:
234 return VK_BLEND_FACTOR_ONE;
235 default:
236 ASSERT(false);
237 }
238
239 return blendState[index].destBlendFactor;
240 }
241
242 bool Context::allTargetsColorClamp() const
243 {
244 // TODO: remove all of this and support VkPhysicalDeviceFeatures::independentBlend instead
245 for (int i = 0; i < RENDERTARGETS; i++)
246 {
247 if (renderTarget[i] && renderTarget[i]->getFormat().isFloatFormat())
248 {
249 return false;
250 }
251 }
252
253 return true;
254 }
255
256 VkBlendOp Context::blendOperation(int index) const
257 {
258 ASSERT((index >= 0) && (index < RENDERTARGETS));
259
260 if(!blendState[index].alphaBlendEnable) return VK_BLEND_OP_SRC_EXT;
261
262 switch(blendState[index].blendOperation)
263 {
264 case VK_BLEND_OP_ADD:
265 if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
266 {
267 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
268 {
269 return VK_BLEND_OP_ZERO_EXT;
270 }
271 else
272 {
273 return VK_BLEND_OP_DST_EXT;
274 }
275 }
276 else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
277 {
278 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
279 {
280 return VK_BLEND_OP_SRC_EXT;
281 }
282 else
283 {
284 return VK_BLEND_OP_ADD;
285 }
286 }
287 else
288 {
289 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
290 {
291 return VK_BLEND_OP_SRC_EXT;
292 }
293 else
294 {
295 return VK_BLEND_OP_ADD;
296 }
297 }
298 case VK_BLEND_OP_SUBTRACT:
299 if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
300 {
301 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
302 }
303 else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
304 {
305 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
306 {
307 return VK_BLEND_OP_SRC_EXT;
308 }
309 else
310 {
311 return VK_BLEND_OP_SUBTRACT;
312 }
313 }
314 else
315 {
316 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
317 {
318 return VK_BLEND_OP_SRC_EXT;
319 }
320 else
321 {
322 return VK_BLEND_OP_SUBTRACT;
323 }
324 }
325 case VK_BLEND_OP_REVERSE_SUBTRACT:
326 if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
327 {
328 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
329 {
330 return VK_BLEND_OP_ZERO_EXT;
331 }
332 else
333 {
334 return VK_BLEND_OP_DST_EXT;
335 }
336 }
337 else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
338 {
339 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
340 {
341 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
342 }
343 else
344 {
345 return VK_BLEND_OP_REVERSE_SUBTRACT;
346 }
347 }
348 else
349 {
350 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
351 {
352 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
353 }
354 else
355 {
356 return VK_BLEND_OP_REVERSE_SUBTRACT;
357 }
358 }
359 case VK_BLEND_OP_MIN:
360 return VK_BLEND_OP_MIN;
361 case VK_BLEND_OP_MAX:
362 return VK_BLEND_OP_MAX;
363 default:
364 ASSERT(false);
365 }
366
367 return blendState[index].blendOperation;
368 }
369
370 VkBlendFactor Context::sourceBlendFactorAlpha(int index) const
371 {
372 ASSERT((index >= 0) && (index < RENDERTARGETS));
373
374 switch (blendState[index].blendOperationAlpha)
375 {
376 case VK_BLEND_OP_ADD:
377 case VK_BLEND_OP_SUBTRACT:
378 case VK_BLEND_OP_REVERSE_SUBTRACT:
379 return blendState[index].sourceBlendFactorAlpha;
380 case VK_BLEND_OP_MIN:
381 return VK_BLEND_FACTOR_ONE;
382 case VK_BLEND_OP_MAX:
383 return VK_BLEND_FACTOR_ONE;
384 default:
385 ASSERT(false);
386 }
387
388 return blendState[index].sourceBlendFactorAlpha;
389 }
390
391 VkBlendFactor Context::destBlendFactorAlpha(int index) const
392 {
393 ASSERT((index >= 0) && (index < RENDERTARGETS));
394
395 switch (blendState[index].blendOperationAlpha)
396 {
397 case VK_BLEND_OP_ADD:
398 case VK_BLEND_OP_SUBTRACT:
399 case VK_BLEND_OP_REVERSE_SUBTRACT:
400 return blendState[index].destBlendFactorAlpha;
401 case VK_BLEND_OP_MIN:
402 return VK_BLEND_FACTOR_ONE;
403 case VK_BLEND_OP_MAX:
404 return VK_BLEND_FACTOR_ONE;
405 default:
406 ASSERT(false);
407 }
408
409 return blendState[index].destBlendFactorAlpha;
410 }
411
412 VkBlendOp Context::blendOperationAlpha(int index) const
413 {
414 ASSERT((index >= 0) && (index < RENDERTARGETS));
415
416 switch (blendState[index].blendOperationAlpha)
417 {
418 case VK_BLEND_OP_ADD:
419 if (sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
420 {
421 if (destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
422 {
423 return VK_BLEND_OP_ZERO_EXT;
424 }
425 else
426 {
427 return VK_BLEND_OP_DST_EXT;
428 }
429 }
430 else if (sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE)
431 {
432 if (destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
433 {
434 return VK_BLEND_OP_SRC_EXT;
435 }
436 else
437 {
438 return VK_BLEND_OP_ADD;
439 }
440 }
441 else
442 {
443 if (destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
444 {
445 return VK_BLEND_OP_SRC_EXT;
446 }
447 else
448 {
449 return VK_BLEND_OP_ADD;
450 }
451 }
452 case VK_BLEND_OP_SUBTRACT:
453 if (sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
454 {
455 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
456 }
457 else if (sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE)
458 {
459 if (destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
460 {
461 return VK_BLEND_OP_SRC_EXT;
462 }
463 else
464 {
465 return VK_BLEND_OP_SUBTRACT;
466 }
467 }
468 else
469 {
470 if (destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
471 {
472 return VK_BLEND_OP_SRC_EXT;
473 }
474 else
475 {
476 return VK_BLEND_OP_SUBTRACT;
477 }
478 }
479 case VK_BLEND_OP_REVERSE_SUBTRACT:
480 if (sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
481 {
482 if (destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
483 {
484 return VK_BLEND_OP_ZERO_EXT;
485 }
486 else
487 {
488 return VK_BLEND_OP_DST_EXT;
489 }
490 }
491 else if (sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE)
492 {
493 if (destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
494 {
495 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
496 }
497 else
498 {
499 return VK_BLEND_OP_REVERSE_SUBTRACT;
500 }
501 }
502 else
503 {
504 if (destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
505 {
506 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
507 }
508 else
509 {
510 return VK_BLEND_OP_REVERSE_SUBTRACT;
511 }
512 }
513 case VK_BLEND_OP_MIN:
514 return VK_BLEND_OP_MIN;
515 case VK_BLEND_OP_MAX:
516 return VK_BLEND_OP_MAX;
517 default:
518 ASSERT(false);
519 }
520
521 return blendState[index].blendOperationAlpha;
522 }
523
524 VkFormat Context::renderTargetInternalFormat(int index) const
525 {
526 ASSERT((index >= 0) && (index < RENDERTARGETS));
527
528 if(renderTarget[index])
529 {
530 return renderTarget[index]->getFormat();
531 }
532 else
533 {
534 return VK_FORMAT_UNDEFINED;
535 }
536 }
537
538 bool Context::colorWriteActive() const
539 {
540 for (int i = 0; i < RENDERTARGETS; i++)
541 {
542 if (colorWriteActive(i))
543 {
544 return true;
545 }
546 }
547
548 return false;
549 }
550
551 int Context::colorWriteActive(int index) const
552 {
553 ASSERT((index >= 0) && (index < RENDERTARGETS));
554
555 if(!renderTarget[index] || renderTarget[index]->getFormat() == VK_FORMAT_UNDEFINED)
556 {
557 return 0;
558 }
559
560 if(blendOperation(index) == VK_BLEND_OP_DST_EXT && destBlendFactor(index) == VK_BLEND_FACTOR_ONE &&
561 (blendOperationAlpha(index) == VK_BLEND_OP_DST_EXT && destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE))
562 {
563 return 0;
564 }
565
566 return colorWriteMask[index];
567 }
568
569 bool Context::colorUsed() const
570 {
571 return colorWriteActive() || (pixelShader && pixelShader->getModes().ContainsKill);
572 }
573}
574