岁月流转,往昔空明

C++博客 首页 新随笔 联系 聚合 管理
  118 Posts :: 3 Stories :: 413 Comments :: 0 Trackbacks

#

     摘要: 没啥好说的,有图有真相。上个逐像素光照的图。
基本上编译器的架构已经确定了,好多功能亟待实现。  阅读全文
posted @ 2011-06-25 16:10 空明流转 阅读(2211) | 评论 (5)编辑 收藏

该项目简报包含了近9个月SALVIA项目的工作进展。

 

项目与配置管理:

  • 源代码管理系统由SVN更换至Mercurial。
  • SoftArt更名为SALVIA。工程、命名空间及相关文档的更新将在Release之前完成。
  • SALVIA启用了LOGO。LOGO在Release之前将视效果酌情调整。
  • 提交版本的LOG信息中启用符合Issue Tracker的格式,使得版本更新可以反映到Issue中。
  • 添加了完整的Unit Test工程,并启用Auto Test系统完成黑盒和回归测试。
  • 合并了LLVM的源码至版本库中;LLVM升级至2.9并进行了适当修改以和Boost的类型系统相一致。
  • Boost升级至1.44或以上。
  • 添加了一个用于分析代码行数的小工具。
  • 更新了部分文档。

Graphics管线:

  • 绘制部分支持OpenGL。
  • 对Subdivision-based Rasterizer进行了进一步优化。
  • 更新了EFLIB的命名空间和文件组织。
  • 支持Centroid Sampling。
  • 支持2x与4xMSAA

SALVIA Shading Language(SASL):

  • 使用新的Combinator-based Parser系统以替换Boost.Spirit,提升了编译速度并降低了目标文件大小。
  • 基于Boost.Wave,SASL提供了和C一致的预处理能力。
  • 添加了完整的Name Mangling和函数重载的能力。
  • 设计并完成了Shader与Host ABI的Memory Layout。现在Shader可以被高效的调用。
  • 提供了JIT的支持。
  • 提供了多编译器的Port。
  • 添加了命令行方式的Compiler。该Compiler接受源代码并输出为LLVM IR。
  • 设计并实现了多语言(General,SIMD Shader,SISD Shader)的编译框架。
  • 提供了可测试可回归的编译器实现。
  • 实现了下列语言要素:
    • 基本标量类型及其变量定义
    • 基本矢量类型及其变量定义
    • 结构体定义及其变量定义
    • 顺序语句
    • 函数声明与定义
    • 算术运算符
    • 成员运算符(.)
    • Swizzle与Write Mask
posted @ 2011-06-01 20:22 空明流转 阅读(1556) | 评论 (0)编辑 收藏

这个PPT主要描述了SALVIA的一些设计细节。这是关于软件渲染器SALVIA迄今为止最详细的文档,也是我近四年来的主要工作和研究内容之一。感谢MSRA的龚敏敏为此文做出的审校工作,他也是此项目的Owner之一。

 

在线的PPT:

原PPT下载:

http://www.cppblog.com/Files/lingjingqiu/Introduction%20to%20SALVIA.zip

posted @ 2011-05-16 16:36 空明流转 阅读(1911) | 评论 (1)编辑 收藏

     摘要: 如何在CPU上高效的模拟执行类似于DirectX这样的Shader?本文所提出的设计方案或许会对你有所启发。
文章内容包括:
1. 什么是Shader的入口函数
2. 如何生成与管线相兼容的标准C函数
3. 如何在shader code中操作图形管线语义值(SV_*)  阅读全文
posted @ 2011-04-14 10:23 空明流转 阅读(1528) | 评论 (0)编辑 收藏

表达式值的存储

LLVM中基本数据类型及存储类型

值是编译器所需要处理的基本数据。它出现在各个角落,条件分支、表达式、返回语句。甚至是函数地址也可以被视作是值类型。

