<<

Rendering Modelled by Category Theory

Jiríˇ Havel Adam Herout Faculty of Information Technology Faculty of Information Technology Brno University of Technology Brno University of Technology ihavel@fit.vutbr.cz herout@fit.vutbr.cz

ABSTRACT This paper describes basic concepts from category theory, which are commonly used in . These con- cepts are applied to shader programming and to the rendering pipeline and the whole rendering pipeline is formally modelled using category theory. This model can be used for more abstract and formal approach to shader programming. Mathemat- ical formalization of the rendering pipeline and its stages can be helpful in shader compiler design, for proving algorithms, complexity analysis, and other tasks. Keywords: Rendering, Shaders, Category Theory 1 INTRODUCTION 2 CATEGORY WITH STREAMS Category theory [9, 3] is an abstraction of mathemati- A category (C) consists of a set of objects (obj C) and cal structures and relations between them. It started as a a set of arrows or morphisms (arr C) that link these "generic abstract nonsense", but now it is heavily used objects. An arrow f : A → B has a domain A and a not only in mathematics, but also in computer science codomain B from obj C. The set of arrows from A to B and especially functional programming. Many categor- is denoted as HomC(A,B). Arrows must be composable ical concepts give rise to common pieces of code used (1a), every object must have one identity arrow (1b) to combine computations together. >From these ab- (1c) and arrow composition must be associative (1d). stractions, especially functors and monads are almost ubiquitous [7]. ∀ f : A → B,g : B → C ∃(g ◦ f ) : A → C (1a) Although the rendering pipeline is programmable, its ∀O ∈ obj C ∃1O : O → O (1b) overall structure is basically fixed. The design of pro- ∀ f : A → B,1B ◦ f = f ◦ 1A = f (1c) gramming languages for shader programming perfectly h ◦ (g ◦ f ) = (h ◦ g) ◦ f (1d) corresponds to the structure. Some experimental shad- ing languages tried to offer a slightly more abstract A classical example is the category Set, whose objects 1 way. Two notable examples are the Gpipe library for are sets and arrows are mappings between those sets. Haskell and Sh [5, 4] for C++. Both are, however, lim- N-ary functions and tuples are modelled using prod- ited to OpenGL 2 or DirectX 8 functionality. ucts – composite objects. Product P is an object con- The Sh library views shaders as objects, that can be sisting of objects Oi,i = 0,...N with projection arrows combined using two operations – serial and parallel (pi : P → Oi) that extract its member objects. For ev- composition. These two operations, however, perfectly ery object Z that has arrows ai : Z → Oi to all members correspond to a category with products, which will be of P, exactly one arrow aP to the product exists, such described in the next section. that ai = pi ◦aP, see Figure 1. An exaple of the product The GPipe library achives the same functionality by type can be the structure data type, that is a product of a different approach. It operates on streams of primi- its elements. When describing function, the arrow aP is tives and transforms them by series of functions – using a combination of functions returning the elements of a functors from the category theory. structure to a function returing the whole structure. The rest of the paper will discuss correspondences between those approaches. Section 2 will introduce a category-based model of the rendering pipeline stages and extend programmingof pipeline stages to a descrip- tion of the whole pipeline. Section 3 will raise the ab- straction of the pipeline description to a composition of transformers. Section 4 summarizes the intro- duced categories as a model of the rendering pipeline.

Figure 1: Product in a category Let us define a category of GPU programs called 1 http://www.haskell.org/haskellwiki/GPipe Gpu. Objects of Gpu are basic and structured datatypes of graphical shaders and arrows are func- B. Arrows of this category are called natural transfor- tions (both built-in and composite). Both structured mations. For every functor F and G from BA, natu- datatypes (structure and array) fullfil the requirement ral transformation φ : F → G and arrow f ∈ A, must for product types2 as do the basic vector types. With φ ◦ F( f )= G( f ) ◦ φ. streams from the following subsection, every possible Natural transformations change only the structure of shader will be an arrow in Gpu. an abstract data type, but the elements of the type are left unchanged. For example, a transformation between 2.1 Streams are Functors an array of streams and a stream of arrays is a natu- Functor is a structure-preserving mapping be- ral transformation. Natural transformations are heavily tween categories. Functor F : A → B be- used in the following subsections. tween categories A and B consists of a map- 2.2 Streams are Monads ping Fobj : obj A → obj B and mappingss → Monad is a special type of functor used in functional FA1,A2 : HomA(A1,A2) HomB(Fobj(A1),Fobj(A2)) for every pair of objects A1, A2 from A. Functors must programming to represent computations and control also preserve arrow composition and identity arrows. structures, to embed side effects, or model a - Homogenous abstract data types like lists, stacks, or ing pipeline. queues are constructed by functors. The Fobj creates Monads in category theory is a functor F, together structured types from the basic ones. The mappings for with two natural transformations η :1C → F and µ : arrows convert simple arrows to arrows working with F2 → F (F2 = F ◦ F). The corresponding triplet in new types – usually doing the same for every element functional programming consists of a functor F and of the new type. In functional programming, this fam- mappings unit : A → F(A) and join : F(F(A)) → F(A) ily of mappings is denoted by map. map : (X → Y) → [6]. (F(X) → F(Y)), where F is a functor, i.e., for a given Mapping unit creates the monad type from arrow on the simple data type, map defines the corre- one element and join merges two layers of sponding arrow on the structured data type. the monad to one. In the category Gpu, the In shader programming, one abstract data type is transformation unit : X → Stream(X) creates a ubiquitous – the stream of values (vertices, primitives, stream with a single element. The transformation fragments). It is a sequence of elements, that is, join : Stream(Stream(X)) → Stream(X) joins a stream however, never handled directly, but implicitly by the of streams to one single stream by concatenation. streaming nature of the rendering pipeline. Stream In functional programming, the bind transformation types in the category Gpu are constructed using a is used more than join and it better describes the prop- functor Stream : Gpu → Gpu. This functor creates erties of monads. streams of elements of any basic type (and recursively bind : (X → F(Y)) → (F(X) → F(Y )) streams of streams). For every X and Y from obj Gpu, the mapping for arrows is simply defined as bind( f )= join ◦ map( f ) → map : (X → Y) → (Stream(X) → Stream(Y)) In Gpu, the transformation bind : (X Stream(Y)) → (Stream(X) → Stream(Y)) uses map( f )(x1,...,xn) = ( f (x1),..., f (xn)). the provided mapping to transform a stream. The type shows that every element of the input stream is The mapping map( f ) transforms every stream element used to create a new stream and such new streams are by the function f , see Figure 2. concatenated together. In other words, 0 − N elements can be created from every single input element and the input elements are processed separately, as shown by Figure 3.

