예제 #1
0
Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
{
	ANKI_LOGI("Initializing Vulkan backend");
	ANKI_CHECK(initInstance(init));
	ANKI_CHECK(initSurface(init));
	ANKI_CHECK(initDevice(init));
	vkGetDeviceQueue(m_device, m_queueIdx, 0, &m_queue);
	ANKI_CHECK(initSwapchain(init));

	{
		VkPipelineCacheCreateInfo ci = {};
		ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
		vkCreatePipelineCache(m_device, &ci, nullptr, &m_pplineCache);
	}

	ANKI_CHECK(initMemory(*init.m_config));
	ANKI_CHECK(m_dsetAlloc.init(getAllocator(), m_device));
	m_pplineLayFactory.init(getAllocator(), m_device, &m_dsetAlloc.getDescriptorSetLayoutFactory());

	for(PerFrame& f : m_perFrame)
	{
		resetFrame(f);
	}

	glslang::InitializeProcess();
	m_fences.init(getAllocator(), m_device);
	m_semaphores.init(getAllocator(), m_device);

	m_queryAlloc.init(getAllocator(), m_device);

	m_samplerCache = getAllocator().newInstance<GrObjectCache>(m_manager);

	// Set m_r8g8b8ImagesSupported
	{
		VkImageFormatProperties props = {};
		VkResult res = vkGetPhysicalDeviceImageFormatProperties(m_physicalDevice,
			VK_FORMAT_R8G8B8_UNORM,
			VK_IMAGE_TYPE_2D,
			VK_IMAGE_TILING_OPTIMAL,
			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
			0,
			&props);

		if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
		{
			ANKI_LOGI("R8G8B8 Images are not supported. Will workaround this");
			m_r8g8b8ImagesSupported = false;
		}
		else
		{
			ANKI_ASSERT(res == VK_SUCCESS);
			ANKI_LOGI("R8G8B8 Images are supported");
			m_r8g8b8ImagesSupported = true;
		}
	}

	// Set m_s8ImagesSupported
	{
		VkImageFormatProperties props = {};
		VkResult res = vkGetPhysicalDeviceImageFormatProperties(m_physicalDevice,
			VK_FORMAT_S8_UINT,
			VK_IMAGE_TYPE_2D,
			VK_IMAGE_TILING_OPTIMAL,
			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
			0,
			&props);

		if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
		{
			ANKI_LOGI("S8 Images are not supported. Will workaround this");
			m_s8ImagesSupported = false;
		}
		else
		{
			ANKI_ASSERT(res == VK_SUCCESS);
			ANKI_LOGI("S8 Images are supported");
			m_s8ImagesSupported = true;
		}
	}

	// Set m_d24S8ImagesSupported
	{
		VkImageFormatProperties props = {};
		VkResult res = vkGetPhysicalDeviceImageFormatProperties(m_physicalDevice,
			VK_FORMAT_D24_UNORM_S8_UINT,
			VK_IMAGE_TYPE_2D,
			VK_IMAGE_TILING_OPTIMAL,
			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
			0,
			&props);

		if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
		{
			ANKI_LOGI("D24S8 Images are not supported. Will workaround this");
			m_d24S8ImagesSupported = false;
		}
		else
		{
			ANKI_ASSERT(res == VK_SUCCESS);
			ANKI_LOGI("D24S8 Images are supported");
			m_d24S8ImagesSupported = true;
		}
	}

	return ErrorCode::NONE;
}
예제 #2
0
//==============================================================================
SceneFrameAllocator<U8> SceneNode::getFrameAllocator() const
{
	ANKI_ASSERT(m_scene);
	return m_scene->getFrameAllocator();
}
		Command(UserCallback callback, void* userData)
		:	m_callback(callback),
			m_userData(userData)
		{
			ANKI_ASSERT(m_callback);
		}
