Ejemplo n.º 1
0
//==============================================================================
Error GlPipelineHandle::commonConstructor(
	GlCommandBufferHandle& commands,
	const GlShaderHandle* progsBegin, const GlShaderHandle* progsEnd)
{
	class Command: public GlCommand
	{
	public:
		GlPipelineHandle m_ppline;
		Array<GlShaderHandle, 6> m_progs;
		U8 m_progsCount;

		Command(GlPipelineHandle& ppline, 
			const GlShaderHandle* progsBegin, const GlShaderHandle* progsEnd)
		:	m_ppline(ppline)
		{
			m_progsCount = 0;
			const GlShaderHandle* prog = progsBegin;
			do
			{
				m_progs[m_progsCount++] = *prog;
			} while(++prog != progsEnd);
		}

		Error operator()(GlCommandBuffer* cmdb)
		{
			Error err = m_ppline._get().create(
				&m_progs[0], &m_progs[0] + m_progsCount,
				cmdb->getGlobalAllocator());

			GlHandleState oldState = m_ppline._setState(
				err ? GlHandleState::ERROR : GlHandleState::CREATED);
			ANKI_ASSERT(oldState == GlHandleState::TO_BE_CREATED);
			(void)oldState;

			return err;
		}
	};

	using Alloc = GlAllocator<GlPipeline>;
	using DeleteCommand = GlDeleteObjectCommand<GlPipeline, Alloc>;
	using Deleter = 
		GlHandleDeferredDeleter<GlPipeline, Alloc, DeleteCommand>;

	Error err = _createAdvanced(
		&commands._get().getQueue().getDevice(),
		commands._get().getGlobalAllocator(), 
		Deleter());

	if(!err)
	{
		_setState(GlHandleState::TO_BE_CREATED);

		commands._pushBackNewCommand<Command>(*this, progsBegin, progsEnd);
	}

	return err;
}
Ejemplo n.º 2
0
//==============================================================================
Error Material::getProgramPipeline(
	const RenderingKey& key, GlPipelineHandle& out)
{
	ANKI_ASSERT(enumToType(key.m_pass) < m_passesCount);
	ANKI_ASSERT(key.m_lod < m_lodsCount);

	Error err = ErrorCode::NONE;

	U tessCount = 1;
	if(m_tessellation)
	{
		tessCount = 2;
	}
	else
	{
		ANKI_ASSERT(!key.m_tessellation);
	}

	U idx = enumToType(key.m_pass) * m_lodsCount * tessCount
		+ key.m_lod * tessCount + key.m_tessellation;

	GlPipelineHandle& ppline = m_pplines[idx];

	// Lazily create it
	if(ANKI_UNLIKELY(!ppline.isCreated()))
	{
		Array<GlShaderHandle, 5> progs;
		U progCount = 0;

		progs[progCount++] = 
			getProgram(key, ShaderType::VERTEX)->getGlProgram();

		if(key.m_tessellation)
		{
			progs[progCount++] = getProgram(
				key, ShaderType::TESSELLATION_CONTROL)->getGlProgram();
			progs[progCount++] = getProgram(
				key, ShaderType::TESSELLATION_EVALUATION)->getGlProgram();
		}

		progs[progCount++] = 
			getProgram(key, ShaderType::FRAGMENT)->getGlProgram();

		GlDevice& gl = m_resources->_getGlDevice();
		GlCommandBufferHandle cmdBuff;
		ANKI_CHECK(cmdBuff.create(&gl));

		ANKI_CHECK(ppline.create(cmdBuff, &progs[0], &progs[0] + progCount));

		cmdBuff.flush();
	}

	out = ppline;

	return err;
}
Ejemplo n.º 3
0
//==============================================================================
void Pps::initInternal(const ConfigSet& config)
{
	m_enabled = config.get("pps.enabled");
	if(!m_enabled)
	{
		return;
	}

	ANKI_ASSERT("Initializing PPS");

	m_ssao.init(config);
	m_hdr.init(config);
	m_lf.init(config);
	m_sslr.init(config);

	// FBO
	GlCommandBufferHandle cmdBuff;
	cmdBuff.create(&getGlDevice());

	m_r->createRenderTarget(m_r->getWidth(), m_r->getHeight(), GL_RGB8, GL_RGB,
		GL_UNSIGNED_BYTE, 1, m_rt);

	m_fb.create(cmdBuff, {{m_rt, GL_COLOR_ATTACHMENT0}});

	// SProg
	String pps(getAllocator());

	pps.sprintf(
		"#define SSAO_ENABLED %u\n"
		"#define HDR_ENABLED %u\n"
		"#define SHARPEN_ENABLED %u\n"
		"#define GAMMA_CORRECTION_ENABLED %u\n"
		"#define FBO_WIDTH %u\n"
		"#define FBO_HEIGHT %u\n",
		m_ssao.getEnabled(), 
		m_hdr.getEnabled(), 
		static_cast<U>(config.get("pps.sharpen")),
		static_cast<U>(config.get("pps.gammaCorrection")),
		m_r->getWidth(),
		m_r->getHeight());

	m_frag.loadToCache(&getResourceManager(),
		"shaders/Pps.frag.glsl", pps.toCString(), "r_");

	m_ppline = m_r->createDrawQuadProgramPipeline(m_frag->getGlProgram());

	cmdBuff.finish();
}
Ejemplo n.º 4
0
//==============================================================================
void Hdr::run(GlCommandBufferHandle& jobs)
{
	ANKI_ASSERT(m_enabled);

	// For the passes it should be NEAREST
	//vblurFai.setFiltering(Texture::TFrustumType::NEAREST);

	// pass 0
	m_vblurFb.bind(jobs, true);
	jobs.setViewport(0, 0, m_width, m_height);
	m_tonePpline.bind(jobs);

	if(m_parameterUpdateTimestamp > m_commonUboUpdateTimestamp)
	{
		updateDefaultBlock(jobs);
		m_commonUboUpdateTimestamp = getGlobTimestamp();
	}

	m_r->getIs()._getRt().bind(jobs, 0);
	m_commonBuff.bindShaderBuffer(jobs, 0);

	m_r->drawQuad(jobs);

	// Blurring passes
	for(U32 i = 0; i < m_blurringIterationsCount; i++)
	{
		if(i == 0)
		{
			jobs.bindTextures(0, {m_hblurRt, m_vblurRt});
		}

		// hpass
		m_hblurFb.bind(jobs, true);
		m_hblurPpline.bind(jobs);		
		m_r->drawQuad(jobs);

		// vpass
		m_vblurFb.bind(jobs, true);
		m_vblurPpline.bind(jobs);
		m_r->drawQuad(jobs);
	}

	// For the next stage it should be LINEAR though
	//vblurFai.setFiltering(Texture::TFrustumType::LINEAR);
}
Ejemplo n.º 5
0
		Error operator()(GlCommandBuffer* commands)
		{
			GlState& state = commands->getQueue().getState();

			if(state.m_crntPpline != m_ppline._get().getGlName())
			{
				m_ppline._get().bind();

				state.m_crntPpline = m_ppline._get().getGlName();
			}

			return ErrorCode::NONE;
		}
