Esempio n. 1
0
static void getStack(CONTEXT& context, char* out, int max_size)
{
	BOOL result;
	HANDLE process;
	HANDLE thread;
	STACKFRAME64 stack;
	char symbol_mem[sizeof(IMAGEHLP_SYMBOL64) + 256];
	IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)symbol_mem;
	DWORD64 displacement;
	char name[256];
	copyString(out, max_size, "Crash callstack:\n");
	memset(&stack, 0, sizeof(STACKFRAME64));

	process = GetCurrentProcess();
	thread = GetCurrentThread();
	displacement = 0;
	DWORD machineType;
#ifdef _WIN64
	machineType = IMAGE_FILE_MACHINE_IA64;
	stack.AddrPC.Offset = context.Rip;
	stack.AddrPC.Mode = AddrModeFlat;
	stack.AddrStack.Offset = context.Rsp;
	stack.AddrStack.Mode = AddrModeFlat;
	stack.AddrFrame.Offset = context.Rbp;
	stack.AddrFrame.Mode = AddrModeFlat;
#else
	machineType = IMAGE_FILE_MACHINE_I386;
	stack.AddrPC.Offset = context.Eip;
	stack.AddrPC.Mode = AddrModeFlat;
	stack.AddrStack.Offset = context.Esp;
	stack.AddrStack.Mode = AddrModeFlat;
	stack.AddrFrame.Offset = context.Ebp;
	stack.AddrFrame.Mode = AddrModeFlat;
#endif

	do
	{
		result = StackWalk64(machineType,
			process,
			thread,
			&stack,
			&context,
			NULL,
			SymFunctionTableAccess64,
			SymGetModuleBase64,
			NULL);

		symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
		symbol->MaxNameLength = 255;

		SymGetSymFromAddr64(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbol);
		UnDecorateSymbolName(symbol->Name, (PSTR)name, 256, UNDNAME_COMPLETE);

		catString(out, max_size, symbol->Name);
		catString(out, max_size, "\n");

	} while (result);
}
Esempio n. 2
0
bool Shader::generateInstances()
{
	for (int i = 0; i < m_instances.size(); ++i)
	{
		LUMIX_DELETE(m_allocator, m_instances[i]);
	}
	m_instances.clear();

	uint32 count = 1 << m_combintions.m_define_count;

	auto* binary_manager = m_resource_manager.get(ResourceManager::SHADER_BINARY);
	char basename[MAX_PATH_LENGTH];
	PathUtils::getBasename(basename, sizeof(basename), getPath().c_str());

	for (uint32 mask = 0; mask < count; ++mask)
	{
		ShaderInstance* instance = LUMIX_NEW(m_allocator, ShaderInstance)(*this);
		m_instances.push(instance);

		instance->m_define_mask = getDefineMaskFromDense(mask);

		for (int pass_idx = 0; pass_idx < m_combintions.m_pass_count; ++pass_idx)
		{
			const char* pass = m_combintions.m_passes[pass_idx];
			char path[MAX_PATH_LENGTH];
			copyString(path, "shaders/compiled/");
			catString(path, basename);
			catString(path, "_");
			catString(path, pass);
			char mask_str[10];
			int actual_mask = mask & m_combintions.m_vs_local_mask[pass_idx];
			toCString(actual_mask, mask_str, sizeof(mask_str));
			catString(path, mask_str);
			catString(path, "_vs.shb");

			Path vs_path(path);
			auto* vs_binary = static_cast<ShaderBinary*>(binary_manager->load(vs_path));
			addDependency(*vs_binary);
			instance->m_binaries[pass_idx * 2] = vs_binary;

			copyString(path, "shaders/compiled/");
			catString(path, basename);
			catString(path, "_");
			catString(path, pass);
			actual_mask = mask & m_combintions.m_fs_local_mask[pass_idx];
			toCString(actual_mask, mask_str, sizeof(mask_str));
			catString(path, mask_str);
			catString(path, "_fs.shb");

			Path fs_path(path);
			auto* fs_binary = static_cast<ShaderBinary*>(binary_manager->load(fs_path));
			addDependency(*fs_binary);
			instance->m_binaries[pass_idx * 2 + 1] = fs_binary;
		}
	}
	return true;
}
Esempio n. 3
0
		void outputToVS(const char* system, const char* message)
		{
			char tmp[2048];
			copyString(tmp, system);
			catString(tmp, ": ");
			catString(tmp, message);
			catString(tmp, "\r");

			OutputDebugString(tmp);
		}