Figure 2: Functorial transformation principle. Streams are not the only functors in the category Gpu, but arrays and basic vector types are functors as well. For these data types, map works similarly to its Figure 3: Monadic transformation schema. stream counterpart. A perfect example of monadic processing of a stream For categories A and B a category BA exists: the is the geometry shader. From every primitive of the functor category, whose objects are functors from A to input stream, zero or more primitives are generated and those new streams are concatenated. Also, the fragment 2 Objects like sums (discriminated unions) or exponentials (partially applied functions) are hard to express on GPU, so will not be used in shader can be described by a monad, as it can output this paper. empty streams or streams with a single element. 2.3 Streams are Comonads For a category C with monad M, which contains ar- rows of type A → M(B),A,B ∈ obj C, exists another Functor and monad are sufficient to describe stream category K, transformers that access single elements of a stream. For accessing multiple elements, a categorical dual to obj K = obj C a monad can be used – the comonad. Comonads can HomK(A,B)= HomC(A,M(B)) represent some information in a context. In the case of streams, the context of each element are the neighbor- The arrow composition in K is defined as gK ◦ fK = ing elements. bind(gC) ◦ fC, so kategory K expresses composition of As dual functor to a monad, comonad is a func- stream transformations. This category is called Kleisli tor with two natural transformations in opposite di- category of C. Dual to Kleisli category, also the CoKleisli category rection as the monad. These are extract : F → 1C and duplicate : F → F2. The functional programming L for every category C exists, with a comonad N. forms are extract : F(X) → X and duplicate : F(X) → obj L = obj C F(F(X)). Mapping extract discards the context of a value and duplicate duplicates the context for every in- HomL(A,B)= HomL(N(A),B) put. Similarly, the arrow composition in L is defined as g ◦ Similarly to monad function bind, comonad has its L fL = gC ◦ extend( fC). dual extend. For the category Gpu, we can construct a pipeline or stream category Pipe. Objects of this categoryare basic → → → extend : (F(X) Y) (F(X) F(Y)) and structured shader types and arrows are functions extend( f )= map( f ) ◦ duplicate of type Stream(X) → Stream(Y). Arrows fall to three groups. As the type suggests, extend can not change the el- • map( f ), f is an arrow of Gpu without streams. ement count, but contrary to bind, the output elements depend on the context of the input elements as shown • bind(g), g is an arrow of the Kleisli category of by Figure 4. Gpu. • extend(h), h is an arrow of the CoKleisli category of Gpu.