Ejemplo n.º 6
0
//==============================================================================
GlBufferHandle::GlBufferHandle(GlCommandBufferHandle& commands,
                               GLenum target, PtrSize size, GLenum flags)
{
    ANKI_ASSERT(!isCreated());

    using Alloc = GlGlobalHeapAllocator<GlBuffer>;

    using DeleteCommand =
        GlDeleteObjectCommand<GlBuffer, GlGlobalHeapAllocator<U8>>;

    using Deleter = GlHandleDeferredDeleter<GlBuffer, Alloc, DeleteCommand>;

    *static_cast<Base::Base*>(this) = Base::Base(
                                          &commands._getQueue().getDevice(),
                                          commands._getQueue().getDevice()._getAllocator(),
                                          Deleter());
    _setState(GlHandleState::TO_BE_CREATED);

    // Fire the command
    commands._pushBackNewCommand<GlBufferCreateCommand>(
        *this, target, size, flags);
}
		Error operator()(GlCommandBuffer* commands)
		{
			GlState& state = commands->getQueue().getState();

			if(state.m_blendSfunc != m_sfactor 
				|| state.m_blendDfunc != m_dfactor)
			{
				glBlendFunc(m_sfactor, m_dfactor);

				state.m_blendSfunc = m_sfactor;
				state.m_blendDfunc = m_dfactor;
			}

			return ErrorCode::NONE;
		}
		Error operator()(GlCommandBuffer* commands)
		{
			GlState& state = commands->getQueue().getState();

			if(state.m_viewport[0] != m_value[0] 
				|| state.m_viewport[1] != m_value[1]
				|| state.m_viewport[2] != m_value[2] 
				|| state.m_viewport[3] != m_value[3])
			{
				glViewport(m_value[0], m_value[1], m_value[2], m_value[3]);

				state.m_viewport = m_value;
			}

			return ErrorCode::NONE;
		}
