void Renderer::threadLoop(int threadIndex) { while(!exitThreads) { taskLoop(threadIndex); suspend[threadIndex]->signal(); resume[threadIndex]->wait(); } }
int main(void) { init(); fdevopen(&serial_console_putc, NULL); pinIsrSetup(); taskLoop(NULL); return 0; }
void Renderer::draw(VkPrimitiveTopology topology, VkIndexType indexType, unsigned int count, int baseVertex, bool update) { #ifndef NDEBUG if(count < minPrimitives || count > maxPrimitives) { return; } #endif context->topology = topology; updateConfiguration(); int ms = context->sampleCount; unsigned int oldMultiSampleMask = context->multiSampleMask; context->multiSampleMask = context->sampleMask & ((unsigned)0xFFFFFFFF >> (32 - ms)); if(!context->multiSampleMask) { return; } context->occlusionEnabled = false; for(auto query : queries) { if(query->type == VK_QUERY_TYPE_OCCLUSION) { context->occlusionEnabled = true; break; } } sync->lock(sw::PRIVATE); if(update || oldMultiSampleMask != context->multiSampleMask) { vertexState = VertexProcessor::update(topology); setupState = SetupProcessor::update(); pixelState = PixelProcessor::update(); vertexRoutine = VertexProcessor::routine(vertexState); setupRoutine = SetupProcessor::routine(setupState); pixelRoutine = PixelProcessor::routine(pixelState); } int batch = batchSize / ms; int (Renderer::*setupPrimitives)(int batch, int count); if(context->isDrawTriangle()) { setupPrimitives = &Renderer::setupTriangles; } else if(context->isDrawLine()) { setupPrimitives = &Renderer::setupLines; } else // Point draw { setupPrimitives = &Renderer::setupPoints; } DrawCall *draw = nullptr; do { for(int i = 0; i < DRAW_COUNT; i++) { if(drawCall[i]->references == -1) { draw = drawCall[i]; drawList[nextDraw & DRAW_COUNT_BITS] = draw; break; } } if(!draw) { resumeApp->wait(); } } while(!draw); DrawData *data = draw->data; if(queries.size() != 0) { draw->queries = new std::list<vk::Query*>(); for(auto &query : queries) { ++query->reference; // Atomic draw->queries->push_back(query); } } draw->topology = topology; draw->indexType = indexType; draw->batchSize = batch; vertexRoutine->bind(); setupRoutine->bind(); pixelRoutine->bind(); draw->vertexRoutine = vertexRoutine; draw->setupRoutine = setupRoutine; draw->pixelRoutine = pixelRoutine; draw->vertexPointer = (VertexProcessor::RoutinePointer)vertexRoutine->getEntry(); draw->setupPointer = (SetupProcessor::RoutinePointer)setupRoutine->getEntry(); draw->pixelPointer = (PixelProcessor::RoutinePointer)pixelRoutine->getEntry(); draw->setupPrimitives = setupPrimitives; draw->setupState = setupState; data->descriptorSets = context->descriptorSets; data->descriptorDynamicOffsets = context->descriptorDynamicOffsets; for(int i = 0; i < MAX_VERTEX_INPUTS; i++) { data->input[i] = context->input[i].buffer; data->stride[i] = context->input[i].vertexStride; } data->indices = context->indexBuffer; if(context->vertexShader->hasBuiltinInput(spv::BuiltInInstanceIndex)) { data->instanceID = context->instanceID; } data->baseVertex = baseVertex; if(pixelState.stencilActive) { data->stencil[0].set(context->frontStencil.reference, context->frontStencil.compareMask, context->frontStencil.writeMask); data->stencil[1].set(context->backStencil.reference, context->backStencil.compareMask, context->backStencil.writeMask); } data->lineWidth = context->lineWidth; data->factor = factor; if(pixelState.transparencyAntialiasing == TRANSPARENCY_ALPHA_TO_COVERAGE) { float ref = context->alphaReference * (1.0f / 255.0f); float margin = sw::min(ref, 1.0f - ref); if(ms == 4) { data->a2c0 = replicate(ref - margin * 0.6f); data->a2c1 = replicate(ref - margin * 0.2f); data->a2c2 = replicate(ref + margin * 0.2f); data->a2c3 = replicate(ref + margin * 0.6f); } else if(ms == 2) { data->a2c0 = replicate(ref - margin * 0.3f); data->a2c1 = replicate(ref + margin * 0.3f); } else ASSERT(false); } if(pixelState.occlusionEnabled) { for(int cluster = 0; cluster < clusterCount; cluster++) { data->occlusion[cluster] = 0; } } #if PERF_PROFILE for(int cluster = 0; cluster < clusterCount; cluster++) { for(int i = 0; i < PERF_TIMERS; i++) { data->cycles[i][cluster] = 0; } } #endif // Viewport { float W = 0.5f * viewport.width; float H = 0.5f * viewport.height; float X0 = viewport.x + W; float Y0 = viewport.y + H; float N = viewport.minDepth; float F = viewport.maxDepth; float Z = F - N; if(context->isDrawTriangle()) { N += context->depthBias; } data->Wx16 = replicate(W * 16); data->Hx16 = replicate(H * 16); data->X0x16 = replicate(X0 * 16 - 8); data->Y0x16 = replicate(Y0 * 16 - 8); data->halfPixelX = replicate(0.5f / W); data->halfPixelY = replicate(0.5f / H); data->viewportHeight = abs(viewport.height); data->slopeDepthBias = context->slopeDepthBias; data->depthRange = Z; data->depthNear = N; } // Target { for(int index = 0; index < RENDERTARGETS; index++) { draw->renderTarget[index] = context->renderTarget[index]; if(draw->renderTarget[index]) { VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->renderTargetLayer[index]) }; data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->getOffsetPointer(offset, VK_IMAGE_ASPECT_COLOR_BIT); data->colorPitchB[index] = context->renderTarget[index]->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0); data->colorSliceB[index] = context->renderTarget[index]->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0); } } draw->depthBuffer = context->depthBuffer; draw->stencilBuffer = context->stencilBuffer; if(draw->depthBuffer) { VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->depthBufferLayer) }; data->depthBuffer = (float*)context->depthBuffer->getOffsetPointer(offset, VK_IMAGE_ASPECT_DEPTH_BIT); data->depthPitchB = context->depthBuffer->rowPitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT, 0); data->depthSliceB = context->depthBuffer->slicePitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT, 0); } if(draw->stencilBuffer) { VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->stencilBufferLayer) }; data->stencilBuffer = (unsigned char*)context->stencilBuffer->getOffsetPointer(offset, VK_IMAGE_ASPECT_STENCIL_BIT); data->stencilPitchB = context->stencilBuffer->rowPitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0); data->stencilSliceB = context->stencilBuffer->slicePitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0); } } // Scissor { data->scissorX0 = scissor.offset.x; data->scissorX1 = scissor.offset.x + scissor.extent.width; data->scissorY0 = scissor.offset.y; data->scissorY1 = scissor.offset.y + scissor.extent.height; } // Push constants { data->pushConstants = context->pushConstants; } draw->primitive = 0; draw->count = count; draw->references = (count + batch - 1) / batch; schedulerMutex.lock(); ++nextDraw; // Atomic schedulerMutex.unlock(); #ifndef NDEBUG if(threadCount == 1) // Use main thread for draw execution { threadsAwake = 1; task[0].type = Task::RESUME; taskLoop(0); } else #endif { if(!threadsAwake) { suspend[0]->wait(); threadsAwake = 1; task[0].type = Task::RESUME; resume[0]->signal(); } } }