对于编译器而言,最基本的值是整数和浮点。其他的值都可以用这两者来表达,例如布尔和指针。如果你是从一个最基本的指令集开始写起,那么整数和浮点的数值运算、转换、基于整数寄存器的跳转和地址取值是一个寄存器机的最基本操作。所有更加高级的操作,例如数组、结构体、指针、函数、对象等,都可以建立在这一基础上。

如果一个指令系统在整数和浮点数之外,额外提供了布尔、分支、函数调用和结构体的支持,那么它与高级语言将会贴近更多,生成代码的方式也更加简单。

在高级语义的数据结构上,LLVM提供了相当良好的支持。它支持的原生类型(First class)包括: 各种精度的整型和浮点数,指针、向量,结构体和数组。这些类型的数据存取和运算都是有指令直接支撑,而不需要自行计算并生成更加原始的指令。

在存储类型上,LLVM提供了Value, Argument, Alloca, GlobalVariable, Pointer五种存储类型。Value是右值,它不可取引用,不可更改。Argument表示了函数实参,它是Value的一个派生类。所以对参数的任何更改行为实际上都是不被允许的。Alloca保存了栈地址,GlobalVariable保存了全局变量的地址,Pointer则是一般意义上的指针。

除了存储指令,LLVM所有的指令都是针对Value的操作,并返回一个Value。所以

Var a = Alloca int
Var b = Alloca int
Var c = Alloca int
c = ADD a, b

这样的操作,在LLVM中实际上是将a和b的地址相加,并把C从变量替换成一个左值(注意,是替换,变量的值没有任何变化)。

在LLVM中,正确的做法应当类似于下面这样:

a = Alloca int
b = Alloca int
c = Alloca int
a_v = load a
b_v = load b
c_v = ADD a, b
store c, c_v

要先将值从变量中读出,进行操作,再保存到另外一个变量中。

表达式值的数据结构

一个的表达式参数或结果可能是左值或右值。例如++x输入一个左值返回一个左值,而x++就返回一个右值。A+B则是需要两个右值并返回一个右值。

一个左值可以很方便的转化为右值,但是右值转化成左值通常是很困难的。地址信息被丢弃了,或者它根本就是一个字面常量,都会导致一个右值将永远是右值。将右值构造成左值的唯一办法,就是构造临时对象并将右值赋予左值。当这个左值被读取时,如果临时对象除了初始化之外从未被写过,并且它关联的右值依然有效,那么这个操作会被优化成直接返回那个原始的右值,从而避免临时左值的读写操作。

在Clang(一个C++编译器的前端)中对左值和右值进行了严格的区分。这是由于C++需要额外的处理临时对象。临时对象意味着尽管它有右值的语义,但是实际上是左值的存储。这是需要将真正的左值和临时的左值区分开,并提供特定语境下的转化。

SASL没有处理复杂的临时对象问题,因此它使用了一个相对简单的办法来解决左右值的判定和存储。

我们设计了一个数据结构,用于保存任何可能的值。

struct Data{
    bool isRef;
    Value* rval;
    Alloca* local;
    GlobalVariable* global;
    struct Aggregated{
        Data* parent;
        int index;
    } agg;
};

rval用于处理Argument和右值时的情况。Local意味着它是一个局部变量,global说明它是一个全局变量,agg则用于处理structure member。Parent指向包含当前变量的聚合变量,index则指明了当前变量在聚合变量中的位次。

SASL提供了load, load_ptr 和 store 来数据的存取,而不要关心它的具体存储类型。

左值/右值语义

在Data这个结构中,rval, local, global和agg四个值是互斥的。当然这里的我们也可以选择union+enum的方式来表达。

首先来看,这个结构如何表达左值/右值语义。

来看isRef,这是一个标记位。它表示了data存储的值究竟是值本身还是地址。如果是isref为真,那么data便可以被认为是一个左值。Isref为假,那么当它是rval的时候,它就是一个真正的右值了。如果是Alloca或者GlobalVariable,因为它们本身就代表了地址,那么它仍然是一个右值。如果是agg,那么要取决于它的聚合量是左值还是右值。

