岁月流转,往昔空明

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

置顶随笔 #

SALVIA是一款光栅化的软件渲染器,设计目标是达到Direct3D 10/11的核心功能的实现。我们的设计目的主要包括以下几点

  • 一个高度可移植的光栅化图形管线的软件实现
  • 图形硬件工作原理的展现和教学
  • 为下一代Many Core处理器架构的计算设备提供高性能的图形绘制能力
  • 提供在GPU一类的流处理器上难以实现,但在Many Core架构的设备上有着显著优势的Features
  • 比图形API更加易于使用的接口
  • 与复杂的渲染技术(如辐射度和光线追踪等)相结合的可伸缩的渲染体系,研究可以提供速度-质量相均衡的渲染架构


SALVIA的接口重点参照了DX10的设计。
以流水线划分Stage;每个Stage及其相关设施的接口,均采用了Object-Oriented的设计风格。
这种设计与D3D9和OGL的状态机风格的设计相比更易于使用,同时也降低了流水线前后级的耦合,对于优化或扩展都是有利的。

目前,SALVIA已经具有了完整的D3D9的流水线级,并有了基本的Demo。
在未来,SALVIA将在维持内核稳定的同时,通过扩展提供先进的图形技术支撑。
同时,我们还将尝试着将一些不易在GPU上实现的算法,以扩展的形式在SALVIA中实现出来,以期提供高于图形API的表现和特性。

SALVIA在近阶段的主要工作包括:

  • Rasterizer的优化
  • SALVIA Shading Language语言特性设计及编译器实现,为SALVIA提供文本化的Shader
  • MSAA,并提供可定制的Sampling Pattern(2x 和 4x,目前尚有Bug)
  • EWA-based Anistropic Filtering
  • 以扩展形式提供的Geometry Shader,Hull Shader和Tesselassion Shader
  • 并行优化(持续优化中)
  • Intel SCC的移植
  • 特性及性能的演示用例
  • 文档撰写 (已经有成员负责此事)


目前,SALVIA已经作为一个开源项目发布在http://code.google.com/p/softart上,最新的代码在Mercurial中。
所有代码除特殊声明外,均为GPL 2协议,您可以在协议许可的范围内自由下载或使用。

如果发现了软件的缺陷,或者有任何好的意见和建议,您可以在项目管理页面上留言,或者联系作者
wuye9036@gmail.com
minmin.gong@gmail.com
我谨代表项目全体成员及用户,对您为本项目的发展做出的独一无二的贡献表示敬意和感谢!


作为一款基于GPL2协议的开源光栅化渲染器,SALVIA的目的当然不仅仅是软件产品那么简单。
我们也希望以SALVIA为基础,建设一个充满智慧与活力的社区。
这个社区里,每一个智慧的闪光,都能够给其他人以启迪;每一个智慧的闪光,都能够使SALVIA向更好的方向迈出一步。

随着SALVIA框架的完成,SALVIA复杂而有挑战性的特性扩充工作已经摆在面前。
无论你

  • 是喜欢Irregular Z Buffer一类不走寻常路的硬件架构技术,期望实现自己的硬件架构;
  • 还是痴迷于运用最新的图形学理论,制作让人眼花缭乱,叹为观止的Demo;
  • 还是希望将SALVIA与商业产品相结合,使其想用户所想,为用户所不能为;

我们都以100%的热忱欢迎您。

为了维持SALVIA核心框架的稳定性,保证代码质量,我们计划将全部的Project Members分为核心组开发者组两部分。

核心组
暂时由 空明流转(wuye9036@gmail.com) 和 Minmin.Gong(minmin.gong@gmail.com) 组成,主要负责架构设计,Shading Language语言标准的制定,SALVIA内核的开发,设计文档和接口约定的撰写,以及主分支的维护工作。

