void Sampler::init(const SamplerInitInfo& init) { m_impl.reset(getAllocator().newInstance<SamplerImpl>(&getManager())); CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo()); cmdb->m_impl->pushBackNewCommand<CreateSamplerCommand>(this, init); cmdb->flush(); }
void Texture::init(const TextureInitInfo& init) { m_impl.reset(getAllocator().newInstance<TextureImpl>(&getManager())); CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo()); cmdb->getImplementation().pushBackNewCommand<CreateTextureCommand>( this, init); cmdb->flush(); }
void OcclusionQuery::init(OcclusionQueryResultBit condRenderingBit) { m_impl.reset(getAllocator().newInstance<OcclusionQueryImpl>(&getManager())); CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo()); cmdb->getImplementation().pushBackNewCommand<CreateOqCommand>( this, condRenderingBit); cmdb->flush(); }
//============================================================================== void FramebufferPtr::create(GrManager* manager, Initializer& init) { CommandBufferPtr cmdb; cmdb.create(manager); Base::create(cmdb.get().getManager()); get().setStateAtomically(GlObject::State::TO_BE_CREATED); cmdb.get().pushBackNewCommand<CreateFramebufferCommand>(*this, init); cmdb.flush(); }
Error MainRenderer::render(SceneGraph& scene) { ANKI_TRACE_START_EVENT(RENDER); // First thing, reset the temp mem pool m_frameAlloc.getMemoryPool().reset(); GrManager& gl = m_r->getGrManager(); CommandBufferInitInfo cinf; cinf.m_hints = m_cbInitHints; CommandBufferPtr cmdb = gl.newInstance<CommandBuffer>(cinf); // Set some of the dynamic state cmdb->setPolygonOffset(0.0, 0.0); // Run renderer RenderingContext ctx(m_frameAlloc); if(m_rDrawToDefaultFb) { ctx.m_outFb = m_defaultFb; ctx.m_outFbWidth = m_width; ctx.m_outFbHeight = m_height; } ctx.m_commandBuffer = cmdb; ctx.m_frustumComponent = &scene.getActiveCamera().getComponent<FrustumComponent>(); ANKI_CHECK(m_r->render(ctx)); // Blit renderer's result to default FB if needed if(!m_rDrawToDefaultFb) { cmdb->beginRenderPass(m_defaultFb); cmdb->setViewport(0, 0, m_width, m_height); cmdb->bindPipeline(m_blitPpline); cmdb->bindResourceGroup(m_rcGroup, 0, nullptr); m_r->drawQuad(cmdb); cmdb->endRenderPass(); } // Flush the command buffer cmdb->flush(); // Set the hints m_cbInitHints = cmdb->computeInitHints(); ANKI_TRACE_STOP_EVENT(RENDER); return ErrorCode::NONE; }
ANKI_TEST(Gr, SimpleDrawcall) { COMMON_BEGIN() PipelinePtr ppline = createSimplePpline(VERT_SRC, FRAG_SRC, *gr); FramebufferPtr fb = createDefaultFb(*gr); U iterations = 100; while(iterations--) { HighRezTimer timer; timer.start(); gr->beginFrame(); CommandBufferInitInfo cinit; CommandBufferPtr cmdb = gr->newInstance<CommandBuffer>(cinit); cmdb->setViewport(0, 0, WIDTH, HEIGHT); cmdb->setPolygonOffset(0.0, 0.0); cmdb->bindPipeline(ppline); cmdb->beginRenderPass(fb); cmdb->drawArrays(3); cmdb->endRenderPass(); cmdb->flush(); gr->swapBuffers(); timer.stop(); const F32 TICK = 1.0 / 30.0; if(timer.getElapsedTime() < TICK) { HighRezTimer::sleep(TICK - timer.getElapsedTime()); } } COMMON_END() }
ANKI_TEST(Gr, DrawWithUniforms) { COMMON_BEGIN() // A non-uploaded buffer BufferPtr b = gr->newInstance<Buffer>(sizeof(Vec4) * 3, BufferUsageBit::UNIFORM_ALL, BufferMapAccessBit::WRITE); Vec4* ptr = static_cast<Vec4*>(b->map(0, sizeof(Vec4) * 3, BufferMapAccessBit::WRITE)); ANKI_TEST_EXPECT_NEQ(ptr, nullptr); ptr[0] = Vec4(1.0, 0.0, 0.0, 0.0); ptr[1] = Vec4(0.0, 1.0, 0.0, 0.0); ptr[2] = Vec4(0.0, 0.0, 1.0, 0.0); b->unmap(); // Resource group ResourceGroupInitInfo rcinit; rcinit.m_uniformBuffers[0].m_buffer = b; rcinit.m_uniformBuffers[0].m_usage = BufferUsageBit::UNIFORM_ALL_GRAPHICS; rcinit.m_uniformBuffers[1].m_uploadedMemory = true; rcinit.m_uniformBuffers[1].m_usage = BufferUsageBit::UNIFORM_ALL_GRAPHICS; ResourceGroupPtr rc = gr->newInstance<ResourceGroup>(rcinit); // Ppline PipelinePtr ppline = createSimplePpline(VERT_UBO_SRC, FRAG_UBO_SRC, *gr); // FB FramebufferPtr fb = createDefaultFb(*gr); const U ITERATION_COUNT = 100; U iterations = ITERATION_COUNT; while(iterations--) { HighRezTimer timer; timer.start(); gr->beginFrame(); // Uploaded buffer TransientMemoryInfo transientInfo; Vec4* rotMat = static_cast<Vec4*>(gr->allocateFrameTransientMemory( sizeof(Vec4), BufferUsageBit::UNIFORM_ALL, transientInfo.m_uniformBuffers[1])); F32 angle = toRad(360.0f / ITERATION_COUNT * iterations); (*rotMat)[0] = cos(angle); (*rotMat)[1] = -sin(angle); (*rotMat)[2] = sin(angle); (*rotMat)[3] = cos(angle); CommandBufferInitInfo cinit; CommandBufferPtr cmdb = gr->newInstance<CommandBuffer>(cinit); cmdb->setViewport(0, 0, WIDTH, HEIGHT); cmdb->setPolygonOffset(0.0, 0.0); cmdb->bindPipeline(ppline); cmdb->beginRenderPass(fb); cmdb->bindResourceGroup(rc, 0, &transientInfo); cmdb->drawArrays(3); cmdb->endRenderPass(); cmdb->flush(); gr->swapBuffers(); timer.stop(); const F32 TICK = 1.0 / 30.0; if(timer.getElapsedTime() < TICK) { HighRezTimer::sleep(TICK - timer.getElapsedTime()); } } COMMON_END() }
//============================================================================== Error TexUploadTask::operator()(AsyncLoaderTaskContext& ctx) { CommandBufferPtr cmdb; // Upload the data for(U depth = m_ctx.m_depth; depth < m_depth; ++depth) { for(U face = m_ctx.m_face; face < m_faces; ++face) { for(U mip = m_ctx.m_mip; mip < m_loader.getMipLevelsCount(); ++mip) { U surfIdx = max(depth, face); const auto& surf = m_loader.getSurface(mip, surfIdx); DynamicBufferToken token; void* data = m_gr->allocateFrameHostVisibleMemory( surf.m_data.getSize(), BufferUsage::TRANSFER, token); if(data) { // There is enough transfer memory memcpy(data, &surf.m_data[0], surf.m_data.getSize()); if(!cmdb) { cmdb = m_gr->newInstance<CommandBuffer>( CommandBufferInitInfo()); } cmdb->textureUpload( m_tex, TextureSurfaceInfo(mip, depth, face), token); } else { // Not enough transfer memory. Move the work to the future if(cmdb) { cmdb->flush(); } m_ctx.m_depth = depth; m_ctx.m_mip = mip; m_ctx.m_face = face; ctx.m_pause = true; ctx.m_resubmitTask = true; return ErrorCode::NONE; } } } } // Finaly enque the command buffer if(cmdb) { cmdb->flush(); } return ErrorCode::NONE; }
//============================================================================== Error TexUploadTask::operator()(AsyncLoaderTaskContext& ctx) { CommandBufferPtr cmdb; // Upload the data for(U layer = m_ctx.m_layer; layer < m_layers; ++layer) { for(U depth = m_ctx.m_depth; depth < m_depth; ++depth) { for(U face = m_ctx.m_face; face < m_faces; ++face) { for(U mip = m_ctx.m_mip; mip < m_loader.getMipLevelsCount(); ++mip) { const auto& surf = m_loader.getSurface(mip, depth, face, layer); TransientMemoryToken token; Error err = ErrorCode::NONE; void* data = m_gr->allocateFrameTransientMemory( surf.m_data.getSize(), BufferUsageBit::TRANSFER_SOURCE, token, &err); if(!err) { // There is enough transfer memory memcpy(data, &surf.m_data[0], surf.m_data.getSize()); if(!cmdb) { cmdb = m_gr->newInstance<CommandBuffer>( CommandBufferInitInfo()); } cmdb->uploadTextureSurface(m_tex, TextureSurfaceInfo(mip, depth, face, layer), token); } else { // Not enough transfer memory. Move the work to the // future if(cmdb) { cmdb->flush(); } m_ctx.m_depth = depth; m_ctx.m_mip = mip; m_ctx.m_face = face; m_ctx.m_layer = layer; ctx.m_pause = true; ctx.m_resubmitTask = true; return ErrorCode::NONE; } } } } } // Finaly enque the command buffer if(cmdb) { cmdb->flush(); } return ErrorCode::NONE; }
//============================================================================== Error MeshLoadTask::operator()(AsyncLoaderTaskContext& ctx) { GrManager& gr = m_manager->getGrManager(); CommandBufferPtr cmdb; // Write vert buff if(m_vertBuff) { TransientMemoryToken token; Error err = ErrorCode::NONE; void* data = gr.allocateFrameTransientMemory( m_loader.getVertexDataSize(), BufferUsage::TRANSFER, token, &err); if(!err) { memcpy( data, m_loader.getVertexData(), m_loader.getVertexDataSize()); cmdb = gr.newInstance<CommandBuffer>(CommandBufferInitInfo()); cmdb->uploadBuffer(m_vertBuff, 0, token); m_vertBuff.reset(nullptr); } else { ctx.m_pause = true; ctx.m_resubmitTask = true; return ErrorCode::NONE; } } // Create index buffer { TransientMemoryToken token; Error err = ErrorCode::NONE; void* data = gr.allocateFrameTransientMemory( m_loader.getIndexDataSize(), BufferUsage::TRANSFER, token, &err); if(!err) { memcpy(data, m_loader.getIndexData(), m_loader.getIndexDataSize()); if(!cmdb) { cmdb = gr.newInstance<CommandBuffer>(CommandBufferInitInfo()); } cmdb->uploadBuffer(m_indicesBuff, 0, token); cmdb->flush(); } else { // Submit prev work if(cmdb) { cmdb->flush(); } ctx.m_pause = true; ctx.m_resubmitTask = true; return ErrorCode::NONE; } } return ErrorCode::NONE; }
ANKI_TEST(Ui, Ui) { Config cfg; initConfig(cfg); cfg.set("window.vsync", 1); cfg.set("window.debugContext", 0); cfg.set("width", 1024); cfg.set("height", 760); cfg.set("rsrc.dataPaths", "engine_data"); NativeWindow* win = createWindow(cfg); Input* in = new Input(); GrManager* gr = createGrManager(cfg, win); PhysicsWorld* physics; ResourceFilesystem* fs; ResourceManager* resource = createResourceManager(cfg, gr, physics, fs); UiManager* ui = new UiManager(); ANKI_TEST_EXPECT_NO_ERR(in->init(win)); StagingGpuMemoryManager* stagingMem = new StagingGpuMemoryManager(); ANKI_TEST_EXPECT_NO_ERR(stagingMem->init(gr, cfg)); HeapAllocator<U8> alloc(allocAligned, nullptr); ANKI_TEST_EXPECT_NO_ERR(ui->init(allocAligned, nullptr, resource, gr, stagingMem, in)); { FontPtr font; ANKI_TEST_EXPECT_NO_ERR(ui->newInstance(font, "UbuntuRegular.ttf", std::initializer_list<U32>{10, 20, 30, 60})); CanvasPtr canvas; ANKI_TEST_EXPECT_NO_ERR(ui->newInstance(canvas, font, 20, win->getWidth(), win->getHeight())); IntrusivePtr<Label> label; ANKI_TEST_EXPECT_NO_ERR(ui->newInstance(label)); Bool done = false; while(!done) { ANKI_TEST_EXPECT_NO_ERR(in->handleEvents()); HighRezTimer timer; timer.start(); canvas->handleInput(); if(in->getKey(KeyCode::ESCAPE)) { done = true; } canvas->beginBuilding(); label->build(canvas); TexturePtr presentTex = gr->acquireNextPresentableTexture(); FramebufferPtr fb; { TextureViewInitInfo init; init.m_texture = presentTex; TextureViewPtr view = gr->newTextureView(init); FramebufferInitInfo fbinit; fbinit.m_colorAttachmentCount = 1; fbinit.m_colorAttachments[0].m_clearValue.m_colorf = {{1.0, 0.0, 1.0, 1.0}}; fbinit.m_colorAttachments[0].m_textureView = view; fb = gr->newFramebuffer(fbinit); } CommandBufferInitInfo cinit; cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH; CommandBufferPtr cmdb = gr->newCommandBuffer(cinit); cmdb->setTextureBarrier(presentTex, TextureUsageBit::NONE, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, TextureSubresourceInfo()); cmdb->beginRenderPass(fb, {{TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE}}, {}); canvas->appendToCommandBuffer(cmdb); cmdb->endRenderPass(); cmdb->setTextureBarrier(presentTex, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, TextureUsageBit::PRESENT, TextureSubresourceInfo()); cmdb->flush(); gr->swapBuffers(); stagingMem->endFrame(); timer.stop(); const F32 TICK = 1.0 / 30.0; if(timer.getElapsedTime() < TICK) { HighRezTimer::sleep(TICK - timer.getElapsedTime()); } } } delete ui; delete stagingMem; delete resource; delete physics; delete fs; GrManager::deleteInstance(gr); delete in; delete win; }