Esempio n. 4
0
		IPlugin* load(const char* path) override
		{
			char path_with_ext[MAX_PATH_LENGTH];
			copyString(path_with_ext, path);
			const char* ext =
			#ifdef _WIN32
				".dll";
			#elif defined __linux__
				".so";
			#else 
				#error Unknown platform
			#endif
			if (!PathUtils::hasExtension(path, ext + 1)) catString(path_with_ext, ext);
			g_log_info.log("Core") << "loading plugin " << path_with_ext;
			typedef IPlugin* (*PluginCreator)(Engine&);
			auto* lib = loadLibrary(path_with_ext);
			if (lib)
			{
				PluginCreator creator = (PluginCreator)getLibrarySymbol(lib, "createPlugin");
				if (creator)
				{
					IPlugin* plugin = creator(m_engine);
					if (!plugin)
					{
						g_log_error.log("Core") << "createPlugin failed.";
						LUMIX_DELETE(m_engine.getAllocator(), plugin);
						ASSERT(false);
					}
					else
					{
						addPlugin(plugin);
						m_libraries.push(lib);
						m_library_loaded.invoke(lib);
						g_log_info.log("Core") << "Plugin loaded.";
						Debug::StackTree::refreshModuleList();
						return plugin;
					}
				}
				else
				{
					g_log_error.log("Core") << "No createPlugin function in plugin.";
				}
				unloadLibrary(lib);
			}
			else
			{
				auto* plugin = StaticPluginRegister::create(path, m_engine);
				if (plugin)
				{
					g_log_info.log("Core") << "Plugin loaded.";
					addPlugin(plugin);
					return plugin;
				}
				g_log_warning.log("Core") << "Failed to load plugin.";
			}
			return nullptr;
		}