如果参数需要左值,那么可以直接从data拷贝,或者使用load_ptr + isRef创建一个新的右值Data。如果参数需要右值,那么可以通过load的方式获取一个右值。

数据存取的实现

llvm::Value* load( cgllvm_sctxt* data ){
  assert(data);
  Value* val = data->val;
  do{
    if( val ){ break; }
    if( data->local ){ val = builder()->CreateLoad( data->local );
      break;
    }
    if( data->global ){
      val = builder()->CreateLoad( data->global );
      break;
    }
    if( data.agg.parent ){
      val = load( data->agg.parent );
      val = builder()->CreateExtractValue( val, data->agg.index );
      break;
    }
  } while(0);

  if( data->is_ref ){val = builder()->CreateLoad( val );}
  return val;
}


llvm::Value* load_ptr( cgllvm_sctxt* data ){

  Value* addr = NULL;
  if( data->val ){ addr = NULL; }
  if( data->local ){
    addr = data->local;
  }
  if( data->global ){
    addr = data->global;
  }
  if( data->agg.parent ){
    addr = builder()->CreateGEP( load_ptr(data->agg.parent), 0, data->arg.index );
  }

  if( data->is_ref ){
    if( !addr ){
      addr = data->val;
    } else {
      addr = builder()->CreateLoad( addr );
    }
  }

  return addr;
}

void store( llvm::Value* v, cgllvm_sctxt* data ){
  Value* addr = load_ptr( data );
  builder()->CreateStore( v, addr );
}
posted @ 2011-04-13 11:04 空明流转 阅读(1650) | 评论 (1)编辑 收藏

这是我为部门内部介绍C++0x(11)时所使用的PPT。

示例代码在

 http://www.cppblog.com/Files/lingjingqiu/Cpp11SamplesGCC.zip

http://www.cppblog.com/Files/lingjingqiu/Cpp11Samples.zip

如果有任何问题,欢迎跟帖询问,我将尽可能的做出解答。

posted @ 2011-03-31 13:05 空明流转 阅读(2293) | 评论 (2)编辑 收藏

大家在公司用到的VCS,一般都是和Issue tracker / Bug tracker 关联到一起的。

 

比方说,我在VCS里面填上update log:

Fixed error about animiation matrix updating.
Bug 223789 updated.
Review 1776.

然后将这个change提交,此时Bug tracker上便会更新,变成这样:

Issues: 987654

一般这里的Bug号,review号和Issue号都会有相应的链接,连接到对应的内容上以方便查阅。

 

那么在Google code里如何实现这一点呢?

首先,如果你在log中涉及了某个issue,并以issue nnn或者是issue #nnn 填上对应的Issue号,那么在SVN的浏览中,自然会产生某个链接,如SALVIA里面的:

Log message

SASL:
  Add syntax_tree_builder into syntax_tree project.
  Add parse_api into parser.
  Add parse_api into syntax tree.
  Issue 49 updated.

此时,Google的Change viewer还会提供相应的超链接。但是当你点到Issue49之后,会发现Issue49并没有更新当前revision的信息。这是怎么回事呢?

答案是,如果想经由Log去更新Issue tracker,必须要按照一定的格式

完整的文章,可以参见google的帮助

这里给大家提供一个快速教程:

首先,整个命令的格式大致如下:

$COMMAND$ issue $ISSUE ID$
$FIELD$: $FIELD$ $CONTENT$
$DESCRIPTION$

COMMAND一共有三种,New,Update,Fixes。含义就不说了,大家都懂。

Field,就是类似于Summary,Owner一类,在Issue Editor的界面上大家都能看到。

Description呢,一方面用于你这次更新的详细说明,另一方面也会提交到Issue Tracker中。

注意,在Update的时候,Field也好,Description也好,至少要填一项,否则Issue tracker是不会给你更新信息的。

下面咱们来举个例子:

Log message

SALVIA:
  Update issue 53 (注意,这里没有句号)
  Issue 53 will be added an new comments.