This category provides a superset of all stream trans- Figure 4: Comonadic transformation schema. formations possible on GPU. In functional program- ming, this kind of structure is called Arrows [2, 8]. In Gpu several implementations of the comonad for From the axioms for functor, monad and comonad streams are possible. Preceding or following elements [1], the following equivalences can be derived: can form a context of a stream element – the underlying implementation can be a delay link for example. The ◦ ◦ actual implementation is not important for the scope of map( f ) map(g)= map( f g) (2a) this paper. map( f ) ◦ bind(g)= bind(map( f ) ◦ g) (2b) The primitive assembly can be viewed as a comonad bind(g) ◦ map( f )= bind(g ◦ f ) (2c) (followed by a monad); however, because of the inde- map( f ) ◦ extend(h)= extend( f ◦ h) (2d) pendence on actual stream contents, primitive assem- extend(h) ◦ map( f )= extend(g ◦ map( f )) (2e) bly can be also modelled as a natural transformation. The tesselation control or hull shaders have also the extend(h) ◦ bind(g)= map(h) ◦ duplicate ◦ join ◦ map(g) comonadic structure, although they do not operate on (2f) stream but on array with index. bind(g) ◦ extend(h)= bind(g ◦ h) ◦ duplicate(x) (2g) 3 PIPELINE CATEGORY When applied to the shader programming, these equations are intutive. Equation (2a) shows that two The previously introduced category Gpu mixes the vertex-shader-like stages can be composed to one. pipeline structure and the stages implementation. We Equations (2b) and (2c) show the composition of can construct a category, that models only the pipeline a geometry-shader-like stage with the following or structure and abstracts the actual implementation of the preceding vertex shader. Equations (2d) and (2e) show stages. the same for a comonadic shader. The category Gpu has product types – tuples (struc- be used to extend the model capability to cover geome- tures) of basic types or streams. For arrows of type try and tesselation shaders. map( f ), the tuples of streams are isomorphicto streams of tuples. Therefore, also streams of tuples have the 5 CONCLUSION properties of product types. The language Sh uses these This paper introduced a model of the rendering pipeline properties for parallel composition of shaders. using category theory. Although the mathematics in When arrows of type bind( f ) are considered, the this paper is not novel, it is not commonly seen in product properties are lost. As outputs of two arrows the field of computer graphics. Two categories are can be differently structured, they cannot be gener- defined and used: Gpu describing pipeline capabili- ally merged together without mutual affection. This ties, structure and implementation and Pipe for abstact- limits Sh-style parallel composition capabilities to ver- ing the pipeline structure and composition from simple tex shader, tesselation evaluation, and fragment shader shaders. without discard. The formalism introduced in this paper can be used The stream category can contain only streams of for classification of different shader operations and for tuples. Because tuples in Pipe are not products, the automatic optimization of shader programs on inter- arrows generally can not be combined in parallel. stage level. Notably the equivalences from equation 2 This parallel composition is limited to functorial and form rewrite rules for moving computations between comonadic arrows. different stages of the rendering pipeline. However ap- plication of these rules is not trivial. Following work 4 MODEL OF THE RENDERING will focus on searching suitable rules, probably using PIPELINE genetical algorithms. Randering pipeline can be described using two cate- The model is inspired by two actual shader languages gories. Gpu models complete GPU functionality from and will be used for their extension. The Pipe category implementation of shader stages to the whole pipeline can be also possibly used to describe generic stream structure. Pipeline category Pipe models the pipeline processing. structure by composition of simple shaders without REFERENCES considering their implementation. [1] Neil Ghani, Christoph Lüth, Federico De Marchi, and John The simple shaders can be classified according to Power. Algebras, coalgebras, monads and comonads, 2001. their capabilities. The pipeline stages can be classified [2] John Hughes. Generalising monads to arrows. Science of Com- similarly. puter Programming, 37:67–111, May 2000. [3] Saunders Mac Lane. Categories for the Woring Mathematician. • Functorial shaders change only single stream ele- Springer, 1971. ments. The results do not depend on the context and [4] Michael McCool, Stefanus Du Toit, Tiberiu Popa, Bryan Chan, the stage cannot change the stream’s structure. Ex- and Kevin Moule. Shader algebra. In SIGGRAPH '04: ACM isting stages: Vertex shader, Tesselation evaluation SIGGRAPH 2004 Papers, pages 787–795, New York, NY, USA, shader, Fragment shader without discard. 2004. ACM. [5] Michael D. McCool, Zheng Qin, and Tiberiu S. Popa. Shader • Monadic shaders can expand and remove elements. metaprogramming. In HWWS '02: Proceedings of the ACM SIG- GRAPH/EUROGRAPHICS conference on Graphics hardware, Their input is limited to one element. Existing stages pages 57–68, Aire-la-Ville, Switzerland, Switzerland, 2002. Eu- : Rasterization, Fragment shader with discard, Frag- rographics Association. ment tests, Geometry shader, Hardware tesselator. [6] Eugenio Moggi. Computational lambda-calculus and monads. pages 14–23. IEEE Computer Society Press, 1988. • Comonadic shaders can process the context of the [7] Eugenio Moggi. Notions of computation and monads. Informa- element – the input consists of several elements tion and Computation, 93:55–92, 1989. (possibly the whole stream). The output is, however, [8] Ross Paterson. A new notation for arrows. In International limited to one element. Existing stages : Primitive Conference on Functional Programming, pages 229–240. ACM assembly. Press, September 2001. [9] R. F. C. Walters. Categories and Computer Science. Cambridge Using equivalences from (2), the stages can be University Press, 1992. composed from multiple simple shaders. Functorial stages can be composed only from functorial shaders. The (co)monadic stages can be composed from both (co)monadic and functorial shaders, as every (co)monad is a functor. Also functorial and comonadic stages can be con- structed using parallel composition. Both Sh and GPipe use only equivalence (2a). Following equivalences can