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. show processlist

    mysql> show processlist; #mysql服务器查看有那些主机连进来,并列出它们查什么库 +-----+------+-----------+------+--------- ...

  2. 如何将win7安装到 移动硬盘/U盘 及 VHD、BCD等相关知识 链接汇总

    如何将win7安装到 移动硬盘/U盘? 从u盘启动win7/2008 R2的方法,更新:换机器免sysprep的方法:http://www.360doc.com/content/11/1103/14/ ...

  3. Xamarin.Android开发实践(十二)

    Xamarin.Android之ContentProvider 一.前言 掌握了如何使用SQLiteOpenHelper之后,我们就可以进行下一步的学习.本章我们将会学习如何使用ContentProv ...

  4. poj 1276 多重背包

    735 3 4 125 6 5 3 350 //735的最大额,3种,4个125,6个5,3个350 633 4 500 30 6 100 1 5 0 1 735 0 0 3 10 100 10 50 ...

  5. 电脑上安装的android虚拟机,能进行基站定位和GPS定位吗?要怎么做才能定位?(转)

    基站定位是通过电信运营商的服务来实现的,至少你得有SIM卡吧,一般电脑是不会有电话功能的吧,所以,通过基站定位不可能. GPS是需要有相应的硬件来支持的,类似于手机需要有GPS模块才可以,电脑一般没有 ...

  6. HDU 5009 Paint Pearls 双向链表优化DP

    Paint Pearls Problem Description   Lee has a string of n pearls. In the beginning, all the pearls ha ...

  7. 【HTML5】表单属性

    * autocomplete autocomplete 属性规定 form 或 input 域应该拥有自动完成功能. 注释:autocomplete 适用于 <form> 标签,以及以下类 ...

  8. 8.Smack类库

    1.登陆IM Connection.DEBUG_ENABLED = true;//首先激活调试模式 1.1建立连接 首先,在启动DSM Message时,客户端通过XMPPConnection与服务器 ...

  9. 2016.6.11 ASP提交数据到SQL server数据乱码解决方法

    1.检查数据库排序规则 China-PRE-90-CS-AI 2.ASP文档中,写入数据的页面的编码和检查提交数据页面的编码一致:

  10. js:数据结构笔记4--队列

    队列是一种特殊的列表,数据结构为FIFO: 定义: function Queue() { this.dataStore = []; this.enqueue = enqueue; this.deque ...