这个时候,Issue track就会更新为:

Comment 1 by project member wuye9036, Today (43 minutes ago)

This issue was updated by revision r462.

  Issue 53 will be added an new comments.

你看,自动更新了吧。但是注意哦。Update那条命令之前的内容,并没有被更新到Issue tracker中。

哈哈,Have fun!

posted @ 2011-03-09 17:05 空明流转 阅读(1652) | 评论 (0)编辑 收藏

这个是我为Autodesk Technical Summit 2011,一个公开的Autodesk技术宣讲会准备的PPT的5分钟简短介绍。在这个Presentation中,将主要讨论关于光栅化的软件渲染器的主要架构,以及在实现和优化方面的技术细节。

image

image

image

image

image

image

image

image

image

image

image

posted @ 2011-03-02 16:33 空明流转 阅读(1616) | 评论 (1)编辑 收藏

http://www.cppblog.com/Files/lingjingqiu/TemplateSample.zip

 

代码在这里。演示了如何讲一个模板类中的普通成员函数和模板函数进行实例化,以实现分离编译。

没有对实例化的原理、编译器关键字和参数进行详细解释,因此仅供对模板有基本常识的人参考。

这段代码本来是在我所在的Team内部供同事参考并用作写一些Demo以测试编译器特性用的。

但是考虑到示例不牵涉到公司产品,并且对大家理解模板规则,缩短富模板代码的编译时间,减少中间文件大小是有一定帮助的,故在博客上放出。

如有不妥之处,请指正。

 

代码在MSVC10和MINGW GCC 4.5.0下通过。

如果有希望其他示例或在其他编译器(平台限Linux,Mac OS,Windows;编译器限GCC 4.0+(含4.0,下同), MSVC 2005+,Intel 11.0+)上测试不通过的,请联系我,谢谢。

posted @ 2011-01-28 19:04 空明流转 阅读(2245) | 评论 (2)编辑 收藏

最近一段时间,SoftArt的所有更新,都集中在编译器上。虽然没有办法赶上在2011年的SoftArt第一版本的alpha发布(也许会更名为Salvia,版本代号为Cryptic Era),但是整体进度还是比较理想的。今天提交了r425,这是一个比较重要的更新。到这个更新为止,编译器在后端的所有API便基本确定了。除去以后对参数和签名的小改动,基本结构已经成型。

Parser,AST,Semantic和Code gen都已经有了相应的原型和对应的测试。接下来基本就是堆代码的体力活了。

接下来,有以下工作比较重要:

0. 未实现的语言特性及对应的测试用例。

1. automatic regression tests的框架。这个框架的名称就叫fart,framework of auto regression tests的简写。这个Test与现有的unit tests稍有不同,他在第一次生成代码的时候,是要人工去检查并执行验证的。以后所有的测试,都是将结论与蓝本进行比较。

2. semantic阶段的出错处理,以及code generate阶段的容错机制。这一部分的将随着编译器的逐步完善而完善。

3. 并行化的代码生成。生成以SIMD方式执行的代码是这个编译器开发的初衷,它也是整个编译器功能中最重要的部分。

4. Host和Runtime部分。这一部分主要负责编译器的初始化,内建函数的注册,与脚本的交互等功能。在这一部分完成后,SoftArt就可以正式将SASL集成进来。

5. Shader API的设计和实现。

简易的计划表:

1.0(~Jun 2011):

不随SoftArt发布。完成进度:0: >60% 1: >80% 2: >20% 3: – 4: – 5: -

2.0(~Q1 2012):

编译器随SoftArt发布。未集成。进度: 0: >75% 1: >90% 2: >40% 3: – 4: – 5: -

3.0(~2013):

集成进softart。进度: 0: >85% 1: >90% 2: >50% 3: – 4: >50% 5: >30%

posted @ 2011-01-26 21:21 空明流转 阅读(1738) | 评论 (2)编辑 收藏

仅列出标题
共12页: 1 2 3 4 5 6 7 8 9 Last