Apple 推出 metal后,除了新的metal framewrok外,也多了一种新的shader语言,最近工作也做了一些metal移植的测试,主要还是现有引擎如何可以快速支持metal的解决方案。这里也想对边写写自己的心得。
 
  metal shader的语法特性更接近SM5的hlsl,所以sm4或sm5的hlsl转化成metal shader更简单,性能跟GLES3.1相似,提供了Vextrex shader, Fragment Shader和Computer Shader。加上移动端图形API的新特性的支持,所以使得次世代游戏引擎面向移动端的移植成为了可能。
 
  像UE4,CE3这种的大型引擎来说,本身shader代码量就很大,要支持多平台,如果写多套shader,不论是在开发还是测试上都会让工作量成倍增加,所以都是选择转化shader的方式来跨平台。目前常用的shader转化,要么是FXC编译HLSL的字节码转化,要么就是直接源代码之间转化。对HLSL->GLSL而言,用字节码转化更简单。但metal shader不提供字节码的格式,所以字节码转化方式可能是行不通了。UE4在开发时的2年里也搜索过能解决SM5的HLSL转化的跨平台编译器,结果只能自己基于Mesa3D的功能进行扩展,开发了HLSLCC。
  
  目前的几个HLSL->GLSL的方案:
  hlsl2glslfork,由ATI的HLSL2GLSL发展而来,也基于了一部分monoshader的代码(UE3最早就是用的monoshader),shader源代码之间的翻译,问题是只支持DX9风格的HLSL,不支持DX10和DX11的一些语法,也没有geometry shader,tesseliaton shadr和 compute shader,现在Unity3d还是用的这个。
 
  KlayGE的HLSL2GLSL,是从HLSL的字节码转化为GLSL。
 
  UE4的HLSLCC,通过在他们在GDC2014上的ppt来看,也是受到glsl-optimizer的设计的影响,这两个都是参考Mesa3D的,不过Mesa3D只是GLSL的分析和转化为Mesa IR,HLSLCC改成了SM5的HLSL的分析功能,并添加了IR->GLSL的converter。并且在UE4.3后,也加入了metal shader的支持。
 
  接下来也是想结合HLSLCC的ppt,说一些自己的看法,HLSLCC的转化流程,是HLSL->AST->IR->GLSL/Metal + ParameterMap,输出使用了glsl-optimizer一部分功能,但实际运行UE4的HLSLCC的时候,还是会有不少问题的。
 
  1. shader marco,像ue的.usf,ce的.fxc,多少会通过使用宏来做一些shader的条件编译,静态分支处理等等,也就类似uber shader的概念,但基本上没有什么转化工具能搞定那么复杂的工作,而且也经常会有vs,ps的多个Entry函数(Main)写到一个usf文件里的情况,直接整个.usf扔给转化工具也是不现实的,ue和ce的解决方法,还是要经过内部的管理,把每个入口函数的部分独立出来,如UE4就是通过定义Golbalshader子类,自己来设置参数和入口函数名等等。然后独立的shader入口函数进行转化。而#include,#define,#if 一类的宏和分支的处理,进行转化前要通过,只留下runtime必须的部分,转化成不同平台的shader并编译为cache保存。
  
 
  2. OGL通过uniform从每帧从CPU->GPU传递参数,为了减少API调用次数,所以DX11提供了const buffer,而ES3.0和metal也提供了uniform buffer的概念,因为对于大型游戏来说,uniform update调用API的数量也是很大一部分消费,所以需要使用const buffer来根据参数更新频率和顺序进行组织,而在不支持这种概念的DX9上,CE3使用了模拟的const buffer来对参数进行缓存重组再进行更新,而UE4虽然直接支持的DX11,但对移动平台ES2.0的设备,没有uniform buffer的特性,他们使用了模拟的Uniform buffer功能(ppt里叫shadow buffer),基于更新频率打包到uniform array。所以,HLSLCC除了输出GLSL外,也有生成Parameter Map的功能。
  3. shader version方面,如果是DX11 HLSL的转化,对hlslcc进行一些修改定制后就可以,本身hlslcc也支持不同版本GL和metal的输出,如果是DX9 风格HLSL的话,就需要进行一些预处理工作了,dx9和dx11的主要变化在semantic,texture和sample的使用上有些变化。例如:
     
Pixel Shader的input,DX11里改为了SV_Position,output里,COLOR被SV_Target替代
DX9:
 

struct vs2ps
{
float4 Pos : POSITION;
float4 TexCd : TEXCOORD0;
};

DX11:

struct vs2ps
{
float4 Pos: SV_POSITION;
float4 TexCd: TEXCOORD0;
};

DX9:

float4 PS(vs2ps In): COLOR

DX11:

float4 PS(vs2ps In): SV_Target 

Texture Sample的定义:

DX9:
texture Tex <string uiname="Texture";>;
sampler Samp = sampler_state //sampler for doing the texture-lookup
{
Texture = (Tex); //apply a texture to the sampler
MipFilter = LINEAR; //sampler states
MinFilter = LINEAR;
MagFilter = LINEAR;
};

DX11:

Texture2D texture;
SamplerState g_samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};

如果要Sample Texture:

DX9:
float4 col = tex2D(Samp, In.TexCd.xy);

DX11:

float4 col = texture2d.Sample( g_samLinear, In.TexCd.xy);

DX9:

float4 col = tex2Dlod(Samp, float4(In.TexCd.xy,,level));

DX11:

float4 col = texture2d.SampleLevel( g_samLinear, In.TexCd.xy,level);

DX9:

float4 col  = tex2Dproj(Samp,screenProj.xyzw);