开发者组将按照工作内容大致分为三种:

  • 文档组:主要负责注释和文档的撰写工作等
  • 编译器组:负责编译器Host特性和Language Bridge的设计和扩充,编译器维护,性能调优等
  • 扩展组:撰写设备或辅助库扩展,如Geometry Shader的Host代码,数学库等

现有开发组成员均具有6-12年不等的开发经验,多数在业内著名企业担任主要开发人员或技术负责人的职位。

我们对开发组成员充分信任,开发组成员将在各自的分支上完成开发工作,在您工作的分支上,您享有完全的写权限。
我们将按期进行所有分支修改的Review工作,并邀请您参与到Review中来,您既是分支的作者,也是其他分支的审阅者。
如果您的修改通过了Review并采纳到主分支中,我们希望能在您的协助下,将您对SALVIA的所思,所想,所为,原原本本的融入到SALVIA主分支中,令它如您所想般的成长。
同时,核心组将会视情况,组织线上或线下的技术交流活动,与大家一起交流技术心得、分享管理经验。当然,也会分享快乐的人生。

如果您希望加入我们这个团队当中,为我们的团队,为SALVIA提供您宝贵的支持,请您准备好您的以下资料

  • ID:常用的ID,最好包括真实姓名
  • Google Account:如果没有,可以申请一个。因为我们的SVN Repository是建立在Google Code上的)
  • 联系方式:IM(QQ,MSN,GTALK)和Email,有手机最好
  • 自我介绍:包括擅长的技术啦,项目经验啦,闲扯也可,呵呵
  • 希望参与的工作
  • 其他要求:唔。。。随便什么要求


发送至邮箱 wuye9036@gmail.com,或在此站点以站内信的方式发送与我。我将尽可能的与您联系并面议。


我们真诚欢迎您的参与,并对您的加盟,表示真心的感谢和由衷的期待!

posted @ 2009-12-07 10:31 空明流转 阅读(1868) | 评论 (15)编辑 收藏

2012年3月8日 #

1. Diagnostic需要提供哪些数据

出错处理和错误提示,是编译器开发过程中重要而繁琐的部分。

诊断信息的格式因编译器和IDE而不同。

SALVIA将采用Visual Studio的格式,即 文件 + 行列 + 类别(等级) + 编号 + 出错信息。例如:

d:\programming\salvia\sasl\test\cgllvm_test\function_test_basic.cpp(16): error C2061: syntax error : identifier 'te'

因此在出错分析的时候,也需要提供如上的一些信息。


2. 诊断信息Diagnostic Item

在以上信息中,文件名和行列号可以在词法分析的时候获得,我们将它作为属性附加在Token中。

类别和编号,对于同一个编译器而言是相对固定的,尽管我们可以用ID来表示,但是它并不直观,编译器检查也较少。与参数匹配时,也比较容易出错。

SASL中的诊断信息将每个错误都使用一个类型来表达:

class diagnostic_item
{
};


class unrecognized_identifier: public diagnostic_item
{
public:
    unrecognized_identifier& token( token_t tok );
    
private:
    static int level;
    static int id;
    static std::string description_template;
    
private:
    std::string ident;
    size_t      row, col;
    // Other properties
};

这样的好处在于可以用Combinator的风格来撰写错误信息。例如这样:

diagnostic_chat.report<unrecognized_identifier>().token( err_tok );

并且由于编译器的保证也比较不容易写错。

 

但是这种写法也有一个很关键的问题,需要为每个错误都定义一个类,工作量很大。SASL对这一问题的处理,自然是传统的大杀器:运用脚本进行生成。

Clang使用了它内置的代码生成工具td来完成生成的工作。

 

3. 诊断信息管理器Diagnostic Chat

Chat是诊断信息的管理工具。它主要要完成以下需求:添加和清理诊断信息,以及在诊断信息的添加清理时提供回调操作。

后者是很有用的,尤其是在调试编译器的时候。你得分清楚究竟是真正的程序错误呢,还是编译器出了错。

Diagnostic Chat的原型如下:

