blob: 825c09f10b9d3b1ccee565fa428da7de3f27b601 [file] [log] [blame]
Nicolas Capens68a82382018-10-02 13:16:55 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "Renderer.hpp"
16
17#include "Clipper.hpp"
Nicolas Capens68a82382018-10-02 13:16:55 -040018#include "Polygon.hpp"
Ben Claytonfccfc562019-12-17 20:37:31 +000019#include "Primitive.hpp"
20#include "Vertex.hpp"
Nicolas Capens1d8c8db2018-11-05 16:30:42 -050021#include "Pipeline/Constants.hpp"
Ben Claytonfccfc562019-12-17 20:37:31 +000022#include "Pipeline/SpirvShader.hpp"
23#include "Reactor/Reactor.hpp"
Ben Clayton25e06e02020-02-07 11:19:08 +000024#include "System/Debug.hpp"
Nicolas Capens1d8c8db2018-11-05 16:30:42 -050025#include "System/Half.hpp"
26#include "System/Math.hpp"
Ben Claytonfccfc562019-12-17 20:37:31 +000027#include "System/Memory.hpp"
Nicolas Capens1d8c8db2018-11-05 16:30:42 -050028#include "System/Timer.hpp"
Antonio Maiorano42fd1592020-04-27 11:30:40 -040029#include "Vulkan/VkConfig.hpp"
Alexis Hetu4f438a52020-06-15 16:13:51 -040030#include "Vulkan/VkDescriptorSet.hpp"
Alexis Hetu35755502019-07-22 13:51:49 -040031#include "Vulkan/VkDevice.hpp"
Alexis Hetue1f51b92019-04-23 15:34:34 -040032#include "Vulkan/VkFence.hpp"
Alexis Hetu6159a852019-02-26 14:42:36 -050033#include "Vulkan/VkImageView.hpp"
Alexis Hetu4f438a52020-06-15 16:13:51 -040034#include "Vulkan/VkPipelineLayout.hpp"
Alexis Hetuf0aa9d52019-04-01 17:06:47 -040035#include "Vulkan/VkQueryPool.hpp"
Nicolas Capens68a82382018-10-02 13:16:55 -040036
Ben Claytone693b622019-09-05 12:48:37 +010037#include "marl/containers.h"
38#include "marl/defer.h"
39#include "marl/trace.h"
Ben Claytoncde4dd92019-08-27 13:15:50 +010040
Nicolas Capens68a82382018-10-02 13:16:55 -040041#undef max
42
Nicolas Capens68a82382018-10-02 13:16:55 -040043#ifndef NDEBUG
44unsigned int minPrimitives = 1;
45unsigned int maxPrimitives = 1 << 21;
46#endif
47
Nicolas Capens157ba262019-12-10 17:49:14 -050048namespace sw {
49
50template<typename T>
51inline bool setBatchIndices(unsigned int batch[128][3], VkPrimitiveTopology topology, VkProvokingVertexModeEXT provokingVertexMode, T indices, unsigned int start, unsigned int triangleCount)
Nicolas Capens68a82382018-10-02 13:16:55 -040052{
Nicolas Capens157ba262019-12-10 17:49:14 -050053 bool provokeFirst = (provokingVertexMode == VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT);
54
55 switch(topology)
Alexis Hetufcbb1452018-11-22 15:46:28 -050056 {
Ben Claytonfccfc562019-12-17 20:37:31 +000057 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
Alexis Hetufcbb1452018-11-22 15:46:28 -050058 {
Ben Claytonfccfc562019-12-17 20:37:31 +000059 auto index = start;
60 auto pointBatch = &(batch[0][0]);
61 for(unsigned int i = 0; i < triangleCount; i++)
62 {
63 *pointBatch++ = indices[index++];
64 }
Alexis Hetufcbb1452018-11-22 15:46:28 -050065
Ben Claytonfccfc562019-12-17 20:37:31 +000066 // Repeat the last index to allow for SIMD width overrun.
67 index--;
68 for(unsigned int i = 0; i < 3; i++)
69 {
70 *pointBatch++ = indices[index];
71 }
72 break;
Nicolas Capens157ba262019-12-10 17:49:14 -050073 }
Ben Claytonfccfc562019-12-17 20:37:31 +000074 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
Nicolas Capens157ba262019-12-10 17:49:14 -050075 {
Ben Claytonfccfc562019-12-17 20:37:31 +000076 auto index = 2 * start;
77 for(unsigned int i = 0; i < triangleCount; i++)
78 {
79 batch[i][0] = indices[index + (provokeFirst ? 0 : 1)];
80 batch[i][1] = indices[index + (provokeFirst ? 1 : 0)];
81 batch[i][2] = indices[index + 1];
Nicolas Capens157ba262019-12-10 17:49:14 -050082
Ben Claytonfccfc562019-12-17 20:37:31 +000083 index += 2;
84 }
85 break;
Nicolas Capens157ba262019-12-10 17:49:14 -050086 }
Ben Claytonfccfc562019-12-17 20:37:31 +000087 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
Nicolas Capens157ba262019-12-10 17:49:14 -050088 {
Ben Claytonfccfc562019-12-17 20:37:31 +000089 auto index = start;
90 for(unsigned int i = 0; i < triangleCount; i++)
91 {
92 batch[i][0] = indices[index + (provokeFirst ? 0 : 1)];
93 batch[i][1] = indices[index + (provokeFirst ? 1 : 0)];
94 batch[i][2] = indices[index + 1];
Nicolas Capens157ba262019-12-10 17:49:14 -050095
Ben Claytonfccfc562019-12-17 20:37:31 +000096 index += 1;
97 }
98 break;
Nicolas Capens157ba262019-12-10 17:49:14 -050099 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000100 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
Nicolas Capens157ba262019-12-10 17:49:14 -0500101 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000102 auto index = 3 * start;
103 for(unsigned int i = 0; i < triangleCount; i++)
104 {
105 batch[i][0] = indices[index + (provokeFirst ? 0 : 2)];
106 batch[i][1] = indices[index + (provokeFirst ? 1 : 0)];
107 batch[i][2] = indices[index + (provokeFirst ? 2 : 1)];
Nicolas Capens157ba262019-12-10 17:49:14 -0500108
Ben Claytonfccfc562019-12-17 20:37:31 +0000109 index += 3;
110 }
111 break;
Nicolas Capens157ba262019-12-10 17:49:14 -0500112 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000113 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
Nicolas Capens157ba262019-12-10 17:49:14 -0500114 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000115 auto index = start;
116 for(unsigned int i = 0; i < triangleCount; i++)
117 {
118 batch[i][0] = indices[index + (provokeFirst ? 0 : 2)];
119 batch[i][1] = indices[index + ((start + i) & 1) + (provokeFirst ? 1 : 0)];
120 batch[i][2] = indices[index + (~(start + i) & 1) + (provokeFirst ? 1 : 0)];
Nicolas Capens157ba262019-12-10 17:49:14 -0500121
Ben Claytonfccfc562019-12-17 20:37:31 +0000122 index += 1;
123 }
124 break;
Nicolas Capens157ba262019-12-10 17:49:14 -0500125 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000126 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
Nicolas Capens157ba262019-12-10 17:49:14 -0500127 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000128 auto index = start + 1;
129 for(unsigned int i = 0; i < triangleCount; i++)
130 {
131 batch[i][provokeFirst ? 0 : 2] = indices[index + 0];
132 batch[i][provokeFirst ? 1 : 0] = indices[index + 1];
133 batch[i][provokeFirst ? 2 : 1] = indices[0];
Nicolas Capens157ba262019-12-10 17:49:14 -0500134
Ben Claytonfccfc562019-12-17 20:37:31 +0000135 index += 1;
136 }
137 break;
Nicolas Capens157ba262019-12-10 17:49:14 -0500138 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000139 default:
140 ASSERT(false);
141 return false;
Nicolas Capens68a82382018-10-02 13:16:55 -0400142 }
143
Nicolas Capens157ba262019-12-10 17:49:14 -0500144 return true;
145}
146
147DrawCall::DrawCall()
148{
Ben Claytonfccfc562019-12-17 20:37:31 +0000149 data = (DrawData *)allocate(sizeof(DrawData));
Nicolas Capens157ba262019-12-10 17:49:14 -0500150 data->constants = &constants;
151}
152
153DrawCall::~DrawCall()
154{
155 deallocate(data);
156}
157
Ben Claytonfccfc562019-12-17 20:37:31 +0000158Renderer::Renderer(vk::Device *device)
159 : device(device)
Nicolas Capens157ba262019-12-10 17:49:14 -0500160{
Ben Claytonbc2af942020-04-14 09:22:14 +0100161 vertexProcessor.setRoutineCacheSize(1024);
162 pixelProcessor.setRoutineCacheSize(1024);
163 setupProcessor.setRoutineCacheSize(1024);
Nicolas Capens157ba262019-12-10 17:49:14 -0500164}
165
166Renderer::~Renderer()
167{
168 drawTickets.take().wait();
169}
170
171// Renderer objects have to be mem aligned to the alignment provided in the class declaration
Ben Claytonfccfc562019-12-17 20:37:31 +0000172void *Renderer::operator new(size_t size)
Nicolas Capens157ba262019-12-10 17:49:14 -0500173{
174 ASSERT(size == sizeof(Renderer)); // This operator can't be called from a derived class
175 return vk::allocate(sizeof(Renderer), alignof(Renderer), vk::DEVICE_MEMORY, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
176}
177
Ben Claytonfccfc562019-12-17 20:37:31 +0000178void Renderer::operator delete(void *mem)
Nicolas Capens157ba262019-12-10 17:49:14 -0500179{
180 vk::deallocate(mem, vk::DEVICE_MEMORY);
181}
182
Ben Claytonfccfc562019-12-17 20:37:31 +0000183void Renderer::draw(const sw::Context *context, VkIndexType indexType, unsigned int count, int baseVertex,
184 TaskEvents *events, int instanceID, int viewID, void *indexBuffer, const VkExtent3D &framebufferExtent,
185 PushConstantStorage const &pushConstants, bool update)
Nicolas Capens157ba262019-12-10 17:49:14 -0500186{
187 if(count == 0) { return; }
188
189 auto id = nextDrawID++;
190 MARL_SCOPED_EVENT("draw %d", id);
191
Nicolas Capens157ba262019-12-10 17:49:14 -0500192 marl::Pool<sw::DrawCall>::Loan draw;
193 {
194 MARL_SCOPED_EVENT("drawCallPool.borrow()");
195 draw = drawCallPool.borrow();
196 }
197 draw->id = id;
198
199 if(update)
200 {
201 MARL_SCOPED_EVENT("update");
Ben Claytonbc2af942020-04-14 09:22:14 +0100202 vertexState = vertexProcessor.update(context);
203 setupState = setupProcessor.update(context);
204 pixelState = pixelProcessor.update(context);
Nicolas Capens157ba262019-12-10 17:49:14 -0500205
Ben Claytonbc2af942020-04-14 09:22:14 +0100206 vertexRoutine = vertexProcessor.routine(vertexState, context->pipelineLayout, context->vertexShader, context->descriptorSets);
207 setupRoutine = setupProcessor.routine(setupState);
208 pixelRoutine = pixelProcessor.routine(pixelState, context->pipelineLayout, context->pixelShader, context->descriptorSets);
Nicolas Capens157ba262019-12-10 17:49:14 -0500209 }
210
Alexis Hetu4f438a52020-06-15 16:13:51 -0400211 draw->containsImageWrite = (context->vertexShader && context->vertexShader->containsImageWrite()) ||
212 (context->pixelShader && context->pixelShader->containsImageWrite());
213
Nicolas Capens157ba262019-12-10 17:49:14 -0500214 DrawCall::SetupFunction setupPrimitives = nullptr;
Nicolas Capens15d3dda2020-06-11 21:40:43 -0400215 int ms = context->sampleCount;
Nicolas Capens157ba262019-12-10 17:49:14 -0500216 unsigned int numPrimitivesPerBatch = MaxBatchSize / ms;
217
218 if(context->isDrawTriangle(false))
219 {
220 switch(context->polygonMode)
221 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000222 case VK_POLYGON_MODE_FILL:
223 setupPrimitives = &DrawCall::setupSolidTriangles;
224 break;
225 case VK_POLYGON_MODE_LINE:
226 setupPrimitives = &DrawCall::setupWireframeTriangles;
227 numPrimitivesPerBatch /= 3;
228 break;
229 case VK_POLYGON_MODE_POINT:
230 setupPrimitives = &DrawCall::setupPointTriangles;
231 numPrimitivesPerBatch /= 3;
232 break;
233 default:
234 UNSUPPORTED("polygon mode: %d", int(context->polygonMode));
235 return;
Nicolas Capens157ba262019-12-10 17:49:14 -0500236 }
237 }
238 else if(context->isDrawLine(false))
239 {
240 setupPrimitives = &DrawCall::setupLines;
241 }
242 else // Point primitive topology
243 {
244 setupPrimitives = &DrawCall::setupPoints;
245 }
246
247 DrawData *data = draw->data;
248 draw->occlusionQuery = occlusionQuery;
249 draw->batchDataPool = &batchDataPool;
250 draw->numPrimitives = count;
251 draw->numPrimitivesPerBatch = numPrimitivesPerBatch;
252 draw->numBatches = (count + draw->numPrimitivesPerBatch - 1) / draw->numPrimitivesPerBatch;
253 draw->topology = context->topology;
254 draw->provokingVertexMode = context->provokingVertexMode;
255 draw->indexType = indexType;
256 draw->lineRasterizationMode = context->lineRasterizationMode;
Alexis Hetu4f438a52020-06-15 16:13:51 -0400257 draw->descriptorSetObjects = context->descriptorSetObjects;
258 draw->pipelineLayout = context->pipelineLayout;
Nicolas Capens157ba262019-12-10 17:49:14 -0500259
260 draw->vertexRoutine = vertexRoutine;
261 draw->setupRoutine = setupRoutine;
262 draw->pixelRoutine = pixelRoutine;
263 draw->setupPrimitives = setupPrimitives;
264 draw->setupState = setupState;
265
266 data->descriptorSets = context->descriptorSets;
267 data->descriptorDynamicOffsets = context->descriptorDynamicOffsets;
268
Ben Claytonfccfc562019-12-17 20:37:31 +0000269 for(int i = 0; i < MAX_INTERFACE_COMPONENTS / 4; i++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500270 {
271 data->input[i] = context->input[i].buffer;
272 data->robustnessSize[i] = context->input[i].robustnessSize;
273 data->stride[i] = context->input[i].vertexStride;
274 }
275
276 data->indices = indexBuffer;
277 data->viewID = viewID;
278 data->instanceID = instanceID;
279 data->baseVertex = baseVertex;
280
281 if(pixelState.stencilActive)
282 {
283 data->stencil[0].set(context->frontStencil.reference, context->frontStencil.compareMask, context->frontStencil.writeMask);
284 data->stencil[1].set(context->backStencil.reference, context->backStencil.compareMask, context->backStencil.writeMask);
285 }
286
287 data->lineWidth = context->lineWidth;
288
Ben Claytonbc2af942020-04-14 09:22:14 +0100289 data->factor = pixelProcessor.factor;
Nicolas Capens157ba262019-12-10 17:49:14 -0500290
291 if(pixelState.alphaToCoverage)
292 {
293 if(ms == 4)
294 {
Nicolas Capens9e5d5472019-12-17 10:16:30 -0500295 data->a2c0 = float4(0.2f);
296 data->a2c1 = float4(0.4f);
297 data->a2c2 = float4(0.6f);
298 data->a2c3 = float4(0.8f);
Nicolas Capens157ba262019-12-10 17:49:14 -0500299 }
300 else if(ms == 2)
301 {
Nicolas Capens9e5d5472019-12-17 10:16:30 -0500302 data->a2c0 = float4(0.25f);
303 data->a2c1 = float4(0.75f);
Nicolas Capens157ba262019-12-10 17:49:14 -0500304 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000305 else
306 ASSERT(false);
Nicolas Capens157ba262019-12-10 17:49:14 -0500307 }
308
309 if(pixelState.occlusionEnabled)
310 {
311 for(int cluster = 0; cluster < MaxClusterCount; cluster++)
312 {
313 data->occlusion[cluster] = 0;
314 }
315 }
316
317 // Viewport
318 {
319 float W = 0.5f * viewport.width;
320 float H = 0.5f * viewport.height;
321 float X0 = viewport.x + W;
322 float Y0 = viewport.y + H;
323 float N = viewport.minDepth;
324 float F = viewport.maxDepth;
325 float Z = F - N;
326 constexpr float subPixF = vk::SUBPIXEL_PRECISION_FACTOR;
327
328 if(context->isDrawTriangle(false))
329 {
330 N += context->depthBias;
Ben Clayton9ad035b2019-08-09 23:44:09 +0100331 }
332
Nicolas Capens9e5d5472019-12-17 10:16:30 -0500333 data->WxF = float4(W * subPixF);
334 data->HxF = float4(H * subPixF);
335 data->X0xF = float4(X0 * subPixF - subPixF / 2);
336 data->Y0xF = float4(Y0 * subPixF - subPixF / 2);
337 data->halfPixelX = float4(0.5f / W);
338 data->halfPixelY = float4(0.5f / H);
Nicolas Capens157ba262019-12-10 17:49:14 -0500339 data->viewportHeight = abs(viewport.height);
340 data->slopeDepthBias = context->slopeDepthBias;
341 data->depthRange = Z;
342 data->depthNear = N;
343 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400344
Nicolas Capens157ba262019-12-10 17:49:14 -0500345 // Target
346 {
347 for(int index = 0; index < RENDERTARGETS; index++)
348 {
349 draw->renderTarget[index] = context->renderTarget[index];
350
351 if(draw->renderTarget[index])
352 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000353 data->colorBuffer[index] = (unsigned int *)context->renderTarget[index]->getOffsetPointer({ 0, 0, 0 }, VK_IMAGE_ASPECT_COLOR_BIT, 0, data->viewID);
Nicolas Capens157ba262019-12-10 17:49:14 -0500354 data->colorPitchB[index] = context->renderTarget[index]->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
355 data->colorSliceB[index] = context->renderTarget[index]->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
356 }
357 }
358
359 draw->depthBuffer = context->depthBuffer;
360 draw->stencilBuffer = context->stencilBuffer;
361
362 if(draw->depthBuffer)
363 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000364 data->depthBuffer = (float *)context->depthBuffer->getOffsetPointer({ 0, 0, 0 }, VK_IMAGE_ASPECT_DEPTH_BIT, 0, data->viewID);
Nicolas Capens157ba262019-12-10 17:49:14 -0500365 data->depthPitchB = context->depthBuffer->rowPitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT, 0);
366 data->depthSliceB = context->depthBuffer->slicePitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT, 0);
367 }
368
369 if(draw->stencilBuffer)
370 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000371 data->stencilBuffer = (unsigned char *)context->stencilBuffer->getOffsetPointer({ 0, 0, 0 }, VK_IMAGE_ASPECT_STENCIL_BIT, 0, data->viewID);
Nicolas Capens157ba262019-12-10 17:49:14 -0500372 data->stencilPitchB = context->stencilBuffer->rowPitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
373 data->stencilSliceB = context->stencilBuffer->slicePitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
374 }
375 }
376
377 // Scissor
378 {
379 data->scissorX0 = clamp<int>(scissor.offset.x, 0, framebufferExtent.width);
380 data->scissorX1 = clamp<int>(scissor.offset.x + scissor.extent.width, 0, framebufferExtent.width);
381 data->scissorY0 = clamp<int>(scissor.offset.y, 0, framebufferExtent.height);
382 data->scissorY1 = clamp<int>(scissor.offset.y + scissor.extent.height, 0, framebufferExtent.height);
383 }
384
385 // Push constants
386 {
387 data->pushConstants = pushConstants;
388 }
389
390 draw->events = events;
391
Alexis Hetu4f438a52020-06-15 16:13:51 -0400392 vk::DescriptorSet::PrepareForSampling(draw->descriptorSetObjects, draw->pipelineLayout);
393
Nicolas Capens157ba262019-12-10 17:49:14 -0500394 DrawCall::run(draw, &drawTickets, clusterQueues);
395}
396
397void DrawCall::setup()
398{
399 if(occlusionQuery != nullptr)
400 {
401 occlusionQuery->start();
402 }
403
404 if(events)
405 {
406 events->start();
407 }
408}
409
410void DrawCall::teardown()
411{
412 if(events)
413 {
414 events->finish();
415 events = nullptr;
416 }
417
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500418 if(occlusionQuery != nullptr)
Nicolas Capens157ba262019-12-10 17:49:14 -0500419 {
420 for(int cluster = 0; cluster < MaxClusterCount; cluster++)
421 {
422 occlusionQuery->add(data->occlusion[cluster]);
423 }
424 occlusionQuery->finish();
425 }
426
427 vertexRoutine = {};
428 setupRoutine = {};
429 pixelRoutine = {};
Alexis Hetu4f438a52020-06-15 16:13:51 -0400430
431 for(auto *rt : renderTarget)
432 {
433 if(rt)
434 {
435 rt->contentsChanged();
436 }
437 }
438
439 if(containsImageWrite)
440 {
441 vk::DescriptorSet::ContentsChanged(descriptorSetObjects, pipelineLayout);
442 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500443}
444
Ben Claytonfccfc562019-12-17 20:37:31 +0000445void DrawCall::run(const marl::Loan<DrawCall> &draw, marl::Ticket::Queue *tickets, marl::Ticket::Queue clusterQueues[MaxClusterCount])
Nicolas Capens157ba262019-12-10 17:49:14 -0500446{
447 draw->setup();
448
449 auto const numPrimitives = draw->numPrimitives;
450 auto const numPrimitivesPerBatch = draw->numPrimitivesPerBatch;
451 auto const numBatches = draw->numBatches;
452
453 auto ticket = tickets->take();
454 auto finally = marl::make_shared_finally([draw, ticket] {
455 MARL_SCOPED_EVENT("FINISH draw %d", draw->id);
456 draw->teardown();
457 ticket.done();
458 });
459
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500460 for(unsigned int batchId = 0; batchId < numBatches; batchId++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500461 {
462 auto batch = draw->batchDataPool->borrow();
463 batch->id = batchId;
464 batch->firstPrimitive = batch->id * numPrimitivesPerBatch;
465 batch->numPrimitives = std::min(batch->firstPrimitive + numPrimitivesPerBatch, numPrimitives) - batch->firstPrimitive;
466
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500467 for(int cluster = 0; cluster < MaxClusterCount; cluster++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500468 {
469 batch->clusterTickets[cluster] = std::move(clusterQueues[cluster].take());
470 }
471
472 marl::schedule([draw, batch, finally] {
Nicolas Capens157ba262019-12-10 17:49:14 -0500473 processVertices(draw.get(), batch.get());
474
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500475 if(!draw->setupState.rasterizerDiscard)
Nicolas Capens157ba262019-12-10 17:49:14 -0500476 {
477 processPrimitives(draw.get(), batch.get());
478
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500479 if(batch->numVisible > 0)
Nicolas Capens157ba262019-12-10 17:49:14 -0500480 {
481 processPixels(draw, batch, finally);
482 return;
483 }
484 }
485
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500486 for(int cluster = 0; cluster < MaxClusterCount; cluster++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500487 {
488 batch->clusterTickets[cluster].done();
489 }
490 });
491 }
492}
493
Ben Claytonfccfc562019-12-17 20:37:31 +0000494void DrawCall::processVertices(DrawCall *draw, BatchData *batch)
Nicolas Capens157ba262019-12-10 17:49:14 -0500495{
496 MARL_SCOPED_EVENT("VERTEX draw %d, batch %d", draw->id, batch->id);
497
498 unsigned int triangleIndices[MaxBatchSize + 1][3]; // One extra for SIMD width overrun. TODO: Adjust to dynamic batch size.
499 {
500 MARL_SCOPED_EVENT("processPrimitiveVertices");
501 processPrimitiveVertices(
Ben Claytonfccfc562019-12-17 20:37:31 +0000502 triangleIndices,
503 draw->data->indices,
504 draw->indexType,
505 batch->firstPrimitive,
506 batch->numPrimitives,
507 draw->topology,
508 draw->provokingVertexMode);
Nicolas Capens157ba262019-12-10 17:49:14 -0500509 }
510
Ben Claytonfccfc562019-12-17 20:37:31 +0000511 auto &vertexTask = batch->vertexTask;
Nicolas Capens157ba262019-12-10 17:49:14 -0500512 vertexTask.primitiveStart = batch->firstPrimitive;
513 // We're only using batch compaction for points, not lines
514 vertexTask.vertexCount = batch->numPrimitives * ((draw->topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) ? 1 : 3);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500515 if(vertexTask.vertexCache.drawCall != draw->id)
Nicolas Capens157ba262019-12-10 17:49:14 -0500516 {
517 vertexTask.vertexCache.clear();
518 vertexTask.vertexCache.drawCall = draw->id;
519 }
520
521 draw->vertexRoutine(&batch->triangles.front().v0, &triangleIndices[0][0], &vertexTask, draw->data);
522}
523
Ben Claytonfccfc562019-12-17 20:37:31 +0000524void DrawCall::processPrimitives(DrawCall *draw, BatchData *batch)
Nicolas Capens157ba262019-12-10 17:49:14 -0500525{
526 MARL_SCOPED_EVENT("PRIMITIVES draw %d batch %d", draw->id, batch->id);
527 auto triangles = &batch->triangles[0];
528 auto primitives = &batch->primitives[0];
529 batch->numVisible = draw->setupPrimitives(triangles, primitives, draw, batch->numPrimitives);
530}
531
Ben Claytonfccfc562019-12-17 20:37:31 +0000532void DrawCall::processPixels(const marl::Loan<DrawCall> &draw, const marl::Loan<BatchData> &batch, const std::shared_ptr<marl::Finally> &finally)
Nicolas Capens157ba262019-12-10 17:49:14 -0500533{
534 struct Data
535 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000536 Data(const marl::Loan<DrawCall> &draw, const marl::Loan<BatchData> &batch, const std::shared_ptr<marl::Finally> &finally)
537 : draw(draw)
538 , batch(batch)
539 , finally(finally)
540 {}
Nicolas Capens157ba262019-12-10 17:49:14 -0500541 marl::Loan<DrawCall> draw;
542 marl::Loan<BatchData> batch;
543 std::shared_ptr<marl::Finally> finally;
544 };
545 auto data = std::make_shared<Data>(draw, batch, finally);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500546 for(int cluster = 0; cluster < MaxClusterCount; cluster++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500547 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000548 batch->clusterTickets[cluster].onCall([data, cluster] {
549 auto &draw = data->draw;
550 auto &batch = data->batch;
Nicolas Capens157ba262019-12-10 17:49:14 -0500551 MARL_SCOPED_EVENT("PIXEL draw %d, batch %d, cluster %d", draw->id, batch->id, cluster);
552 draw->pixelRoutine(&batch->primitives.front(), batch->numVisible, cluster, MaxClusterCount, draw->data);
553 batch->clusterTickets[cluster].done();
554 });
555 }
556}
557
558void Renderer::synchronize()
559{
560 MARL_SCOPED_EVENT("synchronize");
561 auto ticket = drawTickets.take();
562 ticket.wait();
Nicolas Capensd53eeca2020-03-19 13:31:41 -0400563 device->updateSamplingRoutineSnapshotCache();
Nicolas Capens157ba262019-12-10 17:49:14 -0500564 ticket.done();
565}
566
567void DrawCall::processPrimitiveVertices(
Ben Claytonfccfc562019-12-17 20:37:31 +0000568 unsigned int triangleIndicesOut[MaxBatchSize + 1][3],
569 const void *primitiveIndices,
570 VkIndexType indexType,
571 unsigned int start,
572 unsigned int triangleCount,
573 VkPrimitiveTopology topology,
574 VkProvokingVertexModeEXT provokingVertexMode)
Nicolas Capens157ba262019-12-10 17:49:14 -0500575{
576 if(!primitiveIndices)
577 {
578 struct LinearIndex
579 {
580 unsigned int operator[](unsigned int i) { return i; }
581 };
582
583 if(!setBatchIndices(triangleIndicesOut, topology, provokingVertexMode, LinearIndex(), start, triangleCount))
584 {
585 return;
586 }
587 }
588 else
589 {
590 switch(indexType)
591 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000592 case VK_INDEX_TYPE_UINT16:
593 if(!setBatchIndices(triangleIndicesOut, topology, provokingVertexMode, static_cast<const uint16_t *>(primitiveIndices), start, triangleCount))
594 {
595 return;
596 }
597 break;
598 case VK_INDEX_TYPE_UINT32:
599 if(!setBatchIndices(triangleIndicesOut, topology, provokingVertexMode, static_cast<const uint32_t *>(primitiveIndices), start, triangleCount))
600 {
601 return;
602 }
603 break;
604 break;
605 default:
606 ASSERT(false);
Nicolas Capens157ba262019-12-10 17:49:14 -0500607 return;
Nicolas Capens157ba262019-12-10 17:49:14 -0500608 }
609 }
610
611 // setBatchIndices() takes care of the point case, since it's different due to the compaction
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500612 if(topology != VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
Nicolas Capens157ba262019-12-10 17:49:14 -0500613 {
614 // Repeat the last index to allow for SIMD width overrun.
615 triangleIndicesOut[triangleCount][0] = triangleIndicesOut[triangleCount - 1][2];
616 triangleIndicesOut[triangleCount][1] = triangleIndicesOut[triangleCount - 1][2];
617 triangleIndicesOut[triangleCount][2] = triangleIndicesOut[triangleCount - 1][2];
618 }
619}
620
621int DrawCall::setupSolidTriangles(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count)
622{
623 auto &state = drawCall->setupState;
624
Nicolas Capens11cb8912020-01-14 00:24:05 -0500625 int ms = state.multiSampleCount;
Nicolas Capens157ba262019-12-10 17:49:14 -0500626 const DrawData *data = drawCall->data;
627 int visible = 0;
628
629 for(int i = 0; i < count; i++, triangles++)
630 {
631 Vertex &v0 = triangles->v0;
632 Vertex &v1 = triangles->v1;
633 Vertex &v2 = triangles->v2;
634
635 Polygon polygon(&v0.position, &v1.position, &v2.position);
636
Nicolas Capens157ba262019-12-10 17:49:14 -0500637 if((v0.cullMask | v1.cullMask | v2.cullMask) == 0)
638 {
639 continue;
640 }
641
642 if((v0.clipFlags & v1.clipFlags & v2.clipFlags) != Clipper::CLIP_FINITE)
643 {
644 continue;
645 }
646
647 int clipFlagsOr = v0.clipFlags | v1.clipFlags | v2.clipFlags;
648 if(clipFlagsOr != Clipper::CLIP_FINITE)
649 {
650 if(!Clipper::Clip(polygon, clipFlagsOr, *drawCall))
651 {
652 continue;
653 }
654 }
655
656 if(drawCall->setupRoutine(primitives, triangles, &polygon, data))
657 {
658 primitives += ms;
659 visible++;
660 }
661 }
662
663 return visible;
664}
665
666int DrawCall::setupWireframeTriangles(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count)
667{
Ben Claytonfccfc562019-12-17 20:37:31 +0000668 auto &state = drawCall->setupState;
Nicolas Capens157ba262019-12-10 17:49:14 -0500669
Nicolas Capens11cb8912020-01-14 00:24:05 -0500670 int ms = state.multiSampleCount;
Nicolas Capens157ba262019-12-10 17:49:14 -0500671 int visible = 0;
672
673 for(int i = 0; i < count; i++)
674 {
675 const Vertex &v0 = triangles[i].v0;
676 const Vertex &v1 = triangles[i].v1;
677 const Vertex &v2 = triangles[i].v2;
678
679 float d = (v0.y * v1.x - v0.x * v1.y) * v2.w +
680 (v0.x * v2.y - v0.y * v2.x) * v1.w +
681 (v2.x * v1.y - v1.x * v2.y) * v0.w;
682
683 bool frontFacing = (state.frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE) ? (d > 0) : (d < 0);
684 if(state.cullMode & VK_CULL_MODE_FRONT_BIT)
685 {
686 if(frontFacing) continue;
687 }
688 if(state.cullMode & VK_CULL_MODE_BACK_BIT)
689 {
690 if(!frontFacing) continue;
691 }
692
693 Triangle lines[3];
694 lines[0].v0 = v0;
695 lines[0].v1 = v1;
696 lines[1].v0 = v1;
697 lines[1].v1 = v2;
698 lines[2].v0 = v2;
699 lines[2].v1 = v0;
700
701 for(int i = 0; i < 3; i++)
702 {
703 if(setupLine(*primitives, lines[i], *drawCall))
704 {
705 primitives += ms;
706 visible++;
707 }
708 }
709 }
710
711 return visible;
712}
713
714int DrawCall::setupPointTriangles(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count)
715{
Ben Claytonfccfc562019-12-17 20:37:31 +0000716 auto &state = drawCall->setupState;
Nicolas Capens157ba262019-12-10 17:49:14 -0500717
Nicolas Capens11cb8912020-01-14 00:24:05 -0500718 int ms = state.multiSampleCount;
Nicolas Capens157ba262019-12-10 17:49:14 -0500719 int visible = 0;
720
721 for(int i = 0; i < count; i++)
722 {
723 const Vertex &v0 = triangles[i].v0;
724 const Vertex &v1 = triangles[i].v1;
725 const Vertex &v2 = triangles[i].v2;
726
727 float d = (v0.y * v1.x - v0.x * v1.y) * v2.w +
728 (v0.x * v2.y - v0.y * v2.x) * v1.w +
729 (v2.x * v1.y - v1.x * v2.y) * v0.w;
730
731 bool frontFacing = (state.frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE) ? (d > 0) : (d < 0);
732 if(state.cullMode & VK_CULL_MODE_FRONT_BIT)
733 {
734 if(frontFacing) continue;
735 }
736 if(state.cullMode & VK_CULL_MODE_BACK_BIT)
737 {
738 if(!frontFacing) continue;
739 }
740
741 Triangle points[3];
742 points[0].v0 = v0;
743 points[1].v0 = v1;
744 points[2].v0 = v2;
745
746 for(int i = 0; i < 3; i++)
747 {
748 if(setupPoint(*primitives, points[i], *drawCall))
749 {
750 primitives += ms;
751 visible++;
752 }
753 }
754 }
755
756 return visible;
757}
758
759int DrawCall::setupLines(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count)
760{
761 auto &state = drawCall->setupState;
762
763 int visible = 0;
Nicolas Capens11cb8912020-01-14 00:24:05 -0500764 int ms = state.multiSampleCount;
Nicolas Capens157ba262019-12-10 17:49:14 -0500765
766 for(int i = 0; i < count; i++)
767 {
768 if(setupLine(*primitives, *triangles, *drawCall))
769 {
770 primitives += ms;
771 visible++;
772 }
773
774 triangles++;
775 }
776
777 return visible;
778}
779
780int DrawCall::setupPoints(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count)
781{
782 auto &state = drawCall->setupState;
783
784 int visible = 0;
Nicolas Capens11cb8912020-01-14 00:24:05 -0500785 int ms = state.multiSampleCount;
Nicolas Capens157ba262019-12-10 17:49:14 -0500786
787 for(int i = 0; i < count; i++)
788 {
789 if(setupPoint(*primitives, *triangles, *drawCall))
790 {
791 primitives += ms;
792 visible++;
793 }
794
795 triangles++;
796 }
797
798 return visible;
799}
800
801bool DrawCall::setupLine(Primitive &primitive, Triangle &triangle, const DrawCall &draw)
802{
803 const DrawData &data = *draw.data;
804
805 float lineWidth = data.lineWidth;
806
807 Vertex &v0 = triangle.v0;
808 Vertex &v1 = triangle.v1;
809
810 if((v0.cullMask | v1.cullMask) == 0)
811 {
812 return false;
813 }
814
815 const float4 &P0 = v0.position;
816 const float4 &P1 = v1.position;
817
818 if(P0.w <= 0 && P1.w <= 0)
819 {
820 return false;
821 }
822
823 constexpr float subPixF = vk::SUBPIXEL_PRECISION_FACTOR;
824
825 const float W = data.WxF[0] * (1.0f / subPixF);
826 const float H = data.HxF[0] * (1.0f / subPixF);
827
828 float dx = W * (P1.x / P1.w - P0.x / P0.w);
829 float dy = H * (P1.y / P1.w - P0.y / P0.w);
830
831 if(dx == 0 && dy == 0)
832 {
833 return false;
834 }
835
836 if(draw.lineRasterizationMode != VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT)
837 {
838 // Rectangle centered on the line segment
Nicolas Capens68a82382018-10-02 13:16:55 -0400839
840 float4 P[4];
841 int C[4];
842
Nicolas Capens157ba262019-12-10 17:49:14 -0500843 P[0] = P0;
844 P[1] = P1;
845 P[2] = P1;
846 P[3] = P0;
Nicolas Capens68a82382018-10-02 13:16:55 -0400847
Ben Claytonfccfc562019-12-17 20:37:31 +0000848 float scale = lineWidth * 0.5f / sqrt(dx * dx + dy * dy);
Nicolas Capens68a82382018-10-02 13:16:55 -0400849
Nicolas Capens157ba262019-12-10 17:49:14 -0500850 dx *= scale;
851 dy *= scale;
852
853 float dx0h = dx * P0.w / H;
854 float dy0w = dy * P0.w / W;
855
856 float dx1h = dx * P1.w / H;
857 float dy1w = dy * P1.w / W;
858
859 P[0].x += -dy0w;
860 P[0].y += +dx0h;
Alexis Hetu05953ef2019-05-08 16:56:42 -0400861 C[0] = Clipper::ComputeClipFlags(P[0]);
Nicolas Capens68a82382018-10-02 13:16:55 -0400862
Nicolas Capens157ba262019-12-10 17:49:14 -0500863 P[1].x += -dy1w;
864 P[1].y += +dx1h;
Alexis Hetu05953ef2019-05-08 16:56:42 -0400865 C[1] = Clipper::ComputeClipFlags(P[1]);
Nicolas Capens68a82382018-10-02 13:16:55 -0400866
Nicolas Capens157ba262019-12-10 17:49:14 -0500867 P[2].x += +dy1w;
868 P[2].y += -dx1h;
Alexis Hetu05953ef2019-05-08 16:56:42 -0400869 C[2] = Clipper::ComputeClipFlags(P[2]);
Nicolas Capens68a82382018-10-02 13:16:55 -0400870
Nicolas Capens157ba262019-12-10 17:49:14 -0500871 P[3].x += +dy0w;
872 P[3].y += -dx0h;
Alexis Hetu05953ef2019-05-08 16:56:42 -0400873 C[3] = Clipper::ComputeClipFlags(P[3]);
Nicolas Capens68a82382018-10-02 13:16:55 -0400874
Nicolas Capens68a82382018-10-02 13:16:55 -0400875 if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
876 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500877 Polygon polygon(P, 4);
878
Chris Forbes4aad8842019-02-22 13:35:21 -0800879 int clipFlagsOr = C[0] | C[1] | C[2] | C[3];
Nicolas Capens68a82382018-10-02 13:16:55 -0400880
881 if(clipFlagsOr != Clipper::CLIP_FINITE)
882 {
Alexis Hetu05953ef2019-05-08 16:56:42 -0400883 if(!Clipper::Clip(polygon, clipFlagsOr, draw))
Nicolas Capens68a82382018-10-02 13:16:55 -0400884 {
885 return false;
886 }
887 }
888
Antonio Maiorano62edf142019-10-29 14:16:38 -0400889 return draw.setupRoutine(&primitive, &triangle, &polygon, &data);
Nicolas Capens68a82382018-10-02 13:16:55 -0400890 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500891 }
892 else if(false) // TODO(b/80135519): Deprecate
893 {
894 // Connecting diamonds polygon
895 // This shape satisfies the diamond test convention, except for the exit rule part.
896 // Line segments with overlapping endpoints have duplicate fragments.
897 // The ideal algorithm requires half-open line rasterization (b/80135519).
Nicolas Capens68a82382018-10-02 13:16:55 -0400898
Nicolas Capens157ba262019-12-10 17:49:14 -0500899 float4 P[8];
900 int C[8];
901
902 P[0] = P0;
903 P[1] = P0;
904 P[2] = P0;
905 P[3] = P0;
906 P[4] = P1;
907 P[5] = P1;
908 P[6] = P1;
909 P[7] = P1;
910
911 float dx0 = lineWidth * 0.5f * P0.w / W;
912 float dy0 = lineWidth * 0.5f * P0.w / H;
913
914 float dx1 = lineWidth * 0.5f * P1.w / W;
915 float dy1 = lineWidth * 0.5f * P1.w / H;
916
917 P[0].x += -dx0;
918 C[0] = Clipper::ComputeClipFlags(P[0]);
919
920 P[1].y += +dy0;
921 C[1] = Clipper::ComputeClipFlags(P[1]);
922
923 P[2].x += +dx0;
924 C[2] = Clipper::ComputeClipFlags(P[2]);
925
926 P[3].y += -dy0;
927 C[3] = Clipper::ComputeClipFlags(P[3]);
928
929 P[4].x += -dx1;
930 C[4] = Clipper::ComputeClipFlags(P[4]);
931
932 P[5].y += +dy1;
933 C[5] = Clipper::ComputeClipFlags(P[5]);
934
935 P[6].x += +dx1;
936 C[6] = Clipper::ComputeClipFlags(P[6]);
937
938 P[7].y += -dy1;
939 C[7] = Clipper::ComputeClipFlags(P[7]);
940
941 if((C[0] & C[1] & C[2] & C[3] & C[4] & C[5] & C[6] & C[7]) == Clipper::CLIP_FINITE)
942 {
943 float4 L[6];
944
945 if(dx > -dy)
946 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000947 if(dx > dy) // Right
Nicolas Capens157ba262019-12-10 17:49:14 -0500948 {
949 L[0] = P[0];
950 L[1] = P[1];
951 L[2] = P[5];
952 L[3] = P[6];
953 L[4] = P[7];
954 L[5] = P[3];
955 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000956 else // Down
Nicolas Capens157ba262019-12-10 17:49:14 -0500957 {
958 L[0] = P[0];
959 L[1] = P[4];
960 L[2] = P[5];
961 L[3] = P[6];
962 L[4] = P[2];
963 L[5] = P[3];
964 }
965 }
966 else
967 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000968 if(dx > dy) // Up
Nicolas Capens157ba262019-12-10 17:49:14 -0500969 {
970 L[0] = P[0];
971 L[1] = P[1];
972 L[2] = P[2];
973 L[3] = P[6];
974 L[4] = P[7];
975 L[5] = P[4];
976 }
Ben Claytonfccfc562019-12-17 20:37:31 +0000977 else // Left
Nicolas Capens157ba262019-12-10 17:49:14 -0500978 {
979 L[0] = P[1];
980 L[1] = P[2];
981 L[2] = P[3];
982 L[3] = P[7];
983 L[4] = P[4];
984 L[5] = P[5];
985 }
986 }
987
988 Polygon polygon(L, 6);
989
990 int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | C[4] | C[5] | C[6] | C[7];
991
992 if(clipFlagsOr != Clipper::CLIP_FINITE)
993 {
994 if(!Clipper::Clip(polygon, clipFlagsOr, draw))
995 {
996 return false;
997 }
998 }
999
1000 return draw.setupRoutine(&primitive, &triangle, &polygon, &data);
1001 }
1002 }
1003 else
1004 {
1005 // Parallelogram approximating Bresenham line
1006 // This algorithm does not satisfy the ideal diamond-exit rule, but does avoid the
1007 // duplicate fragment rasterization problem and satisfies all of Vulkan's minimum
1008 // requirements for Bresenham line segment rasterization.
1009
1010 float4 P[8];
1011 P[0] = P0;
1012 P[1] = P0;
1013 P[2] = P0;
1014 P[3] = P0;
1015 P[4] = P1;
1016 P[5] = P1;
1017 P[6] = P1;
1018 P[7] = P1;
1019
1020 float dx0 = lineWidth * 0.5f * P0.w / W;
1021 float dy0 = lineWidth * 0.5f * P0.w / H;
1022
1023 float dx1 = lineWidth * 0.5f * P1.w / W;
1024 float dy1 = lineWidth * 0.5f * P1.w / H;
1025
1026 P[0].x += -dx0;
1027 P[1].y += +dy0;
1028 P[2].x += +dx0;
1029 P[3].y += -dy0;
1030 P[4].x += -dx1;
1031 P[5].y += +dy1;
1032 P[6].x += +dx1;
1033 P[7].y += -dy1;
1034
1035 float4 L[4];
1036
1037 if(dx > -dy)
1038 {
Ben Claytonfccfc562019-12-17 20:37:31 +00001039 if(dx > dy) // Right
Nicolas Capens157ba262019-12-10 17:49:14 -05001040 {
1041 L[0] = P[1];
1042 L[1] = P[5];
1043 L[2] = P[7];
1044 L[3] = P[3];
1045 }
Ben Claytonfccfc562019-12-17 20:37:31 +00001046 else // Down
Nicolas Capens157ba262019-12-10 17:49:14 -05001047 {
1048 L[0] = P[0];
1049 L[1] = P[4];
1050 L[2] = P[6];
1051 L[3] = P[2];
1052 }
1053 }
1054 else
1055 {
Ben Claytonfccfc562019-12-17 20:37:31 +00001056 if(dx > dy) // Up
Nicolas Capens157ba262019-12-10 17:49:14 -05001057 {
1058 L[0] = P[0];
1059 L[1] = P[2];
1060 L[2] = P[6];
1061 L[3] = P[4];
1062 }
Ben Claytonfccfc562019-12-17 20:37:31 +00001063 else // Left
Nicolas Capens157ba262019-12-10 17:49:14 -05001064 {
1065 L[0] = P[1];
1066 L[1] = P[3];
1067 L[2] = P[7];
1068 L[3] = P[5];
1069 }
1070 }
1071
1072 int C0 = Clipper::ComputeClipFlags(L[0]);
1073 int C1 = Clipper::ComputeClipFlags(L[1]);
1074 int C2 = Clipper::ComputeClipFlags(L[2]);
1075 int C3 = Clipper::ComputeClipFlags(L[3]);
1076
1077 if((C0 & C1 & C2 & C3) == Clipper::CLIP_FINITE)
1078 {
1079 Polygon polygon(L, 4);
1080
1081 int clipFlagsOr = C0 | C1 | C2 | C3;
1082
1083 if(clipFlagsOr != Clipper::CLIP_FINITE)
1084 {
1085 if(!Clipper::Clip(polygon, clipFlagsOr, draw))
1086 {
1087 return false;
1088 }
1089 }
1090
1091 return draw.setupRoutine(&primitive, &triangle, &polygon, &data);
1092 }
1093 }
1094
1095 return false;
1096}
1097
1098bool DrawCall::setupPoint(Primitive &primitive, Triangle &triangle, const DrawCall &draw)
1099{
1100 const DrawData &data = *draw.data;
1101
1102 Vertex &v = triangle.v0;
1103
1104 if(v.cullMask == 0)
1105 {
Nicolas Capens68a82382018-10-02 13:16:55 -04001106 return false;
1107 }
1108
Nicolas Capens157ba262019-12-10 17:49:14 -05001109 float pSize = v.pointSize;
1110
1111 pSize = clamp(pSize, 1.0f, static_cast<float>(vk::MAX_POINT_SIZE));
1112
1113 float4 P[4];
1114 int C[4];
1115
1116 P[0] = v.position;
1117 P[1] = v.position;
1118 P[2] = v.position;
1119 P[3] = v.position;
1120
1121 const float X = pSize * P[0].w * data.halfPixelX[0];
1122 const float Y = pSize * P[0].w * data.halfPixelY[0];
1123
1124 P[0].x -= X;
1125 P[0].y += Y;
1126 C[0] = Clipper::ComputeClipFlags(P[0]);
1127
1128 P[1].x += X;
1129 P[1].y += Y;
1130 C[1] = Clipper::ComputeClipFlags(P[1]);
1131
1132 P[2].x += X;
1133 P[2].y -= Y;
1134 C[2] = Clipper::ComputeClipFlags(P[2]);
1135
1136 P[3].x -= X;
1137 P[3].y -= Y;
1138 C[3] = Clipper::ComputeClipFlags(P[3]);
1139
1140 Polygon polygon(P, 4);
1141
1142 if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
Nicolas Capens68a82382018-10-02 13:16:55 -04001143 {
Nicolas Capens157ba262019-12-10 17:49:14 -05001144 int clipFlagsOr = C[0] | C[1] | C[2] | C[3];
Chris Forbes0c1adcc2019-08-06 11:10:48 -07001145
Nicolas Capens157ba262019-12-10 17:49:14 -05001146 if(clipFlagsOr != Clipper::CLIP_FINITE)
Chris Forbese1cf8632019-03-08 18:17:35 -08001147 {
Nicolas Capens157ba262019-12-10 17:49:14 -05001148 if(!Clipper::Clip(polygon, clipFlagsOr, draw))
Chris Forbese1cf8632019-03-08 18:17:35 -08001149 {
Nicolas Capens157ba262019-12-10 17:49:14 -05001150 return false;
Chris Forbese1cf8632019-03-08 18:17:35 -08001151 }
1152 }
Nicolas Capens157ba262019-12-10 17:49:14 -05001153
Marc-Antoine Desrochesb44162f2020-03-05 13:35:43 -05001154 primitive.pointSizeInv = 1.0f / pSize;
Nicolas Capens653b9cb2020-03-09 16:50:15 -04001155
Nicolas Capens157ba262019-12-10 17:49:14 -05001156 return draw.setupRoutine(&primitive, &triangle, &polygon, &data);
Chris Forbese1cf8632019-03-08 18:17:35 -08001157 }
1158
Nicolas Capens157ba262019-12-10 17:49:14 -05001159 return false;
Nicolas Capens68a82382018-10-02 13:16:55 -04001160}
Nicolas Capens157ba262019-12-10 17:49:14 -05001161
1162void Renderer::addQuery(vk::Query *query)
1163{
1164 ASSERT(query->getType() == VK_QUERY_TYPE_OCCLUSION);
1165 ASSERT(!occlusionQuery);
1166
1167 occlusionQuery = query;
1168}
1169
1170void Renderer::removeQuery(vk::Query *query)
1171{
1172 ASSERT(query->getType() == VK_QUERY_TYPE_OCCLUSION);
1173 ASSERT(occlusionQuery == query);
1174
1175 occlusionQuery = nullptr;
1176}
1177
Alexis Hetub766e5e2020-01-20 11:40:28 -05001178// TODO(b/137740918): Optimize instancing to use a single draw call.
Ben Claytonfccfc562019-12-17 20:37:31 +00001179void Renderer::advanceInstanceAttributes(Stream *inputs)
Nicolas Capens157ba262019-12-10 17:49:14 -05001180{
1181 for(uint32_t i = 0; i < vk::MAX_VERTEX_INPUT_BINDINGS; i++)
1182 {
1183 auto &attrib = inputs[i];
Alexis Hetub766e5e2020-01-20 11:40:28 -05001184 if((attrib.format != VK_FORMAT_UNDEFINED) && attrib.instanceStride && (attrib.instanceStride < attrib.robustnessSize))
Nicolas Capens157ba262019-12-10 17:49:14 -05001185 {
1186 // Under the casts: attrib.buffer += attrib.instanceStride
1187 attrib.buffer = (void const *)((uintptr_t)attrib.buffer + attrib.instanceStride);
1188 attrib.robustnessSize -= attrib.instanceStride;
1189 }
1190 }
1191}
1192
1193void Renderer::setViewport(const VkViewport &viewport)
1194{
1195 this->viewport = viewport;
1196}
1197
1198void Renderer::setScissor(const VkRect2D &scissor)
1199{
1200 this->scissor = scissor;
1201}
1202
Ben Claytonbc2af942020-04-14 09:22:14 +01001203void Renderer::setBlendConstant(const float4 &blendConstant)
1204{
1205 pixelProcessor.setBlendConstant(blendConstant);
1206}
1207
Nicolas Capens157ba262019-12-10 17:49:14 -05001208} // namespace sw