From 33395eeabdbd98065536b2cb0a2847db1b655c7a Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Sat, 25 Jul 2009 11:30:59 -0500 Subject: [PATCH] move vertex-formats and vertex-arrays to gpu.shaders so we can use them for transform feedback formats --- extra/gpu/render/render-docs.factor | 75 +--------- extra/gpu/render/render.factor | 167 ++------------------- extra/gpu/shaders/shaders-docs.factor | 73 ++++++++- extra/gpu/shaders/shaders.factor | 203 ++++++++++++++++++++++++-- extra/gpu/util/util.factor | 2 +- 5 files changed, 280 insertions(+), 240 deletions(-) diff --git a/extra/gpu/render/render-docs.factor b/extra/gpu/render/render-docs.factor index f198558b06..187f08a7ea 100755 --- a/extra/gpu/render/render-docs.factor +++ b/extra/gpu/render/render-docs.factor @@ -34,13 +34,6 @@ HELP: } { $description "Constructs a " { $link multi-index-range } " tuple." } ; -HELP: -{ $values - { "program-instance" program-instance } { "vertex-formats" "a list of " { $link buffer-ptr } "/" { $link vertex-format } " pairs" } - { "vertex-array" vertex-array } -} -{ $description "Creates a new " { $link vertex-array } " to feed data to " { $snippet "program-instance" } " from the set of " { $link buffer } "s specified in " { $snippet "vertex-formats" } "." } ; - HELP: UNIFORM-TUPLE: { $syntax <" UNIFORM-TUPLE: class-name { "slot" uniform-type dimension } @@ -78,30 +71,9 @@ $nl "A value of a uniform tuple type is a standard Factor tuple. Uniform tuples are constructed with " { $link new } " or " { $link boa } ", and values are placed inside them using standard slot accessors." } ; -HELP: VERTEX-FORMAT: -{ $syntax <" VERTEX-FORMAT: format-name - { "attribute"/f component-type dimension normalize? } - { "attribute"/f component-type dimension normalize? } - ... - { "attribute"/f component-type dimension normalize? } ; "> } -{ $description "Defines a new binary " { $link vertex-format } " for structuring vertex data stored in " { $link buffer } "s. Each " { $snippet "attribute" } " name either corresponds to an input parameter of a vertex shader, or is " { $link f } " to include padding in the vertex format. The " { $link component-type } " determines the format of the components, and the " { $snippet "dimension" } " determines the number of components. If the " { $snippet "component-type" } " is an integer type and " { $snippet "normalize?" } " is true, the component values will be scaled to the range 0.0 to 1.0 when fed to the vertex shader; otherwise, they will be cast to floats retaining their integral values." } ; - -HELP: VERTEX-STRUCT: -{ $syntax <" VERTEX-STRUCT: struct-name format-name "> } -{ $description "Defines a struct C type (like " { $link POSTPONE: C-STRUCT: } ") with the same binary format and component types as the given " { $link vertex-format } "." } ; - HELP: bool-uniform { $class-description "This " { $link uniform-type } " indicates that a slot of a " { $link uniform-tuple } " corresponds to a boolean uniform parameter." } ; -HELP: buffer>vertex-array -{ $values - { "vertex-buffer" buffer } { "program-instance" program-instance } { "format" vertex-format } - { "vertex-array" vertex-array } -} -{ $description "Creates a new " { $link vertex-array } " from the entire contents of a single " { $link buffer } " in a single " { $link vertex-format } " for use with " { $snippet "program-instance" } "." } ; - -{ vertex-array buffer>vertex-array } related-words - HELP: bvec2-uniform { $class-description "This " { $link uniform-type } " indicates that a slot of a " { $link uniform-tuple } " corresponds to a two-component boolean vector uniform parameter." } ; @@ -117,18 +89,6 @@ HELP: define-uniform-tuple } { $description "Defines a new " { $link uniform-tuple } " as a subclass of " { $snippet "superclass" } " with the slots specified by the " { $link uniform } " tuple values in " { $snippet "uniforms" } ". The runtime equivalent of " { $link POSTPONE: UNIFORM-TUPLE: } ". This word must be called inside a compilation unit." } ; -HELP: define-vertex-format -{ $values - { "class" class } { "vertex-attributes" sequence } -} -{ $description "Defines a new " { $link vertex-format } " with the binary format specified by the " { $link vertex-attribute } " tuple values in " { $snippet "vertex-attributes" } ". The runtime equivalent of " { $link POSTPONE: VERTEX-FORMAT: } ". This word must be called inside a compilation unit." } ; - -HELP: define-vertex-struct -{ $values - { "struct-name" string } { "vertex-format" vertex-format } -} -{ $description "Defines a new struct C type from a " { $link vertex-format } ". The runtime equivalent of " { $link POSTPONE: VERTEX-STRUCT: } ". This word must be called inside a compilation unit." } ; - HELP: float-uniform { $class-description "This " { $link uniform-type } " indicates that a slot of a " { $link uniform-tuple } " corresponds to a float uniform parameter." } ; @@ -254,9 +214,10 @@ HELP: render-set { "The " { $snippet "uniforms" } " slot contains a " { $link uniform-tuple } " with values for the shader program's uniform parameters." } { "The " { $snippet "indexes" } " slot contains one of the " { $link vertex-indexes } " types and selects elements from the vertex array to be rendered." } { "The " { $snippet "instances" } " slot, if not " { $link f } ", instructs the GPU to render several instances of the same set of vertexes. Instancing requires OpenGL 3.1 or one of the " { $snippet "GL_EXT_draw_instanced" } " or " { $snippet "GL_ARB_draw_instanced" } " extensions." } -{ "The " { $snippet "framebuffer" } " slot determines the target for the rendering output. Either the " { $link system-framebuffer } " or a user-created " { $link framebuffer } " object can be specified. User-created framebuffers require OpenGL 3.0 or one of the " { $snippet "GL_EXT_framebuffer_object" } " or " { $snippet "GL_ARB_framebuffer_object" } " extensions." } -{ "The " { $snippet "output-attachments" } " slot specifies which of the framebuffer's " { $link color-attachment-ref } "s to write the fragment shader's color output to. If the shader uses " { $snippet "gl_FragColor" } " or " { $snippet "gl_FragData[n]" } " to write its output, then " { $snippet "output-attachments" } " should be an array of " { $link color-attachment-ref } "s, and the output to color attachment binding is determined positionally. If the shader uses named output values, then " { $snippet "output-attachments" } " should be a list of string/" { $link color-attachment-ref } " pairs, mapping output names to color attachments. Named output values are available in GLSL 1.30 or later, and GLSL 1.20 and earlier using the " { $snippet "GL_EXT_gpu_shader4" } " extension." } -} } ; +{ "The " { $snippet "framebuffer" } " slot determines the target for the rendering output. Either the " { $link system-framebuffer } " or a user-created " { $link framebuffer } " object can be specified. " { $link f } " can also be specified to disable rasterization and only run the vertex transformation rendering stage." } +{ "The " { $snippet "output-attachments" } " slot specifies which of the framebuffer's " { $link color-attachment-ref } "s to write the fragment shader's color output to. If the shader uses " { $snippet "gl_FragColor" } " or " { $snippet "gl_FragData[n]" } " to write its output, then " { $snippet "output-attachments" } " should be an array of " { $link color-attachment-ref } "s, and the output to color attachment binding is determined positionally. If the shader uses named output values, then " { $snippet "output-attachments" } " should be a list of string/" { $link color-attachment-ref } " pairs, mapping output names to color attachments." } +} } +{ $notes "User-created framebuffers require OpenGL 3.0 or one of the " { $snippet "GL_EXT_framebuffer_object" } " or " { $snippet "GL_ARB_framebuffer_object" } " extensions. Disabling rasterization requires OpenGL 3.0 or the " { $snippet "GL_EXT_transform_feedback" } " extension. Named output-attachment values are available in GLSL 1.30 or later, and GLSL 1.20 and earlier using the " { $snippet "GL_EXT_gpu_shader4" } " extension." } ; { render render-set } related-words @@ -313,29 +274,6 @@ HELP: vec3-uniform HELP: vec4-uniform { $class-description "This " { $link uniform-type } " indicates that a slot of a " { $link uniform-tuple } " corresponds to a four-component float vector uniform parameter." } ; -HELP: vertex-array -{ $class-description "A " { $snippet "vertex-array" } " object associates a shader " { $link program-instance } " with vertex attribute data from one or more " { $link buffer } "s. The format of the binary data inside these buffers is described using " { $link vertex-format } "s. " { $snippet "vertex-array" } "s are constructed using the " { $link } " or " { $link buffer>vertex-array } " words." } ; - -HELP: vertex-array-buffer -{ $values - { "vertex-array" vertex-array } - { "vertex-buffer" buffer } -} -{ $description "Returns the first " { $link buffer } " object comprised in " { $snippet "vertex-array" } "." } ; - -HELP: vertex-attribute -{ $class-description "This tuple type is passed to " { $link define-vertex-format } " to define a new " { $link vertex-format } " type." } ; - -HELP: vertex-format -{ $class-description "This class encompasses all vertex formats defined by " { $link POSTPONE: VERTEX-FORMAT: } ". A vertex format defines the binary layout of vertex attribute data in a " { $link buffer } " for use as part of a " { $link vertex-array } ". See the " { $link POSTPONE: VERTEX-FORMAT: } " documentation for details on how vertex formats are defined." } ; - -HELP: vertex-format-size -{ $values - { "format" vertex-format } - { "size" integer } -} -{ $description "Returns the size in bytes of a set of vertex attributes in " { $snippet "format" } "." } ; - HELP: vertex-indexes { $class-description "This class is a union of the following tuple types, any of which can be used as the " { $snippet "indexes" } " slot of a " { $link render-set } " to select elements from a " { $link vertex-array } " for rendering." { $list @@ -349,11 +287,6 @@ ARTICLE: "gpu.render" "Rendering" "The " { $vocab-link "gpu.render" } " vocabulary contains words for organizing and submitting data to the GPU for rendering." { $subsection render } { $subsection render-set } -"Render data inside GPU " { $link buffer } "s is organized into " { $link vertex-array } "s for consumption by shader code:" -{ $subsection vertex-array } -{ $subsection } -{ $subsection buffer>vertex-array } -{ $subsection POSTPONE: VERTEX-FORMAT: } { $link uniform-tuple } "s provide Factor types for containing and submitting shader uniform parameters:" { $subsection POSTPONE: UNIFORM-TUPLE: } ; diff --git a/extra/gpu/render/render.factor b/extra/gpu/render/render.factor index 51bd549b7a..3d2fef3807 100644 --- a/extra/gpu/render/render.factor +++ b/extra/gpu/render/render.factor @@ -3,24 +3,17 @@ USING: accessors alien alien.c-types alien.structs arrays assocs classes classes.mixin classes.parser classes.singleton classes.tuple classes.tuple.private combinators combinators.tuple destructors fry generic generic.parser gpu gpu.buffers gpu.framebuffers -gpu.framebuffers.private gpu.shaders gpu.state gpu.textures -gpu.textures.private half-floats images kernel lexer locals -math math.order math.parser namespaces opengl opengl.gl parser -quotations sequences slots sorting specialized-arrays.alien -specialized-arrays.float specialized-arrays.int +gpu.framebuffers.private gpu.shaders gpu.shaders.private gpu.state +gpu.textures gpu.textures.private half-floats images kernel +lexer locals math math.order math.parser namespaces opengl +opengl.gl parser quotations sequences slots sorting +specialized-arrays.alien specialized-arrays.float specialized-arrays.int specialized-arrays.uint strings tr ui.gadgets.worlds variants vocabs.parser words ; IN: gpu.render -UNION: ?string string POSTPONE: f ; UNION: ?integer integer POSTPONE: f ; -TUPLE: vertex-attribute - { name ?string read-only initial: f } - { component-type component-type read-only initial: float-components } - { dim integer read-only initial: 4 } - { normalize? boolean read-only initial: f } ; - VARIANT: uniform-type bool-uniform bvec2-uniform @@ -111,52 +104,12 @@ VARIANT: primitive-mode triangle-strip-mode triangle-fan-mode ; -MIXIN: vertex-format - TUPLE: uniform-tuple ; -GENERIC: vertex-format-size ( format -- size ) - ERROR: invalid-uniform-type uniform ; > vertex-type-size ] [ dim>> ] bi * ; - -: vertex-attributes-size ( vertex-attributes -- size ) - [ vertex-attribute-size ] [ + ] map-reduce ; - : gl-index-type ( index-type -- gl-index-type ) { { ubyte-indexes [ GL_UNSIGNED_BYTE ] } @@ -210,56 +163,6 @@ M: multi-index-elements render-vertex-indexes : (bind-texture-unit) ( texture texture-unit -- ) swap [ GL_TEXTURE0 + glActiveTexture ] [ bind-texture drop ] bi* ; inline -:: [bind-vertex-attribute] ( stride offset vertex-attribute -- stride offset' quot ) - vertex-attribute name>> :> name - vertex-attribute component-type>> :> type - type gl-vertex-type :> gl-type - vertex-attribute dim>> :> dim - vertex-attribute normalize?>> >c-bool :> normalize? - vertex-attribute vertex-attribute-size :> size - - stride offset size + - { - { [ name not ] [ [ 2drop ] ] } - { - [ type unnormalized-integer-components? ] - [ - { - name attribute-index [ glEnableVertexAttribArray ] keep - dim gl-type stride offset - } >quotation :> dip-block - - { dip-block dip glVertexAttribIPointer } >quotation - ] - } - [ - { - name attribute-index [ glEnableVertexAttribArray ] keep - dim gl-type normalize? stride offset - } >quotation :> dip-block - - { dip-block dip glVertexAttribPointer } >quotation - ] - } cond ; - -:: [bind-vertex-format] ( vertex-attributes -- quot ) - vertex-attributes vertex-attributes-size :> stride - stride 0 vertex-attributes [ [bind-vertex-attribute] ] { } map-as 2nip :> attributes-cleave - { attributes-cleave 2cleave } >quotation :> with-block - - { drop vertex-buffer with-block with-buffer-ptr } >quotation ; - -GENERIC: bind-vertex-format ( program-instance buffer-ptr format -- ) - -: define-vertex-format-methods ( class vertex-attributes -- ) - [ - [ \ bind-vertex-format create-method-in ] dip - [bind-vertex-format] define - ] [ - [ \ vertex-format-size create-method-in ] dip - [ \ drop ] dip vertex-attributes-size [ ] 2sequence define - ] 2bi ; - GENERIC: bind-uniform-textures ( program-instance uniform-tuple -- ) GENERIC: bind-uniforms ( program-instance uniform-tuple -- ) @@ -510,12 +413,6 @@ padding-no [ 0 ] initialize "(" ")" surround padding-no inc ; -: vertex-attribute>c-type ( vertex-attribute -- {type,name} ) - [ - [ component-type>> component-type>c-type ] - [ dim>> c-array-dim ] bi append - ] [ name>> [ padding-name ] unless* ] bi 2array ; - : (define-uniform-tuple) ( class superclass uniforms -- ) { [ [ uniform>slot ] map define-tuple-class ] @@ -536,55 +433,12 @@ padding-no [ 0 ] initialize PRIVATE> -: define-vertex-format ( class vertex-attributes -- ) - [ - [ - [ define-singleton-class ] - [ vertex-format add-mixin-instance ] - [ ] tri - ] [ define-vertex-format-methods ] bi* - ] - [ "vertex-format-attributes" set-word-prop ] 2bi ; - -SYNTAX: VERTEX-FORMAT: - CREATE-CLASS parse-definition - [ first4 vertex-attribute boa ] map - define-vertex-format ; - -: define-vertex-struct ( struct-name vertex-format -- ) - [ current-vocab ] dip - "vertex-format-attributes" word-prop [ vertex-attribute>c-type ] map - define-struct ; - -SYNTAX: VERTEX-STRUCT: - scan scan-word define-vertex-struct ; - : define-uniform-tuple ( class superclass uniforms -- ) (define-uniform-tuple) ; inline SYNTAX: UNIFORM-TUPLE: parse-uniform-tuple-definition define-uniform-tuple ; -TUPLE: vertex-array < gpu-object - { program-instance program-instance read-only } - { vertex-buffers sequence read-only } ; - -M: vertex-array dispose - [ [ delete-vertex-array ] when* f ] change-handle drop ; - -: ( program-instance vertex-formats -- vertex-array ) - gen-vertex-array - [ glBindVertexArray [ first2 bind-vertex-format ] with each ] - [ -rot [ first buffer>> ] map vertex-array boa ] 3bi - window-resource ; - -: buffer>vertex-array ( vertex-buffer program-instance format -- vertex-array ) - [ swap ] dip - [ 0 ] dip 2array 1array ; inline - -: vertex-array-buffer ( vertex-array -- vertex-buffer ) - vertex-buffers>> first ; - +UNION: ?any-framebuffer any-framebuffer POSTPONE: f ; + TUPLE: render-set { primitive-mode primitive-mode read-only } { vertex-array vertex-array read-only } { uniforms uniform-tuple read-only } { indexes vertex-indexes initial: T{ index-range } read-only } { instances ?integer initial: f read-only } - { framebuffer any-framebuffer initial: system-framebuffer read-only } + { framebuffer ?any-framebuffer initial: system-framebuffer read-only } { output-attachments sequence initial: { default-attachment } read-only } ; : ( x quot-assoc -- render-set ) @@ -631,7 +487,11 @@ TUPLE: render-set [ vertex-array>> program-instance>> ] [ uniforms>> ] bi [ bind-uniform-textures ] [ bind-uniforms ] 2bi ] - [ GL_DRAW_FRAMEBUFFER swap framebuffer>> framebuffer-handle glBindFramebuffer ] + [ + framebuffer>> + [ GL_DRAW_FRAMEBUFFER swap framebuffer-handle glBindFramebuffer ] + [ GL_RASTERIZER_DISCARD glEnable ] if* + ] [ [ vertex-array>> program-instance>> ] [ framebuffer>> ] @@ -644,5 +504,6 @@ TUPLE: render-set [ render-vertex-indexes-instanced ] [ render-vertex-indexes ] if* ] + [ framebuffer>> [ GL_RASTERIZER_DISCARD glDisable ] unless ] } cleave ; inline diff --git a/extra/gpu/shaders/shaders-docs.factor b/extra/gpu/shaders/shaders-docs.factor index cac61114d6..456a76e5ce 100755 --- a/extra/gpu/shaders/shaders-docs.factor +++ b/extra/gpu/shaders/shaders-docs.factor @@ -1,5 +1,6 @@ ! (c)2009 Joe Groff bsd license -USING: help.markup help.syntax kernel math multiline quotations strings ; +USING: alien.syntax classes gpu.buffers help.markup help.syntax +images kernel math multiline quotations sequences strings ; IN: gpu.shaders HELP: @@ -16,6 +17,13 @@ HELP: } { $description "Compiles an instance of " { $snippet "shader" } " for the current graphics context. If an instance already exists for " { $snippet "shader" } " in the current context, it is reused." } ; +HELP: +{ $values + { "program-instance" program-instance } { "vertex-formats" "a list of " { $link buffer-ptr } "/" { $link vertex-format } " pairs" } + { "vertex-array" vertex-array } +} +{ $description "Creates a new " { $link vertex-array } " to feed data to " { $snippet "program-instance" } " from the set of " { $link buffer } "s specified in " { $snippet "vertex-formats" } "." } ; + HELP: GLSL-PROGRAM: { $syntax "GLSL-PROGRAM: program-name shader shader ... shader ;" } { $description "Defines a new " { $link program } " named " { $snippet "program-name" } ". When the program is instantiated with " { $link } ", it will link together instances of all of the specified " { $link shader } "s to create the program instance." } ; @@ -32,6 +40,18 @@ shader source ; "> } { $description "Defines a new " { $link shader } " of kind " { $link shader-kind } " named " { $snippet "shader-name" } ". The shader will read its source code from the current Factor source file between the " { $snippet "GLSL-SHADER:" } " line and the first subsequent line with a single semicolon on it." } ; +HELP: VERTEX-FORMAT: +{ $syntax <" VERTEX-FORMAT: format-name + { "attribute"/f component-type dimension normalize? } + { "attribute"/f component-type dimension normalize? } + ... + { "attribute"/f component-type dimension normalize? } ; "> } +{ $description "Defines a new binary " { $link vertex-format } " for structuring vertex data stored in " { $link buffer } "s. Each " { $snippet "attribute" } " name either corresponds to an input parameter of a vertex shader, or is " { $link f } " to include padding in the vertex format. The " { $link component-type } " determines the format of the components, and the " { $snippet "dimension" } " determines the number of components. If the " { $snippet "component-type" } " is an integer type and " { $snippet "normalize?" } " is true, the component values will be scaled to the range 0.0 to 1.0 when fed to the vertex shader; otherwise, they will be cast to floats retaining their integral values." } ; + +HELP: VERTEX-STRUCT: +{ $syntax <" VERTEX-STRUCT: struct-name format-name "> } +{ $description "Defines a struct C type (like " { $link POSTPONE: C-STRUCT: } ") with the same binary format and component types as the given " { $link vertex-format } "." } ; + { POSTPONE: GLSL-PROGRAM: POSTPONE: GLSL-SHADER-FILE: POSTPONE: GLSL-SHADER: } related-words HELP: attribute-index @@ -41,6 +61,15 @@ HELP: attribute-index } { $description "Returns the numeric index of the vertex attribute named " { $snippet "attribute-name" } " in " { $snippet "program-instance" } "." } ; +HELP: buffer>vertex-array +{ $values + { "vertex-buffer" buffer } { "program-instance" program-instance } { "format" vertex-format } + { "vertex-array" vertex-array } +} +{ $description "Creates a new " { $link vertex-array } " from the entire contents of a single " { $link buffer } " in a single " { $link vertex-format } " for use with " { $snippet "program-instance" } "." } ; + +{ vertex-array buffer>vertex-array } related-words + HELP: compile-shader-error { $class-description "An error compiling the source for a " { $link shader } "." { $list @@ -48,6 +77,18 @@ HELP: compile-shader-error { "The " { $snippet "log" } " slot contains the error string from the GLSL compiler." } } } ; +HELP: define-vertex-format +{ $values + { "class" class } { "vertex-attributes" sequence } +} +{ $description "Defines a new " { $link vertex-format } " with the binary format specified by the " { $link vertex-attribute } " tuple values in " { $snippet "vertex-attributes" } ". The runtime equivalent of " { $link POSTPONE: VERTEX-FORMAT: } ". This word must be called inside a compilation unit." } ; + +HELP: define-vertex-struct +{ $values + { "struct-name" string } { "vertex-format" vertex-format } +} +{ $description "Defines a new struct C type from a " { $link vertex-format } ". The runtime equivalent of " { $link POSTPONE: VERTEX-STRUCT: } ". This word must be called inside a compilation unit." } ; + HELP: fragment-shader { $class-description "This " { $link shader-kind } " indicates that a " { $link shader } " is a fragment shader." } ; @@ -103,6 +144,29 @@ HELP: uniform-index HELP: vertex-shader { $class-description "This " { $link shader-kind } " indicates that a " { $link shader } " is a vertex shader." } ; +HELP: vertex-array +{ $class-description "A " { $snippet "vertex-array" } " object associates a shader " { $link program-instance } " with vertex attribute data from one or more " { $link buffer } "s. The format of the binary data inside these buffers is described using " { $link vertex-format } "s. " { $snippet "vertex-array" } "s are constructed using the " { $link } " or " { $link buffer>vertex-array } " words." } ; + +HELP: vertex-array-buffer +{ $values + { "vertex-array" vertex-array } + { "vertex-buffer" buffer } +} +{ $description "Returns the first " { $link buffer } " object comprised in " { $snippet "vertex-array" } "." } ; + +HELP: vertex-attribute +{ $class-description "This tuple type is passed to " { $link define-vertex-format } " to define a new " { $link vertex-format } " type." } ; + +HELP: vertex-format +{ $class-description "This class encompasses all vertex formats defined by " { $link POSTPONE: VERTEX-FORMAT: } ". A vertex format defines the binary layout of vertex attribute data in a " { $link buffer } " for use as part of a " { $link vertex-array } ". See the " { $link POSTPONE: VERTEX-FORMAT: } " documentation for details on how vertex formats are defined." } ; + +HELP: vertex-format-size +{ $values + { "format" vertex-format } + { "size" integer } +} +{ $description "Returns the size in bytes of a set of vertex attributes in " { $snippet "format" } "." } ; + ARTICLE: "gpu.shaders" "Shader objects" "The " { $vocab-link "gpu.shaders" } " vocabulary supports defining, compiling, and linking " { $link shader } "s into " { $link program } "s that run on the GPU and control rendering." { $subsection POSTPONE: GLSL-PROGRAM: } @@ -111,6 +175,11 @@ ARTICLE: "gpu.shaders" "Shader objects" "A program must be instantiated for each graphics context it is used in:" { $subsection } "Program instances can be updated on the fly, allowing for interactive development of shaders:" -{ $subsection refresh-program } ; +{ $subsection refresh-program } +"Render data inside GPU " { $link buffer } "s is organized into " { $link vertex-array } "s for consumption by shader code:" +{ $subsection vertex-array } +{ $subsection } +{ $subsection buffer>vertex-array } +{ $subsection POSTPONE: VERTEX-FORMAT: } ; ABOUT: "gpu.shaders" diff --git a/extra/gpu/shaders/shaders.factor b/extra/gpu/shaders/shaders.factor index e11fa639b4..e3b4482c24 100755 --- a/extra/gpu/shaders/shaders.factor +++ b/extra/gpu/shaders/shaders.factor @@ -1,17 +1,29 @@ ! (c)2009 Joe Groff bsd license -USING: accessors arrays assocs combinators -combinators.short-circuit definitions destructors gpu -io.encodings.ascii io.files io.pathnames kernel lexer -locals math math.parser memoize multiline namespaces -opengl.gl opengl.shaders parser sequences +USING: accessors alien alien.c-types alien.structs arrays +assocs classes.mixin classes.parser classes.singleton +combinators combinators.short-circuit definitions destructors +generic.parser gpu gpu.buffers hashtables +images io.encodings.ascii io.files io.pathnames kernel lexer +locals math math.parser memoize multiline namespaces opengl +opengl.gl opengl.shaders parser quotations sequences specialized-arrays.int splitting strings ui.gadgets.worlds -variants hashtables vectors vocabs vocabs.loader words +variants vectors vocabs vocabs.loader vocabs.parser words words.constant ; IN: gpu.shaders VARIANT: shader-kind vertex-shader fragment-shader ; +UNION: ?string string POSTPONE: f ; + +TUPLE: vertex-attribute + { name ?string read-only initial: f } + { component-type component-type read-only initial: float-components } + { dim integer read-only initial: 4 } + { normalize? boolean read-only initial: f } ; + +MIXIN: vertex-format + TUPLE: shader { name word read-only initial: t } { kind shader-kind read-only } @@ -25,6 +37,7 @@ TUPLE: program { filename read-only } { line integer read-only } { shaders array read-only } + { feedback-format vertex-format read-only } { instances hashtable read-only } ; TUPLE: shader-instance < gpu-object @@ -35,8 +48,136 @@ TUPLE: program-instance < gpu-object { program program } { world world } ; +GENERIC: vertex-format-size ( format -- size ) + +MEMO: uniform-index ( program-instance uniform-name -- index ) + [ handle>> ] dip glGetUniformLocation ; +MEMO: attribute-index ( program-instance attribute-name -- index ) + [ handle>> ] dip glGetAttribLocation ; +MEMO: output-index ( program-instance output-name -- index ) + [ handle>> ] dip glGetFragDataLocation ; + > vertex-type-size ] [ dim>> ] bi * ; + +: vertex-attributes-size ( vertex-attributes -- size ) + [ vertex-attribute-size ] [ + ] map-reduce ; + +:: [bind-vertex-attribute] ( stride offset vertex-attribute -- stride offset' quot ) + vertex-attribute name>> :> name + vertex-attribute component-type>> :> type + type gl-vertex-type :> gl-type + vertex-attribute dim>> :> dim + vertex-attribute normalize?>> >c-bool :> normalize? + vertex-attribute vertex-attribute-size :> size + + stride offset size + + { + { [ name not ] [ [ 2drop ] ] } + { + [ type unnormalized-integer-components? ] + [ + { + name attribute-index [ glEnableVertexAttribArray ] keep + dim gl-type stride offset + } >quotation :> dip-block + + { dip-block dip glVertexAttribIPointer } >quotation + ] + } + [ + { + name attribute-index [ glEnableVertexAttribArray ] keep + dim gl-type normalize? stride offset + } >quotation :> dip-block + + { dip-block dip glVertexAttribPointer } >quotation + ] + } cond ; + +:: [bind-vertex-format] ( vertex-attributes -- quot ) + vertex-attributes vertex-attributes-size :> stride + stride 0 vertex-attributes [ [bind-vertex-attribute] ] { } map-as 2nip :> attributes-cleave + { attributes-cleave 2cleave } >quotation :> with-block + + { drop vertex-buffer with-block with-buffer-ptr } >quotation ; + +GENERIC: bind-vertex-format ( program-instance buffer-ptr format -- ) + +: define-vertex-format-methods ( class vertex-attributes -- ) + [ + [ \ bind-vertex-format create-method-in ] dip + [bind-vertex-format] define + ] [ + [ \ vertex-format-size create-method-in ] dip + [ \ drop ] dip vertex-attributes-size [ ] 2sequence define + ] 2bi ; + +: component-type>c-type ( component-type -- c-type ) + { + { ubyte-components [ "uchar" ] } + { ushort-components [ "ushort" ] } + { uint-components [ "uint" ] } + { half-components [ "half" ] } + { float-components [ "float" ] } + { byte-integer-components [ "char" ] } + { ubyte-integer-components [ "uchar" ] } + { short-integer-components [ "short" ] } + { ushort-integer-components [ "ushort" ] } + { int-integer-components [ "int" ] } + { uint-integer-components [ "uint" ] } + } case ; + +: c-array-dim ( dim -- string ) + dup 1 = [ drop "" ] [ number>string "[" "]" surround ] if ; + +SYMBOL: padding-no +padding-no [ 0 ] initialize + +: padding-name ( -- name ) + "padding-" + padding-no get number>string append + "(" ")" surround + padding-no inc ; + +: vertex-attribute>c-type ( vertex-attribute -- {type,name} ) + [ + [ component-type>> component-type>c-type ] + [ dim>> c-array-dim ] bi append + ] [ name>> [ padding-name ] unless* ] bi 2array ; + : shader-filename ( shader/program -- filename ) dup filename>> [ nip ] [ name>> where first ] if* file-name ; @@ -69,6 +210,49 @@ TUPLE: program-instance < gpu-object PRIVATE> +: define-vertex-format ( class vertex-attributes -- ) + [ + [ + [ define-singleton-class ] + [ vertex-format add-mixin-instance ] + [ ] tri + ] [ define-vertex-format-methods ] bi* + ] + [ "vertex-format-attributes" set-word-prop ] 2bi ; + +SYNTAX: VERTEX-FORMAT: + CREATE-CLASS parse-definition + [ first4 vertex-attribute boa ] map + define-vertex-format ; + +: define-vertex-struct ( struct-name vertex-format -- ) + [ current-vocab ] dip + "vertex-format-attributes" word-prop [ vertex-attribute>c-type ] map + define-struct ; + +SYNTAX: VERTEX-STRUCT: + scan scan-word define-vertex-struct ; + +TUPLE: vertex-array < gpu-object + { program-instance program-instance read-only } + { vertex-buffers sequence read-only } ; + +M: vertex-array dispose + [ [ delete-vertex-array ] when* f ] change-handle drop ; + +: ( program-instance vertex-formats -- vertex-array ) + gen-vertex-array + [ glBindVertexArray [ first2 bind-vertex-format ] with each ] + [ -rot [ first buffer>> ] map vertex-array boa ] 3bi + window-resource ; + +: buffer>vertex-array ( vertex-buffer program-instance format -- vertex-array ) + [ swap ] dip + [ 0 ] dip 2array 1array ; inline + +: vertex-array-buffer ( vertex-array -- vertex-buffer ) + vertex-buffers>> first ; + TUPLE: compile-shader-error shader log ; TUPLE: link-program-error program log ; @@ -82,13 +266,6 @@ TUPLE: link-program-error program log ; DEFER: -MEMO: uniform-index ( program-instance uniform-name -- index ) - [ handle>> ] dip glGetUniformLocation ; -MEMO: attribute-index ( program-instance attribute-name -- index ) - [ handle>> ] dip glGetAttribLocation ; -MEMO: output-index ( program-instance output-name -- index ) - [ handle>> ] dip glGetFragDataLocation ; -