现在的位置: 首页 > 综合 > 正文

klimt架构

2017年12月20日 ⁄ 综合 ⁄ 共 2429字 ⁄ 字号 评论关闭

转自:http://blog.csdn.net/Duwchy

 

 

1. Klimt的设计目标

清晰的面向对象设计风格,易于了解Klimt的内部结构;
可扩展的
模块化的组件使得它更容易修改到更高级的版本(硬件光栅器,无线多媒体扩展Wireless-MMX,等等)
支持多种平台,编译系统,和操作系统

2. Klimt的实现方式

由于一些类(比如Context 和 Resterizer)相当庞大,他们被分开为多个源文件。对于每一个类,都有一个以类名命名的主文件(比如 klContext.h),另外的文件就以类为前缀进行命名(如 klContext_oglMatrix.h)
Klimt主要的部分是非常独立于硬件的。硬件依赖目前主要只存在于两个类:
1) klFloat - 实现基础的数据类型。目前有硬件独立的实现和快速的XScale处理器的特定实现(使用 Intel GPP)。
2) klEGLSurface - 由klEGLSurface 派生来的类,实现特定硬件的图形渲染。目前有针对PocketPC的GAPI和PocketHAL的两种实现。对于桌面视窗,图形渲染目标是显示2x zoomed的窗体。

3. Klimt中使用的概念

Klimt使用几种编程理念来提供系统高层编程上的硬件独立和和3D图形的高表现能力。
3.1 模板编程和运算符重载
Klimt 使用大量的模板和运算符重载(总是使用适合于不同编译器的简单语言结构)。这就使得在调试(debug)模式下代码的效率很低(调试模式下的inline函数不会被展开),但使用release模式编译时就可以得到优化。
3.2 浮点类型的提取
Klimt
不使用C的“float”类型作为浮点类型变量,而是用一个封装的类代替。这个封装的类为传统的“float”类型重载了所有主要的运算符。这种封装的有
点是隐藏内部的数据类型并且可以在不改变Klimt的代码的基础上改变这些类型。当有一种高精度的实现需要使用到内部的“float”甚至
“double”数据类型时,这种数据类型在小型的平台上效率是很慢的(在多媒体扩展指令可用的情况下可能有所改变)。如今这种封装有几种实现(调用
klFloat):floating-point, generic fixed-point 和 fixed-point,使用在 Intel
GPP。将来会有更多的实现。
klFloat类型在src/base/klMath.h的文件中定义,要使用这种潜在的数据类型时,请使用预编译。
自从fixed-point的数据类型只提供一种被简化的数据范围和精度之后,为了在调试期间避免这种问题使用klFloat实现的floating-point数据类型会更加方便。
3.3 自动的编译时代码产生
使
用软件渲染来实现诸如OpenGL的具有灵活性的API的一个主要的问题是光栅器的行扫描功能(scanline-function)只能进行一次的优
化。例如一种行扫描功能可以使用阴影,纹理或者z-testing绘制行扫描,但是不使用z-writing,混合和雾化,只有这种顶点功能性的函数可以
执行得非常快时才必须提供这些处理。相反,一个函数想要支持几种不同的可选特性时必须选择是否之用一种特性。基本上,做出决定有两种方式:
1) 逐行扫描(per-scanline)
2) 逐个像素处理(per-pixel)

逐行扫描的情况下,在询问时会有预测试,主要目的是验证每个操作(纹理,阴影等)是否对像素是有用的。例如,加入将要进行纹理操作,这时有一个缓冲区就会
填满纹理的像素数据,接下来这些纹理像素将会被与其他操作的像素的结果合并在一起,比如阴影、雾化等。这种解决方案的优点是具有很高的灵活性和允许使用少
量的代码实现大量的合并(要注意的是只有一个单独的纹理功能);但它的缺点是效率很慢。很容易看出这种缓冲区填充和合并方式要耗费大量的内存带宽,这在移
动的平台是一个严重的瓶颈。另一个降低速度的来源是这种解决方案在每个操作的执行的最后都要执行z-test,这就意味这虽然行扫描对是不可见的,但我们
还是要对每个像素进行纹理、阴影、雾化等操作。最后一个缺点可以通过使用被预z-test(early
z-test)初始化的“visible-pixel”计数器进行改进。因为这个解决方案提供了很大的灵活性,Klimt可能会在以后使用这个方案。

预像素处理的情况下,测试是否是一种针对每个像素的操作。这种方法在一般的情况下会显得很慢。比如我们为每个像素设置条件,以测试是否像素为可见,是否要
写到z-buffer,是否纹理处理,是否阴影处理,是否雾化,是否混合等等。这样的优点是z-test可以提早执行,以至于其他操作可以在像素可见之前
被忽略。
为了优化效率,一般情况下,我们可以使用一个特别的函数去处理一些操作的每一次合并。所以每个函数都有一个操作的固定的集合。这就是
Klimt光栅处理的方式。对于每一个特性的合并,都有一个实现那些特性集合的特殊的函数。这种操作可以导致需要大量的函数,手写每个函数是很不可行的。
幸运的是,Klimt中只有一个函数,这个函数使用预处理命令(#ifdef/#endif)选择在编译时那个操作将被使用。Klimt使用Python
脚本去创建所有存储在文件“klRasterizerSW565_FuncTable.h”中的合并。当这种方案产生快速的代码的同时,也产生太多的代
码。Klimt目前处理的行扫描函数上升到735。这导致最后编译出来的代码库变得相当大(1到2MB)。

4.Klimt的类

Klimt的两个主要的类是 klContext 和 klRasterizer。
klContext
提供C++
的API接口(使用C-wrapper进行封装)并且内部使用klRasterizer。所有klEGL类提供视频内存访问的功能。大量的基础类(存储在
src/base/) 提供向量、矩阵、栈等的功能。下图显示了Klimt三个层次的代码。一个类只能访问同层或者更底层的类。

抱歉!评论已关闭.