class diagnostic_chat
{
public:
    template <typename T> T& report();
    void add_report_diagnostic_handler( DiagnosticHandlerT handler );
};

同时,我们也将Treat Warning As Error,Error Count,Disable Warning,Stop compiling when error occurs等状态和功能所需要的支持添加到Chat中。

所以,Chat除了提供管理之外,也要具有相应的诊断信息的统计功能。

 

4. 过滤器Diagnostic Filter

Filter主要配合IDE使用,从Chat中取出符合条件的诊断信息。Error Count和Disable Warnings等功能也可以通过它来完成。

 

5. Formatter

Formatter用于将DiagnosticItems中的信息转换成人可读的字符串。目前SASL只打算支持Visual Studio的格式,但是相信支持GCC的格式以更好的和Eclipse等第三方IDE集成并不困难。

在C#里面,我们可以用“We need ‘{0}’ not ‘{1}’.”这样的方式来分离description template并延期的产生格式化的字符串。但是在C++中,这种做法并不容易。C的sprintf很难具有延期、渐增的绑定模板的特定,对自定义类型的字符串化的支持也不足,类型安全也比较差;而stream的话,也会面临着将好端端的格式化字符串割裂的问题。SASL使用了boost.format,从一定程度上搞定了这两个问题,从而像C#一样,使用格式化字符串的功能。

posted @ 2012-03-08 21:25 空明流转 阅读(964) | 评论 (0)编辑 收藏

2012年3月6日 #

SALVIA 0.3 出炉了!

这是自2010年8月份以来, SALVIA Milestone 1.0之后最重要的发布!

0.3开始,SALVIA正式支持了Pixel Shader。

自2008年中开始的Shader设计与实现工作基本完成。

未来一年内,SALVIA的工作将集中以下几点:

  1. 在Shader编译器的完善上,比如友善的语法和语义错误提示。
  2. 提升与管线的集成度,进而充分提升性能。
  3. 编译器和编译器生成代码的优化,提高Shader的编译速度和运行速度。
  4. 新的图形特性,如各向异性过滤等。

随着SALVIA整体的逐渐成熟,我们也希望有其他的朋友能来参与和支持这个项目,一同进步。

如果您希望参与到这个项目中,请mail联系我:wuye9036 __at__ gmail dota com.

 

tex2D

posted @ 2012-03-06 17:41 空明流转 阅读(792) | 评论 (0)编辑 收藏

2012年2月24日 #

SALVIA 0.2.5 发布!

项目主页: http://code.google.com/p/softart/

更新列表如下:


0.2.2 - 0.2.5 (Feb 24, 2012)

  • 版本名称发生变化,从原先的Milestone X fix Y的命名方式正式更新为与主版本相同的版本号序列。
  • 取消了对DirectX的强制依赖。
  • 添加了对Visual C++ Express的支持
  • Pixel Shader 进一步增强:
          1. 提供了对分支语句 if 的支持  
          2. 支持 for, while, do-while 循环
          3. 添加了新的内建函数:ddx ddy dot cross sqrt
          4. 添加了纹理取样函数tex2D的原型
  • 对Rasterizer进行了进一步的优化
  • 修正了以下问题:
          1. 在x86上执行vertex shader时可能会Crash的问题
          2. 不能再build配置文件中指定CMake路径的问题
          3. 一些表达式调用时报告函数重载错误的问题
posted @ 2012-02-24 16:56 空明流转 阅读(961) | 评论 (0)编辑 收藏

2011年12月26日 #

SALVIA在Milestone 1.2 Fix 2中,正式提供了一站式编译脚本的支持。

项目主页:http://code.google.com/p/softart/

新的编译步骤如下:

1. 下载Python 3.2并安装。

3. 下载boost 1.44或更新的版本,解压到某个目录下。

5. Clone或下载SALVIA代码包,执行根目录下的build_all.py文件。第一次运行的时候会生成一个project.py,编辑project.py设置相应属性,包括boost代码目录,编译器,configuration等。