Esempio n. 5
0
FileIterator* createFileIterator(const char* path, IAllocator& allocator)
{
	char tmp[MAX_PATH_LENGTH];
	copyString(tmp, path);
	catString(tmp, "/*");
	auto* iter = LUMIX_NEW(allocator, FileIterator);
	iter->allocator = &allocator;
	iter->handle = FindFirstFile(tmp, &iter->ffd);
	iter->is_valid = iter->handle != INVALID_HANDLE_VALUE;
	return iter;
}
Esempio n. 6
0
void registerUniverse(UniverseContext* ctx, lua_State* L)
{
	lua_pushlightuserdata(L, ctx);
	lua_setglobal(L, "g_universe_context");
	
	for (auto* scene : ctx->m_scenes)
	{
		const char* name = scene->getPlugin().getName();
		char tmp[128];

		copyString(tmp, "g_scene_");
		catString(tmp, name);
		lua_pushlightuserdata(L, scene);
		lua_setglobal(L, tmp);
	}

	lua_pushlightuserdata(L, ctx ? ctx->m_universe : nullptr);
	lua_setglobal(L, "g_universe");
}
Esempio n. 7
0
bool Model::parseMeshes(FS::IFile& file)
{
	int object_count = 0;
	file.read(&object_count, sizeof(object_count));
	if (object_count <= 0) return false;

	m_meshes.reserve(object_count);
	char model_dir[MAX_PATH_LENGTH];
	PathUtils::getDir(model_dir, MAX_PATH_LENGTH, getPath().c_str());
	for (int i = 0; i < object_count; ++i)
	{
		int32 str_size;
		file.read(&str_size, sizeof(str_size));
		char material_name[MAX_PATH_LENGTH];
		file.read(material_name, str_size);
		if (str_size >= MAX_PATH_LENGTH) return false;

		material_name[str_size] = 0;

		char material_path[MAX_PATH_LENGTH];
		copyString(material_path, model_dir);
		catString(material_path, material_name);
		catString(material_path, ".mat");

		auto* material_manager = m_resource_manager.get(ResourceManager::MATERIAL);
		Material* material = static_cast<Material*>(material_manager->load(Path(material_path)));

		int32 attribute_array_offset = 0;
		file.read(&attribute_array_offset, sizeof(attribute_array_offset));
		int32 attribute_array_size = 0;
		file.read(&attribute_array_size, sizeof(attribute_array_size));
		int32 indices_offset = 0;
		file.read(&indices_offset, sizeof(indices_offset));
		int32 mesh_tri_count = 0;
		file.read(&mesh_tri_count, sizeof(mesh_tri_count));

		file.read(&str_size, sizeof(str_size));
		if (str_size >= MAX_PATH_LENGTH)
		{
			material_manager->unload(*material);
			return false;
		}
		
		char mesh_name[MAX_PATH_LENGTH];
		mesh_name[str_size] = 0;
		file.read(mesh_name, str_size);

		bgfx::VertexDecl def;
		parseVertexDef(file, &def);
		m_meshes.emplace(def,
						 material,
						 attribute_array_offset,
						 attribute_array_size,
						 indices_offset,
						 mesh_tri_count * 3,
						 mesh_name,
						 m_allocator);
		addDependency(*material);
	}
	return true;
}
Esempio n. 8
0
bool Model::parseMeshesOld(bgfx::VertexDecl global_vertex_decl, FS::IFile& file, FileVersion version, u32 global_flags)
{
	int object_count = 0;
	file.read(&object_count, sizeof(object_count));
	if (object_count <= 0) return false;

	m_meshes.reserve(object_count);
	char model_dir[MAX_PATH_LENGTH];
	PathUtils::getDir(model_dir, MAX_PATH_LENGTH, getPath().c_str());
	struct Offsets
	{
		i32 attribute_array_offset;
		i32 attribute_array_size;
		i32 indices_offset;
		i32 mesh_tri_count;
	};
	Array<Offsets> mesh_offsets(m_allocator);
	for (int i = 0; i < object_count; ++i)
	{
		i32 str_size;
		file.read(&str_size, sizeof(str_size));
		char material_name[MAX_PATH_LENGTH];
		file.read(material_name, str_size);
		if (str_size >= MAX_PATH_LENGTH) return false;

		material_name[str_size] = 0;

		char material_path[MAX_PATH_LENGTH];
		copyString(material_path, model_dir);
		catString(material_path, material_name);
		catString(material_path, ".mat");

		auto* material_manager = m_resource_manager.getOwner().get(Material::TYPE);
		Material* material = static_cast<Material*>(material_manager->load(Path(material_path)));

		Offsets& offsets = mesh_offsets.emplace();
		file.read(&offsets.attribute_array_offset, sizeof(offsets.attribute_array_offset));
		file.read(&offsets.attribute_array_size, sizeof(offsets.attribute_array_size));
		file.read(&offsets.indices_offset, sizeof(offsets.indices_offset));
		file.read(&offsets.mesh_tri_count, sizeof(offsets.mesh_tri_count));

		file.read(&str_size, sizeof(str_size));
		if (str_size >= MAX_PATH_LENGTH)
		{
			material_manager->unload(*material);
			return false;
		}

		char mesh_name[MAX_PATH_LENGTH];
		mesh_name[str_size] = 0;
		file.read(mesh_name, str_size);

		bgfx::VertexDecl vertex_decl = global_vertex_decl;
		if (version <= FileVersion::SINGLE_VERTEX_DECL)
		{
			parseVertexDecl(file, &vertex_decl);
			if (i != 0 && global_vertex_decl.m_hash != vertex_decl.m_hash)
			{
				g_log_error.log("Renderer") << "Model " << getPath().c_str()
					<< " contains meshes with different vertex declarations.";
			}
			if(i == 0) global_vertex_decl = vertex_decl;
		}


		m_meshes.emplace(material,
			vertex_decl,
			mesh_name,
			m_allocator);
		addDependency(*material);
	}

	i32 indices_count = 0;
	file.read(&indices_count, sizeof(indices_count));
	if (indices_count <= 0) return false;

	u32 INDICES_16BIT_FLAG = 1;
	int index_size = global_flags & INDICES_16BIT_FLAG ? 2 : 4;
	Array<u8> indices(m_allocator);
	indices.resize(indices_count * index_size);
	file.read(&indices[0], indices.size());

	i32 vertices_size = 0;
	file.read(&vertices_size, sizeof(vertices_size));
	if (vertices_size <= 0) return false;

	Array<u8> vertices(m_allocator);
	vertices.resize(vertices_size);
	file.read(&vertices[0], vertices.size());

	int vertex_count = 0;
	for (const Offsets& offsets : mesh_offsets)
	{
		vertex_count += offsets.attribute_array_size / global_vertex_decl.getStride();
	}

	if (version > FileVersion::BOUNDING_SHAPES_PRECOMPUTED)
	{
		file.read(&m_bounding_radius, sizeof(m_bounding_radius));
		file.read(&m_aabb, sizeof(m_aabb));
	}

	float bounding_radius_squared = 0;
	Vec3 min_vertex(0, 0, 0);
	Vec3 max_vertex(0, 0, 0);

	int vertex_size = global_vertex_decl.getStride();
	int position_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::Position);
	int uv_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::TexCoord0);
	int weights_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::Weight);
	int bone_indices_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::Indices);
	bool keep_skin = global_vertex_decl.has(bgfx::Attrib::Weight) && global_vertex_decl.has(bgfx::Attrib::Indices);
	for (int i = 0; i < m_meshes.size(); ++i)
	{
		Offsets& offsets = mesh_offsets[i];
		Mesh& mesh = m_meshes[i];
		mesh.indices_count = offsets.mesh_tri_count * 3;
		mesh.indices.resize(mesh.indices_count * index_size);
		copyMemory(&mesh.indices[0], &indices[offsets.indices_offset * index_size], mesh.indices_count * index_size);

		int mesh_vertex_count = offsets.attribute_array_size / global_vertex_decl.getStride();
		int mesh_attributes_array_offset = offsets.attribute_array_offset;
		mesh.vertices.resize(mesh_vertex_count);
		mesh.uvs.resize(mesh_vertex_count);
		if (keep_skin) mesh.skin.resize(mesh_vertex_count);
		for (int j = 0; j < mesh_vertex_count; ++j)
		{
			int offset = mesh_attributes_array_offset + j * vertex_size;
			if (keep_skin)
			{
				mesh.skin[j].weights = *(const Vec4*)&vertices[offset + weights_attribute_offset];
				copyMemory(mesh.skin[j].indices,
					&vertices[offset + bone_indices_attribute_offset],
					sizeof(mesh.skin[j].indices));
			}
			mesh.vertices[j] = *(const Vec3*)&vertices[offset + position_attribute_offset];
			mesh.uvs[j] = *(const Vec2*)&vertices[offset + uv_attribute_offset];
			float sq_len = mesh.vertices[j].squaredLength();
			bounding_radius_squared = Math::maximum(bounding_radius_squared, sq_len > 0 ? sq_len : 0);
			min_vertex.x = Math::minimum(min_vertex.x, mesh.vertices[j].x);
			min_vertex.y = Math::minimum(min_vertex.y, mesh.vertices[j].y);
			min_vertex.z = Math::minimum(min_vertex.z, mesh.vertices[j].z);
			max_vertex.x = Math::maximum(max_vertex.x, mesh.vertices[j].x);
			max_vertex.y = Math::maximum(max_vertex.y, mesh.vertices[j].y);
			max_vertex.z = Math::maximum(max_vertex.z, mesh.vertices[j].z);
		}
	}

	if (version <= FileVersion::BOUNDING_SHAPES_PRECOMPUTED)
	{
		m_bounding_radius = sqrt(bounding_radius_squared);
		m_aabb = AABB(min_vertex, max_vertex);
	}

	for (int i = 0; i < m_meshes.size(); ++i)
	{
		Mesh& mesh = m_meshes[i];
		Offsets offsets = mesh_offsets[i];
		
		ASSERT(!bgfx::isValid(mesh.index_buffer_handle));
		if (global_flags & INDICES_16BIT_FLAG)
		{
			mesh.flags.set(Mesh::Flags::INDICES_16_BIT);
		}
		int indices_size = index_size * mesh.indices_count;
		const bgfx::Memory* mem = bgfx::copy(&indices[offsets.indices_offset * index_size], indices_size);
		mesh.index_buffer_handle = bgfx::createIndexBuffer(mem, index_size == 4 ? BGFX_BUFFER_INDEX32 : 0);
		if (!bgfx::isValid(mesh.index_buffer_handle)) return false;

		ASSERT(!bgfx::isValid(mesh.vertex_buffer_handle));
		const bgfx::Memory* vertices_mem = bgfx::copy(&vertices[offsets.attribute_array_offset], offsets.attribute_array_size);
		mesh.vertex_buffer_handle = bgfx::createVertexBuffer(vertices_mem, mesh.vertex_decl);
		if (!bgfx::isValid(mesh.vertex_buffer_handle)) return false;
	}

	return true;
}
Esempio n. 9
0
bool Model::parseMeshes(const bgfx::VertexDecl& global_vertex_decl, FS::IFile& file, FileVersion version, u32 global_flags)
{
	if (version <= FileVersion::MULTIPLE_VERTEX_DECLS) return parseMeshesOld(global_vertex_decl, file, version, global_flags);
	
	int object_count = 0;
	file.read(&object_count, sizeof(object_count));
	if (object_count <= 0) return false;

	char model_dir[MAX_PATH_LENGTH];
	PathUtils::getDir(model_dir, MAX_PATH_LENGTH, getPath().c_str());

	m_meshes.reserve(object_count);
	for (int i = 0; i < object_count; ++i)
	{
		bgfx::VertexDecl vertex_decl;
		if (!parseVertexDeclEx(file, &vertex_decl)) return false;

		i32 str_size;
		file.read(&str_size, sizeof(str_size));
		char material_name[MAX_PATH_LENGTH];
		file.read(material_name, str_size);
		if (str_size >= MAX_PATH_LENGTH) return false;

		material_name[str_size] = 0;

		char material_path[MAX_PATH_LENGTH];
		copyString(material_path, model_dir);
		catString(material_path, material_name);
		catString(material_path, ".mat");

		auto* material_manager = m_resource_manager.getOwner().get(Material::TYPE);
		Material* material = static_cast<Material*>(material_manager->load(Path(material_path)));
		
		file.read(&str_size, sizeof(str_size));
		char mesh_name[MAX_PATH_LENGTH];
		mesh_name[str_size] = 0;
		file.read(mesh_name, str_size);

		m_meshes.emplace(material, vertex_decl, mesh_name, m_allocator);
		addDependency(*material);
	}

	for (int i = 0; i < object_count; ++i)
	{
		Mesh& mesh = m_meshes[i];
		int index_size;
		int indices_count;
		file.read(&index_size, sizeof(index_size));
		if (index_size != 2 && index_size != 4) return false;
		file.read(&indices_count, sizeof(indices_count));
		if (indices_count <= 0) return false;
		mesh.indices.resize(index_size * indices_count);
		file.read(&mesh.indices[0], mesh.indices.size());

		if (index_size == 2) mesh.flags.set(Mesh::Flags::INDICES_16_BIT);
		mesh.indices_count = indices_count;
		const bgfx::Memory* indices_mem = bgfx::copy(&mesh.indices[0], mesh.indices.size());
		mesh.index_buffer_handle = bgfx::createIndexBuffer(indices_mem);
	}

	for (int i = 0; i < object_count; ++i)
	{
		Mesh& mesh = m_meshes[i];
		int data_size;
		file.read(&data_size, sizeof(data_size));
		const bgfx::Memory* vertices_mem = bgfx::alloc(data_size);
		file.read(vertices_mem->data, vertices_mem->size);

		const bgfx::VertexDecl& vertex_decl = mesh.vertex_decl;
		int position_attribute_offset = vertex_decl.getOffset(bgfx::Attrib::Position);
		int uv_attribute_offset = vertex_decl.getOffset(bgfx::Attrib::TexCoord0);
		int weights_attribute_offset = vertex_decl.getOffset(bgfx::Attrib::Weight);
		int bone_indices_attribute_offset = vertex_decl.getOffset(bgfx::Attrib::Indices);
		bool keep_skin = vertex_decl.has(bgfx::Attrib::Weight) && vertex_decl.has(bgfx::Attrib::Indices);

		int vertex_size = mesh.vertex_decl.getStride();
		int mesh_vertex_count = vertices_mem->size / mesh.vertex_decl.getStride();
		mesh.vertices.resize(mesh_vertex_count);
		mesh.uvs.resize(mesh_vertex_count);
		if (keep_skin) mesh.skin.resize(mesh_vertex_count);
		const u8* vertices = vertices_mem->data;
		for (int j = 0; j < mesh_vertex_count; ++j)
		{
			int offset = j * vertex_size;
			if (keep_skin)
			{
				mesh.skin[j].weights = *(const Vec4*)&vertices[offset + weights_attribute_offset];
				copyMemory(mesh.skin[j].indices,
					&vertices[offset + bone_indices_attribute_offset],
					sizeof(mesh.skin[j].indices));
			}
			mesh.vertices[j] = *(const Vec3*)&vertices[offset + position_attribute_offset];
			mesh.uvs[j] = *(const Vec2*)&vertices[offset + uv_attribute_offset];
		}
		mesh.vertex_buffer_handle = bgfx::createVertexBuffer(vertices_mem, mesh.vertex_decl);
	}
	file.read(&m_bounding_radius, sizeof(m_bounding_radius));
	file.read(&m_aabb, sizeof(m_aabb));

	return true;
}
Esempio n. 10
0
bool Material::deserializeTexture(JsonSerializer& serializer, const char* material_dir)
{
	char path[MAX_PATH_LENGTH];
	serializer.deserializeObjectBegin();
	char label[256];
	bool keep_data = false;
	uint32 flags = 0;
	int atlas_size = -1;

	while (!serializer.isObjectEnd())
	{
		serializer.deserializeLabel(label, sizeof(label));
		if (compareString(label, "source") == 0)
		{
			serializer.deserialize(path, MAX_PATH_LENGTH, "");
			if (path[0] != '\0')
			{
				char texture_path[MAX_PATH_LENGTH];
				if (path[0] != '/' && path[0] != '\\')
				{
					copyString(texture_path, material_dir);
					catString(texture_path, path);
				}
				else
				{
					copyString(texture_path, path);
				}
				m_textures[m_texture_count] = static_cast<Texture*>(
					m_resource_manager.get(ResourceManager::TEXTURE)->load(Path(texture_path)));
				addDependency(*m_textures[m_texture_count]);
			}
		}
		else if (compareString(label, "atlas_size") == 0)
		{
			serializer.deserialize(atlas_size, -1);
		}
		else if (compareString(label, "min_filter") == 0)
		{
			serializer.deserialize(label, sizeof(label), "");
			if (compareString(label, "point") == 0)
			{
				flags |= BGFX_TEXTURE_MIN_POINT;
			}
			else if (compareString(label, "anisotropic") == 0)
			{
				flags |= BGFX_TEXTURE_MIN_ANISOTROPIC;
			}
			else
			{
				g_log_error.log("Renderer") << "Unknown texture filter \"" << label
											<< "\" in material " << getPath().c_str();
			}
		}
		else if (compareString(label, "mag_filter") == 0)
		{
			serializer.deserialize(label, sizeof(label), "");
			if (compareString(label, "point") == 0)
			{
				flags |= BGFX_TEXTURE_MAG_POINT;
			}
			else if (compareString(label, "anisotropic") == 0)
			{
				flags |= BGFX_TEXTURE_MAG_ANISOTROPIC;
			}
			else
			{
				g_log_error.log("Renderer") << "Unknown texture filter \"" << label
											<< "\" in material " << getPath().c_str();
			}
		}
		else if (compareString(label, "u_clamp") == 0)
		{
			bool b;
			serializer.deserialize(b, false);
			if (b)
			{
				flags |= BGFX_TEXTURE_U_CLAMP;
			}
		}
		else if (compareString(label, "v_clamp") == 0)
		{
			bool b;
			serializer.deserialize(b, false);
			if (b)
			{
				flags |= BGFX_TEXTURE_V_CLAMP;
			}
		}
		else if (compareString(label, "w_clamp") == 0)
		{
			bool b;
			serializer.deserialize(b, false);
			if (b)
			{
				flags |= BGFX_TEXTURE_W_CLAMP;
			}
		}
		else if (compareString(label, "keep_data") == 0)
		{
			serializer.deserialize(keep_data, false);
		}
		else
		{
			g_log_warning.log("Renderer") << "Unknown data \"" << label << "\" in material "
										  << getPath().c_str();
			return false;
		}
	}
	if (m_textures[m_texture_count])
	{
		m_textures[m_texture_count]->setAtlasSize(atlas_size);
		m_textures[m_texture_count]->setFlags(flags);

		if (keep_data)
		{
			m_textures[m_texture_count]->addDataReference();
		}
	}
	serializer.deserializeObjectEnd();
	++m_texture_count;
	return true;
}