//==============================================================================
void GlCommandBufferHandle::pushBackOtherCommandBuffer(
	GlCommandBufferHandle& commands)
{
	class Command: public GlCommand
	{
	public:
		GlCommandBufferHandle m_commands;

		Command(GlCommandBufferHandle& commands)
		:	m_commands(commands)
		{}

		Error operator()(GlCommandBuffer*)
		{
			return m_commands._executeAllCommands();
		}
	};

	commands._get().makeImmutable();
	_pushBackNewCommand<Command>(commands);
}
Ejemplo n.º 10
0
//==============================================================================
void Bs::run(GlCommandBufferHandle& jobs)
{
	jobs.enableDepthTest(true);
	jobs.setDepthWriteMask(false);
	jobs.enableBlend(true);

	RenderableDrawer& drawer = m_r->getSceneDrawer();
	drawer.prepareDraw(RenderingStage::BLEND, Pass::COLOR, jobs);

	Camera& cam = m_r->getSceneGraph().getActiveCamera();

	for(auto& it : cam.getVisibilityTestResults().m_renderables)
	{
		drawer.render(cam, it);
	}

	drawer.finishDraw();

	jobs.enableDepthTest(false);
	jobs.setDepthWriteMask(true);
	jobs.enableBlend(false);
}
		Error operator()(GlCommandBuffer*)
		{
			return m_commands._executeAllCommands();
		}
