blob: e41ce74e8262af6fd7d298b2a1b2a14f38061b51 [file] [log] [blame]
Nicolas Capens68a82382018-10-02 13:16:55 -04001// 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"
Nicolas Capens1d8c8db2018-11-05 16:30:42 -050018#include "System/Memory.hpp"
Chris Forbesebe5f7f2019-01-16 10:38:34 -080019#include "Vulkan/VkDebug.hpp"
Alexis Hetu6159a852019-02-26 14:42:36 -050020#include "Vulkan/VkImageView.hpp"
Chris Forbes1845d5e2018-12-27 11:50:15 -080021#include "Pipeline/SpirvShader.hpp"
Nicolas Capens68a82382018-10-02 13:16:55 -040022
23#include <string.h>
24
Nicolas Capens157ba262019-12-10 17:49:14 -050025namespace sw {
26
27Context::Context()
Nicolas Capens68a82382018-10-02 13:16:55 -040028{
Nicolas Capens157ba262019-12-10 17:49:14 -050029 init();
30}
31
32bool Context::isDrawPoint(bool polygonModeAware) const
33{
34 switch(topology)
Nicolas Capens68a82382018-10-02 13:16:55 -040035 {
Nicolas Capens157ba262019-12-10 17:49:14 -050036 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
Chris Forbes4d659342019-05-10 13:40:00 -070037 return true;
Nicolas Capens157ba262019-12-10 17:49:14 -050038 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
51bool 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
70bool 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
88void Context::init()
89{
90 for(int i = 0; i < RENDERTARGETS; ++i)
91 {
92 renderTarget[i] = nullptr;
Chris Forbes4d659342019-05-10 13:40:00 -070093 }
94
Nicolas Capens157ba262019-12-10 17:49:14 -050095 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++)
Nicolas Capens68a82382018-10-02 13:16:55 -0400120 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500121 colorWriteMask[i] = 0x0000000F;
122 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400123
Nicolas Capens157ba262019-12-10 17:49:14 -0500124 pipelineLayout = nullptr;
Alexis Hetu51d51082019-07-15 17:20:40 -0400125
Nicolas Capens157ba262019-12-10 17:49:14 -0500126 pixelShader = nullptr;
127 vertexShader = nullptr;
128
129 occlusionEnabled = false;
130
131 lineWidth = 1.0f;
132
133 sampleMask = 0xFFFFFFFF;
134 alphaToCoverage = false;
135}
136
137bool Context::depthWriteActive() const
138{
139 if(!depthBufferActive()) return false;
140
141 return depthWriteEnable;
142}
143
144bool Context::depthBufferActive() const
145{
146 return depthBuffer && depthBufferEnable;
147}
148
149bool Context::stencilActive() const
150{
151 return stencilBuffer && stencilEnable;
152}
153
154void Context::setBlendState(int index, BlendState state)
155{
156 ASSERT((index >= 0) && (index < RENDERTARGETS));
157
158 blendState[index] = state;
159}
160
161BlendState 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
176bool 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
196VkBlendFactor 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
219VkBlendFactor 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
242bool 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())
Nicolas Capens68a82382018-10-02 13:16:55 -0400248 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500249 return false;
Nicolas Capens68a82382018-10-02 13:16:55 -0400250 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400251 }
252
Nicolas Capens157ba262019-12-10 17:49:14 -0500253 return true;
254}
255
256VkBlendOp 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)
Nicolas Capens68a82382018-10-02 13:16:55 -0400263 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500264 case VK_BLEND_OP_ADD:
265 if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
Nicolas Capens68a82382018-10-02 13:16:55 -0400266 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500267 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
Nicolas Capens68a82382018-10-02 13:16:55 -0400268 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500269 return VK_BLEND_OP_ZERO_EXT;
Chris Forbes3e351312019-05-14 17:33:01 -0700270 }
271 else
272 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500273 return VK_BLEND_OP_DST_EXT;
Chris Forbes3e351312019-05-14 17:33:01 -0700274 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400275 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500276 else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
Nicolas Capens68a82382018-10-02 13:16:55 -0400277 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500278 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 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400286 }
287 else
288 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500289 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
Chris Forbesbc63cf92019-02-28 09:03:38 -0800290 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500291 return VK_BLEND_OP_SRC_EXT;
292 }
293 else
294 {
295 return VK_BLEND_OP_ADD;
Chris Forbesbc63cf92019-02-28 09:03:38 -0800296 }
297 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500298 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);
Nicolas Capens68a82382018-10-02 13:16:55 -0400365 }
366
Nicolas Capens157ba262019-12-10 17:49:14 -0500367 return blendState[index].blendOperation;
368}
369
370VkBlendFactor Context::sourceBlendFactorAlpha(int index) const
371{
372 ASSERT((index >= 0) && (index < RENDERTARGETS));
373
374 switch (blendState[index].blendOperationAlpha)
Nicolas Capens68a82382018-10-02 13:16:55 -0400375 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500376 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);
Nicolas Capens68a82382018-10-02 13:16:55 -0400386 }
387
Nicolas Capens157ba262019-12-10 17:49:14 -0500388 return blendState[index].sourceBlendFactorAlpha;
389}
390
391VkBlendFactor Context::destBlendFactorAlpha(int index) const
392{
393 ASSERT((index >= 0) && (index < RENDERTARGETS));
394
395 switch (blendState[index].blendOperationAlpha)
Nicolas Capens68a82382018-10-02 13:16:55 -0400396 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500397 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
412VkBlendOp 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
524VkFormat 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;
Nicolas Capens68a82382018-10-02 13:16:55 -0400535 }
536}
Nicolas Capens157ba262019-12-10 17:49:14 -0500537
538bool 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
551int 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
569bool Context::colorUsed() const
570{
571 return colorWriteActive() || (pixelShader && pixelShader->getModes().ContainsKill);
572}
573
574} // namespace sw