blob: 87b8dd1e96fe90ca8303e4f8d486ac4997337e7e [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
363 vertexRoutine->bind();
364 setupRoutine->bind();
365 pixelRoutine->bind();
366
367 draw->vertexRoutine = vertexRoutine;
368 draw->setupRoutine = setupRoutine;
369 draw->pixelRoutine = pixelRoutine;
Nicolas Capenseb195b62015-04-28 17:18:42 -0700370 draw->vertexPointer = (VertexProcessor::RoutinePointer)vertexRoutine->getEntry();
John Bauman89401822014-05-06 15:04:28 -0400371 draw->setupPointer = (SetupProcessor::RoutinePointer)setupRoutine->getEntry();
372 draw->pixelPointer = (PixelProcessor::RoutinePointer)pixelRoutine->getEntry();
373 draw->setupPrimitives = setupPrimitives;
374 draw->setupState = setupState;
375
Nicolas Capensf0aef1a2016-05-18 14:44:21 -0400376 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400377 {
378 draw->vertexStream[i] = context->input[i].resource;
379 data->input[i] = context->input[i].buffer;
380 data->stride[i] = context->input[i].stride;
381
382 if(draw->vertexStream[i])
383 {
384 draw->vertexStream[i]->lock(PUBLIC, PRIVATE);
385 }
386 }
387
388 if(context->indexBuffer)
389 {
390 data->indices = (unsigned char*)context->indexBuffer->lock(PUBLIC, PRIVATE) + indexOffset;
391 }
392
393 draw->indexBuffer = context->indexBuffer;
394
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400395 for(int sampler = 0; sampler < TOTAL_IMAGE_UNITS; sampler++)
John Bauman89401822014-05-06 15:04:28 -0400396 {
397 draw->texture[sampler] = 0;
398 }
399
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400400 for(int sampler = 0; sampler < TEXTURE_IMAGE_UNITS; sampler++)
John Bauman89401822014-05-06 15:04:28 -0400401 {
402 if(pixelState.sampler[sampler].textureType != TEXTURE_NULL)
403 {
404 draw->texture[sampler] = context->texture[sampler];
405 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
406
407 data->mipmap[sampler] = context->sampler[sampler].getTextureData();
Alexis Hetu88482c32018-06-05 17:05:17 -0400408
409 requiresSync |= context->sampler[sampler].requiresSync();
John Bauman89401822014-05-06 15:04:28 -0400410 }
411 }
412
413 if(context->pixelShader)
414 {
415 if(draw->psDirtyConstF)
416 {
417 memcpy(&data->ps.cW, PixelProcessor::cW, sizeof(word4) * 4 * (draw->psDirtyConstF < 8 ? draw->psDirtyConstF : 8));
418 memcpy(&data->ps.c, PixelProcessor::c, sizeof(float4) * draw->psDirtyConstF);
419 draw->psDirtyConstF = 0;
420 }
421
422 if(draw->psDirtyConstI)
423 {
424 memcpy(&data->ps.i, PixelProcessor::i, sizeof(int4) * draw->psDirtyConstI);
425 draw->psDirtyConstI = 0;
426 }
427
428 if(draw->psDirtyConstB)
429 {
430 memcpy(&data->ps.b, PixelProcessor::b, sizeof(bool) * draw->psDirtyConstB);
431 draw->psDirtyConstB = 0;
432 }
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400433
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400434 PixelProcessor::lockUniformBuffers(data->ps.u, draw->pUniformBuffers);
435 }
436 else
437 {
438 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
439 {
440 draw->pUniformBuffers[i] = nullptr;
441 }
John Bauman89401822014-05-06 15:04:28 -0400442 }
Nicolas Capensec0936c2016-05-18 12:32:02 -0400443
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500444 if(context->pixelShaderModel() <= 0x0104)
John Bauman89401822014-05-06 15:04:28 -0400445 {
446 for(int stage = 0; stage < 8; stage++)
447 {
448 if(pixelState.textureStage[stage].stageOperation != TextureStage::STAGE_DISABLE || context->pixelShader)
449 {
450 data->textureStage[stage] = context->textureStage[stage].uniforms;
451 }
452 else break;
453 }
454 }
455
456 if(context->vertexShader)
457 {
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500458 if(context->vertexShader->getShaderModel() >= 0x0300)
John Bauman89401822014-05-06 15:04:28 -0400459 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400460 for(int sampler = 0; sampler < VERTEX_TEXTURE_IMAGE_UNITS; sampler++)
John Bauman89401822014-05-06 15:04:28 -0400461 {
Nicolas Capensf878d502017-11-06 15:29:46 -0500462 if(vertexState.sampler[sampler].textureType != TEXTURE_NULL)
John Bauman89401822014-05-06 15:04:28 -0400463 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400464 draw->texture[TEXTURE_IMAGE_UNITS + sampler] = context->texture[TEXTURE_IMAGE_UNITS + sampler];
465 draw->texture[TEXTURE_IMAGE_UNITS + sampler]->lock(PUBLIC, PRIVATE);
John Bauman89401822014-05-06 15:04:28 -0400466
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400467 data->mipmap[TEXTURE_IMAGE_UNITS + sampler] = context->sampler[TEXTURE_IMAGE_UNITS + sampler].getTextureData();
Alexis Hetu88482c32018-06-05 17:05:17 -0400468
469 requiresSync |= context->sampler[TEXTURE_IMAGE_UNITS + sampler].requiresSync();
John Bauman89401822014-05-06 15:04:28 -0400470 }
471 }
472 }
473
474 if(draw->vsDirtyConstF)
475 {
476 memcpy(&data->vs.c, VertexProcessor::c, sizeof(float4) * draw->vsDirtyConstF);
477 draw->vsDirtyConstF = 0;
478 }
479
480 if(draw->vsDirtyConstI)
481 {
482 memcpy(&data->vs.i, VertexProcessor::i, sizeof(int4) * draw->vsDirtyConstI);
483 draw->vsDirtyConstI = 0;
484 }
485
486 if(draw->vsDirtyConstB)
487 {
488 memcpy(&data->vs.b, VertexProcessor::b, sizeof(bool) * draw->vsDirtyConstB);
489 draw->vsDirtyConstB = 0;
490 }
Alexis Hetudd8df682015-06-05 17:08:39 -0400491
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400492 if(context->vertexShader->isInstanceIdDeclared())
Alexis Hetudd8df682015-06-05 17:08:39 -0400493 {
494 data->instanceID = context->instanceID;
495 }
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400496
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400497 VertexProcessor::lockUniformBuffers(data->vs.u, draw->vUniformBuffers);
498 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 -0400499 }
500 else
501 {
502 data->ff = ff;
503
Alexis Hetu04c967a2015-07-08 15:56:17 -0400504 draw->vsDirtyConstF = VERTEX_UNIFORM_VECTORS + 1;
John Bauman89401822014-05-06 15:04:28 -0400505 draw->vsDirtyConstI = 16;
506 draw->vsDirtyConstB = 16;
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400507
508 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
509 {
510 draw->vUniformBuffers[i] = nullptr;
511 }
512
513 for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
514 {
515 draw->transformFeedbackBuffers[i] = nullptr;
516 }
John Bauman89401822014-05-06 15:04:28 -0400517 }
518
519 if(pixelState.stencilActive)
520 {
521 data->stencil[0] = stencil;
522 data->stencil[1] = stencilCCW;
523 }
524
525 if(pixelState.fogActive)
526 {
527 data->fog = fog;
528 }
529
530 if(setupState.isDrawPoint)
531 {
532 data->point = point;
533 }
534
Nicolas Capens235781d2015-01-27 01:46:53 -0500535 data->lineWidth = context->lineWidth;
536
John Bauman89401822014-05-06 15:04:28 -0400537 data->factor = factor;
538
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400539 if(pixelState.transparencyAntialiasing == TRANSPARENCY_ALPHA_TO_COVERAGE)
John Bauman89401822014-05-06 15:04:28 -0400540 {
Alexis Hetua818c452015-06-11 13:06:58 -0400541 float ref = context->alphaReference * (1.0f / 255.0f);
John Bauman89401822014-05-06 15:04:28 -0400542 float margin = sw::min(ref, 1.0f - ref);
543
544 if(ms == 4)
545 {
546 data->a2c0 = replicate(ref - margin * 0.6f);
547 data->a2c1 = replicate(ref - margin * 0.2f);
548 data->a2c2 = replicate(ref + margin * 0.2f);
549 data->a2c3 = replicate(ref + margin * 0.6f);
550 }
551 else if(ms == 2)
552 {
553 data->a2c0 = replicate(ref - margin * 0.3f);
554 data->a2c1 = replicate(ref + margin * 0.3f);
555 }
556 else ASSERT(false);
557 }
558
559 if(pixelState.occlusionEnabled)
560 {
561 for(int cluster = 0; cluster < clusterCount; cluster++)
562 {
563 data->occlusion[cluster] = 0;
564 }
565 }
566
567 #if PERF_PROFILE
568 for(int cluster = 0; cluster < clusterCount; cluster++)
569 {
570 for(int i = 0; i < PERF_TIMERS; i++)
571 {
572 data->cycles[i][cluster] = 0;
573 }
574 }
575 #endif
576
577 // Viewport
578 {
John Bauman19bac1e2014-05-06 15:23:49 -0400579 float W = 0.5f * viewport.width;
580 float H = 0.5f * viewport.height;
581 float X0 = viewport.x0 + W;
582 float Y0 = viewport.y0 + H;
583 float N = viewport.minZ;
584 float F = viewport.maxZ;
John Bauman89401822014-05-06 15:04:28 -0400585 float Z = F - N;
586
587 if(context->isDrawTriangle(false))
588 {
Nicolas Capens3cbeac52017-09-15 11:49:31 -0400589 N += context->depthBias;
John Bauman89401822014-05-06 15:04:28 -0400590 }
591
592 if(complementaryDepthBuffer)
593 {
594 Z = -Z;
595 N = 1 - N;
596 }
597
598 static const float X[5][16] = // Fragment offsets
599 {
600 {+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
601 {-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
602 {-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
603 {+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
604 {+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
605 };
606
607 static const float Y[5][16] = // Fragment offsets
608 {
609 {+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
610 {-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
611 {-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
612 {-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
613 {-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
614 };
615
616 int s = sw::log2(ss);
617
John Bauman19bac1e2014-05-06 15:23:49 -0400618 data->Wx16 = replicate(W * 16);
619 data->Hx16 = replicate(H * 16);
Nicolas Capens5491cb42015-07-02 15:33:29 -0400620 data->X0x16 = replicate(X0 * 16 - 8);
621 data->Y0x16 = replicate(Y0 * 16 - 8);
John Bauman89401822014-05-06 15:04:28 -0400622 data->XXXX = replicate(X[s][q] / W);
623 data->YYYY = replicate(Y[s][q] / H);
John Bauman19bac1e2014-05-06 15:23:49 -0400624 data->halfPixelX = replicate(0.5f / W);
625 data->halfPixelY = replicate(0.5f / H);
626 data->viewportHeight = abs(viewport.height);
Nicolas Capens3cbeac52017-09-15 11:49:31 -0400627 data->slopeDepthBias = context->slopeDepthBias;
John Bauman89401822014-05-06 15:04:28 -0400628 data->depthRange = Z;
629 data->depthNear = N;
630 draw->clipFlags = clipFlags;
631
632 if(clipFlags)
633 {
634 if(clipFlags & Clipper::CLIP_PLANE0) data->clipPlane[0] = clipPlane[0];
635 if(clipFlags & Clipper::CLIP_PLANE1) data->clipPlane[1] = clipPlane[1];
636 if(clipFlags & Clipper::CLIP_PLANE2) data->clipPlane[2] = clipPlane[2];
637 if(clipFlags & Clipper::CLIP_PLANE3) data->clipPlane[3] = clipPlane[3];
638 if(clipFlags & Clipper::CLIP_PLANE4) data->clipPlane[4] = clipPlane[4];
639 if(clipFlags & Clipper::CLIP_PLANE5) data->clipPlane[5] = clipPlane[5];
640 }
641 }
642
643 // Target
644 {
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500645 for(int index = 0; index < RENDERTARGETS; index++)
John Bauman89401822014-05-06 15:04:28 -0400646 {
647 draw->renderTarget[index] = context->renderTarget[index];
648
649 if(draw->renderTarget[index])
650 {
Nicolas Capens8af24c52017-12-11 14:45:01 -0500651 unsigned int layer = context->renderTargetLayer[index];
Alexis Hetu88482c32018-06-05 17:05:17 -0400652 requiresSync |= context->renderTarget[index]->requiresSync();
Nicolas Capens8af24c52017-12-11 14:45:01 -0500653 data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
Nicolas Capensbfa23b32017-12-11 10:06:37 -0500654 data->colorBuffer[index] += q * ms * context->renderTarget[index]->getSliceB(true);
John Bauman89401822014-05-06 15:04:28 -0400655 data->colorPitchB[index] = context->renderTarget[index]->getInternalPitchB();
656 data->colorSliceB[index] = context->renderTarget[index]->getInternalSliceB();
657 }
658 }
659
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400660 draw->depthBuffer = context->depthBuffer;
661 draw->stencilBuffer = context->stencilBuffer;
John Bauman89401822014-05-06 15:04:28 -0400662
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400663 if(draw->depthBuffer)
John Bauman89401822014-05-06 15:04:28 -0400664 {
Nicolas Capens8af24c52017-12-11 14:45:01 -0500665 unsigned int layer = context->depthBufferLayer;
Alexis Hetu88482c32018-06-05 17:05:17 -0400666 requiresSync |= context->depthBuffer->requiresSync();
Nicolas Capens8af24c52017-12-11 14:45:01 -0500667 data->depthBuffer = (float*)context->depthBuffer->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
Nicolas Capensbfa23b32017-12-11 10:06:37 -0500668 data->depthBuffer += q * ms * context->depthBuffer->getSliceB(true);
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400669 data->depthPitchB = context->depthBuffer->getInternalPitchB();
670 data->depthSliceB = context->depthBuffer->getInternalSliceB();
671 }
John Bauman89401822014-05-06 15:04:28 -0400672
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400673 if(draw->stencilBuffer)
674 {
Nicolas Capens8af24c52017-12-11 14:45:01 -0500675 unsigned int layer = context->stencilBufferLayer;
Alexis Hetu88482c32018-06-05 17:05:17 -0400676 requiresSync |= context->stencilBuffer->requiresSync();
Nicolas Capens8af24c52017-12-11 14:45:01 -0500677 data->stencilBuffer = (unsigned char*)context->stencilBuffer->lockStencil(0, 0, layer, MANAGED);
Nicolas Capensbfa23b32017-12-11 10:06:37 -0500678 data->stencilBuffer += q * ms * context->stencilBuffer->getSliceB(true);
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400679 data->stencilPitchB = context->stencilBuffer->getStencilPitchB();
680 data->stencilSliceB = context->stencilBuffer->getStencilSliceB();
John Bauman89401822014-05-06 15:04:28 -0400681 }
682 }
683
John Bauman19bac1e2014-05-06 15:23:49 -0400684 // Scissor
685 {
686 data->scissorX0 = scissor.x0;
687 data->scissorX1 = scissor.x1;
688 data->scissorY0 = scissor.y0;
689 data->scissorY1 = scissor.y1;
690 }
691
John Bauman89401822014-05-06 15:04:28 -0400692 draw->primitive = 0;
693 draw->count = count;
694
695 draw->references = (count + batch - 1) / batch;
696
Nicolas Capensebe67642015-03-20 13:34:51 -0400697 schedulerMutex.lock();
Alexis Hetu6b164c32017-09-20 11:24:52 -0400698 ++nextDraw; // Atomic
Nicolas Capensebe67642015-03-20 13:34:51 -0400699 schedulerMutex.unlock();
John Bauman89401822014-05-06 15:04:28 -0400700
Nicolas Capens0808b4f2017-03-13 17:20:39 -0400701 #ifndef NDEBUG
702 if(threadCount == 1) // Use main thread for draw execution
703 {
704 threadsAwake = 1;
705 task[0].type = Task::RESUME;
706
707 taskLoop(0);
708 }
709 else
710 #endif
John Bauman89401822014-05-06 15:04:28 -0400711 {
Nicolas Capens20248dd2015-08-10 14:07:45 -0400712 if(!threadsAwake)
713 {
714 suspend[0]->wait();
John Bauman89401822014-05-06 15:04:28 -0400715
Nicolas Capens20248dd2015-08-10 14:07:45 -0400716 threadsAwake = 1;
717 task[0].type = Task::RESUME;
718
719 resume[0]->signal();
720 }
721 }
John Bauman89401822014-05-06 15:04:28 -0400722 }
Alexis Hetu90404212018-06-04 11:38:17 -0400723
724 // TODO(sugoi): This is a temporary brute-force workaround to ensure IOSurface synchronization.
Alexis Hetu88482c32018-06-05 17:05:17 -0400725 if(requiresSync)
Alexis Hetu90404212018-06-04 11:38:17 -0400726 {
727 synchronize();
728 }
John Bauman89401822014-05-06 15:04:28 -0400729 }
730
Nicolas Capens426cb5e2017-07-20 14:14:09 -0400731 void Renderer::clear(void *value, Format format, Surface *dest, const Rect &clearRect, unsigned int rgbaMask)
Nicolas Capens81aa97b2017-06-27 17:08:08 -0400732 {
Nicolas Capensbfa23b32017-12-11 10:06:37 -0500733 blitter->clear(value, format, dest, clearRect, rgbaMask);
Nicolas Capens81aa97b2017-06-27 17:08:08 -0400734 }
735
Nicolas Capens1ab837c2017-12-16 02:28:02 -0500736 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 -0400737 {
Nicolas Capens1ab837c2017-12-16 02:28:02 -0500738 blitter->blit(source, sRect, dest, dRect, {filter, isStencil, sRGBconversion});
Nicolas Capens81aa97b2017-06-27 17:08:08 -0400739 }
740
741 void Renderer::blit3D(Surface *source, Surface *dest)
742 {
743 blitter->blit3D(source, dest);
744 }
745
John Bauman89401822014-05-06 15:04:28 -0400746 void Renderer::threadFunction(void *parameters)
747 {
748 Renderer *renderer = static_cast<Parameters*>(parameters)->renderer;
749 int threadIndex = static_cast<Parameters*>(parameters)->threadIndex;
750
751 if(logPrecision < IEEE)
752 {
John Bauman66b8ab22014-05-06 15:57:45 -0400753 CPUID::setFlushToZero(true);
754 CPUID::setDenormalsAreZero(true);
John Bauman89401822014-05-06 15:04:28 -0400755 }
756
757 renderer->threadLoop(threadIndex);
758 }
759
760 void Renderer::threadLoop(int threadIndex)
761 {
762 while(!exitThreads)
763 {
764 taskLoop(threadIndex);
765
766 suspend[threadIndex]->signal();
767 resume[threadIndex]->wait();
768 }
769 }
770
771 void Renderer::taskLoop(int threadIndex)
772 {
773 while(task[threadIndex].type != Task::SUSPEND)
774 {
775 scheduleTask(threadIndex);
776 executeTask(threadIndex);
777 }
778 }
779
780 void Renderer::findAvailableTasks()
781 {
782 // Find pixel tasks
783 for(int cluster = 0; cluster < clusterCount; cluster++)
784 {
785 if(!pixelProgress[cluster].executing)
786 {
787 for(int unit = 0; unit < unitCount; unit++)
788 {
789 if(primitiveProgress[unit].references > 0) // Contains processed primitives
790 {
791 if(pixelProgress[cluster].drawCall == primitiveProgress[unit].drawCall)
792 {
793 if(pixelProgress[cluster].processedPrimitives == primitiveProgress[unit].firstPrimitive) // Previous primitives have been rendered
794 {
795 Task &task = taskQueue[qHead];
796 task.type = Task::PIXELS;
797 task.primitiveUnit = unit;
798 task.pixelCluster = cluster;
799
800 pixelProgress[cluster].executing = true;
801
802 // Commit to the task queue
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400803 qHead = (qHead + 1) & TASK_COUNT_BITS;
John Bauman89401822014-05-06 15:04:28 -0400804 qSize++;
805
806 break;
807 }
808 }
809 }
810 }
811 }
812 }
Nicolas Capensec0936c2016-05-18 12:32:02 -0400813
John Bauman89401822014-05-06 15:04:28 -0400814 // Find primitive tasks
815 if(currentDraw == nextDraw)
816 {
817 return; // No more primitives to process
818 }
819
820 for(int unit = 0; unit < unitCount; unit++)
821 {
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400822 DrawCall *draw = drawList[currentDraw & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -0400823
Alexis Hetu6b164c32017-09-20 11:24:52 -0400824 int primitive = draw->primitive;
825 int count = draw->count;
826
827 if(primitive >= count)
John Bauman89401822014-05-06 15:04:28 -0400828 {
Alexis Hetu6b164c32017-09-20 11:24:52 -0400829 ++currentDraw; // Atomic
John Bauman89401822014-05-06 15:04:28 -0400830
831 if(currentDraw == nextDraw)
832 {
833 return; // No more primitives to process
834 }
835
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400836 draw = drawList[currentDraw & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -0400837 }
838
839 if(!primitiveProgress[unit].references) // Task not already being executed and not still in use by a pixel unit
840 {
Alexis Hetu6b164c32017-09-20 11:24:52 -0400841 primitive = draw->primitive;
842 count = draw->count;
John Bauman89401822014-05-06 15:04:28 -0400843 int batch = draw->batchSize;
844
845 primitiveProgress[unit].drawCall = currentDraw;
846 primitiveProgress[unit].firstPrimitive = primitive;
847 primitiveProgress[unit].primitiveCount = count - primitive >= batch ? batch : count - primitive;
848
849 draw->primitive += batch;
850
851 Task &task = taskQueue[qHead];
852 task.type = Task::PRIMITIVES;
853 task.primitiveUnit = unit;
854
855 primitiveProgress[unit].references = -1;
856
857 // Commit to the task queue
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400858 qHead = (qHead + 1) & TASK_COUNT_BITS;
John Bauman89401822014-05-06 15:04:28 -0400859 qSize++;
860 }
861 }
862 }
863
864 void Renderer::scheduleTask(int threadIndex)
865 {
Nicolas Capensebe67642015-03-20 13:34:51 -0400866 schedulerMutex.lock();
John Bauman89401822014-05-06 15:04:28 -0400867
Alexis Hetu6b164c32017-09-20 11:24:52 -0400868 int curThreadsAwake = threadsAwake;
869
870 if((int)qSize < threadCount - curThreadsAwake + 1)
John Bauman89401822014-05-06 15:04:28 -0400871 {
872 findAvailableTasks();
873 }
874
875 if(qSize != 0)
876 {
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400877 task[threadIndex] = taskQueue[(qHead - qSize) & TASK_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -0400878 qSize--;
879
Alexis Hetu6b164c32017-09-20 11:24:52 -0400880 if(curThreadsAwake != threadCount)
John Bauman89401822014-05-06 15:04:28 -0400881 {
Alexis Hetu6b164c32017-09-20 11:24:52 -0400882 int wakeup = qSize - curThreadsAwake + 1;
John Bauman89401822014-05-06 15:04:28 -0400883
884 for(int i = 0; i < threadCount && wakeup > 0; i++)
885 {
886 if(task[i].type == Task::SUSPEND)
887 {
888 suspend[i]->wait();
889 task[i].type = Task::RESUME;
890 resume[i]->signal();
891
Alexis Hetu6b164c32017-09-20 11:24:52 -0400892 ++threadsAwake; // Atomic
John Bauman89401822014-05-06 15:04:28 -0400893 wakeup--;
894 }
895 }
896 }
897 }
898 else
899 {
900 task[threadIndex].type = Task::SUSPEND;
901
Alexis Hetu6b164c32017-09-20 11:24:52 -0400902 --threadsAwake; // Atomic
John Bauman89401822014-05-06 15:04:28 -0400903 }
904
Nicolas Capensebe67642015-03-20 13:34:51 -0400905 schedulerMutex.unlock();
John Bauman89401822014-05-06 15:04:28 -0400906 }
907
908 void Renderer::executeTask(int threadIndex)
909 {
910 #if PERF_HUD
911 int64_t startTick = Timer::ticks();
912 #endif
913
914 switch(task[threadIndex].type)
915 {
916 case Task::PRIMITIVES:
917 {
918 int unit = task[threadIndex].primitiveUnit;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400919
John Bauman89401822014-05-06 15:04:28 -0400920 int input = primitiveProgress[unit].firstPrimitive;
921 int count = primitiveProgress[unit].primitiveCount;
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400922 DrawCall *draw = drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
Nicolas Capens734392e2016-05-26 11:07:40 -0400923 int (Renderer::*setupPrimitives)(int batch, int count) = draw->setupPrimitives;
John Bauman89401822014-05-06 15:04:28 -0400924
925 processPrimitiveVertices(unit, input, count, draw->count, threadIndex);
926
927 #if PERF_HUD
928 int64_t time = Timer::ticks();
929 vertexTime[threadIndex] += time - startTick;
930 startTick = time;
931 #endif
932
Nicolas Capens734392e2016-05-26 11:07:40 -0400933 int visible = 0;
934
935 if(!draw->setupState.rasterizerDiscard)
936 {
937 visible = (this->*setupPrimitives)(unit, count);
938 }
John Bauman89401822014-05-06 15:04:28 -0400939
940 primitiveProgress[unit].visible = visible;
941 primitiveProgress[unit].references = clusterCount;
942
943 #if PERF_HUD
944 setupTime[threadIndex] += Timer::ticks() - startTick;
945 #endif
946 }
947 break;
948 case Task::PIXELS:
949 {
950 int unit = task[threadIndex].primitiveUnit;
951 int visible = primitiveProgress[unit].visible;
952
953 if(visible > 0)
954 {
955 int cluster = task[threadIndex].pixelCluster;
956 Primitive *primitive = primitiveBatch[unit];
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400957 DrawCall *draw = drawList[pixelProgress[cluster].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -0400958 DrawData *data = draw->data;
959 PixelProcessor::RoutinePointer pixelRoutine = draw->pixelPointer;
960
961 pixelRoutine(primitive, visible, cluster, data);
962 }
963
964 finishRendering(task[threadIndex]);
965
966 #if PERF_HUD
967 pixelTime[threadIndex] += Timer::ticks() - startTick;
968 #endif
969 }
970 break;
971 case Task::RESUME:
972 break;
973 case Task::SUSPEND:
974 break;
975 default:
976 ASSERT(false);
977 }
978 }
979
John Bauman19bac1e2014-05-06 15:23:49 -0400980 void Renderer::synchronize()
981 {
982 sync->lock(sw::PUBLIC);
983 sync->unlock();
984 }
985
John Bauman89401822014-05-06 15:04:28 -0400986 void Renderer::finishRendering(Task &pixelTask)
987 {
988 int unit = pixelTask.primitiveUnit;
989 int cluster = pixelTask.pixelCluster;
990
Alexis Hetubc6ce4f2017-09-27 13:15:59 -0400991 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -0400992 DrawData &data = *draw.data;
993 int primitive = primitiveProgress[unit].firstPrimitive;
994 int count = primitiveProgress[unit].primitiveCount;
Alexis Hetuf4fbcb82016-04-07 11:05:57 -0400995 int processedPrimitives = primitive + count;
John Bauman89401822014-05-06 15:04:28 -0400996
Alexis Hetuf4fbcb82016-04-07 11:05:57 -0400997 pixelProgress[cluster].processedPrimitives = processedPrimitives;
John Bauman89401822014-05-06 15:04:28 -0400998
Nicolas Capensf3304232016-03-10 00:56:16 -0500999 if(pixelProgress[cluster].processedPrimitives >= draw.count)
1000 {
Alexis Hetu6b164c32017-09-20 11:24:52 -04001001 ++pixelProgress[cluster].drawCall; // Atomic
Nicolas Capensf3304232016-03-10 00:56:16 -05001002 pixelProgress[cluster].processedPrimitives = 0;
1003 }
1004
Alexis Hetu6b164c32017-09-20 11:24:52 -04001005 int ref = primitiveProgress[unit].references--; // Atomic
John Bauman89401822014-05-06 15:04:28 -04001006
1007 if(ref == 0)
1008 {
Alexis Hetu6b164c32017-09-20 11:24:52 -04001009 ref = draw.references--; // Atomic
John Bauman89401822014-05-06 15:04:28 -04001010
1011 if(ref == 0)
1012 {
1013 #if PERF_PROFILE
1014 for(int cluster = 0; cluster < clusterCount; cluster++)
1015 {
1016 for(int i = 0; i < PERF_TIMERS; i++)
1017 {
1018 profiler.cycles[i] += data.cycles[i][cluster];
1019 }
1020 }
1021 #endif
1022
1023 if(draw.queries)
1024 {
Alexis Hetubf3fc252017-12-06 14:22:10 -05001025 for(auto &query : *(draw.queries))
John Bauman89401822014-05-06 15:04:28 -04001026 {
Alexis Hetu16116cb2016-03-02 15:59:51 -05001027 switch(query->type)
John Bauman89401822014-05-06 15:04:28 -04001028 {
Alexis Hetu16116cb2016-03-02 15:59:51 -05001029 case Query::FRAGMENTS_PASSED:
1030 for(int cluster = 0; cluster < clusterCount; cluster++)
1031 {
Alexis Hetu6b164c32017-09-20 11:24:52 -04001032 query->data += data.occlusion[cluster];
Alexis Hetu16116cb2016-03-02 15:59:51 -05001033 }
1034 break;
1035 case Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Alexis Hetu6b164c32017-09-20 11:24:52 -04001036 query->data += processedPrimitives;
Alexis Hetu16116cb2016-03-02 15:59:51 -05001037 break;
1038 default:
1039 break;
John Bauman89401822014-05-06 15:04:28 -04001040 }
1041
Alexis Hetu3fc68932018-11-14 10:54:53 -05001042 query->release();
John Bauman89401822014-05-06 15:04:28 -04001043 }
1044
1045 delete draw.queries;
1046 draw.queries = 0;
1047 }
1048
Alexis Hetu1edcd8b2015-11-05 11:12:41 -05001049 for(int i = 0; i < RENDERTARGETS; i++)
John Bauman89401822014-05-06 15:04:28 -04001050 {
1051 if(draw.renderTarget[i])
1052 {
1053 draw.renderTarget[i]->unlockInternal();
1054 }
1055 }
1056
Nicolas Capens3751c1e2016-03-21 14:14:14 -04001057 if(draw.depthBuffer)
John Bauman89401822014-05-06 15:04:28 -04001058 {
Nicolas Capens3751c1e2016-03-21 14:14:14 -04001059 draw.depthBuffer->unlockInternal();
1060 }
1061
1062 if(draw.stencilBuffer)
1063 {
1064 draw.stencilBuffer->unlockStencil();
John Bauman89401822014-05-06 15:04:28 -04001065 }
1066
Alexis Hetu0b65c5e2015-03-31 11:48:57 -04001067 for(int i = 0; i < TOTAL_IMAGE_UNITS; i++)
John Bauman89401822014-05-06 15:04:28 -04001068 {
1069 if(draw.texture[i])
1070 {
1071 draw.texture[i]->unlock();
1072 }
1073 }
1074
Nicolas Capensf0aef1a2016-05-18 14:44:21 -04001075 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -04001076 {
1077 if(draw.vertexStream[i])
1078 {
1079 draw.vertexStream[i]->unlock();
1080 }
1081 }
1082
1083 if(draw.indexBuffer)
1084 {
1085 draw.indexBuffer->unlock();
1086 }
1087
Alexis Hetuc6a57cb2016-04-07 10:48:31 -04001088 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
1089 {
1090 if(draw.pUniformBuffers[i])
1091 {
1092 draw.pUniformBuffers[i]->unlock();
1093 }
1094 if(draw.vUniformBuffers[i])
1095 {
1096 draw.vUniformBuffers[i]->unlock();
1097 }
1098 }
1099
1100 for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
1101 {
1102 if(draw.transformFeedbackBuffers[i])
1103 {
1104 draw.transformFeedbackBuffers[i]->unlock();
1105 }
1106 }
Alexis Hetu2c2a7b22015-10-27 16:12:11 -04001107
John Bauman89401822014-05-06 15:04:28 -04001108 draw.vertexRoutine->unbind();
1109 draw.setupRoutine->unbind();
1110 draw.pixelRoutine->unbind();
1111
John Bauman19bac1e2014-05-06 15:23:49 -04001112 sync->unlock();
1113
John Bauman89401822014-05-06 15:04:28 -04001114 draw.references = -1;
1115 resumeApp->signal();
1116 }
1117 }
1118
1119 pixelProgress[cluster].executing = false;
1120 }
1121
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001122 void Renderer::processPrimitiveVertices(int unit, unsigned int start, unsigned int triangleCount, unsigned int loop, int thread)
John Bauman89401822014-05-06 15:04:28 -04001123 {
1124 Triangle *triangle = triangleBatch[unit];
Alexis Hetu6b164c32017-09-20 11:24:52 -04001125 int primitiveDrawCall = primitiveProgress[unit].drawCall;
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001126 DrawCall *draw = drawList[primitiveDrawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001127 DrawData *data = draw->data;
1128 VertexTask *task = vertexTask[thread];
1129
1130 const void *indices = data->indices;
1131 VertexProcessor::RoutinePointer vertexRoutine = draw->vertexPointer;
1132
Alexis Hetu6b164c32017-09-20 11:24:52 -04001133 if(task->vertexCache.drawCall != primitiveDrawCall)
John Bauman89401822014-05-06 15:04:28 -04001134 {
1135 task->vertexCache.clear();
Alexis Hetu6b164c32017-09-20 11:24:52 -04001136 task->vertexCache.drawCall = primitiveDrawCall;
John Bauman89401822014-05-06 15:04:28 -04001137 }
1138
1139 unsigned int batch[128][3]; // FIXME: Adjust to dynamic batch size
1140
1141 switch(draw->drawType)
1142 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001143 case DRAW_POINTLIST:
John Bauman89401822014-05-06 15:04:28 -04001144 {
1145 unsigned int index = start;
1146
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001147 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001148 {
1149 batch[i][0] = index;
1150 batch[i][1] = index;
1151 batch[i][2] = index;
1152
1153 index += 1;
1154 }
1155 }
1156 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001157 case DRAW_LINELIST:
John Bauman89401822014-05-06 15:04:28 -04001158 {
1159 unsigned int index = 2 * start;
1160
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001161 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001162 {
1163 batch[i][0] = index + 0;
1164 batch[i][1] = index + 1;
1165 batch[i][2] = index + 1;
1166
1167 index += 2;
1168 }
1169 }
1170 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001171 case DRAW_LINESTRIP:
John Bauman89401822014-05-06 15:04:28 -04001172 {
1173 unsigned int index = start;
1174
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001175 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001176 {
1177 batch[i][0] = index + 0;
1178 batch[i][1] = index + 1;
1179 batch[i][2] = index + 1;
1180
1181 index += 1;
1182 }
1183 }
1184 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001185 case DRAW_LINELOOP:
John Bauman89401822014-05-06 15:04:28 -04001186 {
1187 unsigned int index = start;
1188
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001189 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001190 {
1191 batch[i][0] = (index + 0) % loop;
1192 batch[i][1] = (index + 1) % loop;
1193 batch[i][2] = (index + 1) % loop;
1194
1195 index += 1;
1196 }
1197 }
1198 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001199 case DRAW_TRIANGLELIST:
John Bauman89401822014-05-06 15:04:28 -04001200 {
1201 unsigned int index = 3 * start;
1202
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001203 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001204 {
1205 batch[i][0] = index + 0;
1206 batch[i][1] = index + 1;
1207 batch[i][2] = index + 2;
1208
1209 index += 3;
1210 }
1211 }
1212 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001213 case DRAW_TRIANGLESTRIP:
John Bauman89401822014-05-06 15:04:28 -04001214 {
1215 unsigned int index = start;
1216
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001217 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001218 {
Alexis Hetu62cd2bd2017-12-21 13:52:00 -05001219 if(leadingVertexFirst)
1220 {
1221 batch[i][0] = index + 0;
1222 batch[i][1] = index + (index & 1) + 1;
1223 batch[i][2] = index + (~index & 1) + 1;
1224 }
1225 else
1226 {
1227 batch[i][0] = index + (index & 1);
1228 batch[i][1] = index + (~index & 1);
1229 batch[i][2] = index + 2;
1230 }
John Bauman89401822014-05-06 15:04:28 -04001231
1232 index += 1;
1233 }
1234 }
1235 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001236 case DRAW_TRIANGLEFAN:
John Bauman89401822014-05-06 15:04:28 -04001237 {
1238 unsigned int index = start;
1239
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001240 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001241 {
Alexis Hetu62cd2bd2017-12-21 13:52:00 -05001242 if(leadingVertexFirst)
1243 {
1244 batch[i][0] = index + 1;
1245 batch[i][1] = index + 2;
1246 batch[i][2] = 0;
1247 }
1248 else
1249 {
1250 batch[i][0] = 0;
1251 batch[i][1] = index + 1;
1252 batch[i][2] = index + 2;
1253 }
John Bauman89401822014-05-06 15:04:28 -04001254
1255 index += 1;
1256 }
1257 }
1258 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001259 case DRAW_INDEXEDPOINTLIST8:
John Bauman89401822014-05-06 15:04:28 -04001260 {
1261 const unsigned char *index = (const unsigned char*)indices + start;
1262
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001263 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001264 {
1265 batch[i][0] = *index;
1266 batch[i][1] = *index;
1267 batch[i][2] = *index;
1268
1269 index += 1;
1270 }
1271 }
1272 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001273 case DRAW_INDEXEDPOINTLIST16:
John Bauman89401822014-05-06 15:04:28 -04001274 {
1275 const unsigned short *index = (const unsigned short*)indices + start;
1276
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001277 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001278 {
1279 batch[i][0] = *index;
1280 batch[i][1] = *index;
1281 batch[i][2] = *index;
1282
1283 index += 1;
1284 }
1285 }
1286 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001287 case DRAW_INDEXEDPOINTLIST32:
John Bauman89401822014-05-06 15:04:28 -04001288 {
1289 const unsigned int *index = (const unsigned int*)indices + start;
1290
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001291 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001292 {
1293 batch[i][0] = *index;
1294 batch[i][1] = *index;
1295 batch[i][2] = *index;
1296
1297 index += 1;
1298 }
1299 }
1300 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001301 case DRAW_INDEXEDLINELIST8:
John Bauman89401822014-05-06 15:04:28 -04001302 {
1303 const unsigned char *index = (const unsigned char*)indices + 2 * start;
1304
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001305 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001306 {
1307 batch[i][0] = index[0];
1308 batch[i][1] = index[1];
1309 batch[i][2] = index[1];
1310
1311 index += 2;
1312 }
1313 }
1314 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001315 case DRAW_INDEXEDLINELIST16:
John Bauman89401822014-05-06 15:04:28 -04001316 {
1317 const unsigned short *index = (const unsigned short*)indices + 2 * start;
1318
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001319 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001320 {
1321 batch[i][0] = index[0];
1322 batch[i][1] = index[1];
1323 batch[i][2] = index[1];
1324
1325 index += 2;
1326 }
1327 }
1328 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001329 case DRAW_INDEXEDLINELIST32:
John Bauman89401822014-05-06 15:04:28 -04001330 {
1331 const unsigned int *index = (const unsigned int*)indices + 2 * start;
1332
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001333 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001334 {
1335 batch[i][0] = index[0];
1336 batch[i][1] = index[1];
1337 batch[i][2] = index[1];
1338
1339 index += 2;
1340 }
1341 }
1342 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001343 case DRAW_INDEXEDLINESTRIP8:
John Bauman89401822014-05-06 15:04:28 -04001344 {
1345 const unsigned char *index = (const unsigned char*)indices + start;
1346
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001347 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001348 {
1349 batch[i][0] = index[0];
1350 batch[i][1] = index[1];
1351 batch[i][2] = index[1];
1352
1353 index += 1;
1354 }
1355 }
1356 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001357 case DRAW_INDEXEDLINESTRIP16:
John Bauman89401822014-05-06 15:04:28 -04001358 {
1359 const unsigned short *index = (const unsigned short*)indices + start;
1360
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001361 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001362 {
1363 batch[i][0] = index[0];
1364 batch[i][1] = index[1];
1365 batch[i][2] = index[1];
1366
1367 index += 1;
1368 }
1369 }
1370 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001371 case DRAW_INDEXEDLINESTRIP32:
John Bauman89401822014-05-06 15:04:28 -04001372 {
1373 const unsigned int *index = (const unsigned int*)indices + start;
1374
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001375 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001376 {
1377 batch[i][0] = index[0];
1378 batch[i][1] = index[1];
1379 batch[i][2] = index[1];
1380
1381 index += 1;
1382 }
1383 }
1384 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001385 case DRAW_INDEXEDLINELOOP8:
John Bauman89401822014-05-06 15:04:28 -04001386 {
John Bauman66b8ab22014-05-06 15:57:45 -04001387 const unsigned char *index = (const unsigned char*)indices;
John Bauman89401822014-05-06 15:04:28 -04001388
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001389 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001390 {
John Bauman66b8ab22014-05-06 15:57:45 -04001391 batch[i][0] = index[(start + i + 0) % loop];
1392 batch[i][1] = index[(start + i + 1) % loop];
1393 batch[i][2] = index[(start + i + 1) % loop];
John Bauman89401822014-05-06 15:04:28 -04001394 }
1395 }
1396 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001397 case DRAW_INDEXEDLINELOOP16:
John Bauman89401822014-05-06 15:04:28 -04001398 {
John Bauman66b8ab22014-05-06 15:57:45 -04001399 const unsigned short *index = (const unsigned short*)indices;
John Bauman89401822014-05-06 15:04:28 -04001400
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001401 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001402 {
John Bauman66b8ab22014-05-06 15:57:45 -04001403 batch[i][0] = index[(start + i + 0) % loop];
1404 batch[i][1] = index[(start + i + 1) % loop];
1405 batch[i][2] = index[(start + i + 1) % loop];
John Bauman89401822014-05-06 15:04:28 -04001406 }
1407 }
1408 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001409 case DRAW_INDEXEDLINELOOP32:
John Bauman89401822014-05-06 15:04:28 -04001410 {
John Bauman66b8ab22014-05-06 15:57:45 -04001411 const unsigned int *index = (const unsigned int*)indices;
John Bauman89401822014-05-06 15:04:28 -04001412
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001413 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001414 {
John Bauman66b8ab22014-05-06 15:57:45 -04001415 batch[i][0] = index[(start + i + 0) % loop];
1416 batch[i][1] = index[(start + i + 1) % loop];
1417 batch[i][2] = index[(start + i + 1) % loop];
John Bauman89401822014-05-06 15:04:28 -04001418 }
1419 }
1420 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001421 case DRAW_INDEXEDTRIANGLELIST8:
John Bauman89401822014-05-06 15:04:28 -04001422 {
1423 const unsigned char *index = (const unsigned char*)indices + 3 * start;
1424
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001425 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001426 {
1427 batch[i][0] = index[0];
1428 batch[i][1] = index[1];
1429 batch[i][2] = index[2];
1430
1431 index += 3;
1432 }
1433 }
1434 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001435 case DRAW_INDEXEDTRIANGLELIST16:
John Bauman89401822014-05-06 15:04:28 -04001436 {
1437 const unsigned short *index = (const unsigned short*)indices + 3 * start;
1438
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001439 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001440 {
1441 batch[i][0] = index[0];
1442 batch[i][1] = index[1];
1443 batch[i][2] = index[2];
1444
1445 index += 3;
1446 }
1447 }
1448 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001449 case DRAW_INDEXEDTRIANGLELIST32:
John Bauman89401822014-05-06 15:04:28 -04001450 {
1451 const unsigned int *index = (const unsigned int*)indices + 3 * start;
1452
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001453 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001454 {
1455 batch[i][0] = index[0];
1456 batch[i][1] = index[1];
1457 batch[i][2] = index[2];
1458
1459 index += 3;
1460 }
1461 }
1462 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001463 case DRAW_INDEXEDTRIANGLESTRIP8:
John Bauman89401822014-05-06 15:04:28 -04001464 {
1465 const unsigned char *index = (const unsigned char*)indices + start;
1466
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001467 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001468 {
1469 batch[i][0] = index[0];
1470 batch[i][1] = index[((start + i) & 1) + 1];
1471 batch[i][2] = index[(~(start + i) & 1) + 1];
1472
1473 index += 1;
1474 }
1475 }
1476 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001477 case DRAW_INDEXEDTRIANGLESTRIP16:
John Bauman89401822014-05-06 15:04:28 -04001478 {
1479 const unsigned short *index = (const unsigned short*)indices + start;
1480
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001481 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001482 {
1483 batch[i][0] = index[0];
1484 batch[i][1] = index[((start + i) & 1) + 1];
1485 batch[i][2] = index[(~(start + i) & 1) + 1];
1486
1487 index += 1;
1488 }
1489 }
1490 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001491 case DRAW_INDEXEDTRIANGLESTRIP32:
John Bauman89401822014-05-06 15:04:28 -04001492 {
1493 const unsigned int *index = (const unsigned int*)indices + start;
1494
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001495 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001496 {
1497 batch[i][0] = index[0];
1498 batch[i][1] = index[((start + i) & 1) + 1];
1499 batch[i][2] = index[(~(start + i) & 1) + 1];
1500
1501 index += 1;
1502 }
1503 }
1504 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001505 case DRAW_INDEXEDTRIANGLEFAN8:
John Bauman89401822014-05-06 15:04:28 -04001506 {
1507 const unsigned char *index = (const unsigned char*)indices;
1508
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001509 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001510 {
1511 batch[i][0] = index[start + i + 1];
1512 batch[i][1] = index[start + i + 2];
1513 batch[i][2] = index[0];
1514 }
1515 }
1516 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001517 case DRAW_INDEXEDTRIANGLEFAN16:
John Bauman89401822014-05-06 15:04:28 -04001518 {
1519 const unsigned short *index = (const unsigned short*)indices;
1520
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001521 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001522 {
1523 batch[i][0] = index[start + i + 1];
1524 batch[i][1] = index[start + i + 2];
1525 batch[i][2] = index[0];
1526 }
1527 }
1528 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001529 case DRAW_INDEXEDTRIANGLEFAN32:
John Bauman89401822014-05-06 15:04:28 -04001530 {
1531 const unsigned int *index = (const unsigned int*)indices;
1532
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001533 for(unsigned int i = 0; i < triangleCount; i++)
John Bauman89401822014-05-06 15:04:28 -04001534 {
1535 batch[i][0] = index[start + i + 1];
1536 batch[i][1] = index[start + i + 2];
1537 batch[i][2] = index[0];
1538 }
1539 }
1540 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001541 case DRAW_QUADLIST:
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001542 {
1543 unsigned int index = 4 * start / 2;
1544
1545 for(unsigned int i = 0; i < triangleCount; i += 2)
1546 {
1547 batch[i+0][0] = index + 0;
1548 batch[i+0][1] = index + 1;
1549 batch[i+0][2] = index + 2;
1550
Nicolas Capens0bac2852016-05-07 06:09:58 -04001551 batch[i+1][0] = index + 0;
Nicolas Capensc50d35d2015-01-27 01:52:41 -05001552 batch[i+1][1] = index + 2;
1553 batch[i+1][2] = index + 3;
1554
1555 index += 4;
1556 }
1557 }
1558 break;
John Bauman89401822014-05-06 15:04:28 -04001559 default:
1560 ASSERT(false);
Nicolas Capense5284ac2016-01-08 01:30:48 -05001561 return;
John Bauman89401822014-05-06 15:04:28 -04001562 }
1563
Alexis Hetua62a0ca2016-04-20 15:29:51 -04001564 task->primitiveStart = start;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001565 task->vertexCount = triangleCount * 3;
John Bauman89401822014-05-06 15:04:28 -04001566 vertexRoutine(&triangle->v0, (unsigned int*)&batch, task, data);
1567 }
1568
Nicolas Capens734392e2016-05-26 11:07:40 -04001569 int Renderer::setupSolidTriangles(int unit, int count)
John Bauman89401822014-05-06 15:04:28 -04001570 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001571 Triangle *triangle = triangleBatch[unit];
1572 Primitive *primitive = primitiveBatch[unit];
John Bauman89401822014-05-06 15:04:28 -04001573
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001574 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001575 SetupProcessor::State &state = draw.setupState;
1576 const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
1577
1578 int ms = state.multiSample;
1579 int pos = state.positionRegister;
1580 const DrawData *data = draw.data;
1581 int visible = 0;
1582
1583 for(int i = 0; i < count; i++, triangle++)
1584 {
1585 Vertex &v0 = triangle->v0;
1586 Vertex &v1 = triangle->v1;
1587 Vertex &v2 = triangle->v2;
1588
1589 if((v0.clipFlags & v1.clipFlags & v2.clipFlags) == Clipper::CLIP_FINITE)
1590 {
1591 Polygon polygon(&v0.v[pos], &v1.v[pos], &v2.v[pos]);
1592
1593 int clipFlagsOr = v0.clipFlags | v1.clipFlags | v2.clipFlags | draw.clipFlags;
1594
1595 if(clipFlagsOr != Clipper::CLIP_FINITE)
1596 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001597 if(!clipper->clip(polygon, clipFlagsOr, draw))
John Bauman89401822014-05-06 15:04:28 -04001598 {
1599 continue;
1600 }
1601 }
1602
1603 if(setupRoutine(primitive, triangle, &polygon, data))
1604 {
1605 primitive += ms;
1606 visible++;
1607 }
1608 }
1609 }
1610
1611 return visible;
1612 }
1613
Nicolas Capens734392e2016-05-26 11:07:40 -04001614 int Renderer::setupWireframeTriangle(int unit, int count)
John Bauman89401822014-05-06 15:04:28 -04001615 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001616 Triangle *triangle = triangleBatch[unit];
1617 Primitive *primitive = primitiveBatch[unit];
John Bauman89401822014-05-06 15:04:28 -04001618 int visible = 0;
1619
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001620 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001621 SetupProcessor::State &state = draw.setupState;
John Bauman89401822014-05-06 15:04:28 -04001622
1623 const Vertex &v0 = triangle[0].v0;
1624 const Vertex &v1 = triangle[0].v1;
1625 const Vertex &v2 = triangle[0].v2;
1626
1627 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;
1628
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001629 if(state.cullMode == CULL_CLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -04001630 {
1631 if(d >= 0) return 0;
1632 }
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001633 else if(state.cullMode == CULL_COUNTERCLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -04001634 {
1635 if(d <= 0) return 0;
1636 }
1637
1638 // Copy attributes
1639 triangle[1].v0 = v1;
1640 triangle[1].v1 = v2;
1641 triangle[2].v0 = v2;
1642 triangle[2].v1 = v0;
1643
1644 if(state.color[0][0].flat) // FIXME
1645 {
1646 for(int i = 0; i < 2; i++)
1647 {
1648 triangle[1].v0.C[i] = triangle[0].v0.C[i];
John Bauman66b8ab22014-05-06 15:57:45 -04001649 triangle[1].v1.C[i] = triangle[0].v0.C[i];
John Bauman89401822014-05-06 15:04:28 -04001650 triangle[2].v0.C[i] = triangle[0].v0.C[i];
John Bauman66b8ab22014-05-06 15:57:45 -04001651 triangle[2].v1.C[i] = triangle[0].v0.C[i];
John Bauman89401822014-05-06 15:04:28 -04001652 }
1653 }
1654
1655 for(int i = 0; i < 3; i++)
1656 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001657 if(setupLine(*primitive, *triangle, draw))
John Bauman89401822014-05-06 15:04:28 -04001658 {
1659 primitive->area = 0.5f * d;
1660
1661 primitive++;
1662 visible++;
1663 }
1664
1665 triangle++;
1666 }
1667
1668 return visible;
1669 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04001670
Nicolas Capens734392e2016-05-26 11:07:40 -04001671 int Renderer::setupVertexTriangle(int unit, int count)
John Bauman89401822014-05-06 15:04:28 -04001672 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001673 Triangle *triangle = triangleBatch[unit];
1674 Primitive *primitive = primitiveBatch[unit];
John Bauman89401822014-05-06 15:04:28 -04001675 int visible = 0;
1676
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001677 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001678 SetupProcessor::State &state = draw.setupState;
1679
1680 const Vertex &v0 = triangle[0].v0;
1681 const Vertex &v1 = triangle[0].v1;
1682 const Vertex &v2 = triangle[0].v2;
1683
1684 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;
1685
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001686 if(state.cullMode == CULL_CLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -04001687 {
1688 if(d >= 0) return 0;
1689 }
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001690 else if(state.cullMode == CULL_COUNTERCLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -04001691 {
1692 if(d <= 0) return 0;
1693 }
1694
1695 // Copy attributes
1696 triangle[1].v0 = v1;
1697 triangle[2].v0 = v2;
1698
1699 for(int i = 0; i < 3; i++)
1700 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001701 if(setupPoint(*primitive, *triangle, draw))
John Bauman89401822014-05-06 15:04:28 -04001702 {
1703 primitive->area = 0.5f * d;
1704
1705 primitive++;
1706 visible++;
1707 }
1708
1709 triangle++;
1710 }
1711
1712 return visible;
1713 }
1714
Nicolas Capens734392e2016-05-26 11:07:40 -04001715 int Renderer::setupLines(int unit, int count)
John Bauman89401822014-05-06 15:04:28 -04001716 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001717 Triangle *triangle = triangleBatch[unit];
1718 Primitive *primitive = primitiveBatch[unit];
John Bauman89401822014-05-06 15:04:28 -04001719 int visible = 0;
1720
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001721 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001722 SetupProcessor::State &state = draw.setupState;
1723
1724 int ms = state.multiSample;
1725
1726 for(int i = 0; i < count; i++)
1727 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001728 if(setupLine(*primitive, *triangle, draw))
John Bauman89401822014-05-06 15:04:28 -04001729 {
1730 primitive += ms;
1731 visible++;
1732 }
1733
1734 triangle++;
1735 }
1736
1737 return visible;
1738 }
1739
Nicolas Capens734392e2016-05-26 11:07:40 -04001740 int Renderer::setupPoints(int unit, int count)
John Bauman89401822014-05-06 15:04:28 -04001741 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001742 Triangle *triangle = triangleBatch[unit];
1743 Primitive *primitive = primitiveBatch[unit];
John Bauman89401822014-05-06 15:04:28 -04001744 int visible = 0;
1745
Alexis Hetubc6ce4f2017-09-27 13:15:59 -04001746 DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
John Bauman89401822014-05-06 15:04:28 -04001747 SetupProcessor::State &state = draw.setupState;
1748
1749 int ms = state.multiSample;
1750
1751 for(int i = 0; i < count; i++)
1752 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001753 if(setupPoint(*primitive, *triangle, draw))
John Bauman89401822014-05-06 15:04:28 -04001754 {
1755 primitive += ms;
1756 visible++;
1757 }
1758
1759 triangle++;
1760 }
1761
1762 return visible;
1763 }
1764
Nicolas Capens734392e2016-05-26 11:07:40 -04001765 bool Renderer::setupLine(Primitive &primitive, Triangle &triangle, const DrawCall &draw)
John Bauman89401822014-05-06 15:04:28 -04001766 {
1767 const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
1768 const SetupProcessor::State &state = draw.setupState;
1769 const DrawData &data = *draw.data;
1770
Nicolas Capens235781d2015-01-27 01:46:53 -05001771 float lineWidth = data.lineWidth;
1772
John Bauman89401822014-05-06 15:04:28 -04001773 Vertex &v0 = triangle.v0;
1774 Vertex &v1 = triangle.v1;
1775
1776 int pos = state.positionRegister;
1777
1778 const float4 &P0 = v0.v[pos];
1779 const float4 &P1 = v1.v[pos];
1780
1781 if(P0.w <= 0 && P1.w <= 0)
1782 {
1783 return false;
1784 }
1785
John Bauman19bac1e2014-05-06 15:23:49 -04001786 const float W = data.Wx16[0] * (1.0f / 16.0f);
1787 const float H = data.Hx16[0] * (1.0f / 16.0f);
John Bauman89401822014-05-06 15:04:28 -04001788
1789 float dx = W * (P1.x / P1.w - P0.x / P0.w);
1790 float dy = H * (P1.y / P1.w - P0.y / P0.w);
1791
1792 if(dx == 0 && dy == 0)
1793 {
1794 return false;
1795 }
1796
Nicolas Capensd0e4c2d2018-01-09 15:34:26 -05001797 if(state.multiSample > 1) // Rectangle
John Bauman89401822014-05-06 15:04:28 -04001798 {
1799 float4 P[4];
1800 int C[4];
1801
1802 P[0] = P0;
1803 P[1] = P1;
1804 P[2] = P1;
1805 P[3] = P0;
1806
Nicolas Capens235781d2015-01-27 01:46:53 -05001807 float scale = lineWidth * 0.5f / sqrt(dx*dx + dy*dy);
John Bauman89401822014-05-06 15:04:28 -04001808
1809 dx *= scale;
1810 dy *= scale;
1811
John Bauman89401822014-05-06 15:04:28 -04001812 float dx0h = dx * P0.w / H;
1813 float dy0w = dy * P0.w / W;
1814
John Bauman89401822014-05-06 15:04:28 -04001815 float dx1h = dx * P1.w / H;
1816 float dy1w = dy * P1.w / W;
1817
Nicolas Capensb04881b2018-03-16 23:23:06 -04001818 P[0].x += -dy0w;
1819 P[0].y += +dx0h;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001820 C[0] = clipper->computeClipFlags(P[0]);
John Bauman89401822014-05-06 15:04:28 -04001821
Nicolas Capensb04881b2018-03-16 23:23:06 -04001822 P[1].x += -dy1w;
1823 P[1].y += +dx1h;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001824 C[1] = clipper->computeClipFlags(P[1]);
John Bauman89401822014-05-06 15:04:28 -04001825
Nicolas Capensb04881b2018-03-16 23:23:06 -04001826 P[2].x += +dy1w;
1827 P[2].y += -dx1h;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001828 C[2] = clipper->computeClipFlags(P[2]);
John Bauman89401822014-05-06 15:04:28 -04001829
Nicolas Capensb04881b2018-03-16 23:23:06 -04001830 P[3].x += +dy0w;
1831 P[3].y += -dx0h;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001832 C[3] = clipper->computeClipFlags(P[3]);
John Bauman89401822014-05-06 15:04:28 -04001833
1834 if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
1835 {
1836 Polygon polygon(P, 4);
1837
1838 int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | draw.clipFlags;
1839
1840 if(clipFlagsOr != Clipper::CLIP_FINITE)
1841 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001842 if(!clipper->clip(polygon, clipFlagsOr, draw))
John Bauman89401822014-05-06 15:04:28 -04001843 {
1844 return false;
1845 }
1846 }
1847
1848 return setupRoutine(&primitive, &triangle, &polygon, &data);
1849 }
1850 }
1851 else // Diamond test convention
1852 {
1853 float4 P[8];
1854 int C[8];
1855
1856 P[0] = P0;
1857 P[1] = P0;
1858 P[2] = P0;
1859 P[3] = P0;
1860 P[4] = P1;
1861 P[5] = P1;
1862 P[6] = P1;
1863 P[7] = P1;
1864
Nicolas Capens235781d2015-01-27 01:46:53 -05001865 float dx0 = lineWidth * 0.5f * P0.w / W;
1866 float dy0 = lineWidth * 0.5f * P0.w / H;
John Bauman89401822014-05-06 15:04:28 -04001867
Nicolas Capens235781d2015-01-27 01:46:53 -05001868 float dx1 = lineWidth * 0.5f * P1.w / W;
1869 float dy1 = lineWidth * 0.5f * P1.w / H;
John Bauman89401822014-05-06 15:04:28 -04001870
1871 P[0].x += -dx0;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001872 C[0] = clipper->computeClipFlags(P[0]);
John Bauman89401822014-05-06 15:04:28 -04001873
John Bauman19bac1e2014-05-06 15:23:49 -04001874 P[1].y += +dy0;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001875 C[1] = clipper->computeClipFlags(P[1]);
John Bauman89401822014-05-06 15:04:28 -04001876
1877 P[2].x += +dx0;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001878 C[2] = clipper->computeClipFlags(P[2]);
John Bauman89401822014-05-06 15:04:28 -04001879
John Bauman19bac1e2014-05-06 15:23:49 -04001880 P[3].y += -dy0;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001881 C[3] = clipper->computeClipFlags(P[3]);
John Bauman89401822014-05-06 15:04:28 -04001882
1883 P[4].x += -dx1;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001884 C[4] = clipper->computeClipFlags(P[4]);
John Bauman89401822014-05-06 15:04:28 -04001885
John Bauman19bac1e2014-05-06 15:23:49 -04001886 P[5].y += +dy1;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001887 C[5] = clipper->computeClipFlags(P[5]);
John Bauman89401822014-05-06 15:04:28 -04001888
1889 P[6].x += +dx1;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001890 C[6] = clipper->computeClipFlags(P[6]);
John Bauman89401822014-05-06 15:04:28 -04001891
John Bauman19bac1e2014-05-06 15:23:49 -04001892 P[7].y += -dy1;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001893 C[7] = clipper->computeClipFlags(P[7]);
John Bauman89401822014-05-06 15:04:28 -04001894
1895 if((C[0] & C[1] & C[2] & C[3] & C[4] & C[5] & C[6] & C[7]) == Clipper::CLIP_FINITE)
1896 {
1897 float4 L[6];
1898
John Bauman19bac1e2014-05-06 15:23:49 -04001899 if(dx > -dy)
John Bauman89401822014-05-06 15:04:28 -04001900 {
John Bauman19bac1e2014-05-06 15:23:49 -04001901 if(dx > dy) // Right
John Bauman89401822014-05-06 15:04:28 -04001902 {
1903 L[0] = P[0];
1904 L[1] = P[1];
1905 L[2] = P[5];
1906 L[3] = P[6];
1907 L[4] = P[7];
1908 L[5] = P[3];
1909 }
1910 else // Down
1911 {
1912 L[0] = P[0];
1913 L[1] = P[4];
1914 L[2] = P[5];
1915 L[3] = P[6];
1916 L[4] = P[2];
1917 L[5] = P[3];
1918 }
1919 }
1920 else
1921 {
John Bauman19bac1e2014-05-06 15:23:49 -04001922 if(dx > dy) // Up
John Bauman89401822014-05-06 15:04:28 -04001923 {
1924 L[0] = P[0];
1925 L[1] = P[1];
1926 L[2] = P[2];
1927 L[3] = P[6];
1928 L[4] = P[7];
1929 L[5] = P[4];
1930 }
1931 else // Left
1932 {
1933 L[0] = P[1];
1934 L[1] = P[2];
1935 L[2] = P[3];
1936 L[3] = P[7];
1937 L[4] = P[4];
1938 L[5] = P[5];
1939 }
1940 }
1941
1942 Polygon polygon(L, 6);
1943
1944 int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | C[4] | C[5] | C[6] | C[7] | draw.clipFlags;
1945
1946 if(clipFlagsOr != Clipper::CLIP_FINITE)
1947 {
Nicolas Capens734392e2016-05-26 11:07:40 -04001948 if(!clipper->clip(polygon, clipFlagsOr, draw))
John Bauman89401822014-05-06 15:04:28 -04001949 {
1950 return false;
1951 }
1952 }
1953
1954 return setupRoutine(&primitive, &triangle, &polygon, &data);
1955 }
1956 }
1957
1958 return false;
1959 }
1960
Nicolas Capens734392e2016-05-26 11:07:40 -04001961 bool Renderer::setupPoint(Primitive &primitive, Triangle &triangle, const DrawCall &draw)
John Bauman89401822014-05-06 15:04:28 -04001962 {
1963 const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
1964 const SetupProcessor::State &state = draw.setupState;
1965 const DrawData &data = *draw.data;
1966
1967 Vertex &v = triangle.v0;
1968
1969 float pSize;
1970
1971 int pts = state.pointSizeRegister;
1972
Nicolas Capensec0936c2016-05-18 12:32:02 -04001973 if(state.pointSizeRegister != Unused)
John Bauman89401822014-05-06 15:04:28 -04001974 {
1975 pSize = v.v[pts].y;
1976 }
1977 else
1978 {
1979 pSize = data.point.pointSize[0];
1980 }
1981
1982 pSize = clamp(pSize, data.point.pointSizeMin, data.point.pointSizeMax);
1983
1984 float4 P[4];
1985 int C[4];
1986
1987 int pos = state.positionRegister;
1988
1989 P[0] = v.v[pos];
1990 P[1] = v.v[pos];
1991 P[2] = v.v[pos];
1992 P[3] = v.v[pos];
1993
John Bauman19bac1e2014-05-06 15:23:49 -04001994 const float X = pSize * P[0].w * data.halfPixelX[0];
1995 const float Y = pSize * P[0].w * data.halfPixelY[0];
John Bauman89401822014-05-06 15:04:28 -04001996
1997 P[0].x -= X;
John Bauman19bac1e2014-05-06 15:23:49 -04001998 P[0].y += Y;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04001999 C[0] = clipper->computeClipFlags(P[0]);
John Bauman89401822014-05-06 15:04:28 -04002000
2001 P[1].x += X;
John Bauman19bac1e2014-05-06 15:23:49 -04002002 P[1].y += Y;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04002003 C[1] = clipper->computeClipFlags(P[1]);
John Bauman89401822014-05-06 15:04:28 -04002004
2005 P[2].x += X;
John Bauman19bac1e2014-05-06 15:23:49 -04002006 P[2].y -= Y;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04002007 C[2] = clipper->computeClipFlags(P[2]);
John Bauman89401822014-05-06 15:04:28 -04002008
2009 P[3].x -= X;
John Bauman19bac1e2014-05-06 15:23:49 -04002010 P[3].y -= Y;
Nicolas Capens53bf0a12016-05-26 11:19:02 -04002011 C[3] = clipper->computeClipFlags(P[3]);
John Bauman89401822014-05-06 15:04:28 -04002012
2013 triangle.v1 = triangle.v0;
2014 triangle.v2 = triangle.v0;
2015
2016 triangle.v1.X += iround(16 * 0.5f * pSize);
John Bauman19bac1e2014-05-06 15:23:49 -04002017 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 -04002018
2019 Polygon polygon(P, 4);
2020
2021 if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
2022 {
2023 int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | draw.clipFlags;
2024
2025 if(clipFlagsOr != Clipper::CLIP_FINITE)
2026 {
Nicolas Capens734392e2016-05-26 11:07:40 -04002027 if(!clipper->clip(polygon, clipFlagsOr, draw))
John Bauman89401822014-05-06 15:04:28 -04002028 {
2029 return false;
2030 }
2031 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002032
John Bauman89401822014-05-06 15:04:28 -04002033 return setupRoutine(&primitive, &triangle, &polygon, &data);
2034 }
2035
2036 return false;
2037 }
2038
Nicolas Capens7381c992014-05-06 23:48:15 -04002039 void Renderer::initializeThreads()
John Bauman89401822014-05-06 15:04:28 -04002040 {
Nicolas Capens7381c992014-05-06 23:48:15 -04002041 unitCount = ceilPow2(threadCount);
2042 clusterCount = ceilPow2(threadCount);
John Bauman89401822014-05-06 15:04:28 -04002043
2044 for(int i = 0; i < unitCount; i++)
2045 {
2046 triangleBatch[i] = (Triangle*)allocate(batchSize * sizeof(Triangle));
2047 primitiveBatch[i] = (Primitive*)allocate(batchSize * sizeof(Primitive));
2048 }
2049
2050 for(int i = 0; i < threadCount; i++)
2051 {
2052 vertexTask[i] = (VertexTask*)allocate(sizeof(VertexTask));
2053 vertexTask[i]->vertexCache.drawCall = -1;
2054
2055 task[i].type = Task::SUSPEND;
2056
2057 resume[i] = new Event();
2058 suspend[i] = new Event();
2059
2060 Parameters parameters;
2061 parameters.threadIndex = i;
2062 parameters.renderer = this;
2063
2064 exitThreads = false;
2065 worker[i] = new Thread(threadFunction, &parameters);
2066
2067 suspend[i]->wait();
2068 suspend[i]->signal();
2069 }
2070 }
2071
2072 void Renderer::terminateThreads()
2073 {
2074 while(threadsAwake != 0)
2075 {
John Bauman19bac1e2014-05-06 15:23:49 -04002076 Thread::sleep(1);
John Bauman89401822014-05-06 15:04:28 -04002077 }
2078
2079 for(int thread = 0; thread < threadCount; thread++)
2080 {
2081 if(worker[thread])
2082 {
2083 exitThreads = true;
2084 resume[thread]->signal();
2085 worker[thread]->join();
Nicolas Capensec0936c2016-05-18 12:32:02 -04002086
John Bauman89401822014-05-06 15:04:28 -04002087 delete worker[thread];
2088 worker[thread] = 0;
2089 delete resume[thread];
2090 resume[thread] = 0;
2091 delete suspend[thread];
2092 suspend[thread] = 0;
2093 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002094
John Bauman89401822014-05-06 15:04:28 -04002095 deallocate(vertexTask[thread]);
2096 vertexTask[thread] = 0;
2097 }
John Bauman89401822014-05-06 15:04:28 -04002098
John Bauman89401822014-05-06 15:04:28 -04002099 for(int i = 0; i < 16; i++)
2100 {
2101 deallocate(triangleBatch[i]);
2102 triangleBatch[i] = 0;
2103
2104 deallocate(primitiveBatch[i]);
2105 primitiveBatch[i] = 0;
2106 }
2107 }
2108
2109 void Renderer::loadConstants(const VertexShader *vertexShader)
2110 {
2111 if(!vertexShader) return;
2112
Alexis Hetu8dcce862014-11-13 16:43:44 -05002113 size_t count = vertexShader->getLength();
John Bauman89401822014-05-06 15:04:28 -04002114
Alexis Hetu903e0252014-11-25 14:25:32 -05002115 for(size_t i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002116 {
John Bauman19bac1e2014-05-06 15:23:49 -04002117 const Shader::Instruction *instruction = vertexShader->getInstruction(i);
John Bauman89401822014-05-06 15:04:28 -04002118
John Bauman19bac1e2014-05-06 15:23:49 -04002119 if(instruction->opcode == Shader::OPCODE_DEF)
John Bauman89401822014-05-06 15:04:28 -04002120 {
John Bauman19bac1e2014-05-06 15:23:49 -04002121 int index = instruction->dst.index;
John Bauman89401822014-05-06 15:04:28 -04002122 float value[4];
2123
John Bauman19bac1e2014-05-06 15:23:49 -04002124 value[0] = instruction->src[0].value[0];
2125 value[1] = instruction->src[0].value[1];
2126 value[2] = instruction->src[0].value[2];
2127 value[3] = instruction->src[0].value[3];
John Bauman89401822014-05-06 15:04:28 -04002128
2129 setVertexShaderConstantF(index, value);
2130 }
John Bauman19bac1e2014-05-06 15:23:49 -04002131 else if(instruction->opcode == Shader::OPCODE_DEFI)
John Bauman89401822014-05-06 15:04:28 -04002132 {
John Bauman19bac1e2014-05-06 15:23:49 -04002133 int index = instruction->dst.index;
John Bauman89401822014-05-06 15:04:28 -04002134 int integer[4];
2135
John Bauman19bac1e2014-05-06 15:23:49 -04002136 integer[0] = instruction->src[0].integer[0];
2137 integer[1] = instruction->src[0].integer[1];
2138 integer[2] = instruction->src[0].integer[2];
2139 integer[3] = instruction->src[0].integer[3];
John Bauman89401822014-05-06 15:04:28 -04002140
2141 setVertexShaderConstantI(index, integer);
2142 }
John Bauman19bac1e2014-05-06 15:23:49 -04002143 else if(instruction->opcode == Shader::OPCODE_DEFB)
John Bauman89401822014-05-06 15:04:28 -04002144 {
John Bauman19bac1e2014-05-06 15:23:49 -04002145 int index = instruction->dst.index;
2146 int boolean = instruction->src[0].boolean[0];
John Bauman89401822014-05-06 15:04:28 -04002147
2148 setVertexShaderConstantB(index, &boolean);
2149 }
2150 }
2151 }
2152
2153 void Renderer::loadConstants(const PixelShader *pixelShader)
2154 {
2155 if(!pixelShader) return;
2156
Alexis Hetu8dcce862014-11-13 16:43:44 -05002157 size_t count = pixelShader->getLength();
John Bauman89401822014-05-06 15:04:28 -04002158
Alexis Hetu903e0252014-11-25 14:25:32 -05002159 for(size_t i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002160 {
John Bauman19bac1e2014-05-06 15:23:49 -04002161 const Shader::Instruction *instruction = pixelShader->getInstruction(i);
John Bauman89401822014-05-06 15:04:28 -04002162
John Bauman19bac1e2014-05-06 15:23:49 -04002163 if(instruction->opcode == Shader::OPCODE_DEF)
John Bauman89401822014-05-06 15:04:28 -04002164 {
John Bauman19bac1e2014-05-06 15:23:49 -04002165 int index = instruction->dst.index;
John Bauman89401822014-05-06 15:04:28 -04002166 float value[4];
2167
John Bauman19bac1e2014-05-06 15:23:49 -04002168 value[0] = instruction->src[0].value[0];
2169 value[1] = instruction->src[0].value[1];
2170 value[2] = instruction->src[0].value[2];
2171 value[3] = instruction->src[0].value[3];
John Bauman89401822014-05-06 15:04:28 -04002172
2173 setPixelShaderConstantF(index, value);
2174 }
John Bauman19bac1e2014-05-06 15:23:49 -04002175 else if(instruction->opcode == Shader::OPCODE_DEFI)
John Bauman89401822014-05-06 15:04:28 -04002176 {
John Bauman19bac1e2014-05-06 15:23:49 -04002177 int index = instruction->dst.index;
John Bauman89401822014-05-06 15:04:28 -04002178 int integer[4];
2179
John Bauman19bac1e2014-05-06 15:23:49 -04002180 integer[0] = instruction->src[0].integer[0];
2181 integer[1] = instruction->src[0].integer[1];
2182 integer[2] = instruction->src[0].integer[2];
2183 integer[3] = instruction->src[0].integer[3];
John Bauman89401822014-05-06 15:04:28 -04002184
2185 setPixelShaderConstantI(index, integer);
2186 }
John Bauman19bac1e2014-05-06 15:23:49 -04002187 else if(instruction->opcode == Shader::OPCODE_DEFB)
John Bauman89401822014-05-06 15:04:28 -04002188 {
John Bauman19bac1e2014-05-06 15:23:49 -04002189 int index = instruction->dst.index;
2190 int boolean = instruction->src[0].boolean[0];
John Bauman89401822014-05-06 15:04:28 -04002191
2192 setPixelShaderConstantB(index, &boolean);
2193 }
2194 }
2195 }
2196
2197 void Renderer::setIndexBuffer(Resource *indexBuffer)
2198 {
2199 context->indexBuffer = indexBuffer;
2200 }
2201
2202 void Renderer::setMultiSampleMask(unsigned int mask)
2203 {
2204 context->sampleMask = mask;
2205 }
2206
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002207 void Renderer::setTransparencyAntialiasing(TransparencyAntialiasing transparencyAntialiasing)
John Bauman89401822014-05-06 15:04:28 -04002208 {
2209 sw::transparencyAntialiasing = transparencyAntialiasing;
2210 }
2211
2212 bool Renderer::isReadWriteTexture(int sampler)
2213 {
Alexis Hetu1edcd8b2015-11-05 11:12:41 -05002214 for(int index = 0; index < RENDERTARGETS; index++)
John Bauman89401822014-05-06 15:04:28 -04002215 {
2216 if(context->renderTarget[index] && context->texture[sampler] == context->renderTarget[index]->getResource())
2217 {
2218 return true;
2219 }
2220 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002221
Nicolas Capens3751c1e2016-03-21 14:14:14 -04002222 if(context->depthBuffer && context->texture[sampler] == context->depthBuffer->getResource())
John Bauman89401822014-05-06 15:04:28 -04002223 {
2224 return true;
2225 }
2226
2227 return false;
2228 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002229
John Bauman89401822014-05-06 15:04:28 -04002230 void Renderer::updateClipper()
2231 {
2232 if(updateClipPlanes)
2233 {
John Bauman89401822014-05-06 15:04:28 -04002234 if(VertexProcessor::isFixedFunction()) // User plane in world space
2235 {
John Bauman19bac1e2014-05-06 15:23:49 -04002236 const Matrix &scissorWorld = getViewTransform();
John Bauman89401822014-05-06 15:04:28 -04002237
2238 if(clipFlags & Clipper::CLIP_PLANE0) clipPlane[0] = scissorWorld * userPlane[0];
2239 if(clipFlags & Clipper::CLIP_PLANE1) clipPlane[1] = scissorWorld * userPlane[1];
2240 if(clipFlags & Clipper::CLIP_PLANE2) clipPlane[2] = scissorWorld * userPlane[2];
2241 if(clipFlags & Clipper::CLIP_PLANE3) clipPlane[3] = scissorWorld * userPlane[3];
2242 if(clipFlags & Clipper::CLIP_PLANE4) clipPlane[4] = scissorWorld * userPlane[4];
2243 if(clipFlags & Clipper::CLIP_PLANE5) clipPlane[5] = scissorWorld * userPlane[5];
2244 }
2245 else // User plane in clip space
2246 {
John Bauman19bac1e2014-05-06 15:23:49 -04002247 if(clipFlags & Clipper::CLIP_PLANE0) clipPlane[0] = userPlane[0];
2248 if(clipFlags & Clipper::CLIP_PLANE1) clipPlane[1] = userPlane[1];
2249 if(clipFlags & Clipper::CLIP_PLANE2) clipPlane[2] = userPlane[2];
2250 if(clipFlags & Clipper::CLIP_PLANE3) clipPlane[3] = userPlane[3];
2251 if(clipFlags & Clipper::CLIP_PLANE4) clipPlane[4] = userPlane[4];
2252 if(clipFlags & Clipper::CLIP_PLANE5) clipPlane[5] = userPlane[5];
John Bauman89401822014-05-06 15:04:28 -04002253 }
2254
2255 updateClipPlanes = false;
2256 }
2257 }
2258
2259 void Renderer::setTextureResource(unsigned int sampler, Resource *resource)
2260 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -04002261 ASSERT(sampler < TOTAL_IMAGE_UNITS);
John Bauman89401822014-05-06 15:04:28 -04002262
2263 context->texture[sampler] = resource;
2264 }
2265
2266 void Renderer::setTextureLevel(unsigned int sampler, unsigned int face, unsigned int level, Surface *surface, TextureType type)
2267 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -04002268 ASSERT(sampler < TOTAL_IMAGE_UNITS && face < 6 && level < MIPMAP_LEVELS);
Nicolas Capensec0936c2016-05-18 12:32:02 -04002269
John Bauman89401822014-05-06 15:04:28 -04002270 context->sampler[sampler].setTextureLevel(face, level, surface, type);
2271 }
2272
2273 void Renderer::setTextureFilter(SamplerType type, int sampler, FilterType textureFilter)
2274 {
2275 if(type == SAMPLER_PIXEL)
2276 {
2277 PixelProcessor::setTextureFilter(sampler, textureFilter);
2278 }
2279 else
2280 {
2281 VertexProcessor::setTextureFilter(sampler, textureFilter);
2282 }
2283 }
2284
2285 void Renderer::setMipmapFilter(SamplerType type, int sampler, MipmapType mipmapFilter)
2286 {
2287 if(type == SAMPLER_PIXEL)
2288 {
2289 PixelProcessor::setMipmapFilter(sampler, mipmapFilter);
2290 }
2291 else
2292 {
2293 VertexProcessor::setMipmapFilter(sampler, mipmapFilter);
2294 }
2295 }
2296
2297 void Renderer::setGatherEnable(SamplerType type, int sampler, bool enable)
2298 {
2299 if(type == SAMPLER_PIXEL)
2300 {
2301 PixelProcessor::setGatherEnable(sampler, enable);
2302 }
2303 else
2304 {
2305 VertexProcessor::setGatherEnable(sampler, enable);
2306 }
2307 }
2308
2309 void Renderer::setAddressingModeU(SamplerType type, int sampler, AddressingMode addressMode)
2310 {
2311 if(type == SAMPLER_PIXEL)
2312 {
2313 PixelProcessor::setAddressingModeU(sampler, addressMode);
2314 }
2315 else
2316 {
2317 VertexProcessor::setAddressingModeU(sampler, addressMode);
2318 }
2319 }
2320
2321 void Renderer::setAddressingModeV(SamplerType type, int sampler, AddressingMode addressMode)
2322 {
2323 if(type == SAMPLER_PIXEL)
2324 {
2325 PixelProcessor::setAddressingModeV(sampler, addressMode);
2326 }
2327 else
2328 {
2329 VertexProcessor::setAddressingModeV(sampler, addressMode);
2330 }
2331 }
2332
2333 void Renderer::setAddressingModeW(SamplerType type, int sampler, AddressingMode addressMode)
2334 {
2335 if(type == SAMPLER_PIXEL)
2336 {
2337 PixelProcessor::setAddressingModeW(sampler, addressMode);
2338 }
2339 else
2340 {
2341 VertexProcessor::setAddressingModeW(sampler, addressMode);
2342 }
2343 }
2344
2345 void Renderer::setReadSRGB(SamplerType type, int sampler, bool sRGB)
2346 {
2347 if(type == SAMPLER_PIXEL)
2348 {
2349 PixelProcessor::setReadSRGB(sampler, sRGB);
2350 }
2351 else
2352 {
2353 VertexProcessor::setReadSRGB(sampler, sRGB);
2354 }
2355 }
2356
2357 void Renderer::setMipmapLOD(SamplerType type, int sampler, float bias)
2358 {
2359 if(type == SAMPLER_PIXEL)
2360 {
2361 PixelProcessor::setMipmapLOD(sampler, bias);
2362 }
2363 else
2364 {
2365 VertexProcessor::setMipmapLOD(sampler, bias);
2366 }
2367 }
2368
2369 void Renderer::setBorderColor(SamplerType type, int sampler, const Color<float> &borderColor)
2370 {
2371 if(type == SAMPLER_PIXEL)
2372 {
2373 PixelProcessor::setBorderColor(sampler, borderColor);
2374 }
2375 else
2376 {
2377 VertexProcessor::setBorderColor(sampler, borderColor);
2378 }
2379 }
2380
Alexis Hetu617a5d52014-11-13 10:56:20 -05002381 void Renderer::setMaxAnisotropy(SamplerType type, int sampler, float maxAnisotropy)
John Bauman89401822014-05-06 15:04:28 -04002382 {
2383 if(type == SAMPLER_PIXEL)
2384 {
2385 PixelProcessor::setMaxAnisotropy(sampler, maxAnisotropy);
2386 }
2387 else
2388 {
2389 VertexProcessor::setMaxAnisotropy(sampler, maxAnisotropy);
2390 }
2391 }
2392
Alexis Hetu010a4642017-07-18 14:33:04 -04002393 void Renderer::setHighPrecisionFiltering(SamplerType type, int sampler, bool highPrecisionFiltering)
2394 {
2395 if(type == SAMPLER_PIXEL)
2396 {
2397 PixelProcessor::setHighPrecisionFiltering(sampler, highPrecisionFiltering);
2398 }
2399 else
2400 {
2401 VertexProcessor::setHighPrecisionFiltering(sampler, highPrecisionFiltering);
2402 }
2403 }
2404
Alexis Hetu1d01aa32015-09-29 11:50:05 -04002405 void Renderer::setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR)
2406 {
2407 if(type == SAMPLER_PIXEL)
2408 {
2409 PixelProcessor::setSwizzleR(sampler, swizzleR);
2410 }
2411 else
2412 {
2413 VertexProcessor::setSwizzleR(sampler, swizzleR);
2414 }
2415 }
2416
2417 void Renderer::setSwizzleG(SamplerType type, int sampler, SwizzleType swizzleG)
2418 {
2419 if(type == SAMPLER_PIXEL)
2420 {
2421 PixelProcessor::setSwizzleG(sampler, swizzleG);
2422 }
2423 else
2424 {
2425 VertexProcessor::setSwizzleG(sampler, swizzleG);
2426 }
2427 }
2428
2429 void Renderer::setSwizzleB(SamplerType type, int sampler, SwizzleType swizzleB)
2430 {
2431 if(type == SAMPLER_PIXEL)
2432 {
2433 PixelProcessor::setSwizzleB(sampler, swizzleB);
2434 }
2435 else
2436 {
2437 VertexProcessor::setSwizzleB(sampler, swizzleB);
2438 }
2439 }
2440
2441 void Renderer::setSwizzleA(SamplerType type, int sampler, SwizzleType swizzleA)
2442 {
2443 if(type == SAMPLER_PIXEL)
2444 {
2445 PixelProcessor::setSwizzleA(sampler, swizzleA);
2446 }
2447 else
2448 {
2449 VertexProcessor::setSwizzleA(sampler, swizzleA);
2450 }
2451 }
2452
Nicolas Capensf878d502017-11-06 15:29:46 -05002453 void Renderer::setCompareFunc(SamplerType type, int sampler, CompareFunc compFunc)
2454 {
2455 if(type == SAMPLER_PIXEL)
2456 {
2457 PixelProcessor::setCompareFunc(sampler, compFunc);
2458 }
2459 else
2460 {
2461 VertexProcessor::setCompareFunc(sampler, compFunc);
2462 }
2463 }
2464
Alexis Hetu95ac1872016-06-06 13:26:52 -04002465 void Renderer::setBaseLevel(SamplerType type, int sampler, int baseLevel)
2466 {
2467 if(type == SAMPLER_PIXEL)
2468 {
2469 PixelProcessor::setBaseLevel(sampler, baseLevel);
2470 }
2471 else
2472 {
2473 VertexProcessor::setBaseLevel(sampler, baseLevel);
2474 }
2475 }
2476
2477 void Renderer::setMaxLevel(SamplerType type, int sampler, int maxLevel)
2478 {
2479 if(type == SAMPLER_PIXEL)
2480 {
2481 PixelProcessor::setMaxLevel(sampler, maxLevel);
2482 }
2483 else
2484 {
2485 VertexProcessor::setMaxLevel(sampler, maxLevel);
2486 }
2487 }
2488
Alexis Hetu112d81f2016-06-07 12:36:35 -04002489 void Renderer::setMinLod(SamplerType type, int sampler, float minLod)
2490 {
2491 if(type == SAMPLER_PIXEL)
2492 {
2493 PixelProcessor::setMinLod(sampler, minLod);
2494 }
2495 else
2496 {
2497 VertexProcessor::setMinLod(sampler, minLod);
2498 }
2499 }
2500
2501 void Renderer::setMaxLod(SamplerType type, int sampler, float maxLod)
2502 {
2503 if(type == SAMPLER_PIXEL)
2504 {
2505 PixelProcessor::setMaxLod(sampler, maxLod);
2506 }
2507 else
2508 {
2509 VertexProcessor::setMaxLod(sampler, maxLod);
2510 }
2511 }
2512
Alexis Hetu88482c32018-06-05 17:05:17 -04002513 void Renderer::setSyncRequired(SamplerType type, int sampler, bool syncRequired)
2514 {
2515 if(type == SAMPLER_PIXEL)
2516 {
2517 PixelProcessor::setSyncRequired(sampler, syncRequired);
2518 }
2519 else
2520 {
2521 VertexProcessor::setSyncRequired(sampler, syncRequired);
2522 }
2523 }
2524
John Bauman89401822014-05-06 15:04:28 -04002525 void Renderer::setPointSpriteEnable(bool pointSpriteEnable)
2526 {
2527 context->setPointSpriteEnable(pointSpriteEnable);
2528 }
2529
2530 void Renderer::setPointScaleEnable(bool pointScaleEnable)
2531 {
2532 context->setPointScaleEnable(pointScaleEnable);
2533 }
2534
Nicolas Capens235781d2015-01-27 01:46:53 -05002535 void Renderer::setLineWidth(float width)
2536 {
2537 context->lineWidth = width;
2538 }
2539
John Bauman89401822014-05-06 15:04:28 -04002540 void Renderer::setDepthBias(float bias)
2541 {
Nicolas Capens3cbeac52017-09-15 11:49:31 -04002542 context->depthBias = bias;
John Bauman89401822014-05-06 15:04:28 -04002543 }
2544
2545 void Renderer::setSlopeDepthBias(float slopeBias)
2546 {
Nicolas Capens3cbeac52017-09-15 11:49:31 -04002547 context->slopeDepthBias = slopeBias;
John Bauman89401822014-05-06 15:04:28 -04002548 }
2549
Alexis Hetub0f247f2016-02-22 11:42:39 -05002550 void Renderer::setRasterizerDiscard(bool rasterizerDiscard)
2551 {
2552 context->rasterizerDiscard = rasterizerDiscard;
2553 }
2554
John Bauman89401822014-05-06 15:04:28 -04002555 void Renderer::setPixelShader(const PixelShader *shader)
2556 {
2557 context->pixelShader = shader;
2558
2559 loadConstants(shader);
2560 }
2561
2562 void Renderer::setVertexShader(const VertexShader *shader)
2563 {
2564 context->vertexShader = shader;
2565
2566 loadConstants(shader);
2567 }
2568
Alexis Hetub59a58e2016-06-02 11:50:47 -04002569 void Renderer::setPixelShaderConstantF(unsigned int index, const float value[4], unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002570 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002571 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002572 {
2573 if(drawCall[i]->psDirtyConstF < index + count)
2574 {
2575 drawCall[i]->psDirtyConstF = index + count;
2576 }
2577 }
2578
Alexis Hetub59a58e2016-06-02 11:50:47 -04002579 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002580 {
2581 PixelProcessor::setFloatConstant(index + i, value);
2582 value += 4;
2583 }
2584 }
2585
Alexis Hetub59a58e2016-06-02 11:50:47 -04002586 void Renderer::setPixelShaderConstantI(unsigned int index, const int value[4], unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002587 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002588 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002589 {
2590 if(drawCall[i]->psDirtyConstI < index + count)
2591 {
2592 drawCall[i]->psDirtyConstI = index + count;
2593 }
2594 }
2595
Alexis Hetub59a58e2016-06-02 11:50:47 -04002596 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002597 {
2598 PixelProcessor::setIntegerConstant(index + i, value);
2599 value += 4;
2600 }
2601 }
2602
Alexis Hetub59a58e2016-06-02 11:50:47 -04002603 void Renderer::setPixelShaderConstantB(unsigned int index, const int *boolean, unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002604 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002605 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002606 {
2607 if(drawCall[i]->psDirtyConstB < index + count)
2608 {
2609 drawCall[i]->psDirtyConstB = index + count;
2610 }
2611 }
2612
Alexis Hetub59a58e2016-06-02 11:50:47 -04002613 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002614 {
2615 PixelProcessor::setBooleanConstant(index + i, *boolean);
2616 boolean++;
2617 }
2618 }
2619
Alexis Hetub59a58e2016-06-02 11:50:47 -04002620 void Renderer::setVertexShaderConstantF(unsigned int index, const float value[4], unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002621 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002622 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002623 {
2624 if(drawCall[i]->vsDirtyConstF < index + count)
2625 {
2626 drawCall[i]->vsDirtyConstF = index + count;
2627 }
2628 }
2629
Alexis Hetub59a58e2016-06-02 11:50:47 -04002630 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002631 {
2632 VertexProcessor::setFloatConstant(index + i, value);
2633 value += 4;
2634 }
2635 }
2636
Alexis Hetub59a58e2016-06-02 11:50:47 -04002637 void Renderer::setVertexShaderConstantI(unsigned int index, const int value[4], unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002638 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002639 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002640 {
2641 if(drawCall[i]->vsDirtyConstI < index + count)
2642 {
2643 drawCall[i]->vsDirtyConstI = index + count;
2644 }
2645 }
2646
Alexis Hetub59a58e2016-06-02 11:50:47 -04002647 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002648 {
2649 VertexProcessor::setIntegerConstant(index + i, value);
2650 value += 4;
2651 }
2652 }
2653
Alexis Hetub59a58e2016-06-02 11:50:47 -04002654 void Renderer::setVertexShaderConstantB(unsigned int index, const int *boolean, unsigned int count)
John Bauman89401822014-05-06 15:04:28 -04002655 {
Alexis Hetub59a58e2016-06-02 11:50:47 -04002656 for(unsigned int i = 0; i < DRAW_COUNT; i++)
John Bauman89401822014-05-06 15:04:28 -04002657 {
2658 if(drawCall[i]->vsDirtyConstB < index + count)
2659 {
2660 drawCall[i]->vsDirtyConstB = index + count;
2661 }
2662 }
2663
Alexis Hetub59a58e2016-06-02 11:50:47 -04002664 for(unsigned int i = 0; i < count; i++)
John Bauman89401822014-05-06 15:04:28 -04002665 {
2666 VertexProcessor::setBooleanConstant(index + i, *boolean);
2667 boolean++;
2668 }
2669 }
2670
2671 void Renderer::setModelMatrix(const Matrix &M, int i)
2672 {
2673 VertexProcessor::setModelMatrix(M, i);
2674 }
2675
2676 void Renderer::setViewMatrix(const Matrix &V)
2677 {
2678 VertexProcessor::setViewMatrix(V);
2679 updateClipPlanes = true;
2680 }
2681
2682 void Renderer::setBaseMatrix(const Matrix &B)
2683 {
2684 VertexProcessor::setBaseMatrix(B);
2685 updateClipPlanes = true;
2686 }
2687
2688 void Renderer::setProjectionMatrix(const Matrix &P)
2689 {
2690 VertexProcessor::setProjectionMatrix(P);
2691 updateClipPlanes = true;
2692 }
2693
John Bauman89401822014-05-06 15:04:28 -04002694 void Renderer::addQuery(Query *query)
2695 {
2696 queries.push_back(query);
2697 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002698
John Bauman89401822014-05-06 15:04:28 -04002699 void Renderer::removeQuery(Query *query)
2700 {
2701 queries.remove(query);
2702 }
2703
2704 #if PERF_HUD
2705 int Renderer::getThreadCount()
2706 {
2707 return threadCount;
2708 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002709
John Bauman89401822014-05-06 15:04:28 -04002710 int64_t Renderer::getVertexTime(int thread)
2711 {
2712 return vertexTime[thread];
2713 }
2714
2715 int64_t Renderer::getSetupTime(int thread)
2716 {
2717 return setupTime[thread];
2718 }
Nicolas Capensec0936c2016-05-18 12:32:02 -04002719
John Bauman89401822014-05-06 15:04:28 -04002720 int64_t Renderer::getPixelTime(int thread)
2721 {
2722 return pixelTime[thread];
2723 }
2724
2725 void Renderer::resetTimers()
2726 {
2727 for(int thread = 0; thread < threadCount; thread++)
2728 {
2729 vertexTime[thread] = 0;
2730 setupTime[thread] = 0;
2731 pixelTime[thread] = 0;
2732 }
2733 }
2734 #endif
2735
2736 void Renderer::setViewport(const Viewport &viewport)
2737 {
2738 this->viewport = viewport;
2739 }
2740
John Bauman19bac1e2014-05-06 15:23:49 -04002741 void Renderer::setScissor(const Rect &scissor)
2742 {
2743 this->scissor = scissor;
2744 }
2745
John Bauman89401822014-05-06 15:04:28 -04002746 void Renderer::setClipFlags(int flags)
2747 {
2748 clipFlags = flags << 8; // Bottom 8 bits used by legacy frustum
2749 }
2750
2751 void Renderer::setClipPlane(unsigned int index, const float plane[4])
2752 {
Nicolas Capensd2264142015-07-02 17:06:53 -04002753 if(index < MAX_CLIP_PLANES)
John Bauman89401822014-05-06 15:04:28 -04002754 {
2755 userPlane[index] = plane;
2756 }
2757 else ASSERT(false);
2758
2759 updateClipPlanes = true;
2760 }
2761
2762 void Renderer::updateConfiguration(bool initialUpdate)
2763 {
2764 bool newConfiguration = swiftConfig->hasNewConfiguration();
2765
2766 if(newConfiguration || initialUpdate)
2767 {
2768 terminateThreads();
2769
Nicolas Capensc4748c52016-01-01 01:21:18 -05002770 SwiftConfig::Configuration configuration = {};
John Bauman89401822014-05-06 15:04:28 -04002771 swiftConfig->getConfiguration(configuration);
2772
John Bauman66b8ab22014-05-06 15:57:45 -04002773 precacheVertex = !newConfiguration && configuration.precache;
2774 precacheSetup = !newConfiguration && configuration.precache;
2775 precachePixel = !newConfiguration && configuration.precache;
2776
John Bauman89401822014-05-06 15:04:28 -04002777 VertexProcessor::setRoutineCacheSize(configuration.vertexRoutineCacheSize);
2778 PixelProcessor::setRoutineCacheSize(configuration.pixelRoutineCacheSize);
2779 SetupProcessor::setRoutineCacheSize(configuration.setupRoutineCacheSize);
2780
2781 switch(configuration.textureSampleQuality)
2782 {
Nicolas Capens7381c992014-05-06 23:48:15 -04002783 case 0: Sampler::setFilterQuality(FILTER_POINT); break;
2784 case 1: Sampler::setFilterQuality(FILTER_LINEAR); break;
2785 case 2: Sampler::setFilterQuality(FILTER_ANISOTROPIC); break;
2786 default: Sampler::setFilterQuality(FILTER_ANISOTROPIC); break;
John Bauman89401822014-05-06 15:04:28 -04002787 }
2788
2789 switch(configuration.mipmapQuality)
2790 {
2791 case 0: Sampler::setMipmapQuality(MIPMAP_POINT); break;
2792 case 1: Sampler::setMipmapQuality(MIPMAP_LINEAR); break;
Nicolas Capens7381c992014-05-06 23:48:15 -04002793 default: Sampler::setMipmapQuality(MIPMAP_LINEAR); break;
John Bauman89401822014-05-06 15:04:28 -04002794 }
2795
2796 setPerspectiveCorrection(configuration.perspectiveCorrection);
2797
2798 switch(configuration.transcendentalPrecision)
2799 {
2800 case 0:
2801 logPrecision = APPROXIMATE;
2802 expPrecision = APPROXIMATE;
2803 rcpPrecision = APPROXIMATE;
2804 rsqPrecision = APPROXIMATE;
2805 break;
2806 case 1:
2807 logPrecision = PARTIAL;
2808 expPrecision = PARTIAL;
2809 rcpPrecision = PARTIAL;
2810 rsqPrecision = PARTIAL;
2811 break;
2812 case 2:
2813 logPrecision = ACCURATE;
2814 expPrecision = ACCURATE;
2815 rcpPrecision = ACCURATE;
2816 rsqPrecision = ACCURATE;
2817 break;
2818 case 3:
2819 logPrecision = WHQL;
2820 expPrecision = WHQL;
2821 rcpPrecision = WHQL;
2822 rsqPrecision = WHQL;
2823 break;
2824 case 4:
2825 logPrecision = IEEE;
2826 expPrecision = IEEE;
2827 rcpPrecision = IEEE;
2828 rsqPrecision = IEEE;
2829 break;
2830 default:
2831 logPrecision = ACCURATE;
2832 expPrecision = ACCURATE;
2833 rcpPrecision = ACCURATE;
2834 rsqPrecision = ACCURATE;
2835 break;
2836 }
2837
2838 switch(configuration.transparencyAntialiasing)
2839 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002840 case 0: transparencyAntialiasing = TRANSPARENCY_NONE; break;
2841 case 1: transparencyAntialiasing = TRANSPARENCY_ALPHA_TO_COVERAGE; break;
2842 default: transparencyAntialiasing = TRANSPARENCY_NONE; break;
John Bauman89401822014-05-06 15:04:28 -04002843 }
2844
2845 switch(configuration.threadCount)
2846 {
Nicolas Capens7381c992014-05-06 23:48:15 -04002847 case -1: threadCount = CPUID::coreCount(); break;
2848 case 0: threadCount = CPUID::processAffinity(); break;
2849 default: threadCount = configuration.threadCount; break;
John Bauman89401822014-05-06 15:04:28 -04002850 }
2851
2852 CPUID::setEnableSSE4_1(configuration.enableSSE4_1);
2853 CPUID::setEnableSSSE3(configuration.enableSSSE3);
2854 CPUID::setEnableSSE3(configuration.enableSSE3);
2855 CPUID::setEnableSSE2(configuration.enableSSE2);
2856 CPUID::setEnableSSE(configuration.enableSSE);
2857
2858 for(int pass = 0; pass < 10; pass++)
2859 {
2860 optimization[pass] = configuration.optimization[pass];
2861 }
2862
2863 forceWindowed = configuration.forceWindowed;
2864 complementaryDepthBuffer = configuration.complementaryDepthBuffer;
2865 postBlendSRGB = configuration.postBlendSRGB;
2866 exactColorRounding = configuration.exactColorRounding;
2867 forceClearRegisters = configuration.forceClearRegisters;
2868
2869 #ifndef NDEBUG
2870 minPrimitives = configuration.minPrimitives;
2871 maxPrimitives = configuration.maxPrimitives;
2872 #endif
2873 }
Nicolas Capens7381c992014-05-06 23:48:15 -04002874
2875 if(!initialUpdate && !worker[0])
2876 {
2877 initializeThreads();
2878 }
John Bauman89401822014-05-06 15:04:28 -04002879 }
John Bauman89401822014-05-06 15:04:28 -04002880}