//==============================================================================
void TextureResource::loadInternal(const CString& filename, 
	ResourceInitializer& rinit)
{
	GlDevice& gl = rinit.m_resources._getGlDevice();
	GlCommandBufferHandle cmdb;
	cmdb.create(&gl); // Always first to avoid assertions (
	                  // because of the check of the allocator)

	GlTextureHandle::Initializer init;
	U layers = 0;
	Bool driverShouldGenMipmaps = false;

	// Load image
	Image* imgPtr = rinit.m_alloc.newInstance<Image>(rinit.m_alloc);
	Image& img = *imgPtr;
	img.load(filename, rinit.m_resources.getMaxTextureSize());
	
	// width + height
	init.m_width = img.getSurface(0, 0).m_width;
	init.m_height = img.getSurface(0, 0).m_height;
	
	// depth
	if(img.getTextureType() == Image::TextureType::_2D_ARRAY 
		|| img.getTextureType() == Image::TextureType::_3D)
	{
		init.m_depth = img.getDepth();
	}
	else
	{
		init.m_depth = 0;
	}

	// target
	switch(img.getTextureType())
	{
	case Image::TextureType::_2D:
		init.m_target = GL_TEXTURE_2D;
		layers = 1;
		break;
	case Image::TextureType::CUBE:
		init.m_target = GL_TEXTURE_CUBE_MAP;
		layers = 6;
		break;
	case Image::TextureType::_2D_ARRAY:
		init.m_target = GL_TEXTURE_2D_ARRAY;
		layers = init.m_depth;
		break;
	case Image::TextureType::_3D:
		init.m_target = GL_TEXTURE_3D;
		layers = init.m_depth;
	default:
		ANKI_ASSERT(0);
	}

	// Internal format
	if(img.getColorFormat() == Image::ColorFormat::RGB8)
	{
		switch(img.getCompression())
		{
		case Image::DataCompression::RAW:
#if DRIVER_CAN_COMPRESS
			init.m_internalFormat = GL_COMPRESSED_RGB;
#else
			init.m_internalFormat = GL_RGB;
#endif
			driverShouldGenMipmaps = true;
			break;
#if ANKI_GL == ANKI_GL_DESKTOP
		case Image::DataCompression::S3TC:
			init.m_internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
			break;
#else
		case Image::DataCompression::ETC:
			init.m_internalFormat = GL_COMPRESSED_RGB8_ETC2;
			break;
#endif
		default:
			ANKI_ASSERT(0);
		}
	}
	else if(img.getColorFormat() == Image::ColorFormat::RGBA8)
	{
		switch(img.getCompression())
		{
		case Image::DataCompression::RAW:
#if DRIVER_CAN_COMPRESS
			init.m_internalFormat = GL_COMPRESSED_RGBA;
#else
			init.m_internalFormat = GL_RGBA;
#endif
			driverShouldGenMipmaps = true;
			break;
#if ANKI_GL == ANKI_GL_DESKTOP
		case Image::DataCompression::S3TC:
			init.m_internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
			break;
#else
		case Image::DataCompression::ETC:
			init.m_internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC;
			break;
#endif
		default:
			ANKI_ASSERT(0);
		}
	}
	else
	{
		ANKI_ASSERT(0);
	}

	// format
	switch(img.getColorFormat())
	{
	case Image::ColorFormat::RGB8:
		init.m_format = GL_RGB;
		break;
	case Image::ColorFormat::RGBA8:
		init.m_format = GL_RGBA;
		break;
	default:
		ANKI_ASSERT(0);
	}

	// type
	init.m_type = GL_UNSIGNED_BYTE;

	// mipmapsCount
	init.m_mipmapsCount = img.getMipLevelsCount();

	// filteringType
	init.m_filterType = GlTextureHandle::Filter::TRILINEAR;

	// repeat
	init.m_repeat = true;

	// anisotropyLevel
	init.m_anisotropyLevel = rinit.m_resources.getTextureAnisotropy();

	// genMipmaps
	if(init.m_mipmapsCount == 1 || driverShouldGenMipmaps)
	{
		init.m_genMipmaps = true;
	}
	else
	{
		init.m_genMipmaps = false;
	}

	// Now assign the data
	for(U layer = 0; layer < layers; layer++)
	{
		for(U level = 0; level < init.m_mipmapsCount; level++)
		{
			GlClientBufferHandle& buff = init.m_data[level][layer];

			buff.create(
				cmdb, 
				img.getSurface(level, layer).m_data.size(), 
				(void*)&img.getSurface(level, layer).m_data[0]);
		}
	}

	// Add the GL job to create the texture
	m_tex.create(cmdb, init);

	// Add cleanup job
	cmdb.pushBackUserCommand(deleteImageCallback, imgPtr);

	// Finaly enque the GL job chain
	cmdb.flush();

	m_size = UVec3(init.m_width, init.m_height, init.m_depth);
}
Ejemplo n.º 13
0
//==============================================================================
void Pps::run(GlCommandBufferHandle& cmdBuff)
{
	ANKI_ASSERT(m_enabled);

	// First SSAO because it depends on MS where HDR depends on IS
	if(m_ssao.getEnabled())
	{
		m_ssao.run(cmdBuff);
	}

	// Then SSLR because HDR depends on it
	if(m_sslr.getEnabled())
	{
		m_sslr.run(cmdBuff);
	}

	if(m_hdr.getEnabled())
	{
		m_hdr.run(cmdBuff);
	}

	if(m_lf.getEnabled())
	{
		m_lf.run(cmdBuff);
	}

	Bool drawToDefaultFbo = 
		!m_r->getDbg().getEnabled() 
		&& !m_r->getIsOffscreen()
		&& m_r->getRenderingQuality() == 1.0;

	if(drawToDefaultFbo)
	{
		m_r->getDefaultFramebuffer().bind(cmdBuff, true);
		cmdBuff.setViewport(0, 0, m_r->getWindowWidth(), m_r->getWindowHeight());
	}
	else
	{
		m_fb.bind(cmdBuff, true);
		cmdBuff.setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
	}

	m_ppline.bind(cmdBuff);

	m_r->getIs()._getRt().bind(cmdBuff, 0);

	if(m_ssao.getEnabled())
	{
		m_ssao.getRt().bind(cmdBuff, 1);
	}

	if(m_lf.getEnabled())
	{
		m_lf._getRt().bind(cmdBuff, 2);
	}
	else if(m_hdr.getEnabled())
	{
		m_hdr._getRt().bind(cmdBuff, 2);
	}

	m_r->drawQuad(cmdBuff);
}
Ejemplo n.º 14
0
//==============================================================================
void Ssao::initInternal(const ConfigSet& config)
{
	m_enabled = config.get("pps.ssao.enabled");

	if(!m_enabled)
	{
		return;
	}

	m_blurringIterationsCount = 
		config.get("pps.ssao.blurringIterationsCount");

	//
	// Init the widths/heights
	//
	const F32 quality = config.get("pps.ssao.renderingQuality");

	m_width = quality * (F32)m_r->getWidth();
	alignRoundUp(16, m_width);
	m_height = quality * (F32)m_r->getHeight();
	alignRoundUp(16, m_height);

	//
	// create FBOs
	//
	createFb(m_hblurFb, m_hblurRt);
	createFb(m_vblurFb, m_vblurRt);

	//
	// noise texture
	//
	GlCommandBufferHandle cmdb;
	cmdb.create(&getGlDevice());

	GlClientBufferHandle noise;
	noise.create(
		cmdb, sizeof(Vec3) * NOISE_TEX_SIZE * NOISE_TEX_SIZE, nullptr);

	genNoise((Vec3*)noise.getBaseAddress(), 
		(Vec3*)((U8*)noise.getBaseAddress() + noise.getSize()));

	GlTextureHandle::Initializer tinit;

	tinit.m_width = tinit.m_height = NOISE_TEX_SIZE;
	tinit.m_target = GL_TEXTURE_2D;
	tinit.m_internalFormat = GL_RGB32F;
	tinit.m_format = GL_RGB;
	tinit.m_type = GL_FLOAT;
	tinit.m_filterType = GlTextureHandle::Filter::NEAREST;
	tinit.m_repeat = true;
	tinit.m_mipmapsCount = 1;
	tinit.m_data[0][0] = noise;

	m_noiseTex.create(cmdb, tinit);

	//
	// Kernel
	//
	String kernelStr(getAllocator());
	Array<Vec3, KERNEL_SIZE> kernel;

	genKernel(kernel.begin(), kernel.end());
	kernelStr = "vec3[](";
	for(U i = 0; i < kernel.size(); i++)
	{
		String tmp(getAllocator());

		tmp.sprintf("vec3(%f, %f, %f) %s",
			kernel[i].x(), kernel[i].y(), kernel[i].z(),
			(i != kernel.size() - 1) ? ", " : ")");

		kernelStr += tmp;
	}

	//
	// Shaders
	//
	m_uniformsBuff.create(cmdb, GL_SHADER_STORAGE_BUFFER, 
		sizeof(ShaderCommonUniforms), GL_DYNAMIC_STORAGE_BIT);

	String pps(getAllocator());

	// main pass prog
	pps.sprintf(
		"#define NOISE_MAP_SIZE %u\n"
		"#define WIDTH %u\n"
		"#define HEIGHT %u\n"
		"#define KERNEL_SIZE %u\n"
		"#define KERNEL_ARRAY %s\n",
		NOISE_TEX_SIZE, m_width, m_height, KERNEL_SIZE, &kernelStr[0]);

	m_ssaoFrag.loadToCache(&getResourceManager(),
		"shaders/PpsSsao.frag.glsl", pps.toCString(), "r_");


	m_ssaoPpline = m_r->createDrawQuadProgramPipeline(
		m_ssaoFrag->getGlProgram());

	// blurring progs
	const char* SHADER_FILENAME = 
		"shaders/VariableSamplingBlurGeneric.frag.glsl";

	pps.sprintf(
		"#define HPASS\n"
		"#define COL_R\n"
		"#define IMG_DIMENSION %u\n"
		"#define SAMPLES 7\n", 
		m_height);

	m_hblurFrag.loadToCache(&getResourceManager(),
		SHADER_FILENAME, pps.toCString(), "r_");

	m_hblurPpline = m_r->createDrawQuadProgramPipeline(
		m_hblurFrag->getGlProgram());

	pps.sprintf(
		"#define VPASS\n"
		"#define COL_R\n"
		"#define IMG_DIMENSION %u\n"
		"#define SAMPLES 7\n", 
		m_width);

	m_vblurFrag.loadToCache(&getResourceManager(),
		SHADER_FILENAME, pps.toCString(), "r_");

	m_vblurPpline = m_r->createDrawQuadProgramPipeline(
		m_vblurFrag->getGlProgram());

	cmdb.flush();
}
Ejemplo n.º 15
0
//==============================================================================
void Ssao::run(GlCommandBufferHandle& cmdb)
{
	ANKI_ASSERT(m_enabled);

	const Camera& cam = m_r->getSceneGraph().getActiveCamera();

	cmdb.setViewport(0, 0, m_width, m_height);

	// 1st pass
	//
	m_vblurFb.bind(cmdb, true);
	m_ssaoPpline.bind(cmdb);

	m_uniformsBuff.bindShaderBuffer(cmdb, 0);

	Array<GlTextureHandle, 3> tarr = {{
		m_r->getMs()._getSmallDepthRt(),
		m_r->getMs()._getRt1(),
		m_noiseTex}};
	cmdb.bindTextures(0, tarr.begin(), tarr.getSize());

	// Write common block
	if(m_commonUboUpdateTimestamp 
			< m_r->getProjectionParametersUpdateTimestamp()
		|| m_commonUboUpdateTimestamp < cam.FrustumComponent::getTimestamp()
		|| m_commonUboUpdateTimestamp == 1)
	{
		GlClientBufferHandle tmpBuff;
		tmpBuff.create(cmdb, sizeof(ShaderCommonUniforms),
			nullptr);

		ShaderCommonUniforms& blk = 
			*((ShaderCommonUniforms*)tmpBuff.getBaseAddress());

		blk.m_projectionParams = m_r->getProjectionParameters();

		blk.m_projectionMatrix = cam.getProjectionMatrix().getTransposed();

		m_uniformsBuff.write(cmdb, tmpBuff, 0, 0, tmpBuff.getSize());
		m_commonUboUpdateTimestamp = getGlobTimestamp();
	}

	// Draw
	m_r->drawQuad(cmdb);

	// Blurring passes
	//
	for(U i = 0; i < m_blurringIterationsCount; i++)
	{
		if(i == 0)
		{
			Array<GlTextureHandle, 2> tarr = {{m_hblurRt, m_vblurRt}};
			cmdb.bindTextures(0, tarr.begin(), tarr.getSize());
		}

		// hpass
		m_hblurFb.bind(cmdb, true);
		m_hblurPpline.bind(cmdb);
		m_r->drawQuad(cmdb);

		// vpass
		m_vblurFb.bind(cmdb, true);
		m_vblurPpline.bind(cmdb);
		m_r->drawQuad(cmdb);
	}
}