Slang: Language Mechanisms for Extensible Real-Time Shading Systems
Total Page:16
File Type:pdf, Size:1020Kb
Slang: language mechanisms for extensible real-time shading systems YONG HE, Carnegie Mellon University KAYVON FATAHALIAN, Stanford University TIM FOLEY, NVIDIA Designers of real-time rendering engines must balance the conicting goals and GPU eciently, and minimizing CPU overhead using the new of maintaining clear, extensible shading systems and achieving high render- parameter binding model oered by the modern Direct3D 12 and ing performance. In response, engine architects have established eective de- Vulkan graphics APIs. sign patterns for authoring shading systems, and developed engine-specic To help navigate the tension between performance and maintain- code synthesis tools, ranging from preprocessor hacking to domain-specic able/extensible code, engine architects have established eective shading languages, to productively implement these patterns. The problem is design patterns for authoring shading systems, and developed code that proprietary tools add signicant complexity to modern engines, lack ad- vanced language features, and create additional challenges for learning and synthesis tools, ranging from preprocessor hacking, to metapro- adoption. We argue that the advantages of engine-specic code generation gramming, to engine-proprietary domain-specic languages (DSLs) tools can be achieved using the underlying GPU shading language directly, [Tatarchuk and Tchou 2017], for implementing these patterns. For provided the shading language is extended with a small number of best- example, the idea of shader components [He et al. 2017] was recently practice principles from modern, well-established programming languages. presented as a pattern for achieving both high rendering perfor- We identify that adding generics with interface constraints, associated types, mance and maintainable code structure when specializing shader and interface/structure extensions to existing C-like GPU shading languages code to coarse-grained features such as a surface material pattern or enables real-time renderer developers to build shading systems that are a tessellation eect. The idea of shader components is to drive both extensible, maintainable, and execute eciently on modern GPUs without code specialization and CPU-GPU communication using the same the need for additional domain-specic tools. We embody these ideas in an granularity of decomposition, but the implementation of this idea extension of HLSL called Slang, and provide a reference design for a large, extensible shader library implemented using Slang’s features. We rearchitect was coupled to a custom DSL, which presents a barrier to adoption. an open source renderer to use this library and Slang’s compiler services, Beyond the coarse-grained specialization addressed by shader and demonstrate the resulting shading system is substantially simpler, easier components, a modern shading system must be extensible to in- to extend with new features, and achieves higher rendering performance clude new features and to assemble collections of shading eects than the original HLSL-based implementation. into statically optimized GPU shaders. (Examples include: com- posing dierent types of lights, decoupling material patterns from Additional Key Words and Phrases: shading languages, real-time rendering reectance models, adopting closed-form solutions and approxima- ACM Reference format: tions for specic surface-light interactions.) AAA graphics engines Yong He, Kayvon Fatahalian, and Tim Foley. 2018. Slang: language mech- implement proprietary code generation tools to aid with these tasks. anisms for extensible real-time shading systems. ACM Trans. Graph. 37, 4, Unfortunately, metaprogramming tools add complexity on top of Article 1 (August 2018), 13 pages. the underlying shading language, and thus create additional chal- https://doi.org/10.1145/3197517.3201380 lenges for learning and adoption. Engine-specic DSLs often lack advanced language features, and create the problem that shader 1 INTRODUCTION code and learned skills do not transfer between engines. Designers of real-time rendering engines must balance the conict- In this paper we argue that the advantages of specialized DSLs ing goals of facilitating developer productivity and achieving high (both the Spire language used to implement shader components [He rendering performance. Code maintainability and extensibility are et al. 2017] and other proprietary, engine-specic tools) can be key aspects of productivity, particularly since popular commercial achieved using the underlying GPU shading language directly, pro- engines such as Unreal [Epic Games 2015] or Unity [2017] feature vided the shading language is extended with a small number of best- large shader libraries used across many titles, each requiring dif- practice principles from modern, well-established programming ferent shading features. At the same time, to achieve high GPU languages. Our key contribution is to identify the necessary set of rendering performance, an engine must perform key optimizations general-purpose modern programming language features that, when such as statically specializing shader code to the rendering features added to existing C-like GPU shading languages (GLSL/HLSL/Metal), in use, communicating shader parameter data between the CPU can be used by real-time rendering engines to build shading systems that are extensible, maintainable, and execute eciently on modern Permission to make digital or hard copies of all or part of this work for personal or GPUs without the need for additional layered DSLs. Specically, we: classroom use is granted without fee provided that copies are not made or distributed Propose the design of the Slang shading language, a variant of for prot or commercial advantage and that copies bear this notice and the full citation • on the rst page. Copyrights for components of this work owned by others than the HLSL extended with the following general-purpose language author(s) must be honored. Abstracting with credit is permitted. To copy otherwise, or republish, to post on servers or to redistribute to lists, requires prior specic permission features: generics with interface bounds, associated types, and/or a fee. Request permissions from [email protected]. and interface/structure extensions. The choice of features is © 2018 Copyright held by the owner/author(s). Publication rights licensed to Association intended as a minimal set of extensions to meet our perfor- for Computing Machinery. 0730-0301/2018/8-ART1 $15.00 mance and productivity goals, while providing an incremental https://doi.org/10.1145/3197517.3201380 path of adoption for current HLSL developers. ACM Transactions on Graphics, Vol. 37, No. 4, Article 1. Publication date: August 2018. 1:2 • He, Foley, and Fatahalian Engine Framework User Application Shader Library (HLSL) Host Code (C++) Shader Code (HLSL) Host Code (C++) struct Camera { Camera.hlsl class Camera { Camera.h struct MyMaterial { MyMaterial.hlsl class MyMaterial: Material MyMaterial.h float3 worldPos; void setWorldPos(float3 p); Texture2D albedoTex; { float4x4 viewProj; ... SamplerState sampler; Texture* albedoTex; ... void bindParams(Program p); }; Sampler* sampler; }; }; typedef Lambertian MyMatPattern; String getTypeName() struct Lambertian { Lambertian.hlsl class Material { Material.h { float3 albedo; virtual String getTypeName(); MyMatPattern evalPattern( return "MyMaterial"; }; virtual void bindParams(Program p); MyMaterial mat, } float3 evalBxDF( }; SurfaceGeometry geom) void bindParams(Program p) Lambertian bxdf, { { float3 wi, float3 wo) class Lambertian : Material Lambertian.h MyMatPattern pat; p->setParam("albedoTex", { return albedo / PI; } { float3 albedo; pat.albedo = mat.albedoTex albedoTex); String getTypeName() {"Lambertian"} .Sample(mat.sampler, geom.uv); ... ... DisneyBRDF.hlsl void bindParams(p) { return pat; } p->setParam("albedo", albedo); } } }; ... SkinBRDF.hlsl }; QuadLight.hlsl QuadLight.h struct PointLight PointLight.hlsl class Light { Light.h struct QuadLight class QuadLight : Light { virtual String getTypeName(); { float3 vertices[4]; }; { float3 pos; virtual void bindParams(Program p); float3 evalLight( float3 vertices[4]; float3 intensity; }; QuadLight light, String getTypename() }; class LightEnv { MaterialPattern bxdf, { float3 evalLight( Array<Light*> lights; float3 wo) return "QuadLight"; PointLight light, }; { // integrateQuadLight() provided } ...) // by BxDF implementation void bindParams(Program p) { ... } class PointLight : Light { PointLight.h return integarteQuadLight( { ... } float3 pos; float3 intensity; bxdf, light, wo); }; } ... DirectionalLight.hlsl String getTypeName() { return "PointLight"; } int main(...) { main.cpp ... CascadedShadowMap.hlsl }; Camera* cam = new Camera(); Material* mat = new MyMaterial(); ForwardPass.hlsl Program.h Camera gCamera; class Program { LightEnv* lights = new LightEnv(); Material gMaterial; String getFileName(); lights->add(new QuadLight(...)); LightEnv gLights; }; ... float3 forwardPass( ForwardPass* fwd = new ForwardPass(); class ForwardPass ForwardPass.h SurfaceGeometry geom) { context->bindProgram(fwd); : Program float3 V = gCamera.worldPos – geom.P; camera->bindParams(fwd, "gCamera"); { MaterialPattern pat = evalPattern( mat->bindParams(fwd, “gMaterial”); String getFileName() { gMaterial, geometry); lights->bindParams(fwd, “gLights”); return "ForwardPass.hlsl" } return illuminate(gLights, pat, V); context->draw(...); }; } } Fig. 1. An example shading system architecture using HLSL and C++. Le: the framework provides modules