6. 再次运行build_all.py,编译程序。

posted @ 2011-12-26 21:09 空明流转 阅读(1351) | 评论 (4)编辑 收藏

2011年11月22日 #

1. LLVM在x86和x64下都和Microsft C++ ABI的吻合程度不够。目前已知在以下情况下会出错:
  • 参数为结构体的
  • 返回值为结构体
以下情况我没有完整测试过:
  • 返回值为单个浮点
  • 返回值为向量(_m128 / <4 x float>)
  • 参数为向量(_m128 / <4xfloat>)
所以建议大家统一将是结构体的返回值和参数以引用/指针的形式传递。
对于大小为4个或者8个字节的结构体如果希望按值传递,那么需要在LLVM函数的签名上使用i32/i64作为参数类型,并使用bit cast在函数体内强制转换成结构体。

2. LLVM提供了很多的Intrinsics,例如SSE指令集。它在Module上提供了一个getOrCreateTargetIntrinsic,但实际上这个函数是坑爹的。有两个方法可以正确的创建并获取指令集:
  • 使用Module::getOrInsertFunction( intrinsic_name, intrinsic_function_type )。它会自动识别intrinsic的名称并创建function或者是intrinsic。指令需要使用全名。例如 llvm.x86.sse.sqrt.ps.
  • 或者使用Ilvm::Intrinsic::getDeclaration( id ) 来创建。这个id可以在intrinsics.gen中找到。
因为LLVM生成的Intrinsic是全平台的,所以可以在x86上指定ARM汇编的生成,反之亦然。

3. 默认情况下,LLVM的JIT是不会启用InliningPass的,Optimization Level指定为Aggressive也不会。这意味着inlinehint和alwaysinline都是失效的。如果需要inlining得自己修改JIT的源代码。

4. UndefValue是个好东西。这个常量可以使生成的汇编少一条初始化指令。比方说用0初始化,可能对应的汇编就是 xor reg, reg。如果用了Undef,那这条指令就没了。

5.
TypeBuilder很好用,只是不能生成struct等复杂的类型。不过你可以对它做一些修改以让它支持struct和vector。这个时候Boost.MPL就能派上用场了。不过要当心MPL带来漫长的编译时间。
posted @ 2011-11-22 21:04 空明流转 阅读(1405) | 评论 (0)编辑 收藏

2011年8月17日 #

在设计一门语言与其他语言交互的API与ABI(Application Binary Interface,二进制接口)时,调用协议和内存对齐是两个无从回避的问题。

本文将讨论如何在LLVM上生成正确的内存对齐和调用协议的代码。

在这里为了方便和标准起见,假定应用LLVM的语言的Extending和Embedding的对象都是C。

调用协议

先来讨论调用协议。调用协议用于保证调用方和被调用方在二进制/汇编一级上是相容的。合适的调用协议可以帮助构造出以下代码:

// Callee Signature of LLVM code
void __cdecl foo( int a, float b, float4 c);

// C caller
typedef void (__cdecl* fn_ptr)(int, float, float4)
fn_ptr p = static_cast<fn_ptr>( get_jit_function("foo") );
p(1, 1.0, vec);

一般来说调用协议包括参数传递和返回值传递和堆栈平衡三个部分。在x86平台上的C/C++编译器中常见的调用协议有cdecl, fastcall和stdcall。具体的协议内容请参见MSDN。

在C++中还有一类特殊的调用协议thiscall,用于调用对象的成员函数。但是这一类调用协议不同的平台,不同的编译器实现皆有不同,既无书面标准,也无事实标准,再加上virtual call等复杂的情况存在,并不适合用于做跨语言的调用。

对于x64平台而言,在windows下和linux下分别有两种调用协议。

先来看x86。由于x86在cdecl和fastcall上是有着跨平台的标准的,因此LLVM对它的支持是比较完整的。程序只要在创建Function的时候指定Call Convention即可。