예제 #4
0
//==============================================================================
ProgramResourcePointer& Material::getProgram(
	const RenderingKey key, U32 shaderId)
{
	ANKI_ASSERT((U)key.m_pass < m_passesCount);
	ANKI_ASSERT(key.m_lod < m_lodsCount);

	if(key.m_tessellation)
	{
		ANKI_ASSERT(m_tessellation);
	}

	// Calc the count that are before this shader
	U tessCount = m_tessellation ? 2 : 1;
	U count = 0;
	switch(shaderId)
	{
	case 4:
		// Count of geom
		count += 0;
	case 3:
		// Count of tess
		if(m_tessellation)
		{
			count += m_passesCount * m_lodsCount;
		}
	case 2:
		// Count of tess
		if(m_tessellation)
		{
			count += m_passesCount * m_lodsCount;
		}
	case 1:
		// Count of vert
		count += m_passesCount * m_lodsCount * tessCount;
	case 0:
		break;
	default:
		ANKI_ASSERT(0);
	}

	// Calc the idx
	U idx = 0;
	switch(shaderId)
	{
	case 0:
		idx = (U)key.m_pass * m_lodsCount * tessCount + key.m_lod * tessCount 
			+ (key.m_tessellation ? 1 : 0);
		break;
	case 1:
	case 2:
	case 4:
		idx = (U)key.m_pass * m_lodsCount + key.m_lod;
		break;
	default:
		ANKI_ASSERT(0);
	}

	idx += count;
	ANKI_ASSERT(idx < m_progs.size());
	ProgramResourcePointer& out = m_progs[idx];

	if(out.isLoaded())
	{
		ANKI_ASSERT(
			computeShaderTypeIndex(out->getGlProgram().getType()) == shaderId);
	}

	return out;
}
예제 #5
0
//==============================================================================
void Material::populateVariables(const MaterialProgramCreator& mspc)
{
	for(auto in : mspc.getInputVariables())
	{
		if(in.m_constant)
		{
			continue;
		}

		MaterialVariable* mtlvar = nullptr;
		const GlProgramVariable* glvar = nullptr;

		// Find the input variable in one of the programs
		for(const ProgramResourcePointer& progr : m_progs)
		{
			const GlProgramHandle& prog = progr->getGlProgram();

			glvar = prog.tryFindVariable(in.m_name.toCString());
			if(glvar)
			{
				break;
			}
		}

		// Check if variable found
		if(glvar == nullptr)
		{
			throw ANKI_EXCEPTION("Variable not found in "
				"at least one program: %s", &in.m_name[0]);
		}

		switch(glvar->getDataType())
		{
		// samplers
		case GL_SAMPLER_2D:
		case GL_SAMPLER_CUBE:
			{
				TextureResourcePointer tp;
				
				if(in.m_value.size() > 0)
				{
					tp = TextureResourcePointer(
						in.m_value[0].toCString(),
						m_resources);
				}

				auto alloc = m_resources->_getAllocator();
				mtlvar = alloc.newInstance<
					MaterialVariableTemplate<TextureResourcePointer>>(
					glvar, false, &tp, 1, alloc);
			}
			break;
		// F32
		case GL_FLOAT:
			mtlvar = newMaterialVariable<F32>(*glvar, in,
				m_resources->_getAllocator(), m_resources->_getTempAllocator());
			break;
		// vec2
		case GL_FLOAT_VEC2:
			mtlvar = newMaterialVariable<Vec2>(*glvar, in,
				m_resources->_getAllocator(), m_resources->_getTempAllocator());
			break;
		// vec3
		case GL_FLOAT_VEC3:
			mtlvar = newMaterialVariable<Vec3>(*glvar, in,
				m_resources->_getAllocator(), m_resources->_getTempAllocator());
			break;
		// vec4
		case GL_FLOAT_VEC4:
			mtlvar = newMaterialVariable<Vec4>(*glvar, in,
				m_resources->_getAllocator(), m_resources->_getTempAllocator());
			break;
		// mat3
		case GL_FLOAT_MAT3:
			mtlvar = newMaterialVariable<Mat3>(*glvar, in,
				m_resources->_getAllocator(), m_resources->_getTempAllocator());
			break;
		// mat4
		case GL_FLOAT_MAT4:
			mtlvar = newMaterialVariable<Mat4>(*glvar, in,
				m_resources->_getAllocator(), m_resources->_getTempAllocator());
			break;
		// default is error
		default:
			ANKI_ASSERT(0);
		}

		m_vars.push_back(mtlvar);
	}
}
예제 #6
0
//==============================================================================
void Pps::run(GlCommandBufferHandle& jobs)
{
	ANKI_ASSERT(m_enabled);

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

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

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

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

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

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

	m_ppline.bind(jobs);

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

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

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

	m_r->drawQuad(jobs);
}
예제 #7
0
//==============================================================================
Bool Gjk::update(const Support& a)
{
	if(m_count == 2)
	{
		Vec4 ao = -a.m_v;

		// Compute the vectors parallel to the edges we'll test
		Vec4 ab = m_simplex[1].m_v - a.m_v;
		Vec4 ac = m_simplex[2].m_v - a.m_v;

		// Compute the triangle's normal
		Vec4 abc = ab.cross(ac);

		// Compute a vector within the plane of the triangle,
		// Pointing away from the edge ab
		Vec4 abp = ab.cross(abc);

		if(abp.dot(ao) > 0.0)
		{
			// The origin lies outside the triangle, near the edge ab
			m_simplex[2] = m_simplex[1];
			m_simplex[1] = a;

			m_dir = crossAba(ab, ao);

			return false;
		}

		// Perform a similar test for the edge ac
		Vec4 acp = abc.cross(ac);

		if(acp.dot(ao) > 0.0)
		{
			m_simplex[1] = a;
			m_dir = crossAba(ac, ao);

			return false;
		}

		// If we get here, then the origin must be within the triangle,
		// but we care whether it is above or below it, so test
		if(abc.dot(ao) > 0.0)
		{
			m_simplex[3] = m_simplex[2];
			m_simplex[2] = m_simplex[1];
			m_simplex[1] = a;

			m_dir = abc;
		}
		else
		{
			m_simplex[3] = m_simplex[1];
			m_simplex[1] = a;

			m_dir = -abc;
		}

		m_count = 3;

		// Again, need a tetrahedron to enclose the origin
		return false;
	}
	else if(m_count == 3)
	{
		Vec4 ao = -a.m_v;

		Vec4 ab = m_simplex[1].m_v - a.m_v;
		Vec4 ac = m_simplex[2].m_v - a.m_v;

		Vec4 abc = ab.cross(ac);

		Vec4 ad, acd, adb;

		if(abc.dot(ao) > 0.0)
		{
			// In front of triangle ABC
			goto check_face;
		}

		ad = m_simplex[3].m_v - a.m_v;
		acd = ac.cross(ad);

		if(acd.dot(ao) > 0.0)
		{
			// In front of triangle ACD
			m_simplex[1] = m_simplex[2];
			m_simplex[2] = m_simplex[3];

			ab = ac;
			ac = ad;

			abc = acd;
			goto check_face;
		}

		adb = ad.cross(ab);

		if(adb.dot(ao) > 0.0)
		{
			// In front of triangle ADB

			m_simplex[2] = m_simplex[1];
			m_simplex[1] = m_simplex[3];

			ac = ab;
			ab = ad;

			abc = adb;
			goto check_face;
		}

		// Behind all three faces, the origin is in the tetrahedron, we're done
		m_simplex[0] = a;
		m_count = 4;
		return true;

	check_face:

		// We have a CCW wound triangle ABC
		// the point is in front of this triangle
		// it is NOT "below" edge BC
		// it is NOT "above" the plane through A that's parallel to BC
		Vec4 abp = ab.cross(abc);

		if(abp.dot(ao) > 0.0)
		{
			m_simplex[2] = m_simplex[1];
			m_simplex[1] = a;

			m_dir = crossAba(ab, ao);

			m_count = 2;
			return false;
		}

		Vec4 acp = abc.cross(ac);

		if(acp.dot(ao) > 0.0)
		{
			m_simplex[1] = a;

			m_dir = crossAba(ac, ao);

			m_count = 2;
			return false;
		}

		m_simplex[3] = m_simplex[2];
		m_simplex[2] = m_simplex[1];
		m_simplex[1] = a;

		m_dir = abc;
		m_count = 3;

		return false;
	}

	ANKI_ASSERT(0);
	return true;
}
예제 #8
0
void PipelineImpl::initVertexState()
{
	for(U i = 0; i < m_in.m_vertex.m_attributeCount; ++i)
	{
		const VertexAttributeBinding& binding = m_in.m_vertex.m_attributes[i];
		Attribute& cache = m_cache.m_attribs[i];

		// Component count
		if(binding.m_format == PixelFormat(ComponentFormat::R32, TransformFormat::FLOAT))
		{
			cache.m_compCount = 1;
			cache.m_type = GL_FLOAT;
			cache.m_normalized = false;
		}
		else if(binding.m_format == PixelFormat(ComponentFormat::R32G32, TransformFormat::FLOAT))
		{
			cache.m_compCount = 2;
			cache.m_type = GL_FLOAT;
			cache.m_normalized = false;
		}
		else if(binding.m_format == PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT))
		{
			cache.m_compCount = 3;
			cache.m_type = GL_FLOAT;
			cache.m_normalized = false;
		}
		else if(binding.m_format == PixelFormat(ComponentFormat::R32G32B32A32, TransformFormat::FLOAT))
		{
			cache.m_compCount = 4;
			cache.m_type = GL_FLOAT;
			cache.m_normalized = false;
		}
		else if(binding.m_format == PixelFormat(ComponentFormat::R16G16, TransformFormat::FLOAT))
		{
			cache.m_compCount = 2;
			cache.m_type = GL_HALF_FLOAT;
			cache.m_normalized = false;
		}
		else if(binding.m_format == PixelFormat(ComponentFormat::R16G16, TransformFormat::UNORM))
		{
			cache.m_compCount = 2;
			cache.m_type = GL_UNSIGNED_SHORT;
			cache.m_normalized = true;
		}
		else if(binding.m_format == PixelFormat(ComponentFormat::R10G10B10A2, TransformFormat::SNORM))
		{
			cache.m_compCount = 4;
			cache.m_type = GL_INT_2_10_10_10_REV;
			cache.m_normalized = true;
		}
		else if(binding.m_format == PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM))
		{
			cache.m_compCount = 4;
			cache.m_type = GL_UNSIGNED_BYTE;
			cache.m_normalized = true;
		}
		else if(binding.m_format == PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM))
		{
			cache.m_compCount = 3;
			cache.m_type = GL_UNSIGNED_BYTE;
			cache.m_normalized = true;
		}
		else
		{
			ANKI_ASSERT(0 && "TODO");
		}
	}

	m_hashes.m_vertex = computeHash(&m_in.m_vertex, sizeof(m_in.m_vertex));
}
예제 #9
0
static void deletePrograms(GLsizei n, const GLuint* names)
{
	ANKI_ASSERT(n == 1);
	ANKI_ASSERT(names);
	glDeleteProgram(*names);
}
예제 #10
0
Error PipelineImpl::createGlPipeline()
{
	Error err = ErrorCode::NONE;

	// Do checks
	U mask = 0;
	U count = 6;
	while(count-- != 0)
	{
		const ShaderPtr& shader = m_in.m_shaders[count];
		if(shader.isCreated())
		{
			ANKI_ASSERT(count == enumToType(shader->m_impl->m_type));
			mask |= 1 << count;
		}
	}

	if(mask & (1 << 5))
	{
		// Is compute

		m_compute = true;

		ANKI_ASSERT((mask & (1 << 5)) == (1 << 5) && "Compute should be alone in the pipeline");
	}
	else
	{
		m_compute = false;

		const U fragVert = (1 << 0) | (1 << 4);
		ANKI_ASSERT((mask & fragVert) && "Should contain vert and frag");
		(void)fragVert;

		const U tess = (1 << 1) | (1 << 2);
		if((mask & tess) != 0)
		{
			ANKI_ASSERT(((mask & tess) == 0x6) && "Should set both the tessellation shaders");
		}
	}

	// Create and attach programs
	m_glName = glCreateProgram();
	ANKI_ASSERT(m_glName != 0);

	for(U i = 0; i < m_in.m_shaders.getSize(); i++)
	{
		ShaderPtr& shader = m_in.m_shaders[i];

		if(shader.isCreated())
		{
			glAttachShader(m_glName, shader->m_impl->getGlName());

			if(i == U(ShaderType::TESSELLATION_CONTROL) || i == U(ShaderType::TESSELLATION_EVALUATION))
			{
				m_tessellation = true;
			}
		}
	}

	// Validate and check error
	glLinkProgram(m_glName);
	GLint status = 0;
	glGetProgramiv(m_glName, GL_LINK_STATUS, &status);

	if(!status)
	{
		GLint infoLen = 0;
		GLint charsWritten = 0;
		DynamicArrayAuto<char> infoLogTxt(getAllocator());

		glGetProgramiv(m_glName, GL_INFO_LOG_LENGTH, &infoLen);

		infoLogTxt.create(infoLen + 1);

		glGetProgramInfoLog(m_glName, infoLen, &charsWritten, &infoLogTxt[0]);

		ANKI_LOGE("Ppline error log follows (vs:%u, fs:%u):\n%s",
			m_in.m_shaders[ShaderType::VERTEX].isCreated() ? m_in.m_shaders[ShaderType::VERTEX]->m_impl->getGlName()
														   : -1,
			m_in.m_shaders[ShaderType::FRAGMENT].isCreated() ? m_in.m_shaders[ShaderType::FRAGMENT]->m_impl->getGlName()
															 : -1,
			&infoLogTxt[0]);
		err = ErrorCode::USER_DATA;
	}

	return err;
}
예제 #11
0
static GLenum convertBlendMethod(BlendMethod in)
{
	GLenum out = 0;

	switch(in)
	{
	case BlendMethod::ZERO:
		out = GL_ZERO;
		break;
	case BlendMethod::ONE:
		out = GL_ONE;
		break;
	case BlendMethod::SRC_COLOR:
		out = GL_SRC_COLOR;
		break;
	case BlendMethod::ONE_MINUS_SRC_COLOR:
		out = GL_ONE_MINUS_SRC_COLOR;
		break;
	case BlendMethod::DST_COLOR:
		out = GL_DST_COLOR;
		break;
	case BlendMethod::ONE_MINUS_DST_COLOR:
		out = GL_ONE_MINUS_DST_COLOR;
		break;
	case BlendMethod::SRC_ALPHA:
		out = GL_SRC_ALPHA;
		break;
	case BlendMethod::ONE_MINUS_SRC_ALPHA:
		out = GL_ONE_MINUS_SRC_ALPHA;
		break;
	case BlendMethod::DST_ALPHA:
		out = GL_DST_ALPHA;
		break;
	case BlendMethod::ONE_MINUS_DST_ALPHA:
		out = GL_ONE_MINUS_DST_ALPHA;
		break;
	case BlendMethod::CONSTANT_COLOR:
		out = GL_CONSTANT_COLOR;
		break;
	case BlendMethod::ONE_MINUS_CONSTANT_COLOR:
		out = GL_ONE_MINUS_CONSTANT_COLOR;
		break;
	case BlendMethod::CONSTANT_ALPHA:
		out = GL_CONSTANT_ALPHA;
		break;
	case BlendMethod::ONE_MINUS_CONSTANT_ALPHA:
		out = GL_ONE_MINUS_CONSTANT_ALPHA;
		break;
	case BlendMethod::SRC_ALPHA_SATURATE:
		out = GL_SRC_ALPHA_SATURATE;
		break;
	case BlendMethod::SRC1_COLOR:
		out = GL_SRC1_COLOR;
		break;
	case BlendMethod::ONE_MINUS_SRC1_COLOR:
		out = GL_ONE_MINUS_SRC1_COLOR;
		break;
	case BlendMethod::SRC1_ALPHA:
		out = GL_SRC1_ALPHA;
		break;
	case BlendMethod::ONE_MINUS_SRC1_ALPHA:
		out = GL_ONE_MINUS_SRC1_ALPHA;
		break;
	default:
		ANKI_ASSERT(0);
	}

	return out;
}
예제 #12
0
//==============================================================================
void EventManager::unregisterEvent(EventsContainer::Iterator it)
{	
	ANKI_ASSERT(it != m_events.getEnd());
	m_events.erase(getSceneAllocator(), it);
}
예제 #13
0
//==============================================================================
void EventManager::registerEvent(Event* event)
{
	ANKI_ASSERT(event);
	m_events.pushBack(getSceneAllocator(), event);
}
예제 #14
0
//==============================================================================
Error EventManager::create(SceneGraph* scene)
{
	ANKI_ASSERT(scene);
	m_scene = scene;
	return ErrorCode::NONE;
}
예제 #15
0
Error GrManagerImpl::initSwapchain(const GrManagerInitInfo& init)
{
	VkSurfaceCapabilitiesKHR surfaceProperties;
	ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &surfaceProperties));

	if(surfaceProperties.currentExtent.width == MAX_U32 || surfaceProperties.currentExtent.height == MAX_U32)
	{
		ANKI_LOGE("Wrong surface size");
		return ErrorCode::FUNCTION_FAILED;
	}
	m_surfaceWidth = surfaceProperties.currentExtent.width;
	m_surfaceHeight = surfaceProperties.currentExtent.height;

	uint32_t formatCount;
	ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr));

	DynamicArrayAuto<VkSurfaceFormatKHR> formats(getAllocator());
	formats.create(formatCount);
	ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, &formats[0]));

	VkColorSpaceKHR colorspace = VK_COLOR_SPACE_MAX_ENUM_KHR;
	while(formatCount--)
	{
		if(formats[formatCount].format == VK_FORMAT_B8G8R8A8_UNORM)
		{
			m_surfaceFormat = formats[formatCount].format;
			colorspace = formats[formatCount].colorSpace;
			break;
		}
	}

	if(m_surfaceFormat == VK_FORMAT_UNDEFINED)
	{
		ANKI_LOGE("Surface format not found");
		return ErrorCode::FUNCTION_FAILED;
	}

	// Chose present mode
	uint32_t presentModeCount;
	vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, nullptr);
	presentModeCount = min(presentModeCount, 4u);
	Array<VkPresentModeKHR, 4> presentModes;
	vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, &presentModes[0]);

	VkPresentModeKHR presentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
	if(init.m_config->getNumber("vsync"))
	{
		presentMode = VK_PRESENT_MODE_FIFO_KHR;
	}
	else
	{
		for(U i = 0; i < presentModeCount; ++i)
		{
			if(presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
			{
				presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
				break;
			}
			else if(presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)
			{
				presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
				break;
			}
		}
	}

	if(presentMode == VK_PRESENT_MODE_MAX_ENUM_KHR)
	{
		ANKI_LOGE("VK: Couldn't find a present mode");
		return ErrorCode::FUNCTION_FAILED;
	}

	// Create swapchain
	VkSwapchainCreateInfoKHR ci = {};
	ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
	ci.surface = m_surface;
	ci.minImageCount = MAX_FRAMES_IN_FLIGHT;
	ci.imageFormat = m_surfaceFormat;
	ci.imageColorSpace = colorspace;
	ci.imageExtent = surfaceProperties.currentExtent;
	ci.imageArrayLayers = 1;
	ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
	ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
	ci.queueFamilyIndexCount = 1;
	ci.pQueueFamilyIndices = &m_queueIdx;
	ci.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
	ci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
	ci.presentMode = presentMode;
	ci.clipped = false;
	ci.oldSwapchain = VK_NULL_HANDLE;

	ANKI_VK_CHECK(vkCreateSwapchainKHR(m_device, &ci, nullptr, &m_swapchain));

	// Get images
	uint32_t count = 0;
	ANKI_VK_CHECK(vkGetSwapchainImagesKHR(m_device, m_swapchain, &count, nullptr));
	if(count != MAX_FRAMES_IN_FLIGHT)
	{
		ANKI_LOGE("Requested a swapchain with %u images but got one with %u", MAX_FRAMES_IN_FLIGHT, count);
		return ErrorCode::FUNCTION_FAILED;
	}

	ANKI_LOGI("VK: Created a swapchain. Image count: %u, present mode: %u", count, presentMode);

	Array<VkImage, MAX_FRAMES_IN_FLIGHT> images;
	ANKI_VK_CHECK(vkGetSwapchainImagesKHR(m_device, m_swapchain, &count, &images[0]));
	for(U i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
	{
		m_backbuffers[i].m_image = images[i];
		ANKI_ASSERT(images[i]);
	}

	// Create img views
	for(U i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
	{
		VkImageViewCreateInfo ci = {};
		ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
		ci.flags = 0;
		ci.image = m_backbuffers[i].m_image;
		ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
		ci.format = m_surfaceFormat;
		ci.components = {
			VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
		ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
		ci.subresourceRange.baseMipLevel = 0;
		ci.subresourceRange.levelCount = 1;
		ci.subresourceRange.baseArrayLayer = 0;
		ci.subresourceRange.layerCount = 1;

		ANKI_VK_CHECK(vkCreateImageView(m_device, &ci, nullptr, &m_backbuffers[i].m_imageView));
	}

	return ErrorCode::NONE;
}
예제 #16
0
Error Is::initInternal(const ConfigSet& config)
{
	m_maxLightIds = config.getNumber("is.maxLightsPerCluster");

	if(m_maxLightIds == 0)
	{
		ANKI_LOGE("Incorrect number of max light indices");
		return ErrorCode::USER_DATA;
	}

	m_rtMipCount = computeMaxMipmapCount2d(m_r->getWidth(), m_r->getHeight(), 32);
	ANKI_ASSERT(m_rtMipCount);

	U clusterCount = m_r->getTileCountXY().x() * m_r->getTileCountXY().y() * config.getNumber("clusterSizeZ");
	m_clusterCount = clusterCount;
	m_maxLightIds *= clusterCount;

	m_lightBin = getAllocator().newInstance<LightBin>(getAllocator(),
		m_r->getTileCountXY().x(),
		m_r->getTileCountXY().y(),
		config.getNumber("clusterSizeZ"),
		&m_r->getThreadPool(),
		&getGrManager());

	//
	// Load the programs
	//
	StringAuto pps(getAllocator());

	pps.sprintf("\n#define TILE_COUNT_X %u\n"
				"#define TILE_COUNT_Y %u\n"
				"#define CLUSTER_COUNT %u\n"
				"#define RENDERER_WIDTH %u\n"
				"#define RENDERER_HEIGHT %u\n"
				"#define MAX_LIGHT_INDICES %u\n"
				"#define POISSON %u\n"
				"#define INDIRECT_ENABLED %u\n"
				"#define IR_MIPMAP_COUNT %u\n",
		m_r->getTileCountXY().x(),
		m_r->getTileCountXY().y(),
		clusterCount,
		m_r->getWidth(),
		m_r->getHeight(),
		m_maxLightIds,
		m_r->getSm().getPoissonEnabled(),
		1,
		m_r->getIr().getReflectionTextureMipmapCount());

	// point light
	ANKI_CHECK(getResourceManager().loadResourceToCache(m_lightVert, "shaders/Is.vert.glsl", pps.toCString(), "r_"));

	ANKI_CHECK(getResourceManager().loadResourceToCache(m_lightFrag, "shaders/Is.frag.glsl", pps.toCString(), "r_"));

	PipelineInitInfo init;

	init.m_inputAssembler.m_topology = PrimitiveTopology::TRIANGLE_STRIP;
	init.m_depthStencil.m_depthWriteEnabled = false;
	init.m_depthStencil.m_depthCompareFunction = CompareOperation::ALWAYS;
	init.m_color.m_attachmentCount = 1;
	init.m_color.m_attachments[0].m_format = IS_COLOR_ATTACHMENT_PIXEL_FORMAT;
	init.m_shaders[U(ShaderType::VERTEX)] = m_lightVert->getGrShader();
	init.m_shaders[U(ShaderType::FRAGMENT)] = m_lightFrag->getGrShader();
	m_lightPpline = getGrManager().newInstance<Pipeline>(init);

	//
	// Create framebuffer
	//
	m_r->createRenderTarget(m_r->getWidth(),
		m_r->getHeight(),
		IS_COLOR_ATTACHMENT_PIXEL_FORMAT,
		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE
			| TextureUsageBit::SAMPLED_COMPUTE,
		SamplingFilter::LINEAR,
		m_rtMipCount,
		m_rt);

	FramebufferInitInfo fbInit;
	fbInit.m_colorAttachmentCount = 1;
	fbInit.m_colorAttachments[0].m_texture = m_rt;
	fbInit.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
	fbInit.m_colorAttachments[0].m_usageInsideRenderPass = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
	m_fb = getGrManager().newInstance<Framebuffer>(fbInit);

	//
	// Create resource group
	//
	{
		ResourceGroupInitInfo init;
		init.m_textures[0].m_texture = m_r->getMs().m_rt0;
		init.m_textures[1].m_texture = m_r->getMs().m_rt1;
		init.m_textures[2].m_texture = m_r->getMs().m_rt2;
		init.m_textures[3].m_texture = m_r->getMs().m_depthRt;
		init.m_textures[3].m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ;
		init.m_textures[4].m_texture = m_r->getSm().getSpotTextureArray();
		init.m_textures[5].m_texture = m_r->getSm().getOmniTextureArray();

		init.m_textures[6].m_texture = m_r->getIr().getReflectionTexture();
		init.m_textures[7].m_texture = m_r->getIr().getIrradianceTexture();

		init.m_textures[8].m_texture = m_r->getIr().getIntegrationLut();
		init.m_textures[8].m_sampler = m_r->getIr().getIntegrationLutSampler();

		init.m_uniformBuffers[0].m_uploadedMemory = true;
		init.m_uniformBuffers[0].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX;
		init.m_uniformBuffers[1].m_uploadedMemory = true;
		init.m_uniformBuffers[1].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX;
		init.m_uniformBuffers[2].m_uploadedMemory = true;
		init.m_uniformBuffers[2].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX;
		init.m_uniformBuffers[3].m_uploadedMemory = true;
		init.m_uniformBuffers[3].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX;
		init.m_uniformBuffers[4].m_uploadedMemory = true;
		init.m_uniformBuffers[4].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX;

		init.m_storageBuffers[0].m_uploadedMemory = true;
		init.m_storageBuffers[0].m_usage = BufferUsageBit::STORAGE_FRAGMENT_READ | BufferUsageBit::STORAGE_VERTEX_READ;
		init.m_storageBuffers[1].m_uploadedMemory = true;
		init.m_storageBuffers[1].m_usage = BufferUsageBit::STORAGE_FRAGMENT_READ | BufferUsageBit::STORAGE_VERTEX_READ;

		m_rcGroup = getGrManager().newInstance<ResourceGroup>(init);
	}

	TextureInitInfo texinit;
	texinit.m_width = texinit.m_height = 4;
	texinit.m_usage = TextureUsageBit::SAMPLED_FRAGMENT;
	texinit.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
	m_dummyTex = getGrManager().newInstance<Texture>(texinit);

	return ErrorCode::NONE;
}
예제 #17
0
void* GrManagerImpl::reallocateCallback(
	void* userData, void* original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
{
	ANKI_ASSERT(!"TODO");
	return nullptr;
}
예제 #18
0
void HighRezTimer::stop()
{
	ANKI_ASSERT(m_startTime != 0.0);
	ANKI_ASSERT(m_stopTime == 0.0);
	m_stopTime = getCurrentTime();
}
예제 #19
0
//==============================================================================
void DebugDrawer::begin(GLenum primitive)
{
	ANKI_ASSERT(primitive == GL_TRIANGLES || primitive == GL_LINES);
	m_primitive = primitive;
}
예제 #20
0
void Input::init(NativeWindow* /*nativeWindow*/)
{
	ANKI_ASSERT(gAndroidApp);
	gAndroidApp->userData = this;
	gAndroidApp->onAppCmd = handleAndroidEvents;
}
예제 #21
0
//==============================================================================
void TextureResource::loadInternal(const CString& filename, 
	ResourceInitializer& rinit)
{
	GlDevice& gl = rinit.m_resources._getGlDevice();
	GlCommandBufferHandle jobs(&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 = GlClientBufferHandle(
				jobs, 
				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 = GlTextureHandle(jobs, init);

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

	// Finaly enque the GL job chain
	jobs.flush();
}
Error MicroSwapchain::initInternal()
{
	const VkDevice dev = m_factory->m_gr->getDevice();

	// Get the surface size
	VkSurfaceCapabilitiesKHR surfaceProperties;
	U surfaceWidth = 0, surfaceHeight = 0;
	{
		ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
			m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(), &surfaceProperties));

		if(surfaceProperties.currentExtent.width == MAX_U32 || surfaceProperties.currentExtent.height == MAX_U32)
		{
			ANKI_VK_LOGE("Wrong surface size");
			return Error::FUNCTION_FAILED;
		}
		surfaceWidth = surfaceProperties.currentExtent.width;
		surfaceHeight = surfaceProperties.currentExtent.height;
	}

	// Get the surface format
	VkFormat surfaceFormat = VK_FORMAT_END_RANGE;
	VkColorSpaceKHR colorspace = VK_COLOR_SPACE_MAX_ENUM_KHR;
	{
		uint32_t formatCount;
		ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(
			m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(), &formatCount, nullptr));

		DynamicArrayAuto<VkSurfaceFormatKHR> formats(getAllocator());
		formats.create(formatCount);
		ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(
			m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(), &formatCount, &formats[0]));

		while(formatCount--)
		{
			if(formats[formatCount].format == VK_FORMAT_B8G8R8A8_UNORM)
			{
				surfaceFormat = formats[formatCount].format;
				colorspace = formats[formatCount].colorSpace;
				break;
			}
		}

		if(surfaceFormat == VK_FORMAT_UNDEFINED)
		{
			ANKI_VK_LOGE("Surface format not found");
			return Error::FUNCTION_FAILED;
		}
	}

	// Chose present mode
	VkPresentModeKHR presentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
	{
		uint32_t presentModeCount;
		vkGetPhysicalDeviceSurfacePresentModesKHR(
			m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(), &presentModeCount, nullptr);
		presentModeCount = min(presentModeCount, 4u);
		Array<VkPresentModeKHR, 4> presentModes;
		vkGetPhysicalDeviceSurfacePresentModesKHR(
			m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(), &presentModeCount, &presentModes[0]);

		if(m_factory->m_vsync)
		{
			presentMode = VK_PRESENT_MODE_FIFO_KHR;
		}
		else
		{
			for(U i = 0; i < presentModeCount; ++i)
			{
				if(presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
				{
					presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
					break;
				}
				else if(presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)
				{
					presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
					break;
				}
			}
		}

		if(presentMode == VK_PRESENT_MODE_MAX_ENUM_KHR)
		{
			ANKI_VK_LOGE("Couldn't find a present mode");
			return Error::FUNCTION_FAILED;
		}
	}

	// Create swapchain
	{
		VkSwapchainCreateInfoKHR ci = {};
		ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
		ci.surface = m_factory->m_gr->getSurface();
		ci.minImageCount = MAX_FRAMES_IN_FLIGHT;
		ci.imageFormat = surfaceFormat;
		ci.imageColorSpace = colorspace;
		ci.imageExtent = surfaceProperties.currentExtent;
		ci.imageArrayLayers = 1;
		ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
		ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
		ci.queueFamilyIndexCount = 1;
		U32 idx = m_factory->m_gr->getGraphicsQueueIndex();
		ci.pQueueFamilyIndices = &idx;
		ci.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
		ci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
		ci.presentMode = presentMode;
		ci.clipped = false;
		ci.oldSwapchain = VK_NULL_HANDLE;

		ANKI_VK_CHECK(vkCreateSwapchainKHR(dev, &ci, nullptr, &m_swapchain));
	}

	// Get images
	{
		uint32_t count = 0;
		ANKI_VK_CHECK(vkGetSwapchainImagesKHR(dev, m_swapchain, &count, nullptr));
		if(count != MAX_FRAMES_IN_FLIGHT)
		{
			ANKI_VK_LOGE("Requested a swapchain with %u images but got one with %u", MAX_FRAMES_IN_FLIGHT, count);
			return Error::FUNCTION_FAILED;
		}

		ANKI_VK_LOGI("Created a swapchain. Image count: %u, present mode: %u, size: %ux%u, vsync: %u",
			count,
			presentMode,
			surfaceWidth,
			surfaceHeight,
			U32(m_factory->m_vsync));

		Array<VkImage, MAX_FRAMES_IN_FLIGHT> images;
		ANKI_VK_CHECK(vkGetSwapchainImagesKHR(dev, m_swapchain, &count, &images[0]));
		for(U i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
		{
			TextureInitInfo init("SwapchainImg");
			init.m_width = surfaceWidth;
			init.m_height = surfaceHeight;
			init.m_format = Format::B8G8R8A8_UNORM;
			ANKI_ASSERT(surfaceFormat == VK_FORMAT_B8G8R8A8_UNORM);
			init.m_usage = TextureUsageBit::IMAGE_COMPUTE_WRITE | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE
						   | TextureUsageBit::PRESENT;
			init.m_type = TextureType::_2D;

			TextureImpl* tex =
				m_factory->m_gr->getAllocator().newInstance<TextureImpl>(m_factory->m_gr, init.getName());
			m_textures[i].reset(tex);
			ANKI_CHECK(tex->initExternal(images[i], init));
		}
	}

	return Error::NONE;
}
예제 #23
0
//==============================================================================
void Material::parseMaterialTag(const XmlElement& materialEl,
	ResourceInitializer& rinit)
{
	// levelsOfDetail
	//
	XmlElement lodEl = materialEl.getChildElementOptional("levelsOfDetail");

	if(lodEl)
	{
		I tmp = lodEl.getInt();
		m_lodsCount = (tmp < 1) ? 1 : tmp;
	}
	else
	{
		m_lodsCount = 1;
	}

	// shadow
	//
	XmlElement shadowEl = materialEl.getChildElementOptional("shadow");

	if(shadowEl)
	{
		m_shadow = shadowEl.getInt();
	}

	// blendFunctions
	//
	XmlElement blendFunctionsEl =
		materialEl.getChildElementOptional("blendFunctions");

	if(blendFunctionsEl)
	{
		// sFactor
		m_blendingSfactor = blendToEnum(
			blendFunctionsEl.getChildElement("sFactor").getText());

		// dFactor
		m_blendingDfactor = blendToEnum(
			blendFunctionsEl.getChildElement("dFactor").getText());
	}
	else
	{
		m_passesCount = 2;
	}

	// depthTesting
	//
	XmlElement depthTestingEl =
		materialEl.getChildElementOptional("depthTesting");

	if(depthTestingEl)
	{
		m_depthTesting = depthTestingEl.getInt();
	}

	// wireframe
	//
	XmlElement wireframeEl = materialEl.getChildElementOptional("wireframe");

	if(wireframeEl)
	{
		m_wireframe = wireframeEl.getInt();
	}

	// shaderProgram
	//
	MaterialProgramCreator mspc(
		materialEl.getChildElement("programs"),
		rinit.m_tempAlloc);

	m_tessellation = mspc.hasTessellation();
	U tessCount = m_tessellation ? 2 : 1;

	// Alloc program vector
	U progCount = 0;
	progCount += m_passesCount * m_lodsCount * tessCount;
	if(m_tessellation)
	{
		progCount += m_passesCount * m_lodsCount * 2;
	}
	progCount += m_passesCount * m_lodsCount;
	m_progs.resize(progCount);

	// Aloc progam descriptors
	m_pplines.resize(m_passesCount * m_lodsCount * tessCount);

	m_hash = 0;
	for(U shader = 0; shader < 5; shader++)
	{
		if(!m_tessellation && (shader == 1 || shader == 2))
		{
			continue;
		}

		if(shader == 3)
		{
			continue;
		}

		for(U level = 0; level < m_lodsCount; ++level)
		{
			for(U pid = 0; pid < m_passesCount; ++pid)
			{
				for(U tess = 0; tess < tessCount; ++tess)
				{
					TempResourceString src(rinit.m_tempAlloc);

					src.sprintf("#define LOD %u\n"
						"#define PASS %u\n"
						"#define TESSELLATION %u\n", 
						level, pid, tess);

					TempResourceString filename =
						createProgramSourceToChache(src);

					RenderingKey key((Pass)pid, level, tess);
					ProgramResourcePointer& progr = getProgram(key, shader);
					progr.load(filename.toCString(), &rinit.m_resources);

					// Update the hash
					m_hash ^= computeHash(&src[0], src.getLength());
				}
			}
		}
	}

	populateVariables(mspc);

	// Get uniform block size
	ANKI_ASSERT(m_progs.size() > 0);
	m_shaderBlockSize = 
		m_progs[0]->getGlProgram().findBlock("bDefaultBlock").getSize();
}
예제 #24
0
//==============================================================================
void GlBuffer::create(GLenum target, U32 sizeInBytes,
	const void* dataPtr, GLbitfield flags)
{
	ANKI_ASSERT(!isCreated());

	if(target == GL_UNIFORM_BUFFER)
	{
		GLint64 maxBufferSize;
		glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxBufferSize);

		if(sizeInBytes > 16384)
		{
			ANKI_LOGW("The size (%u) of the uniform buffer is greater "
				"than the spec's min", sizeInBytes);
		} 
		else if(sizeInBytes > (PtrSize)maxBufferSize)
		{
			ANKI_LOGW("The size (%u) of the uniform buffer is greater "
				"than the implementation's min (%u)", sizeInBytes, 
				maxBufferSize);
		}
	}
	else if(target == GL_SHADER_STORAGE_BUFFER)
	{
		GLint64 maxBufferSize;
		glGetInteger64v(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxBufferSize);

		if(sizeInBytes > pow(2, 24))
		{
			ANKI_LOGW("The size (%u) of the uniform buffer is greater "
				"than the spec's min", sizeInBytes);
		} 
		else if(sizeInBytes > (PtrSize)maxBufferSize)
		{
			ANKI_LOGW("The size (%u) of the shader storage buffer is greater "
				"than the implementation's min (%u)", sizeInBytes, 
				maxBufferSize);
		}
	}

	m_target = target;
	m_size = sizeInBytes;

	ANKI_ASSERT(m_size > 0 && "Unacceptable size");

	// Create
	glGenBuffers(1, &m_glName);

	glBindBuffer(m_target, m_glName);
	glBufferStorage(m_target, m_size, dataPtr, flags);

	// Map if needed
	if((flags & GL_MAP_PERSISTENT_BIT) && (flags & GL_MAP_COHERENT_BIT))
	{
		const GLbitfield mapbits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT 
			| GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;

		m_persistentMapping = 
			glMapBufferRange(m_target, 0, sizeInBytes, flags & mapbits);
		ANKI_ASSERT(m_persistentMapping != nullptr);
	}
}
예제 #25
0
//==============================================================================
void SceneNode::removeComponent(SceneComponent* comp)
{
	ANKI_ASSERT(0 && "TODO");
}
예제 #26
0
	void visit(const TRenderableVariableTemplate& rvar)
	{
		typedef typename TRenderableVariableTemplate::Type DataType;
		const GlProgramVariable& glvar = rvar.getGlProgramVariable();

		// Array size
		U arraySize;
		if(rvar.isInstanced())
		{
			arraySize = std::min<U>(m_instanceCount, glvar.getArraySize());
		}
		else
		{
			arraySize = glvar.getArraySize();
		}

		// Set uniform
		//
		Bool hasWorldTrfs = m_renderable->getHasWorldTransforms();
		const Mat4& vp = m_fr->getViewProjectionMatrix();
		const Mat4& v = m_fr->getViewMatrix();

		switch(rvar.getBuildinId())
		{
		case BuildinMaterialVariableId::NO_BUILDIN:
			uniSet<DataType>(glvar, rvar.begin(), arraySize);
			break;
		case BuildinMaterialVariableId::MVP_MATRIX:
			if(hasWorldTrfs)
			{
				Mat4* mvp = m_drawer->m_r->getSceneGraph().getFrameAllocator().
					newInstance<Mat4>(arraySize);

				for(U i = 0; i < arraySize; i++)
				{
					Transform worldTrf;

					m_renderable->getRenderWorldTransform(
						m_visibleNode->getSpatialIndex(i), worldTrf);

					mvp[i] = vp * Mat4(worldTrf);
				}

				uniSet(glvar, &mvp[0], arraySize);
			}
			else
			{
				ANKI_ASSERT(arraySize == 1 && "Shouldn't instance that one");
				uniSet(glvar, &vp, 1);
			}
			break;
		case BuildinMaterialVariableId::MV_MATRIX:
			{
				ANKI_ASSERT(hasWorldTrfs);
				Mat4* mv = m_drawer->m_r->getSceneGraph().getFrameAllocator().
					newInstance<Mat4>(arraySize);

				for(U i = 0; i < arraySize; i++)
				{
					Transform worldTrf;

					m_renderable->getRenderWorldTransform(
						m_visibleNode->getSpatialIndex(i), worldTrf);

					mv[i] = v * Mat4(worldTrf);
				}

				uniSet(glvar, &mv[0], arraySize);
			}
			break;
		case BuildinMaterialVariableId::VP_MATRIX:
			uniSet(glvar, &vp, 1);
			break;
		case BuildinMaterialVariableId::NORMAL_MATRIX:
			if(hasWorldTrfs)
			{
				Mat3* normMats = 
					m_drawer->m_r->getSceneGraph().getFrameAllocator().
					newInstance<Mat3>(arraySize);

				for(U i = 0; i < arraySize; i++)
				{
					Transform worldTrf;

					m_renderable->getRenderWorldTransform(
						m_visibleNode->getSpatialIndex(i), worldTrf);

					Mat4 mv = v * Mat4(worldTrf);
					normMats[i] = mv.getRotationPart();
					normMats[i].reorthogonalize();
				}

				uniSet(glvar, &normMats[0], arraySize);
			}
			else
			{
				ANKI_ASSERT(arraySize == 1
					&& "Having that instanced doesn't make sense");

				Mat3 normMat = v.getRotationPart();

				uniSet(glvar, &normMat, 1);
			}
			break;
		case BuildinMaterialVariableId::BILLBOARD_MVP_MATRIX:
			{
				// Calc the billboard rotation matrix
				Mat3 rot =
					m_fr->getViewMatrix().getRotationPart().getTransposed();

				Mat4* bmvp = 
					m_drawer->m_r->getSceneGraph().getFrameAllocator().
					newInstance<Mat4>(arraySize);

				for(U i = 0; i < arraySize; i++)
				{
					Transform trf;
					m_renderable->getRenderWorldTransform(i, trf);
					trf.setRotation(Mat3x4(rot));
					bmvp[i] = vp * Mat4(trf);
				}

				uniSet(glvar, &bmvp[0], arraySize);
			}
			break;
		case BuildinMaterialVariableId::MAX_TESS_LEVEL:
			{
				F32 maxtess = 
					rvar.RenderComponentVariable:: template operator[]<F32>(0);
				F32 tess = 0.0;
				
				if(m_flod >= 1.0)
				{
					tess = 1.0;
				}
				else
				{
					tess = maxtess - m_flod * maxtess;
					tess = std::max(tess, 1.0f);
				}
				
				uniSet(glvar, &tess, 1);
			}
			break;
		case BuildinMaterialVariableId::BLURRING:
			{
				F32 blurring = 0.0;
				uniSet(glvar, &blurring, 1);
			}
			break;
		case BuildinMaterialVariableId::MS_DEPTH_MAP:
			{
				auto unit = glvar.getTextureUnit();

				m_drawer->m_r->getMs()._getSmallDepthRt().bind(m_jobs, unit);
			}
			break;
		default:
			ANKI_ASSERT(0);
			break;
		}
	}
예제 #27
0
//==============================================================================
OctreeNode* Octree::placeInternal(const Aabb& aabb, U depth, OctreeNode& node)
{
	if(depth >= maxDepth)
	{
		return &node;
	}

	for(U i = 0; i < 2; ++i)
	{
		for(U j = 0; j < 2; ++j)
		{
			for(U k = 0; k < 2; ++k)
			{
				U id = i * 4 + j * 2 + k;

				// Get the node's AABB. If there is no node then calculate the
				// AABB
				Aabb childAabb;
				Bool child = node.children[id] != nullptr;
				if(child)
				{
					// There is a child
					childAabb = node.children[id]->aabb;
				}
				else
				{
					// Calculate
					calcAabb(i, j, k, node.aabb, childAabb);
				}

				// If aabb its completely inside the target => go deeper
				if(aabb.getMax() <= childAabb.getMax() 
					&& aabb.getMin() >= childAabb.getMin())
				{
					if(!child)
					{
#if ANKI_CFG_OCTREE_THREAD_SAFE
						node.mtx.lock();
					
						// Check again now that the mutex is locked
						volatile Bool checkAgain = node.children[id] == nullptr;
						if(checkAgain)
#endif
						{
							SceneAllocator<U8> alloc =
								sector->getSectorGroup().getSceneGraph().
								getAllocator();

							// Create new node if needed
							OctreeNode* newNode =
								ANKI_NEW(OctreeNode, alloc,
								childAabb, &node, alloc);

							node.addChild(id, newNode);
						}
#if ANKI_CFG_OCTREE_THREAD_SAFE
						node.mtx.unlock();
#endif
					}

					ANKI_ASSERT(node.children[id]);
					return placeInternal(aabb, depth + 1, *node.children[id]);
				}
			} // k
		} // j
	} // i

	return &node;
}
예제 #28
0
Error DescriptorSetLayoutFactory::getOrCreateLayout(const DescriptorSetLayoutInfo& dsinf, VkDescriptorSetLayout& out)
{
	out = VK_NULL_HANDLE;
	LockGuard<Mutex> lock(m_mtx);

	auto it = m_map.find(dsinf);

	if(it != m_map.getEnd())
	{
		out = *it;
	}
	else
	{
		// Create the layout

		VkDescriptorSetLayoutCreateInfo ci = {};
		ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;

		const U BINDING_COUNT =
			MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS + MAX_STORAGE_BUFFER_BINDINGS + MAX_IMAGE_BINDINGS;

		Array<VkDescriptorSetLayoutBinding, BINDING_COUNT> bindings;
		memset(&bindings[0], 0, sizeof(bindings));
		ci.pBindings = &bindings[0];

		U count = 0;
		U bindingIdx = 0;

		// Combined image samplers
		for(U i = 0; i < dsinf.m_texCount; ++i)
		{
			VkDescriptorSetLayoutBinding& binding = bindings[count++];
			binding.binding = bindingIdx++;
			binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
			binding.descriptorCount = 1;
			binding.stageFlags = VK_SHADER_STAGE_ALL;
		}

		// Uniform buffers
		bindingIdx = MAX_TEXTURE_BINDINGS;
		for(U i = 0; i < dsinf.m_uniCount; ++i)
		{
			VkDescriptorSetLayoutBinding& binding = bindings[count++];
			binding.binding = bindingIdx++;
			binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
			binding.descriptorCount = 1;
			binding.stageFlags = VK_SHADER_STAGE_ALL;
		}

		// Storage buffers
		bindingIdx = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS;
		for(U i = 0; i < dsinf.m_storageCount; ++i)
		{
			VkDescriptorSetLayoutBinding& binding = bindings[count++];
			binding.binding = bindingIdx++;
			binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
			binding.descriptorCount = 1;
			binding.stageFlags = VK_SHADER_STAGE_ALL;
		}

		// Images
		bindingIdx = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS + MAX_STORAGE_BUFFER_BINDINGS;
		for(U i = 0; i < dsinf.m_imgCount; ++i)
		{
			VkDescriptorSetLayoutBinding& binding = bindings[count++];
			binding.binding = bindingIdx++;
			binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
			binding.descriptorCount = 1;
			binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
		}

		ANKI_ASSERT(count <= BINDING_COUNT);
		ci.bindingCount = count;

		ANKI_VK_CHECK(vkCreateDescriptorSetLayout(m_dev, &ci, nullptr, &out));

		m_map.pushBack(m_alloc, dsinf, out);
	}

	return ErrorCode::NONE;
}