blob: de1ab7b909de52f2e550589d7620b06699b60726 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// 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.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "Renderer.hpp"
16
17#include "Clipper.hpp"
John Bauman89401822014-05-06 15:04:28 -040018#include "Surface.hpp"
John Bauman89401822014-05-06 15:04:28 -040019#include "Primitive.hpp"
20#include "Polygon.hpp"
Nicolas Capens708c24b2017-10-26 13:07:10 -040021#include "Main/FrameBuffer.hpp"
22#include "Main/SwiftConfig.hpp"
John Bauman19bac1e2014-05-06 15:23:49 -040023#include "Reactor/Reactor.hpp"
Nicolas Capens708c24b2017-10-26 13:07:10 -040024#include "Shader/Constants.hpp"
25#include "Common/MutexLock.hpp"
26#include "Common/CPUID.hpp"
27#include "Common/Memory.hpp"
28#include "Common/Resource.hpp"
29#include "Common/Half.hpp"
30#include "Common/Math.hpp"
31#include "Common/Timer.hpp"
32#include "Common/Debug.hpp"
John Bauman89401822014-05-06 15:04:28 -040033
John Bauman89401822014-05-06 15:04:28 -040034#undef max
35
John Bauman19bac1e2014-05-06 15:23:49 -040036bool disableServer = true;
John Bauman89401822014-05-06 15:04:28 -040037
38#ifndef NDEBUG
39unsigned int minPrimitives = 1;
40unsigned int maxPrimitives = 1 << 21;
41#endif
42
43namespace sw
44{
John Bauman19bac1e2014-05-06 15:23:49 -040045 extern bool halfIntegerCoordinates; // Pixel centers are not at integer coordinates
46 extern bool symmetricNormalizedDepth; // [-1, 1] instead of [0, 1]
47 extern bool booleanFaceRegister;
48 extern bool fullPixelPositionRegister;
Nicolas Capens44ffb652015-08-04 16:11:24 -040049 extern bool leadingVertexFirst; // Flat shading uses first vertex, else last
50 extern bool secondaryColor; // Specular lighting is applied after texturing
Alexis Hetu56f256e2017-07-21 11:41:13 -040051 extern bool colorsDefaultToZero;
John Bauman19bac1e2014-05-06 15:23:49 -040052
John Bauman89401822014-05-06 15:04:28 -040053 extern bool forceWindowed;
54 extern bool complementaryDepthBuffer;
55 extern bool postBlendSRGB;
56 extern bool exactColorRounding;
Nicolas Capensa0f4be82014-10-22 14:35:30 -040057 extern TransparencyAntialiasing transparencyAntialiasing;
John Bauman89401822014-05-06 15:04:28 -040058 extern bool forceClearRegisters;
59
John Bauman66b8ab22014-05-06 15:57:45 -040060 extern bool precacheVertex;
61 extern bool precacheSetup;
62 extern bool precachePixel;
63
Alexis Hetuf2520e12017-10-26 14:57:17 -040064 static const int batchSize = 128;
65 AtomicInt threadCount(1);
Alexis Hetu8beb2402017-09-27 10:31:28 -040066 AtomicInt Renderer::unitCount(1);
67 AtomicInt Renderer::clusterCount(1);
John Bauman89401822014-05-06 15:04:28 -040068
John Bauman19bac1e2014-05-06 15:23:49 -040069 TranscendentalPrecision logPrecision = ACCURATE;
70 TranscendentalPrecision expPrecision = ACCURATE;
71 TranscendentalPrecision rcpPrecision = ACCURATE;
72 TranscendentalPrecision rsqPrecision = ACCURATE;
73 bool perspectiveCorrection = true;
74
Alexis Hetu9e22c542018-07-30 15:09:01 -040075 static void setGlobalRenderingSettings(Conventions conventions, bool exactColorRounding)
76 {
77 static bool initialized = false;
78
79 if(!initialized)
80 {
81 sw::halfIntegerCoordinates = conventions.halfIntegerCoordinates;
82 sw::symmetricNormalizedDepth = conventions.symmetricNormalizedDepth;
83 sw::booleanFaceRegister = conventions.booleanFaceRegister;
84 sw::fullPixelPositionRegister = conventions.fullPixelPositionRegister;
85 sw::leadingVertexFirst = conventions.leadingVertexFirst;
86 sw::secondaryColor = conventions.secondaryColor;
87 sw::colorsDefaultToZero = conventions.colorsDefaultToZero;
88 sw::exactColorRounding = exactColorRounding;
89 initialized = true;
90 }
91 }
92
John Bauman89401822014-05-06 15:04:28 -040093 struct Parameters
94 {
95 Renderer *renderer;
96 int threadIndex;
97 };
98
Alexis Hetu3fc68932018-11-14 10:54:53 -050099 Query::Query(Type type) : building(false), data(0), type(type), reference(1)
100 {
101 }
102
103 void Query::addRef()
104 {
105 ++reference; // Atomic
106 }
107
108 void Query::release()
109 {
110 int ref = reference--; // Atomic
111
112 ASSERT(ref >= 0);
113
114 if(ref == 0)
115 {
116 delete this;
117 }
118 }
119
John Bauman89401822014-05-06 15:04:28 -0400120 DrawCall::DrawCall()
121 {
122 queries = 0;
123
Alexis Hetu04c967a2015-07-08 15:56:17 -0400124 vsDirtyConstF = VERTEX_UNIFORM_VECTORS + 1;
John Bauman89401822014-05-06 15:04:28 -0400125 vsDirtyConstI = 16;
126 vsDirtyConstB = 16;
127
Alexis Hetu04c967a2015-07-08 15:56:17 -0400128 psDirtyConstF = FRAGMENT_UNIFORM_VECTORS;
John Bauman89401822014-05-06 15:04:28 -0400129 psDirtyConstI = 16;
130 psDirtyConstB = 16;
131
132 references = -1;
133
134 data = (DrawData*)allocate(sizeof(DrawData));
135 data->constants = &constants;
136 }
137
138 DrawCall::~DrawCall()
139 {
140 delete queries;
141
142 deallocate(data);
143 }
144
Nicolas Capens485f92c2016-01-01 23:17:42 -0500145 Renderer::Renderer(Context *context, Conventions conventions, bool exactColorRounding) : VertexProcessor(context), PixelProcessor(context), SetupProcessor(context), context(context), viewport()
John Bauman89401822014-05-06 15:04:28 -0400146 {
Alexis Hetu9e22c542018-07-30 15:09:01 -0400147 setGlobalRenderingSettings(conventions, exactColorRounding);
John Bauman89401822014-05-06 15:04:28 -0400148
John Bauman19bac1e2014-05-06 15:23:49 -0400149 setRenderTarget(0, 0);
Nicolas Capens00bfa182016-05-20 21:30:54 -0700150 clipper = new Clipper(symmetricNormalizedDepth);
Nicolas Capens81aa97b2017-06-27 17:08:08 -0400151 blitter = new Blitter;
John Bauman89401822014-05-06 15:04:28 -0400152
John Bauman89401822014-05-06 15:04:28 -0400153 updateViewMatrix = true;
154 updateBaseMatrix = true;
155 updateProjectionMatrix = true;
156 updateClipPlanes = true;
157
158 #if PERF_HUD
159 resetTimers();
160 #endif
161
162 for(int i = 0; i < 16; i++)
163 {
164 vertexTask[i] = 0;
165
166 worker[i] = 0;
167 resume[i] = 0;
168 suspend[i] = 0;
169 }
170
171 threadsAwake = 0;
172 resumeApp = new Event();
173
174 currentDraw = 0;
175 nextDraw = 0;
176
177 qHead = 0;
178 qSize = 0;
179
180 for(int i = 0; i < 16; i++)
181 {
182 triangleBatch[i] = 0;
183 primitiveBatch[i] = 0;
184 }
185
186 for(int draw = 0; draw < DRAW_COUNT; draw++)
187 {
188 drawCall[draw] = new DrawCall();
189 drawList[draw] = drawCall[draw];
190 }
191
192 for(int unit = 0; unit < 16; unit++)
193 {
194 primitiveProgress[unit].init();
195 }
196
197 for(int cluster = 0; cluster < 16; cluster++)
198 {
199 pixelProgress[cluster].init();
200 }
201
202 clipFlags = 0;
203
204 swiftConfig = new SwiftConfig(disableServer);
205 updateConfiguration(true);
John Bauman19bac1e2014-05-06 15:23:49 -0400206
207 sync = new Resource(0);
John Bauman89401822014-05-06 15:04:28 -0400208 }
209
210 Renderer::~Renderer()
211 {
Ben Clayton3fc635a2019-02-12 11:24:29 +0000212 sync->lock(EXCLUSIVE);
John Bauman19bac1e2014-05-06 15:23:49 -0400213 sync->destruct();
Ben Clayton3fc635a2019-02-12 11:24:29 +0000214 terminateThreads();
215 sync->unlock();
John Bauman19bac1e2014-05-06 15:23:49 -0400216
John Bauman89401822014-05-06 15:04:28 -0400217 delete clipper;
Nicolas Capens81aa97b2017-06-27 17:08:08 -0400218 clipper = nullptr;
219
220 delete blitter;
221 blitter = nullptr;
John Bauman89401822014-05-06 15:04:28 -0400222
John Bauman89401822014-05-06 15:04:28 -0400223 delete resumeApp;
Ben Clayton3fc635a2019-02-12 11:24:29 +0000224 resumeApp = nullptr;
John Bauman89401822014-05-06 15:04:28 -0400225
226 for(int draw = 0; draw < DRAW_COUNT; draw++)
227 {
228 delete drawCall[draw];
Ben Clayton3fc635a2019-02-12 11:24:29 +0000229 drawCall[draw] = nullptr;
John Bauman89401822014-05-06 15:04:28 -0400230 }
231
John Bauman89401822014-05-06 15:04:28 -0400232 delete swiftConfig;
Ben Clayton3fc635a2019-02-12 11:24:29 +0000233 swiftConfig = nullptr;
John Bauman89401822014-05-06 15:04:28 -0400234 }
235
Alexis Hetu81519cf2016-09-08 13:59:50 -0400236 // This object has to be mem aligned
Nicolas Capensedba65b2016-10-20 14:57:26 -0400237 void* Renderer::operator new(size_t size)
238 {
239 ASSERT(size == sizeof(Renderer)); // This operator can't be called from a derived class
240 return sw::allocate(sizeof(Renderer), 16);
241 }
242
243 void Renderer::operator delete(void * mem)
244 {
245 sw::deallocate(mem);
Alexis Hetu81519cf2016-09-08 13:59:50 -0400246 }
247
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400248 void Renderer::draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update)
John Bauman89401822014-05-06 15:04:28 -0400249 {
250 #ifndef NDEBUG
251 if(count < minPrimitives || count > maxPrimitives)
252 {
253 return;
254 }
255 #endif
256
257 context->drawType = drawType;
258
259 updateConfiguration();
260 updateClipper();
261
John Bauman66b8ab22014-05-06 15:57:45 -0400262 int ss = context->getSuperSampleCount();
263 int ms = context->getMultiSampleCount();
Alexis Hetu88482c32018-06-05 17:05:17 -0400264 bool requiresSync = false;
John Bauman89401822014-05-06 15:04:28 -0400265
266 for(int q = 0; q < ss; q++)
267 {
Nicolas Capens5d961882016-01-01 23:18:14 -0500268 unsigned int oldMultiSampleMask = context->multiSampleMask;
John Bauman19bac1e2014-05-06 15:23:49 -0400269 context->multiSampleMask = (context->sampleMask >> (ms * q)) & ((unsigned)0xFFFFFFFF >> (32 - ms));
John Bauman89401822014-05-06 15:04:28 -0400270
271 if(!context->multiSampleMask)
272 {
273 continue;
274 }
275
John Bauman19bac1e2014-05-06 15:23:49 -0400276 sync->lock(sw::PRIVATE);
277
John Bauman89401822014-05-06 15:04:28 -0400278 if(update || oldMultiSampleMask != context->multiSampleMask)
279 {
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400280 vertexState = VertexProcessor::update(drawType);
John Bauman89401822014-05-06 15:04:28 -0400281 setupState = SetupProcessor::update();
282 pixelState = PixelProcessor::update();
283
284 vertexRoutine = VertexProcessor::routine(vertexState);
285 setupRoutine = SetupProcessor::routine(setupState);
286 pixelRoutine = PixelProcessor::routine(pixelState);
287 }
288
289 int batch = batchSize / ms;
290
Nicolas Capens734392e2016-05-26 11:07:40 -0400291 int (Renderer::*setupPrimitives)(int batch, int count);
Nicolas Capens235781d2015-01-27 01:46:53 -0500292
John Bauman89401822014-05-06 15:04:28 -0400293 if(context->isDrawTriangle())
294 {
295 switch(context->fillMode)
296 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400297 case FILL_SOLID:
Nicolas Capens734392e2016-05-26 11:07:40 -0400298 setupPrimitives = &Renderer::setupSolidTriangles;
John Bauman89401822014-05-06 15:04:28 -0400299 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400300 case FILL_WIREFRAME:
Nicolas Capens734392e2016-05-26 11:07:40 -0400301 setupPrimitives = &Renderer::setupWireframeTriangle;
John Bauman89401822014-05-06 15:04:28 -0400302 batch = 1;
303 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400304 case FILL_VERTEX:
Nicolas Capens734392e2016-05-26 11:07:40 -0400305 setupPrimitives = &Renderer::setupVertexTriangle;
John Bauman89401822014-05-06 15:04:28 -0400306 batch = 1;
307 break;
Alexis Hetu05c32b92016-06-23 11:32:07 -0400308 default:
309 ASSERT(false);
310 return;
John Bauman89401822014-05-06 15:04:28 -0400311 }
312 }
313 else if(context->isDrawLine())
314 {
Nicolas Capens734392e2016-05-26 11:07:40 -0400315 setupPrimitives = &Renderer::setupLines;
John Bauman89401822014-05-06 15:04:28 -0400316 }
317 else // Point draw
318 {
Nicolas Capens734392e2016-05-26 11:07:40 -0400319 setupPrimitives = &Renderer::setupPoints;
John Bauman89401822014-05-06 15:04:28 -0400320 }
321
Nicolas Capensa6bc61d2017-12-20 11:07:45 -0500322 DrawCall *draw = nullptr;
John Bauman89401822014-05-06 15:04:28 -0400323
324 do
325 {
326 for(int i = 0; i < DRAW_COUNT; i++)
327 {
328 if(drawCall[i]->references == -1)
329 {
330 draw = drawCall[i];
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400331 drawList[nextDraw & DRAW_COUNT_BITS] = draw;
John Bauman89401822014-05-06 15:04:28 -0400332
333 break;
334 }
335 }
336
337 if(!draw)
338 {
339 resumeApp->wait();
340 }
341 }
342 while(!draw);
343
344 DrawData *data = draw->data;
345
346 if(queries.size() != 0)
347 {
Alexis Hetu16116cb2016-03-02 15:59:51 -0500348 draw->queries = new std::list<Query*>();
349 bool includePrimitivesWrittenQueries = vertexState.transformFeedbackQueryEnabled && vertexState.transformFeedbackEnabled;
Alexis Hetubf3fc252017-12-06 14:22:10 -0500350 for(auto &query : queries)
John Bauman89401822014-05-06 15:04:28 -0400351 {
Alexis Hetubf3fc252017-12-06 14:22:10 -0500352 if(includePrimitivesWrittenQueries || (query->type != Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN))
Alexis Hetu16116cb2016-03-02 15:59:51 -0500353 {
Alexis Hetu3fc68932018-11-14 10:54:53 -0500354 query->addRef();
Alexis Hetubf3fc252017-12-06 14:22:10 -0500355 draw->queries->push_back(query);
Alexis Hetu16116cb2016-03-02 15:59:51 -0500356 }
John Bauman89401822014-05-06 15:04:28 -0400357 }
John Bauman89401822014-05-06 15:04:28 -0400358 }
359
360 draw->drawType = drawType;
361 draw->batchSize = batch;
362
John Bauman89401822014-05-06 15:04:28 -0400363 draw->vertexRoutine = vertexRoutine;
364 draw->setupRoutine = setupRoutine;
365 draw->pixelRoutine = pixelRoutine;
Nicolas Capenseb195b62015-04-28 17:18:42 -0700366 draw->vertexPointer = (VertexProcessor::RoutinePointer)vertexRoutine->getEntry();
John Bauman89401822014-05-06 15:04:28 -0400367 draw->setupPointer = (SetupProcessor::RoutinePointer)setupRoutine->getEntry();
368 draw->pixelPointer = (PixelProcessor::RoutinePointer)pixelRoutine->getEntry();
369 draw->setupPrimitives = setupPrimitives;
370 draw->setupState = setupState;
371
Nicolas Capensf0aef1a2016-05-18 14:44:21 -0400372 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400373 {
374 draw->vertexStream[i] = context->input[i].resource;
375 data->input[i] = context->input[i].buffer;
376 data->stride[i] = context->input[i].stride;
377
378 if(draw->vertexStream[i])
379 {
380 draw->vertexStream[i]->lock(PUBLIC, PRIVATE);
381 }
382 }
383
384 if(context->indexBuffer)
385 {
386 data->indices = (unsigned char*)context->indexBuffer->lock(PUBLIC, PRIVATE) + indexOffset;
387 }
388
389 draw->indexBuffer = context->indexBuffer;
390
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400391 for(int sampler = 0; sampler < TOTAL_IMAGE_UNITS; sampler++)
John Bauman89401822014-05-06 15:04:28 -0400392 {
393 draw->texture[sampler] = 0;
394 }
395
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400396 for(int sampler = 0; sampler < TEXTURE_IMAGE_UNITS; sampler++)
John Bauman89401822014-05-06 15:04:28 -0400397 {
398 if(pixelState.sampler[sampler].textureType != TEXTURE_NULL)
399 {
400 draw->texture[sampler] = context->texture[sampler];
401 draw->texture[sampler]->lock(PUBLIC, isReadWriteTexture(sampler) ? MANAGED : PRIVATE); // If the texure is both read and written, use the same read/write lock as render targets
402
403 data->mipmap[sampler] = context->sampler[sampler].getTextureData();
Alexis Hetu88482c32018-06-05 17:05:17 -0400404
405 requiresSync |= context->sampler[sampler].requiresSync();
John Bauman89401822014-05-06 15:04:28 -0400406 }
407 }
408
409 if(context->pixelShader)
410 {
411 if(draw->psDirtyConstF)
412 {
413 memcpy(&data->ps.cW, PixelProcessor::cW, sizeof(word4) * 4 * (draw->psDirtyConstF < 8 ? draw->psDirtyConstF : 8));
414 memcpy(&data->ps.c, PixelProcessor::c, sizeof(float4) * draw->psDirtyConstF);
415 draw->psDirtyConstF = 0;
416 }
417
418 if(draw->psDirtyConstI)
419 {
420 memcpy(&data->ps.i, PixelProcessor::i, sizeof(int4) * draw->psDirtyConstI);
421 draw->psDirtyConstI = 0;
422 }
423
424 if(draw->psDirtyConstB)
425 {
426 memcpy(&data->ps.b, PixelProcessor::b, sizeof(bool) * draw->psDirtyConstB);
427 draw->psDirtyConstB = 0;
428 }
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400429
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400430 PixelProcessor::lockUniformBuffers(data->ps.u, draw->pUniformBuffers);
431 }
432 else
433 {
434 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
435 {
436 draw->pUniformBuffers[i] = nullptr;
437 }
John Bauman89401822014-05-06 15:04:28 -0400438 }
Nicolas Capensec0936c2016-05-18 12:32:02 -0400439
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500440 if(context->pixelShaderModel() <= 0x0104)
John Bauman89401822014-05-06 15:04:28 -0400441 {
442 for(int stage = 0; stage < 8; stage++)
443 {
444 if(pixelState.textureStage[stage].stageOperation != TextureStage::STAGE_DISABLE || context->pixelShader)
445 {
446 data->textureStage[stage] = context->textureStage[stage].uniforms;
447 }
448 else break;
449 }
450 }
451
452 if(context->vertexShader)
453 {
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500454 if(context->vertexShader->getShaderModel() >= 0x0300)
John Bauman89401822014-05-06 15:04:28 -0400455 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400456 for(int sampler = 0; sampler < VERTEX_TEXTURE_IMAGE_UNITS; sampler++)
John Bauman89401822014-05-06 15:04:28 -0400457 {
Nicolas Capensf878d502017-11-06 15:29:46 -0500458 if(vertexState.sampler[sampler].textureType != TEXTURE_NULL)
John Bauman89401822014-05-06 15:04:28 -0400459 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400460 draw->texture[TEXTURE_IMAGE_UNITS + sampler] = context->texture[TEXTURE_IMAGE_UNITS + sampler];
461 draw->texture[TEXTURE_IMAGE_UNITS + sampler]->lock(PUBLIC, PRIVATE);
John Bauman89401822014-05-06 15:04:28 -0400462
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400463 data->mipmap[TEXTURE_IMAGE_UNITS + sampler] = context->sampler[TEXTURE_IMAGE_UNITS + sampler].getTextureData();
Alexis Hetu88482c32018-06-05 17:05:17 -0400464
465 requiresSync |= context->sampler[TEXTURE_IMAGE_UNITS + sampler].requiresSync();
John Bauman89401822014-05-06 15:04:28 -0400466 }
467 }
468 }
469
470 if(draw->vsDirtyConstF)
471 {
472 memcpy(&data->vs.c, VertexProcessor::c, sizeof(float4) * draw->vsDirtyConstF);
473 draw->vsDirtyConstF = 0;
474 }
475
476 if(draw->vsDirtyConstI)
477 {
478 memcpy(&data->vs.i, VertexProcessor::i, sizeof(int4) * draw->vsDirtyConstI);
479 draw->vsDirtyConstI = 0;
480 }
481
482 if(draw->vsDirtyConstB)
483 {
484 memcpy(&data->vs.b, VertexProcessor::b, sizeof(bool) * draw->vsDirtyConstB);
485 draw->vsDirtyConstB = 0;
486 }
Alexis Hetudd8df682015-06-05 17:08:39 -0400487
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400488 if(context->vertexShader->isInstanceIdDeclared())
Alexis Hetudd8df682015-06-05 17:08:39 -0400489 {
490 data->instanceID = context->instanceID;
491 }
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400492
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400493 VertexProcessor::lockUniformBuffers(data->vs.u, draw->vUniformBuffers);
494 VertexProcessor::lockTransformFeedbackBuffers(data->vs.t, data->vs.reg, data->vs.row, data->vs.col, data->vs.str, draw->transformFeedbackBuffers);
John Bauman89401822014-05-06 15:04:28 -0400495 }
496 else
497 {
498 data->ff = ff;
499
Alexis Hetu04c967a2015-07-08 15:56:17 -0400500 draw->vsDirtyConstF = VERTEX_UNIFORM_VECTORS + 1;
John Bauman89401822014-05-06 15:04:28 -0400501 draw->vsDirtyConstI = 16;
502 draw->vsDirtyConstB = 16;
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400503
504 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
505 {
506 draw->vUniformBuffers[i] = nullptr;
507 }
508
509 for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
510 {
511 draw->transformFeedbackBuffers[i] = nullptr;
512 }
John Bauman89401822014-05-06 15:04:28 -0400513 }
514
515 if(pixelState.stencilActive)
516 {
517 data->stencil[0] = stencil;
518 data->stencil[1] = stencilCCW;
519 }
520
521 if(pixelState.fogActive)
522 {
523 data->fog = fog;
524 }
525
526 if(setupState.isDrawPoint)
527 {
528 data->point = point;
529 }
530
Nicolas Capens235781d2015-01-27 01:46:53 -0500531 data->lineWidth = context->lineWidth;
532
John Bauman89401822014-05-06 15:04:28 -0400533 data->factor = factor;
534
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400535 if(pixelState.transparencyAntialiasing == TRANSPARENCY_ALPHA_TO_COVERAGE)
John Bauman89401822014-05-06 15:04:28 -0400536 {
Alexis Hetua818c452015-06-11 13:06:58 -0400537 float ref = context->alphaReference * (1.0f / 255.0f);
John Bauman89401822014-05-06 15:04:28 -0400538 float margin = sw::min(ref, 1.0f - ref);
539
540 if(ms == 4)
541 {
542 data->a2c0 = replicate(ref - margin * 0.6f);
543 data->a2c1 = replicate(ref - margin * 0.2f);
544 data->a2c2 = replicate(ref + margin * 0.2f);
545 data->a2c3 = replicate(ref + margin * 0.6f);
546 }
547 else if(ms == 2)
548 {
549 data->a2c0 = replicate(ref - margin * 0.3f);
550 data->a2c1 = replicate(ref + margin * 0.3f);
551 }
552 else ASSERT(false);
553 }
554
555 if(pixelState.occlusionEnabled)
556 {
557 for(int cluster = 0; cluster < clusterCount; cluster++)
558 {
559 data->occlusion[cluster] = 0;
560 }
561 }
562
563 #if PERF_PROFILE
564 for(int cluster = 0; cluster < clusterCount; cluster++)
565 {
566 for(int i = 0; i < PERF_TIMERS; i++)
567 {
568 data->cycles[i][cluster] = 0;
569 }
570 }
571 #endif
572
573 // Viewport
574 {
John Bauman19bac1e2014-05-06 15:23:49 -0400575 float W = 0.5f * viewport.width;
576 float H = 0.5f * viewport.height;
577 float X0 = viewport.x0 + W;
578 float Y0 = viewport.y0 + H;
579 float N = viewport.minZ;
580 float F = viewport.maxZ;
John Bauman89401822014-05-06 15:04:28 -0400581 float Z = F - N;
582
583 if(context->isDrawTriangle(false))
584 {
Nicolas Capens3cbeac52017-09-15 11:49:31 -0400585 N += context->depthBias;
John Bauman89401822014-05-06 15:04:28 -0400586 }
587
588 if(complementaryDepthBuffer)
589 {
590 Z = -Z;
591 N = 1 - N;
592 }
593
594 static const float X[5][16] = // Fragment offsets
595 {
596 {+0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f}, // 1 sample
597 {-0.2500f, +0.2500f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f}, // 2 samples
598 {-0.3000f, +0.1000f, +0.3000f, -0.1000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f}, // 4 samples
599 {+0.1875f, -0.3125f, +0.3125f, -0.4375f, -0.0625f, +0.4375f, +0.0625f, -0.1875f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f}, // 8 samples
600 {+0.2553f, -0.1155f, +0.1661f, -0.1828f, +0.2293f, -0.4132f, -0.1773f, -0.0577f, +0.3891f, -0.4656f, +0.4103f, +0.4248f, -0.2109f, +0.3966f, -0.2664f, -0.3872f} // 16 samples
601 };
602
603 static const float Y[5][16] = // Fragment offsets
604 {
605 {+0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f}, // 1 sample
606 {-0.2500f, +0.2500f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f}, // 2 samples
607 {-0.1000f, -0.3000f, +0.1000f, +0.3000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f}, // 4 samples
608 {-0.4375f, -0.3125f, -0.1875f, -0.0625f, +0.0625f, +0.1875f, +0.3125f, +0.4375f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f}, // 8 samples
609 {-0.4503f, +0.1883f, +0.3684f, -0.4668f, -0.0690f, -0.1315f, +0.4999f, +0.0728f, +0.1070f, -0.3086f, +0.3725f, -0.1547f, -0.1102f, -0.3588f, +0.1789f, +0.0269f} // 16 samples
610 };
611
612 int s = sw::log2(ss);
613
John Bauman19bac1e2014-05-06 15:23:49 -0400614 data->Wx16 = replicate(W * 16);
615 data->Hx16 = replicate(H * 16);
Nicolas Capens5491cb42015-07-02 15:33:29 -0400616 data->X0x16 = replicate(X0 * 16 - 8);
617 data->Y0x16 = replicate(Y0 * 16 - 8);
John Bauman89401822014-05-06 15:04:28 -0400618 data->XXXX = replicate(X[s][q] / W);
619 data->YYYY = replicate(Y[s][q] / H);
John Bauman19bac1e2014-05-06 15:23:49 -0400620 data->halfPixelX = replicate(0.5f / W);
621 data->halfPixelY = replicate(0.5f / H);
622 data->viewportHeight = abs(viewport.height);
Nicolas Capens3cbeac52017-09-15 11:49:31 -0400623 data->slopeDepthBias = context->slopeDepthBias;
John Bauman89401822014-05-06 15:04:28 -0400624 data->depthRange = Z;
625 data->depthNear = N;
626 draw->clipFlags = clipFlags;
627
628 if(clipFlags)
629 {
630 if(clipFlags & Clipper::CLIP_PLANE0) data->clipPlane[0] = clipPlane[0];
631 if(clipFlags & Clipper::CLIP_PLANE1) data->clipPlane[1] = clipPlane[1];
632 if(clipFlags & Clipper::CLIP_PLANE2) data->clipPlane[2] = clipPlane[2];
633 if(clipFlags & Clipper::CLIP_PLANE3) data->clipPlane[3] = clipPlane[3];
634 if(clipFlags & Clipper::CLIP_PLANE4) data->clipPlane[4] = clipPlane[4];
635 if(clipFlags & Clipper::CLIP_PLANE5) data->clipPlane[5] = clipPlane[5];
636 }
637 }
638
639 // Target
640 {
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500641 for(int index = 0; index < RENDERTARGETS; index++)
John Bauman89401822014-05-06 15:04:28 -0400642 {
643 draw->renderTarget[index] = context->renderTarget[index];
644
645 if(draw->renderTarget[index])
646 {
Nicolas Capens8af24c52017-12-11 14:45:01 -0500647 unsigned int layer = context->renderTargetLayer[index];
Alexis Hetu88482c32018-06-05 17:05:17 -0400648 requiresSync |= context->renderTarget[index]->requiresSync();
Nicolas Capens8af24c52017-12-11 14:45:01 -0500649 data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
Nicolas Capensbfa23b32017-12-11 10:06:37 -0500650 data->colorBuffer[index] += q * ms * context->renderTarget[index]->getSliceB(true);
John Bauman89401822014-05-06 15:04:28 -0400651 data->colorPitchB[index] = context->renderTarget[index]->getInternalPitchB();
652 data->colorSliceB[index] = context->renderTarget[index]->getInternalSliceB();
653 }
654 }
655
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400656 draw->depthBuffer = context->depthBuffer;
657 draw->stencilBuffer = context->stencilBuffer;
John Bauman89401822014-05-06 15:04:28 -0400658
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400659 if(draw->depthBuffer)
John Bauman89401822014-05-06 15:04:28 -0400660 {
Nicolas Capens8af24c52017-12-11 14:45:01 -0500661 unsigned int layer = context->depthBufferLayer;
Alexis Hetu88482c32018-06-05 17:05:17 -0400662 requiresSync |= context->depthBuffer->requiresSync();
Nicolas Capens8af24c52017-12-11 14:45:01 -0500663 data->depthBuffer = (float*)context->depthBuffer->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
Nicolas Capensbfa23b32017-12-11 10:06:37 -0500664 data->depthBuffer += q * ms * context->depthBuffer->getSliceB(true);
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400665 data->depthPitchB = context->depthBuffer->getInternalPitchB();
666 data->depthSliceB = context->depthBuffer->getInternalSliceB();
667 }
John Bauman89401822014-05-06 15:04:28 -0400668
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400669 if(draw->stencilBuffer)
670 {
Nicolas Capens8af24c52017-12-11 14:45:01 -0500671 unsigned int layer = context->stencilBufferLayer;
Alexis Hetu88482c32018-06-05 17:05:17 -0400672 requiresSync |= context->stencilBuffer->requiresSync();
Nicolas Capens8af24c52017-12-11 14:45:01 -0500673 data->stencilBuffer = (unsigned char*)context->stencilBuffer->lockStencil(0, 0, layer, MANAGED);
Nicolas Capensbfa23b32017-12-11 10:06:37 -0500674 data->stencilBuffer += q * ms * context->stencilBuffer->getSliceB(true);
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400675 data->stencilPitchB = context->stencilBuffer->getStencilPitchB();
676 data->stencilSliceB = context->stencilBuffer->getStencilSliceB();
John Bauman89401822014-05-06 15:04:28 -0400677 }
678 }
679
John Bauman19bac1e2014-05-06 15:23:49 -0400680 // Scissor
681 {
682 data->scissorX0 = scissor.x0;
683 data->scissorX1 = scissor.x1;
684 data->scissorY0 = scissor.y0;
685 data->scissorY1 = scissor.y1;
686 }
687
John Bauman89401822014-05-06 15:04:28 -0400688 draw->primitive = 0;
689 draw->count = count;
690
691 draw->references = (count + batch - 1) / batch;
692
Nicolas Capensebe67642015-03-20 13:34:51 -0400693 schedulerMutex.lock();
Alexis Hetu6b164c32017-09-20 11:24:52 -0400694 ++nextDraw; // Atomic
Nicolas Capensebe67642015-03-20 13:34:51 -0400695 schedulerMutex.unlock();
John Bauman89401822014-05-06 15:04:28 -0400696
Nicolas Capens0808b4f2017-03-13 17:20:39 -0400697 #ifndef NDEBUG
698 if(threadCount == 1) // Use main thread for draw execution
699 {
700 threadsAwake = 1;
701 task[0].type = Task::RESUME;
702
703 taskLoop(0);
704 }
705 else
706 #endif
John Bauman89401822014-05-06 15:04:28 -0400707 {
Nicolas Capens20248dd2015-08-10 14:07:45 -0400708 if(!threadsAwake)
709 {
710 suspend[0]->wait();
John Bauman89401822014-05-06 15:04:28 -0400711
Nicolas Capens20248dd2015-08-10 14:07:45 -0400712 threadsAwake = 1;
713 task[0].type = Task::RESUME;
714
715 resume[0]->signal();
716 }
717 }
John Bauman89401822014-05-06 15:04:28 -0400718 }
Alexis Hetu90404212018-06-04 11:38:17 -0400719
720 // TODO(sugoi): This is a temporary brute-force workaround to ensure IOSurface synchronization.
Alexis Hetu88482c32018-06-05 17:05:17 -0400721 if(requiresSync)
Alexis Hetu90404212018-06-04 11:38:17 -0400722 {
723 synchronize();
724 }
John Bauman89401822014-05-06 15:04:28 -0400725 }
726
Nicolas Capens426cb5e2017-07-20 14:14:09 -0400727 void Renderer::clear(void *value, Format format, Surface *dest, const Rect &clearRect, unsigned int rgbaMask)
Nicolas Capens81aa97b2017-06-27 17:08:08 -0400728 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -0500729 blitter->clear(value, format, dest, clearRect, rgbaMask);
Nicolas Capens81aa97b2017-06-27 17:08:08 -0400730 }
731
Nicolas Capens1ab837c2017-12-16 02:28:02 -0500732 void Renderer::blit(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil, bool sRGBconversion)
Nicolas Capens81aa97b2017-06-27 17:08:08 -0400733 {
Nicolas Capens1ab837c2017-12-16 02:28:02 -0500734 blitter->blit(source, sRect, dest, dRect, {filter, isStencil, sRGBconversion});
Nicolas Capens81aa97b2017-06-27 17:08:08 -0400735 }
736
737 void Renderer::blit3D(Surface *source, Surface *dest)
738 {
739 blitter->blit3D(source, dest);
740 }
741
John Bauman89401822014-05-06 15:04:28 -0400742 void Renderer::threadFunction(void *parameters)
743 {
744 Renderer *renderer = static_cast<Parameters*>(parameters)->renderer;
745 int threadIndex = static_cast<Parameters*>(parameters)->threadIndex;
746
747 if(logPrecision < IEEE)
748 {
John Bauman66b8ab22014-05-06 15:57:45 -0400749 CPUID::setFlushToZero(true);
750 CPUID::setDenormalsAreZero(true);
John Bauman89401822014-05-06 15:04:28 -0400751 }
752
753 renderer->threadLoop(threadIndex);
754 }
755
756 void Renderer::threadLoop(int threadIndex)
757 {
758 while(!exitThreads)
759 {
760 taskLoop(threadIndex);
761
762 suspend[threadIndex]->signal();
763 resume[threadIndex]->wait();
764 }
765 }
766
767 void Renderer::taskLoop(int threadIndex)
768 {
769 while(task[threadIndex].type != Task::SUSPEND)
770 {
771 scheduleTask(threadIndex);
772 executeTask(threadIndex);
773 }
774 }
775
776 void Renderer::findAvailableTasks()
777 {
778 // Find pixel tasks
779 for(int cluster = 0; cluster < clusterCount; cluster++)
780 {
781 if(!pixelProgress[cluster].executing)
782 {
783 for(int unit = 0; unit < unitCount; unit++)
784 {
785 if(primitiveProgress[unit].references > 0) // Contains processed primitives
786 {
787 if(pixelProgress[cluster].drawCall == primitiveProgress[unit].drawCall)
788 {
789 if(pixelProgress[cluster].processedPrimitives == primitiveProgress[unit].firstPrimitive) // Previous primitives have been rendered
790 {
791 Task &task = taskQueue[qHead];
792 task.type = Task::PIXELS;
793 task.primitiveUnit = unit;
794 task.pixelCluster = cluster;
795
796 pixelProgress[cluster].executing = true;
797
798 // Commit to the task queue
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400799 qHead = (qHead + 1) & TASK_COUNT_BITS;
John Bauman89401822014-05-06 15:04:28 -0400800 qSize++;
801
802 break;
803 }
804 }
805 }
806 }
807 }
808 }
Nicolas Capensec0936c2016-05-18 12:32:02 -0400809
John Bauman89401822014-05-06 15:04:28 -0400810 // Find primitive tasks
811 if(currentDraw == nextDraw)
812 {
813 return; // No more primitives to process
814 }
815
816 for(int unit = 0; unit < unitCount; unit++)
817 {
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400818 DrawCall *draw = drawList[currentDraw & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -0400819
Alexis Hetu6b164c32017-09-20 11:24:52 -0400820 int primitive = draw->primitive;
821 int count = draw->count;
822
823 if(primitive >= count)
John Bauman89401822014-05-06 15:04:28 -0400824 {
Alexis Hetu6b164c32017-09-20 11:24:52 -0400825 ++currentDraw; // Atomic
John Bauman89401822014-05-06 15:04:28 -0400826
827 if(currentDraw == nextDraw)
828 {
829 return; // No more primitives to process
830 }
831
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400832 draw = drawList[currentDraw & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -0400833 }
834
835 if(!primitiveProgress[unit].references) // Task not already being executed and not still in use by a pixel unit
836 {
Alexis Hetu6b164c32017-09-20 11:24:52 -0400837 primitive = draw->primitive;
838 count = draw->count;
John Bauman89401822014-05-06 15:04:28 -0400839 int batch = draw->batchSize;
840
841 primitiveProgress[unit].drawCall = currentDraw;
842 primitiveProgress[unit].firstPrimitive = primitive;
843 primitiveProgress[unit].primitiveCount = count - primitive >= batch ? batch : count - primitive;
844
845 draw->primitive += batch;
846
847 Task &task = taskQueue[qHead];
848 task.type = Task::PRIMITIVES;
849 task.primitiveUnit = unit;
850
851 primitiveProgress[unit].references = -1;
852
853 // Commit to the task queue
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400854 qHead = (qHead + 1) & TASK_COUNT_BITS;
John Bauman89401822014-05-06 15:04:28 -0400855 qSize++;
856 }
857 }
858 }
859
860 void Renderer::scheduleTask(int threadIndex)
861 {
Nicolas Capensebe67642015-03-20 13:34:51 -0400862 schedulerMutex.lock();
John Bauman89401822014-05-06 15:04:28 -0400863
Alexis Hetu6b164c32017-09-20 11:24:52 -0400864 int curThreadsAwake = threadsAwake;
865
866 if((int)qSize < threadCount - curThreadsAwake + 1)
John Bauman89401822014-05-06 15:04:28 -0400867 {
868 findAvailableTasks();
869 }
870
871 if(qSize != 0)
872 {
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400873 task[threadIndex] = taskQueue[(qHead - qSize) & TASK_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -0400874 qSize--;
875
Alexis Hetu6b164c32017-09-20 11:24:52 -0400876 if(curThreadsAwake != threadCount)
John Bauman89401822014-05-06 15:04:28 -0400877 {
Alexis Hetu6b164c32017-09-20 11:24:52 -0400878 int wakeup = qSize - curThreadsAwake + 1;
John Bauman89401822014-05-06 15:04:28 -0400879
880 for(int i = 0; i < threadCount && wakeup > 0; i++)
881 {
882 if(task[i].type == Task::SUSPEND)
883 {
884 suspend[i]->wait();
885 task[i].type = Task::RESUME;
886 resume[i]->signal();
887
Alexis Hetu6b164c32017-09-20 11:24:52 -0400888 ++threadsAwake; // Atomic
John Bauman89401822014-05-06 15:04:28 -0400889 wakeup--;
890 }
891 }
892 }
893 }
894 else
895 {
896 task[threadIndex].type = Task::SUSPEND;
897
Alexis Hetu6b164c32017-09-20 11:24:52 -0400898 --threadsAwake; // Atomic
John Bauman89401822014-05-06 15:04:28 -0400899 }
900
Nicolas Capensebe67642015-03-20 13:34:51 -0400901 schedulerMutex.unlock();
John Bauman89401822014-05-06 15:04:28 -0400902 }
903
904 void Renderer::executeTask(int threadIndex)
905 {
906 #if PERF_HUD
907 int64_t startTick = Timer::ticks();
908 #endif
909
910 switch(task[threadIndex].type)
911 {
912 case Task::PRIMITIVES:
913 {
914 int unit = task[threadIndex].primitiveUnit;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400915
John Bauman89401822014-05-06 15:04:28 -0400916 int input = primitiveProgress[unit].firstPrimitive;
917 int count = primitiveProgress[unit].primitiveCount;
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400918 DrawCall *draw = drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
Nicolas Capens734392e2016-05-26 11:07:40 -0400919 int (Renderer::*setupPrimitives)(int batch, int count) = draw->setupPrimitives;
John Bauman89401822014-05-06 15:04:28 -0400920
921 processPrimitiveVertices(unit, input, count, draw->count, threadIndex);
922
923 #if PERF_HUD
924 int64_t time = Timer::ticks();
925 vertexTime[threadIndex] += time - startTick;
926 startTick = time;
927 #endif
928
Nicolas Capens734392e2016-05-26 11:07:40 -0400929 int visible = 0;
930
931 if(!draw->setupState.rasterizerDiscard)
932 {
933 visible = (this->*setupPrimitives)(unit, count);
934 }
John Bauman89401822014-05-06 15:04:28 -0400935
936 primitiveProgress[unit].visible = visible;
937 primitiveProgress[unit].references = clusterCount;
938
939 #if PERF_HUD
940 setupTime[threadIndex] += Timer::ticks() - startTick;
941 #endif
942 }
943 break;
944 case Task::PIXELS:
945 {
946 int unit = task[threadIndex].primitiveUnit;
947 int visible = primitiveProgress[unit].visible;
948
949 if(visible > 0)
950 {
951 int cluster = task[threadIndex].pixelCluster;
952 Primitive *primitive = primitiveBatch[unit];
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400953 DrawCall *draw = drawList[pixelProgress[cluster].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -0400954 DrawData *data = draw->data;
955 PixelProcessor::RoutinePointer pixelRoutine = draw->pixelPointer;
956
957 pixelRoutine(primitive, visible, cluster, data);
958 }
959
960 finishRendering(task[threadIndex]);
961
962 #if PERF_HUD
963 pixelTime[threadIndex] += Timer::ticks() - startTick;
964 #endif
965 }
966 break;
967 case Task::RESUME:
968 break;
969 case Task::SUSPEND:
970 break;
971 default:
972 ASSERT(false);
973 }
974 }
975
John Bauman19bac1e2014-05-06 15:23:49 -0400976 void Renderer::synchronize()
977 {
978 sync->lock(sw::PUBLIC);
979 sync->unlock();
980 }
981
John Bauman89401822014-05-06 15:04:28 -0400982 void Renderer::finishRendering(Task &pixelTask)
983 {
984 int unit = pixelTask.primitiveUnit;
985 int cluster = pixelTask.pixelCluster;
986
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400987 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -0400988 DrawData &data = *draw.data;
989 int primitive = primitiveProgress[unit].firstPrimitive;
990 int count = primitiveProgress[unit].primitiveCount;
Alexis Hetuf4fbcb82016-04-07 11:05:57 -0400991 int processedPrimitives = primitive + count;
John Bauman89401822014-05-06 15:04:28 -0400992
Alexis Hetuf4fbcb82016-04-07 11:05:57 -0400993 pixelProgress[cluster].processedPrimitives = processedPrimitives;
John Bauman89401822014-05-06 15:04:28 -0400994
Nicolas Capensf3304232016-03-10 00:56:16 -0500995 if(pixelProgress[cluster].processedPrimitives >= draw.count)
996 {
Alexis Hetu6b164c32017-09-20 11:24:52 -0400997 ++pixelProgress[cluster].drawCall; // Atomic
Nicolas Capensf3304232016-03-10 00:56:16 -0500998 pixelProgress[cluster].processedPrimitives = 0;
999 }
1000
Alexis Hetu6b164c32017-09-20 11:24:52 -04001001 int ref = primitiveProgress[unit].references--; // Atomic
John Bauman89401822014-05-06 15:04:28 -04001002
1003 if(ref == 0)
1004 {
Alexis Hetu6b164c32017-09-20 11:24:52 -04001005 ref = draw.references--; // Atomic
John Bauman89401822014-05-06 15:04:28 -04001006
1007 if(ref == 0)
1008 {
1009 #if PERF_PROFILE
1010 for(int cluster = 0; cluster < clusterCount; cluster++)
1011 {
1012 for(int i = 0; i < PERF_TIMERS; i++)
1013 {
1014 profiler.cycles[i] += data.cycles[i][cluster];
1015 }
1016 }
1017 #endif
1018
1019 if(draw.queries)
1020 {
Alexis Hetubf3fc252017-12-06 14:22:10 -05001021 for(auto &query : *(draw.queries))
John Bauman89401822014-05-06 15:04:28 -04001022 {
Alexis Hetu16116cb2016-03-02 15:59:51 -05001023 switch(query->type)
John Bauman89401822014-05-06 15:04:28 -04001024 {
Alexis Hetu16116cb2016-03-02 15:59:51 -05001025 case Query::FRAGMENTS_PASSED:
1026 for(int cluster = 0; cluster < clusterCount; cluster++)
1027 {
Alexis Hetu6b164c32017-09-20 11:24:52 -04001028 query->data += data.occlusion[cluster];
Alexis Hetu16116cb2016-03-02 15:59:51 -05001029 }
1030 break;
1031 case Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Alexis Hetu6b164c32017-09-20 11:24:52 -04001032 query->data += processedPrimitives;
Alexis Hetu16116cb2016-03-02 15:59:51 -05001033 break;
1034 default:
1035 break;
John Bauman89401822014-05-06 15:04:28 -04001036 }
1037
Alexis Hetu3fc68932018-11-14 10:54:53 -05001038 query->release();
John Bauman89401822014-05-06 15:04:28 -04001039 }
1040
1041 delete draw.queries;
1042 draw.queries = 0;
1043 }
1044
Alexis Hetu1edcd8b2015-11-05 11:12:41 -05001045 for(int i = 0; i < RENDERTARGETS; i++)
John Bauman89401822014-05-06 15:04:28 -04001046 {
1047 if(draw.renderTarget[i])
1048 {
1049 draw.renderTarget[i]->unlockInternal();
1050 }
1051 }
1052
Nicolas Capens3751c1e2016-03-21 14:14:14 -04001053 if(draw.depthBuffer)
John Bauman89401822014-05-06 15:04:28 -04001054 {
Nicolas Capens3751c1e2016-03-21 14:14:14 -04001055 draw.depthBuffer->unlockInternal();
1056 }
1057
1058 if(draw.stencilBuffer)
1059 {
1060 draw.stencilBuffer->unlockStencil();
John Bauman89401822014-05-06 15:04:28 -04001061 }
1062
Alexis Hetu0b65c5e2015-03-31 11:48:57 -04001063 for(int i = 0; i < TOTAL_IMAGE_UNITS; i++)
John Bauman89401822014-05-06 15:04:28 -04001064 {
1065 if(draw.texture[i])
1066 {
1067 draw.texture[i]->unlock();
1068 }
1069 }
1070
Nicolas Capensf0aef1a2016-05-18 14:44:21 -04001071 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -04001072 {
1073 if(draw.vertexStream[i])
1074 {
1075 draw.vertexStream[i]->unlock();
1076 }
1077 }
1078
1079 if(draw.indexBuffer)
1080 {
1081 draw.indexBuffer->unlock();
1082 }
1083
Alexis Hetuc6a57cb2016-04-07 10:48:31 -04001084 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
1085 {
1086 if(draw.pUniformBuffers[i])
1087 {
1088 draw.pUniformBuffers[i]->unlock();
1089 }
1090 if(draw.vUniformBuffers[i])
1091 {
1092 draw.vUniformBuffers[i]->unlock();
1093 }
1094 }
1095
1096 for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
1097 {
1098 if(draw.transformFeedbackBuffers[i])
1099 {
1100 draw.transformFeedbackBuffers[i]->unlock();
1101 }
1102 }
Alexis Hetu2c2a7b22015-10-27 16:12:11 -04001103
Ben Clayton6897e9b2019-07-16 17:27:27 +01001104 draw.vertexRoutine.reset();
1105 draw.setupRoutine.reset();
1106 draw.pixelRoutine.reset();
John Bauman89401822014-05-06 15:04:28 -04001107
John Bauman19bac1e2014-05-06 15:23:49 -04001108 sync->unlock();
1109
John Bauman89401822014-05-06 15:04:28 -04001110 draw.references = -1;
1111 resumeApp->signal();
1112 }
1113 }
1114
1115 pixelProgress[cluster].executing = false;
1116 }
1117
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001118 void Renderer::processPrimitiveVertices(int unit, unsigned int start, unsigned int triangleCount, unsigned int loop, int thread)
John Bauman89401822014-05-06 15:04:28 -04001119 {
1120 Triangle *triangle = triangleBatch[unit];
Alexis Hetu6b164c32017-09-20 11:24:52 -04001121 int primitiveDrawCall = primitiveProgress[unit].drawCall;
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001122 DrawCall *draw = drawList[primitiveDrawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001123 DrawData *data = draw->data;
1124 VertexTask *task = vertexTask[thread];
1125
1126 const void *indices = data->indices;
1127 VertexProcessor::RoutinePointer vertexRoutine = draw->vertexPointer;
1128
Alexis Hetu6b164c32017-09-20 11:24:52 -04001129 if(task->vertexCache.drawCall != primitiveDrawCall)
John Bauman89401822014-05-06 15:04:28 -04001130 {
1131 task->vertexCache.clear();
Alexis Hetu6b164c32017-09-20 11:24:52 -04001132 task->vertexCache.drawCall = primitiveDrawCall;
John Bauman89401822014-05-06 15:04:28 -04001133 }
1134
1135 unsigned int batch[128][3]; // FIXME: Adjust to dynamic batch size
1136
1137 switch(draw->drawType)
1138 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001139 case DRAW_POINTLIST:
John Bauman89401822014-05-06 15:04:28 -04001140 {
1141 unsigned int index = start;
1142
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001143 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001144 {
1145 batch[i][0] = index;
1146 batch[i][1] = index;
1147 batch[i][2] = index;
1148
1149 index += 1;
1150 }
1151 }
1152 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001153 case DRAW_LINELIST:
John Bauman89401822014-05-06 15:04:28 -04001154 {
1155 unsigned int index = 2 * start;
1156
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001157 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001158 {
1159 batch[i][0] = index + 0;
1160 batch[i][1] = index + 1;
1161 batch[i][2] = index + 1;
1162
1163 index += 2;
1164 }
1165 }
1166 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001167 case DRAW_LINESTRIP:
John Bauman89401822014-05-06 15:04:28 -04001168 {
1169 unsigned int index = start;
1170
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001171 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001172 {
1173 batch[i][0] = index + 0;
1174 batch[i][1] = index + 1;
1175 batch[i][2] = index + 1;
1176
1177 index += 1;
1178 }
1179 }
1180 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001181 case DRAW_LINELOOP:
John Bauman89401822014-05-06 15:04:28 -04001182 {
1183 unsigned int index = start;
1184
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001185 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001186 {
1187 batch[i][0] = (index + 0) % loop;
1188 batch[i][1] = (index + 1) % loop;
1189 batch[i][2] = (index + 1) % loop;
1190
1191 index += 1;
1192 }
1193 }
1194 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001195 case DRAW_TRIANGLELIST:
John Bauman89401822014-05-06 15:04:28 -04001196 {
1197 unsigned int index = 3 * start;
1198
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001199 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001200 {
1201 batch[i][0] = index + 0;
1202 batch[i][1] = index + 1;
1203 batch[i][2] = index + 2;
1204
1205 index += 3;
1206 }
1207 }
1208 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001209 case DRAW_TRIANGLESTRIP:
John Bauman89401822014-05-06 15:04:28 -04001210 {
1211 unsigned int index = start;
1212
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001213 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001214 {
Alexis Hetu62cd2bd2017-12-21 13:52:00 -05001215 if(leadingVertexFirst)
1216 {
1217 batch[i][0] = index + 0;
1218 batch[i][1] = index + (index & 1) + 1;
1219 batch[i][2] = index + (~index & 1) + 1;
1220 }
1221 else
1222 {
1223 batch[i][0] = index + (index & 1);
1224 batch[i][1] = index + (~index & 1);
1225 batch[i][2] = index + 2;
1226 }
John Bauman89401822014-05-06 15:04:28 -04001227
1228 index += 1;
1229 }
1230 }
1231 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001232 case DRAW_TRIANGLEFAN:
John Bauman89401822014-05-06 15:04:28 -04001233 {
1234 unsigned int index = start;
1235
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001236 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001237 {
Alexis Hetu62cd2bd2017-12-21 13:52:00 -05001238 if(leadingVertexFirst)
1239 {
1240 batch[i][0] = index + 1;
1241 batch[i][1] = index + 2;
1242 batch[i][2] = 0;
1243 }
1244 else
1245 {
1246 batch[i][0] = 0;
1247 batch[i][1] = index + 1;
1248 batch[i][2] = index + 2;
1249 }
John Bauman89401822014-05-06 15:04:28 -04001250
1251 index += 1;
1252 }
1253 }
1254 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001255 case DRAW_INDEXEDPOINTLIST8:
John Bauman89401822014-05-06 15:04:28 -04001256 {
1257 const unsigned char *index = (const unsigned char*)indices + start;
1258
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001259 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001260 {
1261 batch[i][0] = *index;
1262 batch[i][1] = *index;
1263 batch[i][2] = *index;
1264
1265 index += 1;
1266 }
1267 }
1268 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001269 case DRAW_INDEXEDPOINTLIST16:
John Bauman89401822014-05-06 15:04:28 -04001270 {
1271 const unsigned short *index = (const unsigned short*)indices + start;
1272
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001273 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001274 {
1275 batch[i][0] = *index;
1276 batch[i][1] = *index;
1277 batch[i][2] = *index;
1278
1279 index += 1;
1280 }
1281 }
1282 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001283 case DRAW_INDEXEDPOINTLIST32:
John Bauman89401822014-05-06 15:04:28 -04001284 {
1285 const unsigned int *index = (const unsigned int*)indices + start;
1286
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001287 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001288 {
1289 batch[i][0] = *index;
1290 batch[i][1] = *index;
1291 batch[i][2] = *index;
1292
1293 index += 1;
1294 }
1295 }
1296 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001297 case DRAW_INDEXEDLINELIST8:
John Bauman89401822014-05-06 15:04:28 -04001298 {
1299 const unsigned char *index = (const unsigned char*)indices + 2 * start;
1300
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001301 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001302 {
1303 batch[i][0] = index[0];
1304 batch[i][1] = index[1];
1305 batch[i][2] = index[1];
1306
1307 index += 2;
1308 }
1309 }
1310 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001311 case DRAW_INDEXEDLINELIST16:
John Bauman89401822014-05-06 15:04:28 -04001312 {
1313 const unsigned short *index = (const unsigned short*)indices + 2 * start;
1314
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001315 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001316 {
1317 batch[i][0] = index[0];
1318 batch[i][1] = index[1];
1319 batch[i][2] = index[1];
1320
1321 index += 2;
1322 }
1323 }
1324 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001325 case DRAW_INDEXEDLINELIST32:
John Bauman89401822014-05-06 15:04:28 -04001326 {
1327 const unsigned int *index = (const unsigned int*)indices + 2 * start;
1328
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001329 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001330 {
1331 batch[i][0] = index[0];
1332 batch[i][1] = index[1];
1333 batch[i][2] = index[1];
1334
1335 index += 2;
1336 }
1337 }
1338 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001339 case DRAW_INDEXEDLINESTRIP8:
John Bauman89401822014-05-06 15:04:28 -04001340 {
1341 const unsigned char *index = (const unsigned char*)indices + start;
1342
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001343 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001344 {
1345 batch[i][0] = index[0];
1346 batch[i][1] = index[1];
1347 batch[i][2] = index[1];
1348
1349 index += 1;
1350 }
1351 }
1352 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001353 case DRAW_INDEXEDLINESTRIP16:
John Bauman89401822014-05-06 15:04:28 -04001354 {
1355 const unsigned short *index = (const unsigned short*)indices + start;
1356
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001357 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001358 {
1359 batch[i][0] = index[0];
1360 batch[i][1] = index[1];
1361 batch[i][2] = index[1];
1362
1363 index += 1;
1364 }
1365 }
1366 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001367 case DRAW_INDEXEDLINESTRIP32:
John Bauman89401822014-05-06 15:04:28 -04001368 {
1369 const unsigned int *index = (const unsigned int*)indices + start;
1370
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001371 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001372 {
1373 batch[i][0] = index[0];
1374 batch[i][1] = index[1];
1375 batch[i][2] = index[1];
1376
1377 index += 1;
1378 }
1379 }
1380 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001381 case DRAW_INDEXEDLINELOOP8:
John Bauman89401822014-05-06 15:04:28 -04001382 {
John Bauman66b8ab22014-05-06 15:57:45 -04001383 const unsigned char *index = (const unsigned char*)indices;
John Bauman89401822014-05-06 15:04:28 -04001384
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001385 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001386 {
John Bauman66b8ab22014-05-06 15:57:45 -04001387 batch[i][0] = index[(start + i + 0) % loop];
1388 batch[i][1] = index[(start + i + 1) % loop];
1389 batch[i][2] = index[(start + i + 1) % loop];
John Bauman89401822014-05-06 15:04:28 -04001390 }
1391 }
1392 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001393 case DRAW_INDEXEDLINELOOP16:
John Bauman89401822014-05-06 15:04:28 -04001394 {
John Bauman66b8ab22014-05-06 15:57:45 -04001395 const unsigned short *index = (const unsigned short*)indices;
John Bauman89401822014-05-06 15:04:28 -04001396
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001397 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001398 {
John Bauman66b8ab22014-05-06 15:57:45 -04001399 batch[i][0] = index[(start + i + 0) % loop];
1400 batch[i][1] = index[(start + i + 1) % loop];
1401 batch[i][2] = index[(start + i + 1) % loop];
John Bauman89401822014-05-06 15:04:28 -04001402 }
1403 }
1404 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001405 case DRAW_INDEXEDLINELOOP32:
John Bauman89401822014-05-06 15:04:28 -04001406 {
John Bauman66b8ab22014-05-06 15:57:45 -04001407 const unsigned int *index = (const unsigned int*)indices;
John Bauman89401822014-05-06 15:04:28 -04001408
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001409 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001410 {
John Bauman66b8ab22014-05-06 15:57:45 -04001411 batch[i][0] = index[(start + i + 0) % loop];
1412 batch[i][1] = index[(start + i + 1) % loop];
1413 batch[i][2] = index[(start + i + 1) % loop];
John Bauman89401822014-05-06 15:04:28 -04001414 }
1415 }
1416 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001417 case DRAW_INDEXEDTRIANGLELIST8:
John Bauman89401822014-05-06 15:04:28 -04001418 {
1419 const unsigned char *index = (const unsigned char*)indices + 3 * start;
1420
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001421 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001422 {
1423 batch[i][0] = index[0];
1424 batch[i][1] = index[1];
1425 batch[i][2] = index[2];
1426
1427 index += 3;
1428 }
1429 }
1430 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001431 case DRAW_INDEXEDTRIANGLELIST16:
John Bauman89401822014-05-06 15:04:28 -04001432 {
1433 const unsigned short *index = (const unsigned short*)indices + 3 * start;
1434
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001435 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001436 {
1437 batch[i][0] = index[0];
1438 batch[i][1] = index[1];
1439 batch[i][2] = index[2];
1440
1441 index += 3;
1442 }
1443 }
1444 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001445 case DRAW_INDEXEDTRIANGLELIST32:
John Bauman89401822014-05-06 15:04:28 -04001446 {
1447 const unsigned int *index = (const unsigned int*)indices + 3 * start;
1448
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001449 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001450 {
1451 batch[i][0] = index[0];
1452 batch[i][1] = index[1];
1453 batch[i][2] = index[2];
1454
1455 index += 3;
1456 }
1457 }
1458 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001459 case DRAW_INDEXEDTRIANGLESTRIP8:
John Bauman89401822014-05-06 15:04:28 -04001460 {
1461 const unsigned char *index = (const unsigned char*)indices + start;
1462
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001463 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001464 {
1465 batch[i][0] = index[0];
1466 batch[i][1] = index[((start + i) & 1) + 1];
1467 batch[i][2] = index[(~(start + i) & 1) + 1];
1468
1469 index += 1;
1470 }
1471 }
1472 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001473 case DRAW_INDEXEDTRIANGLESTRIP16:
John Bauman89401822014-05-06 15:04:28 -04001474 {
1475 const unsigned short *index = (const unsigned short*)indices + start;
1476
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001477 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001478 {
1479 batch[i][0] = index[0];
1480 batch[i][1] = index[((start + i) & 1) + 1];
1481 batch[i][2] = index[(~(start + i) & 1) + 1];
1482
1483 index += 1;
1484 }
1485 }
1486 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001487 case DRAW_INDEXEDTRIANGLESTRIP32:
John Bauman89401822014-05-06 15:04:28 -04001488 {
1489 const unsigned int *index = (const unsigned int*)indices + start;
1490
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001491 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001492 {
1493 batch[i][0] = index[0];
1494 batch[i][1] = index[((start + i) & 1) + 1];
1495 batch[i][2] = index[(~(start + i) & 1) + 1];
1496
1497 index += 1;
1498 }
1499 }
1500 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001501 case DRAW_INDEXEDTRIANGLEFAN8:
John Bauman89401822014-05-06 15:04:28 -04001502 {
1503 const unsigned char *index = (const unsigned char*)indices;
1504
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001505 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001506 {
1507 batch[i][0] = index[start + i + 1];
1508 batch[i][1] = index[start + i + 2];
1509 batch[i][2] = index[0];
1510 }
1511 }
1512 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001513 case DRAW_INDEXEDTRIANGLEFAN16:
John Bauman89401822014-05-06 15:04:28 -04001514 {
1515 const unsigned short *index = (const unsigned short*)indices;
1516
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001517 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001518 {
1519 batch[i][0] = index[start + i + 1];
1520 batch[i][1] = index[start + i + 2];
1521 batch[i][2] = index[0];
1522 }
1523 }
1524 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001525 case DRAW_INDEXEDTRIANGLEFAN32:
John Bauman89401822014-05-06 15:04:28 -04001526 {
1527 const unsigned int *index = (const unsigned int*)indices;
1528
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001529 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001530 {
1531 batch[i][0] = index[start + i + 1];
1532 batch[i][1] = index[start + i + 2];
1533 batch[i][2] = index[0];
1534 }
1535 }
1536 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001537 case DRAW_QUADLIST:
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001538 {
1539 unsigned int index = 4 * start / 2;
1540
1541 for(unsigned int i = 0; i < triangleCount; i += 2)
1542 {
1543 batch[i+0][0] = index + 0;
1544 batch[i+0][1] = index + 1;
1545 batch[i+0][2] = index + 2;
1546
Nicolas Capens0bac2852016-05-07 06:09:58 -04001547 batch[i+1][0] = index + 0;
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001548 batch[i+1][1] = index + 2;
1549 batch[i+1][2] = index + 3;
1550
1551 index += 4;
1552 }
1553 }
1554 break;
John Bauman89401822014-05-06 15:04:28 -04001555 default:
1556 ASSERT(false);
Nicolas Capense5284ac2016-01-08 01:30:48 -05001557 return;
John Bauman89401822014-05-06 15:04:28 -04001558 }
1559
Alexis Hetua62a0ca2016-04-20 15:29:51 -04001560 task->primitiveStart = start;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001561 task->vertexCount = triangleCount * 3;
John Bauman89401822014-05-06 15:04:28 -04001562 vertexRoutine(&triangle->v0, (unsigned int*)&batch, task, data);
1563 }
1564
Nicolas Capens734392e2016-05-26 11:07:40 -04001565 int Renderer::setupSolidTriangles(int unit, int count)
John Bauman89401822014-05-06 15:04:28 -04001566 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001567 Triangle *triangle = triangleBatch[unit];
1568 Primitive *primitive = primitiveBatch[unit];
John Bauman89401822014-05-06 15:04:28 -04001569
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001570 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001571 SetupProcessor::State &state = draw.setupState;
1572 const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
1573
1574 int ms = state.multiSample;
1575 int pos = state.positionRegister;
1576 const DrawData *data = draw.data;
1577 int visible = 0;
1578
1579 for(int i = 0; i < count; i++, triangle++)
1580 {
1581 Vertex &v0 = triangle->v0;
1582 Vertex &v1 = triangle->v1;
1583 Vertex &v2 = triangle->v2;
1584
1585 if((v0.clipFlags & v1.clipFlags & v2.clipFlags) == Clipper::CLIP_FINITE)
1586 {
1587 Polygon polygon(&v0.v[pos], &v1.v[pos], &v2.v[pos]);
1588
1589 int clipFlagsOr = v0.clipFlags | v1.clipFlags | v2.clipFlags | draw.clipFlags;
1590
1591 if(clipFlagsOr != Clipper::CLIP_FINITE)
1592 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001593 if(!clipper->clip(polygon, clipFlagsOr, draw))
John Bauman89401822014-05-06 15:04:28 -04001594 {
1595 continue;
1596 }
1597 }
1598
1599 if(setupRoutine(primitive, triangle, &polygon, data))
1600 {
1601 primitive += ms;
1602 visible++;
1603 }
1604 }
1605 }
1606
1607 return visible;
1608 }
1609
Nicolas Capens734392e2016-05-26 11:07:40 -04001610 int Renderer::setupWireframeTriangle(int unit, int count)
John Bauman89401822014-05-06 15:04:28 -04001611 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001612 Triangle *triangle = triangleBatch[unit];
1613 Primitive *primitive = primitiveBatch[unit];
John Bauman89401822014-05-06 15:04:28 -04001614 int visible = 0;
1615
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001616 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001617 SetupProcessor::State &state = draw.setupState;
John Bauman89401822014-05-06 15:04:28 -04001618
1619 const Vertex &v0 = triangle[0].v0;
1620 const Vertex &v1 = triangle[0].v1;
1621 const Vertex &v2 = triangle[0].v2;
1622
1623 float d = (v0.y * v1.x - v0.x * v1.y) * v2.w + (v0.x * v2.y - v0.y * v2.x) * v1.w + (v2.x * v1.y - v1.x * v2.y) * v0.w;
1624
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001625 if(state.cullMode == CULL_CLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -04001626 {
1627 if(d >= 0) return 0;
1628 }
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001629 else if(state.cullMode == CULL_COUNTERCLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -04001630 {
1631 if(d <= 0) return 0;
1632 }
1633
1634 // Copy attributes
1635 triangle[1].v0 = v1;
1636 triangle[1].v1 = v2;
1637 triangle[2].v0 = v2;
1638 triangle[2].v1 = v0;
1639
1640 if(state.color[0][0].flat) // FIXME
1641 {
1642 for(int i = 0; i < 2; i++)
1643 {
1644 triangle[1].v0.C[i] = triangle[0].v0.C[i];
John Bauman66b8ab22014-05-06 15:57:45 -04001645 triangle[1].v1.C[i] = triangle[0].v0.C[i];
John Bauman89401822014-05-06 15:04:28 -04001646 triangle[2].v0.C[i] = triangle[0].v0.C[i];
John Bauman66b8ab22014-05-06 15:57:45 -04001647 triangle[2].v1.C[i] = triangle[0].v0.C[i];
John Bauman89401822014-05-06 15:04:28 -04001648 }
1649 }
1650
1651 for(int i = 0; i < 3; i++)
1652 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001653 if(setupLine(*primitive, *triangle, draw))
John Bauman89401822014-05-06 15:04:28 -04001654 {
1655 primitive->area = 0.5f * d;
1656
1657 primitive++;
1658 visible++;
1659 }
1660
1661 triangle++;
1662 }
1663
1664 return visible;
1665 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04001666
Nicolas Capens734392e2016-05-26 11:07:40 -04001667 int Renderer::setupVertexTriangle(int unit, int count)
John Bauman89401822014-05-06 15:04:28 -04001668 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001669 Triangle *triangle = triangleBatch[unit];
1670 Primitive *primitive = primitiveBatch[unit];
John Bauman89401822014-05-06 15:04:28 -04001671 int visible = 0;
1672
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001673 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001674 SetupProcessor::State &state = draw.setupState;
1675
1676 const Vertex &v0 = triangle[0].v0;
1677 const Vertex &v1 = triangle[0].v1;
1678 const Vertex &v2 = triangle[0].v2;
1679
1680 float d = (v0.y * v1.x - v0.x * v1.y) * v2.w + (v0.x * v2.y - v0.y * v2.x) * v1.w + (v2.x * v1.y - v1.x * v2.y) * v0.w;
1681
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001682 if(state.cullMode == CULL_CLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -04001683 {
1684 if(d >= 0) return 0;
1685 }
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001686 else if(state.cullMode == CULL_COUNTERCLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -04001687 {
1688 if(d <= 0) return 0;
1689 }
1690
1691 // Copy attributes
1692 triangle[1].v0 = v1;
1693 triangle[2].v0 = v2;
1694
1695 for(int i = 0; i < 3; i++)
1696 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001697 if(setupPoint(*primitive, *triangle, draw))
John Bauman89401822014-05-06 15:04:28 -04001698 {
1699 primitive->area = 0.5f * d;
1700
1701 primitive++;
1702 visible++;
1703 }
1704
1705 triangle++;
1706 }
1707
1708 return visible;
1709 }
1710
Nicolas Capens734392e2016-05-26 11:07:40 -04001711 int Renderer::setupLines(int unit, int count)
John Bauman89401822014-05-06 15:04:28 -04001712 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001713 Triangle *triangle = triangleBatch[unit];
1714 Primitive *primitive = primitiveBatch[unit];
John Bauman89401822014-05-06 15:04:28 -04001715 int visible = 0;
1716
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001717 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001718 SetupProcessor::State &state = draw.setupState;
1719
1720 int ms = state.multiSample;
1721
1722 for(int i = 0; i < count; i++)
1723 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001724 if(setupLine(*primitive, *triangle, draw))
John Bauman89401822014-05-06 15:04:28 -04001725 {
1726 primitive += ms;
1727 visible++;
1728 }
1729
1730 triangle++;
1731 }
1732
1733 return visible;
1734 }
1735
Nicolas Capens734392e2016-05-26 11:07:40 -04001736 int Renderer::setupPoints(int unit, int count)
John Bauman89401822014-05-06 15:04:28 -04001737 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001738 Triangle *triangle = triangleBatch[unit];
1739 Primitive *primitive = primitiveBatch[unit];
John Bauman89401822014-05-06 15:04:28 -04001740 int visible = 0;
1741
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001742 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001743 SetupProcessor::State &state = draw.setupState;
1744
1745 int ms = state.multiSample;
1746
1747 for(int i = 0; i < count; i++)
1748 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001749 if(setupPoint(*primitive, *triangle, draw))
John Bauman89401822014-05-06 15:04:28 -04001750 {
1751 primitive += ms;
1752 visible++;
1753 }
1754
1755 triangle++;
1756 }
1757
1758 return visible;
1759 }
1760
Nicolas Capens734392e2016-05-26 11:07:40 -04001761 bool Renderer::setupLine(Primitive &primitive, Triangle &triangle, const DrawCall &draw)
John Bauman89401822014-05-06 15:04:28 -04001762 {
1763 const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
1764 const SetupProcessor::State &state = draw.setupState;
1765 const DrawData &data = *draw.data;
1766
Nicolas Capens235781d2015-01-27 01:46:53 -05001767 float lineWidth = data.lineWidth;
1768
John Bauman89401822014-05-06 15:04:28 -04001769 Vertex &v0 = triangle.v0;
1770 Vertex &v1 = triangle.v1;
1771
1772 int pos = state.positionRegister;
1773
1774 const float4 &P0 = v0.v[pos];
1775 const float4 &P1 = v1.v[pos];
1776
1777 if(P0.w <= 0 && P1.w <= 0)
1778 {
1779 return false;
1780 }
1781
John Bauman19bac1e2014-05-06 15:23:49 -04001782 const float W = data.Wx16[0] * (1.0f / 16.0f);
1783 const float H = data.Hx16[0] * (1.0f / 16.0f);
John Bauman89401822014-05-06 15:04:28 -04001784
1785 float dx = W * (P1.x / P1.w - P0.x / P0.w);
1786 float dy = H * (P1.y / P1.w - P0.y / P0.w);
1787
1788 if(dx == 0 && dy == 0)
1789 {
1790 return false;
1791 }
1792
Nicolas Capens66ba1f92019-11-08 16:29:24 -05001793 if(state.multiSample > 1)
John Bauman89401822014-05-06 15:04:28 -04001794 {
Nicolas Capens66ba1f92019-11-08 16:29:24 -05001795 // Rectangle centered on the line segment
1796
John Bauman89401822014-05-06 15:04:28 -04001797 float4 P[4];
1798 int C[4];
1799
1800 P[0] = P0;
1801 P[1] = P1;
1802 P[2] = P1;
1803 P[3] = P0;
1804
Nicolas Capens235781d2015-01-27 01:46:53 -05001805 float scale = lineWidth * 0.5f / sqrt(dx*dx + dy*dy);
John Bauman89401822014-05-06 15:04:28 -04001806
1807 dx *= scale;
1808 dy *= scale;
1809
John Bauman89401822014-05-06 15:04:28 -04001810 float dx0h = dx * P0.w / H;
1811 float dy0w = dy * P0.w / W;
1812
John Bauman89401822014-05-06 15:04:28 -04001813 float dx1h = dx * P1.w / H;
1814 float dy1w = dy * P1.w / W;
1815
Nicolas Capensb04881b2018-03-16 23:23:06 -04001816 P[0].x += -dy0w;
1817 P[0].y += +dx0h;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001818 C[0] = clipper->computeClipFlags(P[0]);
John Bauman89401822014-05-06 15:04:28 -04001819
Nicolas Capensb04881b2018-03-16 23:23:06 -04001820 P[1].x += -dy1w;
1821 P[1].y += +dx1h;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001822 C[1] = clipper->computeClipFlags(P[1]);
John Bauman89401822014-05-06 15:04:28 -04001823
Nicolas Capensb04881b2018-03-16 23:23:06 -04001824 P[2].x += +dy1w;
1825 P[2].y += -dx1h;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001826 C[2] = clipper->computeClipFlags(P[2]);
John Bauman89401822014-05-06 15:04:28 -04001827
Nicolas Capensb04881b2018-03-16 23:23:06 -04001828 P[3].x += +dy0w;
1829 P[3].y += -dx0h;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001830 C[3] = clipper->computeClipFlags(P[3]);
John Bauman89401822014-05-06 15:04:28 -04001831
1832 if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
1833 {
1834 Polygon polygon(P, 4);
1835
1836 int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | draw.clipFlags;
1837
1838 if(clipFlagsOr != Clipper::CLIP_FINITE)
1839 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001840 if(!clipper->clip(polygon, clipFlagsOr, draw))
John Bauman89401822014-05-06 15:04:28 -04001841 {
1842 return false;
1843 }
1844 }
1845
1846 return setupRoutine(&primitive, &triangle, &polygon, &data);
1847 }
1848 }
Nicolas Capens66ba1f92019-11-08 16:29:24 -05001849 else if(true)
John Bauman89401822014-05-06 15:04:28 -04001850 {
Nicolas Capens66ba1f92019-11-08 16:29:24 -05001851 // Connecting diamonds polygon
1852 // This shape satisfies the diamond test convention, except for the exit rule part.
1853 // Line segments with overlapping endpoints have duplicate fragments.
1854 // The ideal algorithm requires half-open line rasterization (b/80135519).
1855
John Bauman89401822014-05-06 15:04:28 -04001856 float4 P[8];
1857 int C[8];
1858
1859 P[0] = P0;
1860 P[1] = P0;
1861 P[2] = P0;
1862 P[3] = P0;
1863 P[4] = P1;
1864 P[5] = P1;
1865 P[6] = P1;
1866 P[7] = P1;
1867
Nicolas Capens235781d2015-01-27 01:46:53 -05001868 float dx0 = lineWidth * 0.5f * P0.w / W;
1869 float dy0 = lineWidth * 0.5f * P0.w / H;
John Bauman89401822014-05-06 15:04:28 -04001870
Nicolas Capens235781d2015-01-27 01:46:53 -05001871 float dx1 = lineWidth * 0.5f * P1.w / W;
1872 float dy1 = lineWidth * 0.5f * P1.w / H;
John Bauman89401822014-05-06 15:04:28 -04001873
1874 P[0].x += -dx0;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001875 C[0] = clipper->computeClipFlags(P[0]);
John Bauman89401822014-05-06 15:04:28 -04001876
John Bauman19bac1e2014-05-06 15:23:49 -04001877 P[1].y += +dy0;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001878 C[1] = clipper->computeClipFlags(P[1]);
John Bauman89401822014-05-06 15:04:28 -04001879
1880 P[2].x += +dx0;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001881 C[2] = clipper->computeClipFlags(P[2]);
John Bauman89401822014-05-06 15:04:28 -04001882
John Bauman19bac1e2014-05-06 15:23:49 -04001883 P[3].y += -dy0;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001884 C[3] = clipper->computeClipFlags(P[3]);
John Bauman89401822014-05-06 15:04:28 -04001885
1886 P[4].x += -dx1;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001887 C[4] = clipper->computeClipFlags(P[4]);
John Bauman89401822014-05-06 15:04:28 -04001888
John Bauman19bac1e2014-05-06 15:23:49 -04001889 P[5].y += +dy1;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001890 C[5] = clipper->computeClipFlags(P[5]);
John Bauman89401822014-05-06 15:04:28 -04001891
1892 P[6].x += +dx1;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001893 C[6] = clipper->computeClipFlags(P[6]);
John Bauman89401822014-05-06 15:04:28 -04001894
John Bauman19bac1e2014-05-06 15:23:49 -04001895 P[7].y += -dy1;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001896 C[7] = clipper->computeClipFlags(P[7]);
John Bauman89401822014-05-06 15:04:28 -04001897
1898 if((C[0] & C[1] & C[2] & C[3] & C[4] & C[5] & C[6] & C[7]) == Clipper::CLIP_FINITE)
1899 {
1900 float4 L[6];
1901
John Bauman19bac1e2014-05-06 15:23:49 -04001902 if(dx > -dy)
John Bauman89401822014-05-06 15:04:28 -04001903 {
John Bauman19bac1e2014-05-06 15:23:49 -04001904 if(dx > dy) // Right
John Bauman89401822014-05-06 15:04:28 -04001905 {
1906 L[0] = P[0];
1907 L[1] = P[1];
1908 L[2] = P[5];
1909 L[3] = P[6];
1910 L[4] = P[7];
1911 L[5] = P[3];
1912 }
1913 else // Down
1914 {
1915 L[0] = P[0];
1916 L[1] = P[4];
1917 L[2] = P[5];
1918 L[3] = P[6];
1919 L[4] = P[2];
1920 L[5] = P[3];
1921 }
1922 }
1923 else
1924 {
John Bauman19bac1e2014-05-06 15:23:49 -04001925 if(dx > dy) // Up
John Bauman89401822014-05-06 15:04:28 -04001926 {
1927 L[0] = P[0];
1928 L[1] = P[1];
1929 L[2] = P[2];
1930 L[3] = P[6];
1931 L[4] = P[7];
1932 L[5] = P[4];
1933 }
1934 else // Left
1935 {
1936 L[0] = P[1];
1937 L[1] = P[2];
1938 L[2] = P[3];
1939 L[3] = P[7];
1940 L[4] = P[4];
1941 L[5] = P[5];
1942 }
1943 }
1944
1945 Polygon polygon(L, 6);
1946
1947 int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | C[4] | C[5] | C[6] | C[7] | draw.clipFlags;
1948
1949 if(clipFlagsOr != Clipper::CLIP_FINITE)
1950 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001951 if(!clipper->clip(polygon, clipFlagsOr, draw))
John Bauman89401822014-05-06 15:04:28 -04001952 {
1953 return false;
1954 }
1955 }
1956
1957 return setupRoutine(&primitive, &triangle, &polygon, &data);
1958 }
1959 }
Nicolas Capens66ba1f92019-11-08 16:29:24 -05001960 else
1961 {
1962 // Parallelogram approximating Bresenham line
1963 // This algorithm does not satisfy the ideal diamond-exit rule, but does avoid the
1964 // duplicate fragment rasterization problem and satisfies all of Vulkan's minimum
1965 // requirements for Bresenham line segment rasterization.
1966
1967 float4 P[8];
1968 P[0] = P0;
1969 P[1] = P0;
1970 P[2] = P0;
1971 P[3] = P0;
1972 P[4] = P1;
1973 P[5] = P1;
1974 P[6] = P1;
1975 P[7] = P1;
1976
1977 float dx0 = lineWidth * 0.5f * P0.w / W;
1978 float dy0 = lineWidth * 0.5f * P0.w / H;
1979
1980 float dx1 = lineWidth * 0.5f * P1.w / W;
1981 float dy1 = lineWidth * 0.5f * P1.w / H;
1982
1983 P[0].x += -dx0;
1984 P[1].y += +dy0;
1985 P[2].x += +dx0;
1986 P[3].y += -dy0;
1987 P[4].x += -dx1;
1988 P[5].y += +dy1;
1989 P[6].x += +dx1;
1990 P[7].y += -dy1;
1991
1992 float4 L[4];
1993
1994 if(dx > -dy)
1995 {
1996 if(dx > dy) // Right
1997 {
1998 L[0] = P[1];
1999 L[1] = P[5];
2000 L[2] = P[7];
2001 L[3] = P[3];
2002 }
2003 else // Down
2004 {
2005 L[0] = P[0];
2006 L[1] = P[4];
2007 L[2] = P[6];
2008 L[3] = P[2];
2009 }
2010 }
2011 else
2012 {
2013 if(dx > dy) // Up
2014 {
2015 L[0] = P[0];
2016 L[1] = P[2];
2017 L[2] = P[6];
2018 L[3] = P[4];
2019 }
2020 else // Left
2021 {
2022 L[0] = P[1];
2023 L[1] = P[3];
2024 L[2] = P[7];
2025 L[3] = P[5];
2026 }
2027 }
2028
2029 int C0 = clipper->computeClipFlags(L[0]);
2030 int C1 = clipper->computeClipFlags(L[1]);
2031 int C2 = clipper->computeClipFlags(L[2]);
2032 int C3 = clipper->computeClipFlags(L[3]);
2033
2034 if((C0 & C1 & C2 & C3) == Clipper::CLIP_FINITE)
2035 {
2036 Polygon polygon(L, 4);
2037
2038 int clipFlagsOr = C0 | C1 | C2 | C3;
2039
2040 if(clipFlagsOr != Clipper::CLIP_FINITE)
2041 {
2042 if(!clipper->clip(polygon, clipFlagsOr, draw))
2043 {
2044 return false;
2045 }
2046 }
2047
2048 return setupRoutine(&primitive, &triangle, &polygon, &data);
2049 }
2050 }
John Bauman89401822014-05-06 15:04:28 -04002051
2052 return false;
2053 }
2054
Nicolas Capens734392e2016-05-26 11:07:40 -04002055 bool Renderer::setupPoint(Primitive &primitive, Triangle &triangle, const DrawCall &draw)
John Bauman89401822014-05-06 15:04:28 -04002056 {
2057 const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
2058 const SetupProcessor::State &state = draw.setupState;
2059 const DrawData &data = *draw.data;
2060
2061 Vertex &v = triangle.v0;
2062
2063 float pSize;
2064
2065 int pts = state.pointSizeRegister;
2066
Nicolas Capensec0936c2016-05-18 12:32:02 -04002067 if(state.pointSizeRegister != Unused)
John Bauman89401822014-05-06 15:04:28 -04002068 {
2069 pSize = v.v[pts].y;
2070 }
2071 else
2072 {
2073 pSize = data.point.pointSize[0];
2074 }
2075
2076 pSize = clamp(pSize, data.point.pointSizeMin, data.point.pointSizeMax);
2077
2078 float4 P[4];
2079 int C[4];
2080
2081 int pos = state.positionRegister;
2082
2083 P[0] = v.v[pos];
2084 P[1] = v.v[pos];
2085 P[2] = v.v[pos];
2086 P[3] = v.v[pos];
2087
John Bauman19bac1e2014-05-06 15:23:49 -04002088 const float X = pSize * P[0].w * data.halfPixelX[0];
2089 const float Y = pSize * P[0].w * data.halfPixelY[0];
John Bauman89401822014-05-06 15:04:28 -04002090
2091 P[0].x -= X;
John Bauman19bac1e2014-05-06 15:23:49 -04002092 P[0].y += Y;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04002093 C[0] = clipper->computeClipFlags(P[0]);
John Bauman89401822014-05-06 15:04:28 -04002094
2095 P[1].x += X;
John Bauman19bac1e2014-05-06 15:23:49 -04002096 P[1].y += Y;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04002097 C[1] = clipper->computeClipFlags(P[1]);
John Bauman89401822014-05-06 15:04:28 -04002098
2099 P[2].x += X;
John Bauman19bac1e2014-05-06 15:23:49 -04002100 P[2].y -= Y;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04002101 C[2] = clipper->computeClipFlags(P[2]);
John Bauman89401822014-05-06 15:04:28 -04002102
2103 P[3].x -= X;
John Bauman19bac1e2014-05-06 15:23:49 -04002104 P[3].y -= Y;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04002105 C[3] = clipper->computeClipFlags(P[3]);
John Bauman89401822014-05-06 15:04:28 -04002106
John Bauman89401822014-05-06 15:04:28 -04002107 Polygon polygon(P, 4);
2108
2109 if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
2110 {
2111 int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | draw.clipFlags;
2112
2113 if(clipFlagsOr != Clipper::CLIP_FINITE)
2114 {
Nicolas Capens734392e2016-05-26 11:07:40 -04002115 if(!clipper->clip(polygon, clipFlagsOr, draw))
John Bauman89401822014-05-06 15:04:28 -04002116 {
2117 return false;
2118 }
2119 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002120
Sean Risser6d55ba72019-07-15 12:42:15 -04002121 triangle.v1 = triangle.v0;
2122 triangle.v2 = triangle.v0;
2123
2124 triangle.v1.X += iround(16 * 0.5f * pSize);
2125 triangle.v2.Y -= iround(16 * 0.5f * pSize) * (data.Hx16[0] > 0.0f ? 1 : -1); // Both Direct3D and OpenGL expect (0, 0) in the top-left corner
John Bauman89401822014-05-06 15:04:28 -04002126 return setupRoutine(&primitive, &triangle, &polygon, &data);
2127 }
2128
2129 return false;
2130 }
2131
Nicolas Capens7381c992014-05-06 23:48:15 -04002132 void Renderer::initializeThreads()
John Bauman89401822014-05-06 15:04:28 -04002133 {
Nicolas Capens7381c992014-05-06 23:48:15 -04002134 unitCount = ceilPow2(threadCount);
2135 clusterCount = ceilPow2(threadCount);
John Bauman89401822014-05-06 15:04:28 -04002136
2137 for(int i = 0; i < unitCount; i++)
2138 {
2139 triangleBatch[i] = (Triangle*)allocate(batchSize * sizeof(Triangle));
2140 primitiveBatch[i] = (Primitive*)allocate(batchSize * sizeof(Primitive));
2141 }
2142
2143 for(int i = 0; i < threadCount; i++)
2144 {
2145 vertexTask[i] = (VertexTask*)allocate(sizeof(VertexTask));
2146 vertexTask[i]->vertexCache.drawCall = -1;
2147
2148 task[i].type = Task::SUSPEND;
2149
2150 resume[i] = new Event();
2151 suspend[i] = new Event();
2152
2153 Parameters parameters;
2154 parameters.threadIndex = i;
2155 parameters.renderer = this;
2156
2157 exitThreads = false;
2158 worker[i] = new Thread(threadFunction, &parameters);
2159
2160 suspend[i]->wait();
2161 suspend[i]->signal();
2162 }
2163 }
2164
2165 void Renderer::terminateThreads()
2166 {
2167 while(threadsAwake != 0)
2168 {
John Bauman19bac1e2014-05-06 15:23:49 -04002169 Thread::sleep(1);
John Bauman89401822014-05-06 15:04:28 -04002170 }
2171
2172 for(int thread = 0; thread < threadCount; thread++)
2173 {
2174 if(worker[thread])
2175 {
2176 exitThreads = true;
2177 resume[thread]->signal();
2178 worker[thread]->join();
Nicolas Capensec0936c2016-05-18 12:32:02 -04002179
John Bauman89401822014-05-06 15:04:28 -04002180 delete worker[thread];
2181 worker[thread] = 0;
2182 delete resume[thread];
2183 resume[thread] = 0;
2184 delete suspend[thread];
2185 suspend[thread] = 0;
2186 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002187
John Bauman89401822014-05-06 15:04:28 -04002188 deallocate(vertexTask[thread]);
2189 vertexTask[thread] = 0;
2190 }
John Bauman89401822014-05-06 15:04:28 -04002191
John Bauman89401822014-05-06 15:04:28 -04002192 for(int i = 0; i < 16; i++)
2193 {
2194 deallocate(triangleBatch[i]);
2195 triangleBatch[i] = 0;
2196
2197 deallocate(primitiveBatch[i]);
2198 primitiveBatch[i] = 0;
2199 }
2200 }
2201
2202 void Renderer::loadConstants(const VertexShader *vertexShader)
2203 {
2204 if(!vertexShader) return;
2205
Alexis Hetu8dcce862014-11-13 16:43:44 -05002206 size_t count = vertexShader->getLength();
John Bauman89401822014-05-06 15:04:28 -04002207
Alexis Hetu903e0252014-11-25 14:25:32 -05002208 for(size_t i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002209 {
John Bauman19bac1e2014-05-06 15:23:49 -04002210 const Shader::Instruction *instruction = vertexShader->getInstruction(i);
John Bauman89401822014-05-06 15:04:28 -04002211
John Bauman19bac1e2014-05-06 15:23:49 -04002212 if(instruction->opcode == Shader::OPCODE_DEF)
John Bauman89401822014-05-06 15:04:28 -04002213 {
John Bauman19bac1e2014-05-06 15:23:49 -04002214 int index = instruction->dst.index;
John Bauman89401822014-05-06 15:04:28 -04002215 float value[4];
2216
John Bauman19bac1e2014-05-06 15:23:49 -04002217 value[0] = instruction->src[0].value[0];
2218 value[1] = instruction->src[0].value[1];
2219 value[2] = instruction->src[0].value[2];
2220 value[3] = instruction->src[0].value[3];
John Bauman89401822014-05-06 15:04:28 -04002221
2222 setVertexShaderConstantF(index, value);
2223 }
John Bauman19bac1e2014-05-06 15:23:49 -04002224 else if(instruction->opcode == Shader::OPCODE_DEFI)
John Bauman89401822014-05-06 15:04:28 -04002225 {
John Bauman19bac1e2014-05-06 15:23:49 -04002226 int index = instruction->dst.index;
John Bauman89401822014-05-06 15:04:28 -04002227 int integer[4];
2228
John Bauman19bac1e2014-05-06 15:23:49 -04002229 integer[0] = instruction->src[0].integer[0];
2230 integer[1] = instruction->src[0].integer[1];
2231 integer[2] = instruction->src[0].integer[2];
2232 integer[3] = instruction->src[0].integer[3];
John Bauman89401822014-05-06 15:04:28 -04002233
2234 setVertexShaderConstantI(index, integer);
2235 }
John Bauman19bac1e2014-05-06 15:23:49 -04002236 else if(instruction->opcode == Shader::OPCODE_DEFB)
John Bauman89401822014-05-06 15:04:28 -04002237 {
John Bauman19bac1e2014-05-06 15:23:49 -04002238 int index = instruction->dst.index;
2239 int boolean = instruction->src[0].boolean[0];
John Bauman89401822014-05-06 15:04:28 -04002240
2241 setVertexShaderConstantB(index, &boolean);
2242 }
2243 }
2244 }
2245
2246 void Renderer::loadConstants(const PixelShader *pixelShader)
2247 {
2248 if(!pixelShader) return;
2249
Alexis Hetu8dcce862014-11-13 16:43:44 -05002250 size_t count = pixelShader->getLength();
John Bauman89401822014-05-06 15:04:28 -04002251
Alexis Hetu903e0252014-11-25 14:25:32 -05002252 for(size_t i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002253 {
John Bauman19bac1e2014-05-06 15:23:49 -04002254 const Shader::Instruction *instruction = pixelShader->getInstruction(i);
John Bauman89401822014-05-06 15:04:28 -04002255
John Bauman19bac1e2014-05-06 15:23:49 -04002256 if(instruction->opcode == Shader::OPCODE_DEF)
John Bauman89401822014-05-06 15:04:28 -04002257 {
John Bauman19bac1e2014-05-06 15:23:49 -04002258 int index = instruction->dst.index;
John Bauman89401822014-05-06 15:04:28 -04002259 float value[4];
2260
John Bauman19bac1e2014-05-06 15:23:49 -04002261 value[0] = instruction->src[0].value[0];
2262 value[1] = instruction->src[0].value[1];
2263 value[2] = instruction->src[0].value[2];
2264 value[3] = instruction->src[0].value[3];
John Bauman89401822014-05-06 15:04:28 -04002265
2266 setPixelShaderConstantF(index, value);
2267 }
John Bauman19bac1e2014-05-06 15:23:49 -04002268 else if(instruction->opcode == Shader::OPCODE_DEFI)
John Bauman89401822014-05-06 15:04:28 -04002269 {
John Bauman19bac1e2014-05-06 15:23:49 -04002270 int index = instruction->dst.index;
John Bauman89401822014-05-06 15:04:28 -04002271 int integer[4];
2272
John Bauman19bac1e2014-05-06 15:23:49 -04002273 integer[0] = instruction->src[0].integer[0];
2274 integer[1] = instruction->src[0].integer[1];
2275 integer[2] = instruction->src[0].integer[2];
2276 integer[3] = instruction->src[0].integer[3];
John Bauman89401822014-05-06 15:04:28 -04002277
2278 setPixelShaderConstantI(index, integer);
2279 }
John Bauman19bac1e2014-05-06 15:23:49 -04002280 else if(instruction->opcode == Shader::OPCODE_DEFB)
John Bauman89401822014-05-06 15:04:28 -04002281 {
John Bauman19bac1e2014-05-06 15:23:49 -04002282 int index = instruction->dst.index;
2283 int boolean = instruction->src[0].boolean[0];
John Bauman89401822014-05-06 15:04:28 -04002284
2285 setPixelShaderConstantB(index, &boolean);
2286 }
2287 }
2288 }
2289
2290 void Renderer::setIndexBuffer(Resource *indexBuffer)
2291 {
2292 context->indexBuffer = indexBuffer;
2293 }
2294
2295 void Renderer::setMultiSampleMask(unsigned int mask)
2296 {
2297 context->sampleMask = mask;
2298 }
2299
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002300 void Renderer::setTransparencyAntialiasing(TransparencyAntialiasing transparencyAntialiasing)
John Bauman89401822014-05-06 15:04:28 -04002301 {
2302 sw::transparencyAntialiasing = transparencyAntialiasing;
2303 }
2304
2305 bool Renderer::isReadWriteTexture(int sampler)
2306 {
Alexis Hetu1edcd8b2015-11-05 11:12:41 -05002307 for(int index = 0; index < RENDERTARGETS; index++)
John Bauman89401822014-05-06 15:04:28 -04002308 {
2309 if(context->renderTarget[index] && context->texture[sampler] == context->renderTarget[index]->getResource())
2310 {
2311 return true;
2312 }
2313 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002314
Nicolas Capens3751c1e2016-03-21 14:14:14 -04002315 if(context->depthBuffer && context->texture[sampler] == context->depthBuffer->getResource())
John Bauman89401822014-05-06 15:04:28 -04002316 {
2317 return true;
2318 }
2319
2320 return false;
2321 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002322
John Bauman89401822014-05-06 15:04:28 -04002323 void Renderer::updateClipper()
2324 {
2325 if(updateClipPlanes)
2326 {
John Bauman89401822014-05-06 15:04:28 -04002327 if(VertexProcessor::isFixedFunction()) // User plane in world space
2328 {
John Bauman19bac1e2014-05-06 15:23:49 -04002329 const Matrix &scissorWorld = getViewTransform();
John Bauman89401822014-05-06 15:04:28 -04002330
2331 if(clipFlags & Clipper::CLIP_PLANE0) clipPlane[0] = scissorWorld * userPlane[0];
2332 if(clipFlags & Clipper::CLIP_PLANE1) clipPlane[1] = scissorWorld * userPlane[1];
2333 if(clipFlags & Clipper::CLIP_PLANE2) clipPlane[2] = scissorWorld * userPlane[2];
2334 if(clipFlags & Clipper::CLIP_PLANE3) clipPlane[3] = scissorWorld * userPlane[3];
2335 if(clipFlags & Clipper::CLIP_PLANE4) clipPlane[4] = scissorWorld * userPlane[4];
2336 if(clipFlags & Clipper::CLIP_PLANE5) clipPlane[5] = scissorWorld * userPlane[5];
2337 }
2338 else // User plane in clip space
2339 {
John Bauman19bac1e2014-05-06 15:23:49 -04002340 if(clipFlags & Clipper::CLIP_PLANE0) clipPlane[0] = userPlane[0];
2341 if(clipFlags & Clipper::CLIP_PLANE1) clipPlane[1] = userPlane[1];
2342 if(clipFlags & Clipper::CLIP_PLANE2) clipPlane[2] = userPlane[2];
2343 if(clipFlags & Clipper::CLIP_PLANE3) clipPlane[3] = userPlane[3];
2344 if(clipFlags & Clipper::CLIP_PLANE4) clipPlane[4] = userPlane[4];
2345 if(clipFlags & Clipper::CLIP_PLANE5) clipPlane[5] = userPlane[5];
John Bauman89401822014-05-06 15:04:28 -04002346 }
2347
2348 updateClipPlanes = false;
2349 }
2350 }
2351
2352 void Renderer::setTextureResource(unsigned int sampler, Resource *resource)
2353 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -04002354 ASSERT(sampler < TOTAL_IMAGE_UNITS);
John Bauman89401822014-05-06 15:04:28 -04002355
2356 context->texture[sampler] = resource;
2357 }
2358
2359 void Renderer::setTextureLevel(unsigned int sampler, unsigned int face, unsigned int level, Surface *surface, TextureType type)
2360 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -04002361 ASSERT(sampler < TOTAL_IMAGE_UNITS && face < 6 && level < MIPMAP_LEVELS);
Nicolas Capensec0936c2016-05-18 12:32:02 -04002362
John Bauman89401822014-05-06 15:04:28 -04002363 context->sampler[sampler].setTextureLevel(face, level, surface, type);
2364 }
2365
2366 void Renderer::setTextureFilter(SamplerType type, int sampler, FilterType textureFilter)
2367 {
2368 if(type == SAMPLER_PIXEL)
2369 {
2370 PixelProcessor::setTextureFilter(sampler, textureFilter);
2371 }
2372 else
2373 {
2374 VertexProcessor::setTextureFilter(sampler, textureFilter);
2375 }
2376 }
2377
2378 void Renderer::setMipmapFilter(SamplerType type, int sampler, MipmapType mipmapFilter)
2379 {
2380 if(type == SAMPLER_PIXEL)
2381 {
2382 PixelProcessor::setMipmapFilter(sampler, mipmapFilter);
2383 }
2384 else
2385 {
2386 VertexProcessor::setMipmapFilter(sampler, mipmapFilter);
2387 }
2388 }
2389
2390 void Renderer::setGatherEnable(SamplerType type, int sampler, bool enable)
2391 {
2392 if(type == SAMPLER_PIXEL)
2393 {
2394 PixelProcessor::setGatherEnable(sampler, enable);
2395 }
2396 else
2397 {
2398 VertexProcessor::setGatherEnable(sampler, enable);
2399 }
2400 }
2401
2402 void Renderer::setAddressingModeU(SamplerType type, int sampler, AddressingMode addressMode)
2403 {
2404 if(type == SAMPLER_PIXEL)
2405 {
2406 PixelProcessor::setAddressingModeU(sampler, addressMode);
2407 }
2408 else
2409 {
2410 VertexProcessor::setAddressingModeU(sampler, addressMode);
2411 }
2412 }
2413
2414 void Renderer::setAddressingModeV(SamplerType type, int sampler, AddressingMode addressMode)
2415 {
2416 if(type == SAMPLER_PIXEL)
2417 {
2418 PixelProcessor::setAddressingModeV(sampler, addressMode);
2419 }
2420 else
2421 {
2422 VertexProcessor::setAddressingModeV(sampler, addressMode);
2423 }
2424 }
2425
2426 void Renderer::setAddressingModeW(SamplerType type, int sampler, AddressingMode addressMode)
2427 {
2428 if(type == SAMPLER_PIXEL)
2429 {
2430 PixelProcessor::setAddressingModeW(sampler, addressMode);
2431 }
2432 else
2433 {
2434 VertexProcessor::setAddressingModeW(sampler, addressMode);
2435 }
2436 }
2437
2438 void Renderer::setReadSRGB(SamplerType type, int sampler, bool sRGB)
2439 {
2440 if(type == SAMPLER_PIXEL)
2441 {
2442 PixelProcessor::setReadSRGB(sampler, sRGB);
2443 }
2444 else
2445 {
2446 VertexProcessor::setReadSRGB(sampler, sRGB);
2447 }
2448 }
2449
2450 void Renderer::setMipmapLOD(SamplerType type, int sampler, float bias)
2451 {
2452 if(type == SAMPLER_PIXEL)
2453 {
2454 PixelProcessor::setMipmapLOD(sampler, bias);
2455 }
2456 else
2457 {
2458 VertexProcessor::setMipmapLOD(sampler, bias);
2459 }
2460 }
2461
2462 void Renderer::setBorderColor(SamplerType type, int sampler, const Color<float> &borderColor)
2463 {
2464 if(type == SAMPLER_PIXEL)
2465 {
2466 PixelProcessor::setBorderColor(sampler, borderColor);
2467 }
2468 else
2469 {
2470 VertexProcessor::setBorderColor(sampler, borderColor);
2471 }
2472 }
2473
Alexis Hetu617a5d52014-11-13 10:56:20 -05002474 void Renderer::setMaxAnisotropy(SamplerType type, int sampler, float maxAnisotropy)
John Bauman89401822014-05-06 15:04:28 -04002475 {
2476 if(type == SAMPLER_PIXEL)
2477 {
2478 PixelProcessor::setMaxAnisotropy(sampler, maxAnisotropy);
2479 }
2480 else
2481 {
2482 VertexProcessor::setMaxAnisotropy(sampler, maxAnisotropy);
2483 }
2484 }
2485
Alexis Hetu010a4642017-07-18 14:33:04 -04002486 void Renderer::setHighPrecisionFiltering(SamplerType type, int sampler, bool highPrecisionFiltering)
2487 {
2488 if(type == SAMPLER_PIXEL)
2489 {
2490 PixelProcessor::setHighPrecisionFiltering(sampler, highPrecisionFiltering);
2491 }
2492 else
2493 {
2494 VertexProcessor::setHighPrecisionFiltering(sampler, highPrecisionFiltering);
2495 }
2496 }
2497
Alexis Hetu1d01aa32015-09-29 11:50:05 -04002498 void Renderer::setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR)
2499 {
2500 if(type == SAMPLER_PIXEL)
2501 {
2502 PixelProcessor::setSwizzleR(sampler, swizzleR);
2503 }
2504 else
2505 {
2506 VertexProcessor::setSwizzleR(sampler, swizzleR);
2507 }
2508 }
2509
2510 void Renderer::setSwizzleG(SamplerType type, int sampler, SwizzleType swizzleG)
2511 {
2512 if(type == SAMPLER_PIXEL)
2513 {
2514 PixelProcessor::setSwizzleG(sampler, swizzleG);
2515 }
2516 else
2517 {
2518 VertexProcessor::setSwizzleG(sampler, swizzleG);
2519 }
2520 }
2521
2522 void Renderer::setSwizzleB(SamplerType type, int sampler, SwizzleType swizzleB)
2523 {
2524 if(type == SAMPLER_PIXEL)
2525 {
2526 PixelProcessor::setSwizzleB(sampler, swizzleB);
2527 }
2528 else
2529 {
2530 VertexProcessor::setSwizzleB(sampler, swizzleB);
2531 }
2532 }
2533
2534 void Renderer::setSwizzleA(SamplerType type, int sampler, SwizzleType swizzleA)
2535 {
2536 if(type == SAMPLER_PIXEL)
2537 {
2538 PixelProcessor::setSwizzleA(sampler, swizzleA);
2539 }
2540 else
2541 {
2542 VertexProcessor::setSwizzleA(sampler, swizzleA);
2543 }
2544 }
2545
Nicolas Capensf878d502017-11-06 15:29:46 -05002546 void Renderer::setCompareFunc(SamplerType type, int sampler, CompareFunc compFunc)
2547 {
2548 if(type == SAMPLER_PIXEL)
2549 {
2550 PixelProcessor::setCompareFunc(sampler, compFunc);
2551 }
2552 else
2553 {
2554 VertexProcessor::setCompareFunc(sampler, compFunc);
2555 }
2556 }
2557
Alexis Hetu95ac1872016-06-06 13:26:52 -04002558 void Renderer::setBaseLevel(SamplerType type, int sampler, int baseLevel)
2559 {
2560 if(type == SAMPLER_PIXEL)
2561 {
2562 PixelProcessor::setBaseLevel(sampler, baseLevel);
2563 }
2564 else
2565 {
2566 VertexProcessor::setBaseLevel(sampler, baseLevel);
2567 }
2568 }
2569
2570 void Renderer::setMaxLevel(SamplerType type, int sampler, int maxLevel)
2571 {
2572 if(type == SAMPLER_PIXEL)
2573 {
2574 PixelProcessor::setMaxLevel(sampler, maxLevel);
2575 }
2576 else
2577 {
2578 VertexProcessor::setMaxLevel(sampler, maxLevel);
2579 }
2580 }
2581
Alexis Hetu112d81f2016-06-07 12:36:35 -04002582 void Renderer::setMinLod(SamplerType type, int sampler, float minLod)
2583 {
2584 if(type == SAMPLER_PIXEL)
2585 {
2586 PixelProcessor::setMinLod(sampler, minLod);
2587 }
2588 else
2589 {
2590 VertexProcessor::setMinLod(sampler, minLod);
2591 }
2592 }
2593
2594 void Renderer::setMaxLod(SamplerType type, int sampler, float maxLod)
2595 {
2596 if(type == SAMPLER_PIXEL)
2597 {
2598 PixelProcessor::setMaxLod(sampler, maxLod);
2599 }
2600 else
2601 {
2602 VertexProcessor::setMaxLod(sampler, maxLod);
2603 }
2604 }
2605
Alexis Hetu88482c32018-06-05 17:05:17 -04002606 void Renderer::setSyncRequired(SamplerType type, int sampler, bool syncRequired)
2607 {
2608 if(type == SAMPLER_PIXEL)
2609 {
2610 PixelProcessor::setSyncRequired(sampler, syncRequired);
2611 }
2612 else
2613 {
2614 VertexProcessor::setSyncRequired(sampler, syncRequired);
2615 }
2616 }
2617
John Bauman89401822014-05-06 15:04:28 -04002618 void Renderer::setPointSpriteEnable(bool pointSpriteEnable)
2619 {
2620 context->setPointSpriteEnable(pointSpriteEnable);
2621 }
2622
2623 void Renderer::setPointScaleEnable(bool pointScaleEnable)
2624 {
2625 context->setPointScaleEnable(pointScaleEnable);
2626 }
2627
Nicolas Capens235781d2015-01-27 01:46:53 -05002628 void Renderer::setLineWidth(float width)
2629 {
2630 context->lineWidth = width;
2631 }
2632
John Bauman89401822014-05-06 15:04:28 -04002633 void Renderer::setDepthBias(float bias)
2634 {
Nicolas Capens3cbeac52017-09-15 11:49:31 -04002635 context->depthBias = bias;
John Bauman89401822014-05-06 15:04:28 -04002636 }
2637
2638 void Renderer::setSlopeDepthBias(float slopeBias)
2639 {
Nicolas Capens3cbeac52017-09-15 11:49:31 -04002640 context->slopeDepthBias = slopeBias;
John Bauman89401822014-05-06 15:04:28 -04002641 }
2642
Alexis Hetub0f247f2016-02-22 11:42:39 -05002643 void Renderer::setRasterizerDiscard(bool rasterizerDiscard)
2644 {
2645 context->rasterizerDiscard = rasterizerDiscard;
2646 }
2647
John Bauman89401822014-05-06 15:04:28 -04002648 void Renderer::setPixelShader(const PixelShader *shader)
2649 {
2650 context->pixelShader = shader;
2651
2652 loadConstants(shader);
2653 }
2654
2655 void Renderer::setVertexShader(const VertexShader *shader)
2656 {
2657 context->vertexShader = shader;
2658
2659 loadConstants(shader);
2660 }
2661
Alexis Hetub59a58e2016-06-02 11:50:47 -04002662 void Renderer::setPixelShaderConstantF(unsigned int index, const float value[4], unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002663 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002664 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002665 {
2666 if(drawCall[i]->psDirtyConstF < index + count)
2667 {
2668 drawCall[i]->psDirtyConstF = index + count;
2669 }
2670 }
2671
Alexis Hetub59a58e2016-06-02 11:50:47 -04002672 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002673 {
2674 PixelProcessor::setFloatConstant(index + i, value);
2675 value += 4;
2676 }
2677 }
2678
Alexis Hetub59a58e2016-06-02 11:50:47 -04002679 void Renderer::setPixelShaderConstantI(unsigned int index, const int value[4], unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002680 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002681 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002682 {
2683 if(drawCall[i]->psDirtyConstI < index + count)
2684 {
2685 drawCall[i]->psDirtyConstI = index + count;
2686 }
2687 }
2688
Alexis Hetub59a58e2016-06-02 11:50:47 -04002689 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002690 {
2691 PixelProcessor::setIntegerConstant(index + i, value);
2692 value += 4;
2693 }
2694 }
2695
Alexis Hetub59a58e2016-06-02 11:50:47 -04002696 void Renderer::setPixelShaderConstantB(unsigned int index, const int *boolean, unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002697 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002698 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002699 {
2700 if(drawCall[i]->psDirtyConstB < index + count)
2701 {
2702 drawCall[i]->psDirtyConstB = index + count;
2703 }
2704 }
2705
Alexis Hetub59a58e2016-06-02 11:50:47 -04002706 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002707 {
2708 PixelProcessor::setBooleanConstant(index + i, *boolean);
2709 boolean++;
2710 }
2711 }
2712
Alexis Hetub59a58e2016-06-02 11:50:47 -04002713 void Renderer::setVertexShaderConstantF(unsigned int index, const float value[4], unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002714 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002715 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002716 {
2717 if(drawCall[i]->vsDirtyConstF < index + count)
2718 {
2719 drawCall[i]->vsDirtyConstF = index + count;
2720 }
2721 }
2722
Alexis Hetub59a58e2016-06-02 11:50:47 -04002723 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002724 {
2725 VertexProcessor::setFloatConstant(index + i, value);
2726 value += 4;
2727 }
2728 }
2729
Alexis Hetub59a58e2016-06-02 11:50:47 -04002730 void Renderer::setVertexShaderConstantI(unsigned int index, const int value[4], unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002731 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002732 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002733 {
2734 if(drawCall[i]->vsDirtyConstI < index + count)
2735 {
2736 drawCall[i]->vsDirtyConstI = index + count;
2737 }
2738 }
2739
Alexis Hetub59a58e2016-06-02 11:50:47 -04002740 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002741 {
2742 VertexProcessor::setIntegerConstant(index + i, value);
2743 value += 4;
2744 }
2745 }
2746
Alexis Hetub59a58e2016-06-02 11:50:47 -04002747 void Renderer::setVertexShaderConstantB(unsigned int index, const int *boolean, unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002748 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002749 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002750 {
2751 if(drawCall[i]->vsDirtyConstB < index + count)
2752 {
2753 drawCall[i]->vsDirtyConstB = index + count;
2754 }
2755 }
2756
Alexis Hetub59a58e2016-06-02 11:50:47 -04002757 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002758 {
2759 VertexProcessor::setBooleanConstant(index + i, *boolean);
2760 boolean++;
2761 }
2762 }
2763
2764 void Renderer::setModelMatrix(const Matrix &M, int i)
2765 {
2766 VertexProcessor::setModelMatrix(M, i);
2767 }
2768
2769 void Renderer::setViewMatrix(const Matrix &V)
2770 {
2771 VertexProcessor::setViewMatrix(V);
2772 updateClipPlanes = true;
2773 }
2774
2775 void Renderer::setBaseMatrix(const Matrix &B)
2776 {
2777 VertexProcessor::setBaseMatrix(B);
2778 updateClipPlanes = true;
2779 }
2780
2781 void Renderer::setProjectionMatrix(const Matrix &P)
2782 {
2783 VertexProcessor::setProjectionMatrix(P);
2784 updateClipPlanes = true;
2785 }
2786
John Bauman89401822014-05-06 15:04:28 -04002787 void Renderer::addQuery(Query *query)
2788 {
2789 queries.push_back(query);
2790 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002791
John Bauman89401822014-05-06 15:04:28 -04002792 void Renderer::removeQuery(Query *query)
2793 {
2794 queries.remove(query);
2795 }
2796
2797 #if PERF_HUD
2798 int Renderer::getThreadCount()
2799 {
2800 return threadCount;
2801 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002802
John Bauman89401822014-05-06 15:04:28 -04002803 int64_t Renderer::getVertexTime(int thread)
2804 {
2805 return vertexTime[thread];
2806 }
2807
2808 int64_t Renderer::getSetupTime(int thread)
2809 {
2810 return setupTime[thread];
2811 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002812
John Bauman89401822014-05-06 15:04:28 -04002813 int64_t Renderer::getPixelTime(int thread)
2814 {
2815 return pixelTime[thread];
2816 }
2817
2818 void Renderer::resetTimers()
2819 {
2820 for(int thread = 0; thread < threadCount; thread++)
2821 {
2822 vertexTime[thread] = 0;
2823 setupTime[thread] = 0;
2824 pixelTime[thread] = 0;
2825 }
2826 }
2827 #endif
2828
2829 void Renderer::setViewport(const Viewport &viewport)
2830 {
2831 this->viewport = viewport;
2832 }
2833
John Bauman19bac1e2014-05-06 15:23:49 -04002834 void Renderer::setScissor(const Rect &scissor)
2835 {
2836 this->scissor = scissor;
2837 }
2838
John Bauman89401822014-05-06 15:04:28 -04002839 void Renderer::setClipFlags(int flags)
2840 {
2841 clipFlags = flags << 8; // Bottom 8 bits used by legacy frustum
2842 }
2843
2844 void Renderer::setClipPlane(unsigned int index, const float plane[4])
2845 {
Nicolas Capensd2264142015-07-02 17:06:53 -04002846 if(index < MAX_CLIP_PLANES)
John Bauman89401822014-05-06 15:04:28 -04002847 {
2848 userPlane[index] = plane;
2849 }
2850 else ASSERT(false);
2851
2852 updateClipPlanes = true;
2853 }
2854
2855 void Renderer::updateConfiguration(bool initialUpdate)
2856 {
2857 bool newConfiguration = swiftConfig->hasNewConfiguration();
2858
2859 if(newConfiguration || initialUpdate)
2860 {
2861 terminateThreads();
2862
Nicolas Capensc4748c52016-01-01 01:21:18 -05002863 SwiftConfig::Configuration configuration = {};
John Bauman89401822014-05-06 15:04:28 -04002864 swiftConfig->getConfiguration(configuration);
2865
John Bauman66b8ab22014-05-06 15:57:45 -04002866 precacheVertex = !newConfiguration && configuration.precache;
2867 precacheSetup = !newConfiguration && configuration.precache;
2868 precachePixel = !newConfiguration && configuration.precache;
2869
John Bauman89401822014-05-06 15:04:28 -04002870 VertexProcessor::setRoutineCacheSize(configuration.vertexRoutineCacheSize);
2871 PixelProcessor::setRoutineCacheSize(configuration.pixelRoutineCacheSize);
2872 SetupProcessor::setRoutineCacheSize(configuration.setupRoutineCacheSize);
2873
2874 switch(configuration.textureSampleQuality)
2875 {
Nicolas Capens7381c992014-05-06 23:48:15 -04002876 case 0: Sampler::setFilterQuality(FILTER_POINT); break;
2877 case 1: Sampler::setFilterQuality(FILTER_LINEAR); break;
2878 case 2: Sampler::setFilterQuality(FILTER_ANISOTROPIC); break;
2879 default: Sampler::setFilterQuality(FILTER_ANISOTROPIC); break;
John Bauman89401822014-05-06 15:04:28 -04002880 }
2881
2882 switch(configuration.mipmapQuality)
2883 {
2884 case 0: Sampler::setMipmapQuality(MIPMAP_POINT); break;
2885 case 1: Sampler::setMipmapQuality(MIPMAP_LINEAR); break;
Nicolas Capens7381c992014-05-06 23:48:15 -04002886 default: Sampler::setMipmapQuality(MIPMAP_LINEAR); break;
John Bauman89401822014-05-06 15:04:28 -04002887 }
2888
2889 setPerspectiveCorrection(configuration.perspectiveCorrection);
2890
2891 switch(configuration.transcendentalPrecision)
2892 {
2893 case 0:
2894 logPrecision = APPROXIMATE;
2895 expPrecision = APPROXIMATE;
2896 rcpPrecision = APPROXIMATE;
2897 rsqPrecision = APPROXIMATE;
2898 break;
2899 case 1:
2900 logPrecision = PARTIAL;
2901 expPrecision = PARTIAL;
2902 rcpPrecision = PARTIAL;
2903 rsqPrecision = PARTIAL;
2904 break;
2905 case 2:
2906 logPrecision = ACCURATE;
2907 expPrecision = ACCURATE;
2908 rcpPrecision = ACCURATE;
2909 rsqPrecision = ACCURATE;
2910 break;
2911 case 3:
2912 logPrecision = WHQL;
2913 expPrecision = WHQL;
2914 rcpPrecision = WHQL;
2915 rsqPrecision = WHQL;
2916 break;
2917 case 4:
2918 logPrecision = IEEE;
2919 expPrecision = IEEE;
2920 rcpPrecision = IEEE;
2921 rsqPrecision = IEEE;
2922 break;
2923 default:
2924 logPrecision = ACCURATE;
2925 expPrecision = ACCURATE;
2926 rcpPrecision = ACCURATE;
2927 rsqPrecision = ACCURATE;
2928 break;
2929 }
2930
2931 switch(configuration.transparencyAntialiasing)
2932 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002933 case 0: transparencyAntialiasing = TRANSPARENCY_NONE; break;
2934 case 1: transparencyAntialiasing = TRANSPARENCY_ALPHA_TO_COVERAGE; break;
2935 default: transparencyAntialiasing = TRANSPARENCY_NONE; break;
John Bauman89401822014-05-06 15:04:28 -04002936 }
2937
2938 switch(configuration.threadCount)
2939 {
Nicolas Capens7381c992014-05-06 23:48:15 -04002940 case -1: threadCount = CPUID::coreCount(); break;
2941 case 0: threadCount = CPUID::processAffinity(); break;
2942 default: threadCount = configuration.threadCount; break;
John Bauman89401822014-05-06 15:04:28 -04002943 }
2944
2945 CPUID::setEnableSSE4_1(configuration.enableSSE4_1);
2946 CPUID::setEnableSSSE3(configuration.enableSSSE3);
2947 CPUID::setEnableSSE3(configuration.enableSSE3);
2948 CPUID::setEnableSSE2(configuration.enableSSE2);
2949 CPUID::setEnableSSE(configuration.enableSSE);
2950
Ben Clayton55bc37a2019-07-04 12:17:12 +01002951 rr::Config::Edit cfg;
2952 cfg.clearOptimizationPasses();
2953 for(auto pass : configuration.optimization)
John Bauman89401822014-05-06 15:04:28 -04002954 {
Ben Clayton55bc37a2019-07-04 12:17:12 +01002955 if (pass != rr::Optimization::Pass::Disabled) { cfg.add(pass); }
John Bauman89401822014-05-06 15:04:28 -04002956 }
Ben Clayton55bc37a2019-07-04 12:17:12 +01002957 rr::Nucleus::adjustDefaultConfig(cfg);
John Bauman89401822014-05-06 15:04:28 -04002958
2959 forceWindowed = configuration.forceWindowed;
2960 complementaryDepthBuffer = configuration.complementaryDepthBuffer;
2961 postBlendSRGB = configuration.postBlendSRGB;
2962 exactColorRounding = configuration.exactColorRounding;
2963 forceClearRegisters = configuration.forceClearRegisters;
2964
2965 #ifndef NDEBUG
2966 minPrimitives = configuration.minPrimitives;
2967 maxPrimitives = configuration.maxPrimitives;
2968 #endif
2969 }
Nicolas Capens7381c992014-05-06 23:48:15 -04002970
2971 if(!initialUpdate && !worker[0])
2972 {
2973 initializeThreads();
2974 }
John Bauman89401822014-05-06 15:04:28 -04002975 }
John Bauman89401822014-05-06 15:04:28 -04002976}