blob: b5f36bf9d3af3ec6ea3ad10b112534f116c8b5f2 [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"
Ben Claytonfccfc562019-12-17 20:37:31 +000018#include "Pipeline/SpirvShader.hpp"
Ben Clayton25e06e02020-02-07 11:19:08 +000019#include "System/Debug.hpp"
Nicolas Capens1d8c8db2018-11-05 16:30:42 -050020#include "System/Memory.hpp"
Alexis Hetu6159a852019-02-26 14:42:36 -050021#include "Vulkan/VkImageView.hpp"
Nicolas Capens68a82382018-10-02 13:16:55 -040022
23#include <string.h>
24
Nicolas Capens157ba262019-12-10 17:49:14 -050025namespace sw {
26
Nicolas Capens157ba262019-12-10 17:49:14 -050027bool Context::isDrawPoint(bool polygonModeAware) const
28{
29 switch(topology)
Nicolas Capens68a82382018-10-02 13:16:55 -040030 {
Ben Claytonfccfc562019-12-17 20:37:31 +000031 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
32 return true;
33 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
34 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
35 return false;
36 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
37 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
38 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
39 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_POINT) : false;
40 default:
Nicolas Capens865f8892020-01-21 14:27:10 -050041 UNSUPPORTED("topology %d", int(topology));
Nicolas Capens157ba262019-12-10 17:49:14 -050042 }
43 return false;
44}
45
46bool Context::isDrawLine(bool polygonModeAware) const
47{
48 switch(topology)
49 {
Ben Claytonfccfc562019-12-17 20:37:31 +000050 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
51 return false;
52 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
53 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
54 return true;
55 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
56 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
57 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
58 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_LINE) : false;
59 default:
Nicolas Capens865f8892020-01-21 14:27:10 -050060 UNSUPPORTED("topology %d", int(topology));
Nicolas Capens157ba262019-12-10 17:49:14 -050061 }
62 return false;
63}
64
65bool Context::isDrawTriangle(bool polygonModeAware) const
66{
67 switch(topology)
68 {
Ben Claytonfccfc562019-12-17 20:37:31 +000069 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
70 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
71 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
72 return false;
73 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
74 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
75 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
76 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_FILL) : true;
77 default:
Nicolas Capens865f8892020-01-21 14:27:10 -050078 UNSUPPORTED("topology %d", int(topology));
Nicolas Capens157ba262019-12-10 17:49:14 -050079 }
80 return false;
81}
82
Nicolas Capens157ba262019-12-10 17:49:14 -050083bool Context::depthWriteActive() const
84{
85 if(!depthBufferActive()) return false;
86
87 return depthWriteEnable;
88}
89
90bool Context::depthBufferActive() const
91{
92 return depthBuffer && depthBufferEnable;
93}
94
95bool Context::stencilActive() const
96{
97 return stencilBuffer && stencilEnable;
98}
99
100void Context::setBlendState(int index, BlendState state)
101{
102 ASSERT((index >= 0) && (index < RENDERTARGETS));
103
104 blendState[index] = state;
105}
106
107BlendState Context::getBlendState(int index) const
108{
109 ASSERT((index >= 0) && (index < RENDERTARGETS));
110
111 BlendState activeBlendState;
112 activeBlendState.alphaBlendEnable = alphaBlendActive(index);
113 activeBlendState.sourceBlendFactor = sourceBlendFactor(index);
114 activeBlendState.destBlendFactor = destBlendFactor(index);
115 activeBlendState.blendOperation = blendOperation(index);
116 activeBlendState.sourceBlendFactorAlpha = sourceBlendFactorAlpha(index);
117 activeBlendState.destBlendFactorAlpha = destBlendFactorAlpha(index);
118 activeBlendState.blendOperationAlpha = blendOperationAlpha(index);
119 return activeBlendState;
120}
121
122bool Context::alphaBlendActive(int index) const
123{
124 ASSERT((index >= 0) && (index < RENDERTARGETS));
125
126 if(!blendState[index].alphaBlendEnable)
127 {
128 return false;
129 }
130
131 if(!colorUsed())
132 {
133 return false;
134 }
135
136 bool colorBlend = !(blendOperation(index) == VK_BLEND_OP_SRC_EXT && sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE);
137 bool alphaBlend = !(blendOperationAlpha(index) == VK_BLEND_OP_SRC_EXT && sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE);
138
139 return colorBlend || alphaBlend;
140}
141
142VkBlendFactor Context::sourceBlendFactor(int index) const
143{
144 ASSERT((index >= 0) && (index < RENDERTARGETS));
145
146 if(!blendState[index].alphaBlendEnable) return VK_BLEND_FACTOR_ONE;
147
148 switch(blendState[index].blendOperation)
149 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000150 case VK_BLEND_OP_ADD:
151 case VK_BLEND_OP_SUBTRACT:
152 case VK_BLEND_OP_REVERSE_SUBTRACT:
153 return blendState[index].sourceBlendFactor;
154 case VK_BLEND_OP_MIN:
155 return VK_BLEND_FACTOR_ONE;
156 case VK_BLEND_OP_MAX:
157 return VK_BLEND_FACTOR_ONE;
158 default:
159 ASSERT(false);
Nicolas Capens157ba262019-12-10 17:49:14 -0500160 }
161
162 return blendState[index].sourceBlendFactor;
163}
164
165VkBlendFactor Context::destBlendFactor(int index) const
166{
167 ASSERT((index >= 0) && (index < RENDERTARGETS));
168
169 if(!blendState[index].alphaBlendEnable) return VK_BLEND_FACTOR_ONE;
170
171 switch(blendState[index].blendOperation)
172 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000173 case VK_BLEND_OP_ADD:
174 case VK_BLEND_OP_SUBTRACT:
175 case VK_BLEND_OP_REVERSE_SUBTRACT:
176 return blendState[index].destBlendFactor;
177 case VK_BLEND_OP_MIN:
178 return VK_BLEND_FACTOR_ONE;
179 case VK_BLEND_OP_MAX:
180 return VK_BLEND_FACTOR_ONE;
181 default:
182 ASSERT(false);
Nicolas Capens157ba262019-12-10 17:49:14 -0500183 }
184
185 return blendState[index].destBlendFactor;
186}
187
188bool Context::allTargetsColorClamp() const
189{
190 // TODO: remove all of this and support VkPhysicalDeviceFeatures::independentBlend instead
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500191 for(int i = 0; i < RENDERTARGETS; i++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500192 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500193 if(renderTarget[i] && renderTarget[i]->getFormat().isFloatFormat())
Nicolas Capens68a82382018-10-02 13:16:55 -0400194 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500195 return false;
Nicolas Capens68a82382018-10-02 13:16:55 -0400196 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400197 }
198
Nicolas Capens157ba262019-12-10 17:49:14 -0500199 return true;
200}
201
202VkBlendOp Context::blendOperation(int index) const
203{
204 ASSERT((index >= 0) && (index < RENDERTARGETS));
205
206 if(!blendState[index].alphaBlendEnable) return VK_BLEND_OP_SRC_EXT;
207
208 switch(blendState[index].blendOperation)
Nicolas Capens68a82382018-10-02 13:16:55 -0400209 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000210 case VK_BLEND_OP_ADD:
211 if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
Nicolas Capens68a82382018-10-02 13:16:55 -0400212 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000213 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
214 {
215 return VK_BLEND_OP_ZERO_EXT;
216 }
217 else
218 {
219 return VK_BLEND_OP_DST_EXT;
220 }
221 }
222 else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
223 {
224 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
225 {
226 return VK_BLEND_OP_SRC_EXT;
227 }
228 else
229 {
230 return VK_BLEND_OP_ADD;
231 }
Chris Forbes3e351312019-05-14 17:33:01 -0700232 }
233 else
234 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000235 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
236 {
237 return VK_BLEND_OP_SRC_EXT;
238 }
239 else
240 {
241 return VK_BLEND_OP_ADD;
242 }
Chris Forbes3e351312019-05-14 17:33:01 -0700243 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000244 case VK_BLEND_OP_SUBTRACT:
245 if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
Nicolas Capens157ba262019-12-10 17:49:14 -0500246 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000247 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
248 }
249 else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
250 {
251 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
252 {
253 return VK_BLEND_OP_SRC_EXT;
254 }
255 else
256 {
257 return VK_BLEND_OP_SUBTRACT;
258 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500259 }
260 else
261 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000262 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
263 {
264 return VK_BLEND_OP_SRC_EXT;
265 }
266 else
267 {
268 return VK_BLEND_OP_SUBTRACT;
269 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500270 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000271 case VK_BLEND_OP_REVERSE_SUBTRACT:
272 if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
Chris Forbesbc63cf92019-02-28 09:03:38 -0800273 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000274 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
275 {
276 return VK_BLEND_OP_ZERO_EXT;
277 }
278 else
279 {
280 return VK_BLEND_OP_DST_EXT;
281 }
282 }
283 else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
284 {
285 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
286 {
287 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
288 }
289 else
290 {
291 return VK_BLEND_OP_REVERSE_SUBTRACT;
292 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500293 }
294 else
295 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000296 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
297 {
298 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
299 }
300 else
301 {
302 return VK_BLEND_OP_REVERSE_SUBTRACT;
303 }
Chris Forbesbc63cf92019-02-28 09:03:38 -0800304 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000305 case VK_BLEND_OP_MIN:
306 return VK_BLEND_OP_MIN;
307 case VK_BLEND_OP_MAX:
308 return VK_BLEND_OP_MAX;
309 default:
310 ASSERT(false);
Nicolas Capens68a82382018-10-02 13:16:55 -0400311 }
312
Nicolas Capens157ba262019-12-10 17:49:14 -0500313 return blendState[index].blendOperation;
314}
315
316VkBlendFactor Context::sourceBlendFactorAlpha(int index) const
317{
318 ASSERT((index >= 0) && (index < RENDERTARGETS));
319
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500320 switch(blendState[index].blendOperationAlpha)
Nicolas Capens68a82382018-10-02 13:16:55 -0400321 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000322 case VK_BLEND_OP_ADD:
323 case VK_BLEND_OP_SUBTRACT:
324 case VK_BLEND_OP_REVERSE_SUBTRACT:
325 return blendState[index].sourceBlendFactorAlpha;
326 case VK_BLEND_OP_MIN:
327 return VK_BLEND_FACTOR_ONE;
328 case VK_BLEND_OP_MAX:
329 return VK_BLEND_FACTOR_ONE;
330 default:
331 ASSERT(false);
Nicolas Capens68a82382018-10-02 13:16:55 -0400332 }
333
Nicolas Capens157ba262019-12-10 17:49:14 -0500334 return blendState[index].sourceBlendFactorAlpha;
335}
336
337VkBlendFactor Context::destBlendFactorAlpha(int index) const
338{
339 ASSERT((index >= 0) && (index < RENDERTARGETS));
340
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500341 switch(blendState[index].blendOperationAlpha)
Nicolas Capens68a82382018-10-02 13:16:55 -0400342 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000343 case VK_BLEND_OP_ADD:
344 case VK_BLEND_OP_SUBTRACT:
345 case VK_BLEND_OP_REVERSE_SUBTRACT:
346 return blendState[index].destBlendFactorAlpha;
347 case VK_BLEND_OP_MIN:
348 return VK_BLEND_FACTOR_ONE;
349 case VK_BLEND_OP_MAX:
350 return VK_BLEND_FACTOR_ONE;
351 default:
352 ASSERT(false);
Nicolas Capens157ba262019-12-10 17:49:14 -0500353 }
354
355 return blendState[index].destBlendFactorAlpha;
356}
357
358VkBlendOp Context::blendOperationAlpha(int index) const
359{
360 ASSERT((index >= 0) && (index < RENDERTARGETS));
361
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500362 switch(blendState[index].blendOperationAlpha)
Nicolas Capens157ba262019-12-10 17:49:14 -0500363 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000364 case VK_BLEND_OP_ADD:
365 if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
Nicolas Capens157ba262019-12-10 17:49:14 -0500366 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000367 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
368 {
369 return VK_BLEND_OP_ZERO_EXT;
370 }
371 else
372 {
373 return VK_BLEND_OP_DST_EXT;
374 }
375 }
376 else if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE)
377 {
378 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
379 {
380 return VK_BLEND_OP_SRC_EXT;
381 }
382 else
383 {
384 return VK_BLEND_OP_ADD;
385 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500386 }
387 else
388 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000389 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
390 {
391 return VK_BLEND_OP_SRC_EXT;
392 }
393 else
394 {
395 return VK_BLEND_OP_ADD;
396 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500397 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000398 case VK_BLEND_OP_SUBTRACT:
399 if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
Nicolas Capens157ba262019-12-10 17:49:14 -0500400 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000401 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
402 }
403 else if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE)
404 {
405 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
406 {
407 return VK_BLEND_OP_SRC_EXT;
408 }
409 else
410 {
411 return VK_BLEND_OP_SUBTRACT;
412 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500413 }
414 else
415 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000416 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
417 {
418 return VK_BLEND_OP_SRC_EXT;
419 }
420 else
421 {
422 return VK_BLEND_OP_SUBTRACT;
423 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500424 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000425 case VK_BLEND_OP_REVERSE_SUBTRACT:
426 if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
Nicolas Capens157ba262019-12-10 17:49:14 -0500427 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000428 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
429 {
430 return VK_BLEND_OP_ZERO_EXT;
431 }
432 else
433 {
434 return VK_BLEND_OP_DST_EXT;
435 }
436 }
437 else if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE)
438 {
439 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
440 {
441 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
442 }
443 else
444 {
445 return VK_BLEND_OP_REVERSE_SUBTRACT;
446 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500447 }
448 else
449 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000450 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
451 {
452 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
453 }
454 else
455 {
456 return VK_BLEND_OP_REVERSE_SUBTRACT;
457 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500458 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000459 case VK_BLEND_OP_MIN:
460 return VK_BLEND_OP_MIN;
461 case VK_BLEND_OP_MAX:
462 return VK_BLEND_OP_MAX;
463 default:
464 ASSERT(false);
Nicolas Capens157ba262019-12-10 17:49:14 -0500465 }
466
467 return blendState[index].blendOperationAlpha;
468}
469
470VkFormat Context::renderTargetInternalFormat(int index) const
471{
472 ASSERT((index >= 0) && (index < RENDERTARGETS));
473
474 if(renderTarget[index])
475 {
476 return renderTarget[index]->getFormat();
477 }
478 else
479 {
480 return VK_FORMAT_UNDEFINED;
Nicolas Capens68a82382018-10-02 13:16:55 -0400481 }
482}
Nicolas Capens157ba262019-12-10 17:49:14 -0500483
484bool Context::colorWriteActive() const
485{
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500486 for(int i = 0; i < RENDERTARGETS; i++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500487 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500488 if(colorWriteActive(i))
Nicolas Capens157ba262019-12-10 17:49:14 -0500489 {
490 return true;
491 }
492 }
493
494 return false;
495}
496
497int Context::colorWriteActive(int index) const
498{
499 ASSERT((index >= 0) && (index < RENDERTARGETS));
500
501 if(!renderTarget[index] || renderTarget[index]->getFormat() == VK_FORMAT_UNDEFINED)
502 {
503 return 0;
504 }
505
506 if(blendOperation(index) == VK_BLEND_OP_DST_EXT && destBlendFactor(index) == VK_BLEND_FACTOR_ONE &&
507 (blendOperationAlpha(index) == VK_BLEND_OP_DST_EXT && destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE))
508 {
509 return 0;
510 }
511
512 return colorWriteMask[index];
513}
514
515bool Context::colorUsed() const
516{
517 return colorWriteActive() || (pixelShader && pixelShader->getModes().ContainsKill);
518}
519
520} // namespace sw