//==============================================================================
void RenderingThread::start()
{
	ANKI_ASSERT(m_tail == 0 && m_head == 0);
	m_queue.create(m_manager->getAllocator(), QUEUE_SIZE);

	// Swap buffers stuff
	m_swapBuffersCommands =
		m_manager->newInstance<CommandBuffer>(CommandBufferInitInfo());
	m_swapBuffersCommands->getImplementation()
		.pushBackNewCommand<SwapBuffersCommand>(this);

	m_manager->getImplementation().pinContextToCurrentThread(false);

	// Start thread
	m_thread.start(this, threadCallback);

	// Create sync command buffer
	m_syncCommands =
		m_manager->newInstance<CommandBuffer>(CommandBufferInitInfo());
	m_syncCommands->getImplementation().pushBackNewCommand<SyncCommand>(this);

	m_emptyCmdb =
		m_manager->newInstance<CommandBuffer>(CommandBufferInitInfo());
	m_emptyCmdb->getImplementation().pushBackNewCommand<EmptyCommand>();
}
Example #2
0
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();
}
Example #3
0
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();
}
Example #5
0
void GlObject::destroyDeferred(GrManager& manager, GlDeleteFunction deleteCallback)
{
	class DeleteGlObjectCommand final : public GlCommand
	{
	public:
		GlObject::GlDeleteFunction m_callback;
		GLuint m_glName;

		DeleteGlObjectCommand(GlObject::GlDeleteFunction callback, GLuint name)
			: m_callback(callback)
			, m_glName(name)
		{
		}

		Error operator()(GlState&)
		{
			m_callback(1, &m_glName);
			return Error::NONE;
		}
	};

	if(m_glName == 0)
	{
		return;
	}

	RenderingThread& thread = static_cast<GrManagerImpl&>(manager).getRenderingThread();

	if(!thread.isServerThread())
	{
		CommandBufferPtr commands;

		commands = manager.newCommandBuffer(CommandBufferInitInfo());
		static_cast<CommandBufferImpl&>(*commands).pushBackNewCommand<DeleteGlObjectCommand>(deleteCallback, m_glName);
		static_cast<CommandBufferImpl&>(*commands).flush();
	}
	else
	{
		deleteCallback(1, &m_glName);
	}

	m_glName = 0;
}
TextureView* TextureView::newInstance(GrManager* manager, const TextureViewInitInfo& init)
{
	class CreateTextureViewCommand final : public GlCommand
	{
	public:
		TextureViewPtr m_view;

		CreateTextureViewCommand(TextureView* view)
			: m_view(view)
		{
		}

		Error operator()(GlState&)
		{
			TextureViewImpl& impl = static_cast<TextureViewImpl&>(*m_view);

			impl.init();

			GlObject::State oldState = impl.setStateAtomically(GlObject::State::CREATED);
			ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
			(void)oldState;

			return Error::NONE;
		}
	};

	TextureViewImpl* impl = manager->getAllocator().newInstance<TextureViewImpl>(manager, init.getName());
	impl->getRefcount().fetchAdd(1); // Hold a reference in case the command finishes and deletes quickly

	// Need to pre-init because some funcs ask for members and we don't want to serialize
	impl->preInit(init);

	CommandBufferPtr cmdb = manager->newCommandBuffer(CommandBufferInitInfo());
	static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CreateTextureViewCommand>(impl);
	static_cast<CommandBufferImpl&>(*cmdb).flush();

	return impl;
}
Example #7
0
Sampler* Sampler::newInstance(GrManager* manager, const SamplerInitInfo& init)
{
	class CreateSamplerCommand : public GlCommand
	{
	public:
		SamplerPtr m_sampler;
		SamplerInitInfo m_init;

		CreateSamplerCommand(Sampler* sampler, const SamplerInitInfo& init)
			: m_sampler(sampler)
			, m_init(init)
		{
		}

		Error operator()(GlState&)
		{
			SamplerImpl& impl = static_cast<SamplerImpl&>(*m_sampler);

			impl.init(m_init);

			GlObject::State oldState = impl.setStateAtomically(GlObject::State::CREATED);
			(void)oldState;
			ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);

			return Error::NONE;
		}
	};

	SamplerImpl* impl = manager->getAllocator().newInstance<SamplerImpl>(manager, init.getName());
	impl->getRefcount().fetchAdd(1); // Hold a reference in case the command finishes and deletes quickly

	CommandBufferPtr cmdb = manager->newCommandBuffer(CommandBufferInitInfo());
	static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CreateSamplerCommand>(impl, init);
	static_cast<CommandBufferImpl&>(*cmdb).flush();

	return impl;
}
//==============================================================================
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;
}
Example #10
0
//==============================================================================
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;
}