Esempio n. 1
0
//==============================================================================
ScriptManager::ScriptManager(HeapAllocator<U8>& alloc)
	: LuaBinder(alloc)
{
	ANKI_LOGI("Initializing scripting engine...");

	// Global functions
	ANKI_SCRIPT_CALL_WRAP(Anki);

	// Math
	ANKI_SCRIPT_CALL_WRAP(Vec2);
	ANKI_SCRIPT_CALL_WRAP(Vec3);
	ANKI_SCRIPT_CALL_WRAP(Vec4);
	ANKI_SCRIPT_CALL_WRAP(Mat3);

	// Renderer
	ANKI_SCRIPT_CALL_WRAP(Dbg);
	ANKI_SCRIPT_CALL_WRAP(MainRenderer);

	// Scene
	ANKI_SCRIPT_CALL_WRAP(MoveComponent);
	ANKI_SCRIPT_CALL_WRAP(SceneNode);
	ANKI_SCRIPT_CALL_WRAP(ModelNode);
	ANKI_SCRIPT_CALL_WRAP(InstanceNode);
	ANKI_SCRIPT_CALL_WRAP(SceneGraph);

	ANKI_LOGI("Scripting engine initialized");
}
Esempio n. 2
0
void GpuMemoryManager::init(VkPhysicalDevice pdev, VkDevice dev, GrAllocator<U8> alloc)
{
	ANKI_ASSERT(pdev);
	ANKI_ASSERT(dev);

	// Print some info
	for(const ClassInf& c : CLASSES)
	{
		ANKI_LOGI("VK: GPU mem class. Chunk size: %u, slotSize: %u, allocsPerChunk %u",
			c.m_chunkSize,
			c.m_slotSize,
			c.m_chunkSize / c.m_slotSize);
	}

	vkGetPhysicalDeviceMemoryProperties(pdev, &m_memoryProperties);

	m_alloc = alloc;

	m_ifaces.create(alloc, m_memoryProperties.memoryTypeCount);
	for(U i = 0; i < m_ifaces.getSize(); ++i)
	{
		Interface& iface = m_ifaces[i];

		iface.m_alloc = alloc;
		iface.m_dev = dev;
		iface.m_memTypeIdx = i;
	}

	// One allocator per type per linear/non-linear resources
	m_callocs.create(alloc, m_memoryProperties.memoryTypeCount * 2);
	for(U i = 0; i < m_callocs.getSize(); ++i)
	{
		m_callocs[i].init(m_alloc, &m_ifaces[i / 2]);
	}
}
Esempio n. 3
0
Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
{
	uint32_t count = 0;
	vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &count, nullptr);
	ANKI_LOGI("VK: Number of queue families: %u\n", count);

	DynamicArrayAuto<VkQueueFamilyProperties> queueInfos(getAllocator());
	queueInfos.create(count);
	vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &count, &queueInfos[0]);

	uint32_t desiredFamilyIdx = MAX_U32;
	const VkQueueFlags DESITED_QUEUE_FLAGS = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT;
	for(U i = 0; i < count; ++i)
	{
		if((queueInfos[i].queueFlags & DESITED_QUEUE_FLAGS) == DESITED_QUEUE_FLAGS)
		{
			VkBool32 supportsPresent = false;
			ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &supportsPresent));

			if(supportsPresent)
			{
				desiredFamilyIdx = i;
				break;
			}
		}
	}

	if(desiredFamilyIdx == MAX_U32)
	{
		ANKI_LOGE("Couldn't find a queue family with graphics+compute+transfer+present."
				  "The assumption was wrong. The code needs to be reworked");
		return ErrorCode::FUNCTION_FAILED;
	}

	m_queueIdx = desiredFamilyIdx;

	F32 priority = 1.0;
	VkDeviceQueueCreateInfo q = {};
	q.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
	q.queueFamilyIndex = desiredFamilyIdx;
	q.queueCount = 1;
	q.pQueuePriorities = &priority;

	static Array<const char*, 1> DEV_EXTENSIONS = {{VK_KHR_SWAPCHAIN_EXTENSION_NAME}};

	VkDeviceCreateInfo ci = {};
	ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
	ci.queueCreateInfoCount = 1;
	ci.pQueueCreateInfos = &q;
	ci.enabledExtensionCount = DEV_EXTENSIONS.getSize();
	ci.ppEnabledExtensionNames = &DEV_EXTENSIONS[0];
	ci.pEnabledFeatures = &m_devFeatures;

	ANKI_VK_CHECK(vkCreateDevice(m_physicalDevice, &ci, nullptr, &m_device));

	return ErrorCode::NONE;
}
//==============================================================================
Error ScriptManager::create(
	AllocAlignedCallback allocCb, 
	void* allocCbData, SceneGraph* scene)
{
	ANKI_LOGI("Initializing scripting engine...");

	m_scene = scene;
	m_alloc = ChainAllocator<U8>(allocCb, allocCbData, 1024, 1.0, 0);

	Error err = m_lua.create(m_alloc, this);
	if(err) return err;

	// Wrap stuff
	lua_State* l = m_lua.getLuaState();

	ANKI_SCRIPT_CALL_WRAP(Math);
	ANKI_SCRIPT_CALL_WRAP(Renderer);
	ANKI_SCRIPT_CALL_WRAP(Scene);

	ANKI_LOGI("Scripting engine initialized");
	return err;
}
Esempio n. 5
0
static void handleAndroidEvents(android_app* app, int32_t cmd)
{
	Input* input = (Input*)app->userData;
	ANKI_ASSERT(input != nullptr);

	switch(cmd)
	{
	case APP_CMD_TERM_WINDOW:
	case APP_CMD_LOST_FOCUS:
		ANKI_LOGI("New event 0x%x", cmd);
		input->addEvent(Input::WINDOW_CLOSED_EVENT);
		break;
	}
}
Esempio n. 6
0
//==============================================================================
void RenderingThread::prepare()
{
	m_manager->getImplementation().pinContextToCurrentThread(true);

	// Ignore the first error
	glGetError();

	ANKI_LOGI("OpenGL async thread started: OpenGL version %s, GLSL version %s",
		reinterpret_cast<const char*>(glGetString(GL_VERSION)),
		reinterpret_cast<const char*>(
				  glGetString(GL_SHADING_LANGUAGE_VERSION)));

	// Get thread id
	m_serverThreadId = Thread::getCurrentThreadId();

	// Init state
	m_manager->getImplementation().getState().initRenderThread();

	// Init dyn mem
	m_manager->getImplementation().getDynamicMemoryManager().initRenderThread();
}
Esempio n. 7
0
Error MainRenderer::create(ThreadPool* threadpool,
	ResourceManager* resources,
	GrManager* gr,
	AllocAlignedCallback allocCb,
	void* allocCbUserData,
	const ConfigSet& config,
	Timestamp* globTimestamp)
{
	ANKI_LOGI("Initializing main renderer");

	m_alloc = HeapAllocator<U8>(allocCb, allocCbUserData);
	m_frameAlloc = StackAllocator<U8>(allocCb, allocCbUserData, 1024 * 1024 * 10, 1.0);

	// Init default FB
	m_width = config.getNumber("width");
	m_height = config.getNumber("height");
	FramebufferInitInfo fbInit;
	fbInit.m_colorAttachmentCount = 1;
	fbInit.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
	m_defaultFb = gr->newInstance<Framebuffer>(fbInit);

	// Init renderer and manipulate the width/height
	ConfigSet config2 = config;
	m_renderingQuality = config.getNumber("renderingQuality");
	UVec2 size(m_renderingQuality * F32(m_width), m_renderingQuality * F32(m_height));
	size.x() = getAlignedRoundDown(TILE_SIZE, size.x() / 2) * 2;
	size.y() = getAlignedRoundDown(TILE_SIZE, size.y() / 2) * 2;

	config2.set("width", size.x());
	config2.set("height", size.y());

	m_rDrawToDefaultFb = m_renderingQuality == 1.0;

	m_r.reset(m_alloc.newInstance<Renderer>());
	ANKI_CHECK(m_r->init(threadpool, resources, gr, m_alloc, m_frameAlloc, config2, globTimestamp, m_rDrawToDefaultFb));

	// Set the default preprocessor string
	m_materialShaderSource.sprintf(m_alloc,
		"#define ANKI_RENDERER_WIDTH %u\n"
		"#define ANKI_RENDERER_HEIGHT %u\n"
		"#define TILE_SIZE %u\n",
		m_r->getWidth(),
		m_r->getHeight(),
		TILE_SIZE);

	// Init other
	if(!m_rDrawToDefaultFb)
	{
		ANKI_CHECK(m_r->getResourceManager().loadResource("shaders/Final.frag.glsl", m_blitFrag));

		ColorStateInfo colorState;
		colorState.m_attachmentCount = 1;
		colorState.m_attachments[0].m_format.m_components = ComponentFormat::DEFAULT_FRAMEBUFFER;
		m_r->createDrawQuadPipeline(m_blitFrag->getGrShader(), colorState, m_blitPpline);

		// Init RC group
		ResourceGroupInitInfo rcinit;
		rcinit.m_textures[0].m_texture = m_r->getPps().getRt();
		m_rcGroup = m_r->getGrManager().newInstance<ResourceGroup>(rcinit);
		ANKI_LOGI("The main renderer will have to blit the offscreen renderer's result");
	}

	ANKI_LOGI("Main renderer initialized. Rendering size %ux%u", m_width, m_height);

	return ErrorCode::NONE;
}
Esempio n. 8
0
MainRenderer::~MainRenderer()
{
	ANKI_LOGI("Destroying main renderer");
	m_materialShaderSource.destroy(m_alloc);
}
Esempio n. 9
0
//==============================================================================
static ANKI_USE_RESULT Error loadAnkiTexture(
	const CString& filename, 
	U32 maxTextureSize,
	ImageLoader::DataCompression& preferredCompression,
	DArray<ImageLoader::Surface>& surfaces,
	GenericMemoryPoolAllocator<U8>& alloc,
	U8& depth, 
	U8& mipLevels, 
	ImageLoader::TextureType& textureType,
	ImageLoader::ColorFormat& colorFormat)
{
	File file;
	ANKI_CHECK(file.open(filename, 
		File::OpenFlag::READ | File::OpenFlag::BINARY 
		| File::OpenFlag::LITTLE_ENDIAN));

	//
	// Read and check the header
	//
	AnkiTextureHeader header;
	ANKI_CHECK(file.read(&header, sizeof(AnkiTextureHeader)));

	if(std::memcmp(&header.m_magic[0], "ANKITEX1", 8) != 0)
	{
		ANKI_LOGE("Wrong magic word");
		return ErrorCode::USER_DATA;
	}

	if(header.m_width == 0 
		|| !isPowerOfTwo(header.m_width) 
		|| header.m_width > 4096
		|| header.m_height == 0 
		|| !isPowerOfTwo(header.m_height) 
		|| header.m_height > 4096)
	{
		ANKI_LOGE("Incorrect width/height value");
		return ErrorCode::USER_DATA;
	}

	if(header.m_depth < 1 || header.m_depth > 16)
	{
		ANKI_LOGE("Zero or too big depth");
		return ErrorCode::USER_DATA;
	}

	if(header.m_type < ImageLoader::TextureType::_2D 
		|| header.m_type > ImageLoader::TextureType::_2D_ARRAY)
	{
		ANKI_LOGE("Incorrect header: texture type");
		return ErrorCode::USER_DATA;
	}

	if(header.m_colorFormat < ImageLoader::ColorFormat::RGB8 
		|| header.m_colorFormat > ImageLoader::ColorFormat::RGBA8)
	{
		ANKI_LOGE("Incorrect header: color format");
		return ErrorCode::USER_DATA;
	}

	if((header.m_compressionFormats & preferredCompression) 
		== ImageLoader::DataCompression::NONE)
	{
		ANKI_LOGI("File does not contain the requested compression");

		// Fallback
		preferredCompression = ImageLoader::DataCompression::RAW;

		if((header.m_compressionFormats & preferredCompression) 
			== ImageLoader::DataCompression::NONE)
		{
			ANKI_LOGI("File does not contain raw compression");
			return ErrorCode::USER_DATA;
		}
	}

	if(header.m_normal != 0 && header.m_normal != 1)
	{
		ANKI_LOGE("Incorrect header: normal");
		return ErrorCode::USER_DATA;
	}

	// Check mip levels
	U size = min(header.m_width, header.m_height);
	U maxsize = max(header.m_width, header.m_height);
	mipLevels = 0;
	U tmpMipLevels = 0;
	while(size >= 4) // The minimum size is 4x4
	{
		++tmpMipLevels;

		if(maxsize <= maxTextureSize)
		{
			++mipLevels;
		}

		size /= 2;
		maxsize /= 2;
	}

	if(header.m_mipLevels > tmpMipLevels)
	{
		ANKI_LOGE("Incorrect number of mip levels");
		return ErrorCode::USER_DATA;
	}

	mipLevels = min<U>(mipLevels, header.m_mipLevels);

	colorFormat = header.m_colorFormat;

	switch(header.m_type)
	{
	case ImageLoader::TextureType::_2D:
		depth = 1;
		break;
	case ImageLoader::TextureType::CUBE:
		depth = 6;
		break;
	case ImageLoader::TextureType::_3D:
	case ImageLoader::TextureType::_2D_ARRAY:
		depth = header.m_depth;
		break;
	default:
		ANKI_ASSERT(0);
	}

	textureType = header.m_type;

	//
	// Move file pointer
	//

	if(preferredCompression == ImageLoader::DataCompression::RAW)
	{
		// Do nothing
	}
	else if(preferredCompression == ImageLoader::DataCompression::S3TC)
	{
		if((header.m_compressionFormats & ImageLoader::DataCompression::RAW)
			!= ImageLoader::DataCompression::NONE)
		{
			// If raw compression is present then skip it
			ANKI_CHECK(file.seek(
				calcSizeOfSegment(header, ImageLoader::DataCompression::RAW), 
				File::SeekOrigin::CURRENT));
		}
	}
	else if(preferredCompression == ImageLoader::DataCompression::ETC)
	{
		if((header.m_compressionFormats & ImageLoader::DataCompression::RAW)
			!= ImageLoader::DataCompression::NONE)
		{
			// If raw compression is present then skip it
			ANKI_CHECK(file.seek(
				calcSizeOfSegment(header, ImageLoader::DataCompression::RAW), 
				File::SeekOrigin::CURRENT));
		}

		if((header.m_compressionFormats & ImageLoader::DataCompression::S3TC)
			!= ImageLoader::DataCompression::NONE)
		{
			// If s3tc compression is present then skip it
			ANKI_CHECK(file.seek(
				calcSizeOfSegment(header, ImageLoader::DataCompression::S3TC), 
				File::SeekOrigin::CURRENT));
		}
	}

	//
	// It's time to read
	//

	// Allocate the surfaces 
	surfaces.create(alloc, mipLevels * depth);

	// Read all surfaces
	U mipWidth = header.m_width;
	U mipHeight = header.m_height;
	U index = 0;
	for(U mip = 0; mip < header.m_mipLevels; mip++)
	{
		for(U d = 0; d < depth; d++)
		{
			U dataSize = calcSurfaceSize(
				mipWidth, mipHeight, preferredCompression, 
				header.m_colorFormat);

			// Check if this mipmap can be skipped because of size
			if(max(mipWidth, mipHeight) <= maxTextureSize)
			{
				ImageLoader::Surface& surf = surfaces[index++];
				surf.m_width = mipWidth;
				surf.m_height = mipHeight;

				surf.m_data.create(alloc, dataSize);

				ANKI_CHECK(file.read(&surf.m_data[0], dataSize));
			}
			else
			{
				ANKI_CHECK(file.seek(dataSize, File::SeekOrigin::CURRENT));
			}
		}

		mipWidth /= 2;
		mipHeight /= 2;
	}

	return ErrorCode::NONE;
}
//==============================================================================
void NativeWindowImpl::create(NativeWindowInitInfo& init)
{
	Array<EGLint, 256> attribs;
	U attr = 0;
	EGLint configsCount;
	EGLint format;
	EGLConfig config;

	ANKI_LOGI("Creating native window");

	ANKI_ASSERT(gAndroidApp);
	android_app& andApp = *gAndroidApp;
	loopUntilWindowIsReady(andApp);

	// EGL init
	//
	display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	if(display == EGL_NO_DISPLAY)
	{
		throw ANKI_EXCEPTION("Failed to create display");
	}

	int major, minor;
	if(eglInitialize(display, &major, &minor) == EGL_FALSE)
	{
		throw ANKI_EXCEPTION("Failed to initialize EGL");
	}

	//
	// EGL config
	//
	attribs[attr++] = EGL_SURFACE_TYPE;
	attribs[attr++] = EGL_WINDOW_BIT;

	attribs[attr++] = EGL_RENDERABLE_TYPE;
	attribs[attr++] = EGL_OPENGL_ES2_BIT;

	if(init.samplesCount > 1)
	{
		attribs[attr++] = EGL_SAMPLES;
		attribs[attr++] = init.samplesCount;
	}

	attribs[attr++] = EGL_RED_SIZE;
	attribs[attr++] = init.rgbaBits[0];
	attribs[attr++] = EGL_GREEN_SIZE;
	attribs[attr++] = init.rgbaBits[1];
	attribs[attr++] = EGL_BLUE_SIZE;
	attribs[attr++] = init.rgbaBits[2];
	attribs[attr++] = EGL_ALPHA_SIZE;
	attribs[attr++] = init.rgbaBits[3];

	attribs[attr++] = EGL_DEPTH_SIZE;
	attribs[attr++] = init.depthBits;
	attribs[attr++] = EGL_STENCIL_SIZE;
	attribs[attr++] = init.stencilBits;

	attribs[attr++] = EGL_NONE;

	if(eglChooseConfig(display, &attribs[0], &config, 1, &configsCount)
		== EGL_FALSE)
	{
		throw ANKI_EXCEPTION("Failed to query required EGL configs");
	}

	if(configsCount == 0)
	{
		throw ANKI_EXCEPTION("No matching EGL configs found");
	}

	eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);

	ANKI_ASSERT(andApp.window);
	ANativeWindow_setBuffersGeometry(andApp.window, 0, 0, format);

	// Surface
	//
	surface = eglCreateWindowSurface(display, config, andApp.window, NULL);
	if(surface == EGL_NO_SURFACE)
	{
		throw ANKI_EXCEPTION("Cannot create surface");
	}

	// Context
	//
	EGLint ctxAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};

	context = eglCreateContext(display, config, EGL_NO_CONTEXT, ctxAttribs);
	if(context == EGL_NO_CONTEXT)
	{
		throw ANKI_EXCEPTION("Cannot create context");
	}

	if(eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
	{
		throw ANKI_EXCEPTION("Cannot make the context current");
	}

	// Query width and height
	//
	EGLint w, h;
	eglQuerySurface(display, surface, EGL_WIDTH, &w);
	eglQuerySurface(display, surface, EGL_HEIGHT, &h);

	init.width = w;
	init.height = h;
}
Esempio n. 11
0
//==============================================================================
ScriptManager::~ScriptManager()
{
	ANKI_LOGI("Destroying scripting engine...");
}
//==============================================================================
Error NativeWindow::create(Initializer& init, HeapAllocator<U8>& alloc)
{
	m_alloc = alloc;
	m_impl = m_alloc.newInstance<NativeWindowImpl>();

	if(SDL_Init(INIT_SUBSYSTEMS) != 0)
	{
		ANKI_LOGE("SDL_Init() failed");
		return ErrorCode::FUNCTION_FAILED;
	}
	
	//
	// Set GL attributes
	//
	ANKI_LOGI("Creating SDL window (OpenGL context to be requested %u.%u)...", 
		init.m_majorVersion, init.m_minorVersion);

	if(SDL_GL_SetAttribute(SDL_GL_RED_SIZE, init.m_rgbaBits[0]) != 0
		|| SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, init.m_rgbaBits[1]) != 0
		|| SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, init.m_rgbaBits[2]) != 0
		|| SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, init.m_rgbaBits[3]) != 0
		|| SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, init.m_depthBits) != 0
		|| SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, init.m_doubleBuffer) != 0
		|| SDL_GL_SetAttribute(
			SDL_GL_CONTEXT_MAJOR_VERSION, init.m_majorVersion) != 0
		|| SDL_GL_SetAttribute(
			SDL_GL_CONTEXT_MINOR_VERSION, init.m_minorVersion) != 0
		|| SDL_GL_SetAttribute(
			SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE) != 0)
	{
		ANKI_LOGE("SDL_GL_SetAttribute() failed");
		return ErrorCode::FUNCTION_FAILED;
	}

	if(init.m_debugContext)
	{
		if(SDL_GL_SetAttribute(
			SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG) != 0)
		{
			ANKI_LOGE("SDL_GL_SetAttribute() failed");
			return ErrorCode::FUNCTION_FAILED;
		}
	}

	//
	// Create window
	//
	U32 flags = SDL_WINDOW_OPENGL;

	if(init.m_fullscreenDesktopRez)
	{
		flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
	}

	m_impl->m_window = SDL_CreateWindow(
    	init.m_title,
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 
		init.m_width, init.m_height, flags);

	if(m_impl->m_window == nullptr)
	{
		ANKI_LOGE("SDL_CreateWindow() failed");
		return ErrorCode::FUNCTION_FAILED;
	}

	// Set the size after loading a fullscreen window
	if(init.m_fullscreenDesktopRez)
	{
		int w, h;
		SDL_GetWindowSize(m_impl->m_window, &w, &h);

		m_width = w;
		m_height = h;
	}
	else
	{
		m_width = init.m_width;
		m_height = init.m_height;
	}

	//
	// Create context
	//
	m_impl->m_context = SDL_GL_CreateContext(m_impl->m_window);

	if(m_impl->m_context == nullptr)
	{
		ANKI_LOGE("SDL_GL_CreateContext() failed");
		return ErrorCode::FUNCTION_FAILED;
	}

	//
	// GLEW
	//
	glewExperimental = GL_TRUE;
	if(glewInit() != GLEW_OK)
	{
		ANKI_LOGE("GLEW initialization failed");
		return ErrorCode::FUNCTION_FAILED;
	}
	glGetError();

	ANKI_LOGI("SDL window created");
	return ErrorCode::NONE;
}
Esempio n. 13
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;
}
Esempio n. 14
0
Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
{
	// Create the instance
	//
	static Array<const char*, 8> LAYERS = {{"VK_LAYER_LUNARG_core_validation",
		"VK_LAYER_LUNARG_swapchain",
		"VK_LAYER_LUNARG_image",
		"VK_LAYER_GOOGLE_threading",
		"VK_LAYER_LUNARG_parameter_validation",
		"VK_LAYER_GOOGLE_unique_objects",
		"VK_LAYER_LUNARG_object_tracker",
		"VK_LAYER_LUNARG_standard_validation"}};

	static Array<const char*, 2> EXTENSIONS = {{VK_KHR_SURFACE_EXTENSION_NAME,
#if ANKI_OS == ANKI_OS_LINUX
		VK_KHR_XCB_SURFACE_EXTENSION_NAME
#elif ANKI_OS == ANKI_OS_WINDOWS
		VK_KHR_WIN32_SURFACE_EXTENSION_NAME
#else
#error TODO
#endif
	}};

	VkApplicationInfo app = {};
	app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
	app.pApplicationName = "unamed";
	app.applicationVersion = 1;
	app.pEngineName = "AnKi 3D Engine";
	app.engineVersion = (ANKI_VERSION_MAJOR << 1) | ANKI_VERSION_MINOR;
	app.apiVersion = VK_MAKE_VERSION(1, 0, 3);

	VkInstanceCreateInfo ci = {};
	ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
	ci.pApplicationInfo = &app;

	if(init.m_config->getNumber("debugContext"))
	{
		ANKI_LOGI("VK: Will enable debug layers");
		ci.enabledLayerCount = LAYERS.getSize();
		ci.ppEnabledLayerNames = &LAYERS[0];
	}

	ci.enabledExtensionCount = EXTENSIONS.getSize();
	ci.ppEnabledExtensionNames = &EXTENSIONS[0];

#if ANKI_GR_MANAGER_DEBUG_MEMMORY
	VkAllocationCallbacks allocCbs = {};
	VkAllocationCallbacks* pallocCbs = &allocCbs;
	allocCbs.pUserData = this;
	allocCbs.pfnAllocation = allocateCallback;
	allocCbs.pfnReallocation = reallocateCallback;
	allocCbs.pfnFree = freeCallback;
#else
	VkAllocationCallbacks* pallocCbs = nullptr;
#endif

	ANKI_VK_CHECK(vkCreateInstance(&ci, pallocCbs, &m_instance));

	// Create the physical device
	//
	uint32_t count = 0;
	ANKI_VK_CHECK(vkEnumeratePhysicalDevices(m_instance, &count, nullptr));
	ANKI_LOGI("VK: Number of physical devices: %u", count);
	if(count < 1)
	{
		ANKI_LOGE("Wrong number of physical devices");
		return ErrorCode::FUNCTION_FAILED;
	}

	count = 1;
	ANKI_VK_CHECK(vkEnumeratePhysicalDevices(m_instance, &count, &m_physicalDevice));

	vkGetPhysicalDeviceProperties(m_physicalDevice, &m_devProps);

	// Find vendor
	switch(m_devProps.vendorID)
	{
	case 0x13B5:
		m_vendor = GpuVendor::ARM;
		break;
	case 0x10DE:
		m_vendor = GpuVendor::NVIDIA;
		break;
	case 0x1002:
	case 0x1022:
		m_vendor = GpuVendor::AMD;
		break;
	}
	ANKI_LOGI("GPU vendor is %s", &GPU_VENDOR_STR[m_vendor][0]);

	vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_devFeatures);

	return ErrorCode::NONE;
}
Esempio n. 15
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;
}