DX11:

float4 col = Samp.Sample(g_samLinear, .creenProj.xy / screenProj.w );

4 GLES3.1和metal里都提供了compute shader的功能,metal shader里叫kernel function,很可惜,这部分UE4也还没支持,所以HLSLCC里也还没实现Compute Shader的转化,但相信不久以后也会支持了,拭目以待吧。

总结,自己这方面的工作也是刚开始,所以描述的深度也有限,随着额工作深入,应该会对HLSLCC和各种API如何优化做进一步分析

 

关于Shader的跨平台方案的考虑的更多相关文章

  1. 引擎设计跟踪(九.14.2d) [翻译] shader的跨平台方案之2014

    Origin: http://aras-p.info/blog/2014/03/28/cross-platform-shaders-in-2014/ 简译 translation: 作者在2012年写 ...

  2. 最火移动端跨平台方案盘点:React Native、weex、Flutter

    1.前言 跨平台一直是老生常谈的话题,cordova.ionic.react-native.weex.kotlin-native.flutter等跨平台框架的百花齐放,颇有一股推倒原生开发者的势头. ...

  3. 热门跨平台方案对比:WEEX、React Native、Flutter和PWA

    本文主要对WEEX.React Native.Flutter和PWA几大热门跨平台方案进行简单的介绍和对比.内容选自<WEEX跨平台开发实战> (WEEX项目负责人力荐,从入门到实战,教你 ...

  4. 移动端跨平台方案对比:React Native、weex、Flutter

    跨平台一直是老生常谈的话题,cordova.ionic.react-native.weex.kotlin-native.flutter等跨平台框架百花齐放,颇有一股推倒原生开发者的势头. 为什么我们需 ...

  5. 剖析虚幻渲染体系(08)- Shader体系

    目录 8.1 本篇概述 8.2 Shader基础 8.2.1 FShader 8.2.2 Shader Parameter 8.2.3 Uniform Buffer 8.2.4 Vertex Fact ...

  6. Shader学习笔记

    Shader学习笔记 例子: Shader "SrfShader1"{ //定义显示在Inspector中的变量,并从Inspector中获取值 Properties{ _Colo ...

  7. C#移动跨平台开发(2)Xamarin移动跨平台解决方案是如何工作的?

    概述 上一篇 C#移动跨平台开发(1)环境准备发布之后不久,无独有偶,微软宣布了开放.NET框架源代码并且会为Windows.Mac和Linux开发一个核心运行时(Core CLR),这也是开源的!I ...

  8. 利用C#开发移动跨平台Hybrid App(一):从Native端聊Hybrid的实现

    0x00 前言 前一段时间分别读了两篇博客,分别是叶小钗兄的<浅谈Hybrid技术的设计与实现>以及徐磊哥的<从技术经理的角度算一算,如何可以多快好省的做个app>.受到了很多 ...

  9. 跨平台运行 Rafy 首次部署记录

    一直想在 Linux 上使用 MONO 试试运行 Rafy,最近因为业务需要,总算是真正地试验了一次.下面是本次部署记录的一些要点. Linux 这次部署,我是和两位同事一起来试验的.由于我们对 Li ...

随机推荐

  1. Android之自定义控件入门

    本文主要讲述了实现安卓button点击变色与利用ViewPager实现图片自动轮播效果 我伞可以看到在很多应用中,安卓按钮按下时与正常时状态是不同的,这种效果也很容易达到. 第一步:创建XML文件定义 ...

  2. hadoop机架感知

    背景 分布式的集群通常包含非常多的机器,由于受到机架槽位和交换机网口的限制,通常大型的分布式集群都会跨好几个机架,由多个机架上的机器共同组成一个分布式集群.机架内的机器之间的网络速度通常都会高于跨机架 ...

  3. kvm NET 和 BRIDGE

    net: <interface type='network'> <mac address='52:54:00:e1:ac:43'/> <source network='d ...

  4. mysql 主主复制(双主复制)+ 配置KEEPALIVED实现热备

    binlog-do-db和replicate-do-db表示需要同步的数据库 binlog-ignore-db和replicate-ignore-db表示不需要同步的数据库 云端服务器为master配 ...

  5. Java Hour 54 Spring Framework 1

    总之,Srping Framework 很好很强大. 1 Spring Framework 介绍 省下你和transcation APIs, JMX APIs, JMS APIs 交流的功夫. 1.1 ...

  6. 思考探索,如何才能高效访问我的这个DataTable?

    需求 一切都是空的,除了Money,只有需求才是最真的,你懂的. 最近接到个略显棘手的需求,思索再三,想出两种方法,可觉得都不太好,这里与大家讨论一下. 需求如下: 用户需要在现有的某个grid中添加 ...

  7. 如何扫描出Android系统媒体库中视频文件

    Android系统启动时会去扫描系统文件,并将系统支持的视频文件(mp4,3gp,wmv)扫描到媒体库(MediaStore)中,下面代码演示如何获得这些文件的信息: publicstatic Lis ...

  8. hdu 1181 变形课

    变形课 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submis ...

  9. cmd.ExecuteNonQuery();和cmd.ExecuteScalar();

    C#...cmd.ExecuteNonQuery();是返回执行命令后影响的参数 返回符合你条件的所有语句,如果你要数据库里某张表的数据,说执行这个命令后他返回的是就是这张表的全部数据cmd.Exec ...

  10. 了解Json

    Json(JavaScript Object Notation) 是一种轻量级的数据交换格式,它是基于JavaScript的一个子集. 数据格式简单, 易于读写, 占用带宽小. {'age':'12' ...