但是对于x64,LLVM的支持便不是那么完善。以windows为例,windows的x64调用协议要求以rcx,rdx,r8,r9寄存器传递前四个不大于64bit的参数,其余参数放在栈上。如果参数大于64bit,则要求传递它的指针。浮点使用xmm0-3来传递。但是对于LLVM而言,一旦参数大于64bit,它便会将整个对象而不是指针压到栈上传递。因此在遇到x64时,需要小心处理API部分的调用协议。

在这里,我们需要将所有超过64bit的结构体处理成指针(或者拷贝后处理成指针)传递。

同时,LLVM提供了readonly和byval两个参数属性(Attribute)来确保参数的值语义。前者意味着传入的指针所指向的值是不被修改的,(类似于T const*),而后者会对传入的指针做一份内存拷贝,确保写值不被传递出函数(类似于值拷贝)。这样,LLVM生成的函数便可以MSVC生成的x64代码正确调用了。

内存对齐

与移动平台的体系结构相比,x86对内存对齐的条件算是相当宽松的了。大部分的指令对内存对齐基本上是没有特殊要求的。只有一些SIMD的指令会对内存对齐有所限定,例如movaps。

为了方便后端生成SIMD代码,LLVM提供了vector类型,例如vector<float, 1>。在代码生成的时候,vector会编译成最有可能的SIMD类型。因此在x86平台上,vector<float, 1-4>都被处理成类似于__m128的类型,更长的vector则被拆分成多个__m128类型。

这实际上意味着,所有的vector都应该遵循16Bytes对齐的原则。

考虑到我们的需求,类似于struct{ float[3]; }这样的结构,如果能表示为vector<float, 3>显然适合一些数学运算,例如shuffle,逐元素的add,sub,mul,同时LLVM指令的选择也更加灵活。但是显然,这个结构体有两个条件是不满足的:16字节对齐和16字节的大小(movups和movaps都是一次取16字节)。这会造成边界下读写的内存越界。因此非常可惜,这些数据必须表示为struct{ float ,float, float }。在读取的时候,也会生成正确的指令:movss。

那么,对于一般的非对齐的vec4应用vector<float,4>行不行呢?

答案是,很困难。对于LLVM而言,他们在设计的时候就没有过多的考虑vector在非对齐时候的应用。尽管load和store都能够指定alignment以生成非对齐的内存操作(例如movups)并且确实会起效,但是由于代码优化、临时存取等特性的存在,导致一些非load和store的内存操作仍然是要求对齐的(例如生成了addaps xmm, [addr])。此时仍然有可能为非对齐的数据生成了内存对齐的指令。

因此综合权衡,SASL在API界面上使用了struct{float x,y,z,w;} 这样的ABI来表示数据,在代码生成时,会首先将struct的数据转换成vector,然后再执行其它的操作,兼顾ABI与SIMD;同时对于Intrinsic,由于并不暴露给Host,所以它们仍然尽可能使用Vector,便于LLVM进行优化。

posted @ 2011-08-17 13:58 空明流转 阅读(1526) | 评论 (2)编辑 收藏

2011年7月17日 #

项目主页:

源码下载地址:

版本:
  • Milestone 1.1 Fix 1
更新记录:
  • 添加了了新的Demo:Sponza
  • Wavefront Obj添加了32位索引的支持。
  • 修复了 Wavefront Obj 错误的顶点共享的问题。
  • 修复了 Mip-map 计算错误的问题。
  • 修复了对多边形错误剔除的问题。
Demo下载:

Demo截图

image

image

image

posted @ 2011-07-17 17:46 空明流转 阅读(1075) | 评论 (0)编辑 收藏

2011年6月25日 #

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

2011年6月1日 #

该项目简报包含了近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 空明流转 阅读(1232) | 评论 (0)编辑 收藏

2011年5月16日 #

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

 

在线的PPT:

原PPT下载:

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

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

仅列出标题  下一页