From 2ee103191c2c3d00c8914ecdbdc5c61eeb754e5b Mon Sep 17 00:00:00 2001 From: Dany LE Date: Fri, 12 Aug 2022 16:37:53 +0200 Subject: [PATCH] OPENGL Rendering Performance improvement --- Diya/DiyaApplicationLauncher.class.st | 33 +++++++++++++++++++-------- Diya/DiyaBoot.class.st | 9 ++++---- Diya/DiyaClock.class.st | 17 ++++++++++++-- Diya/DiyaExampleApp.class.st | 7 ++++++ Diya/DiyaImageTex.class.st | 1 - Diya/DiyaNode.class.st | 33 +++++++++++++++------------ Diya/DiyaRendererContext.class.st | 11 +++++++-- Diya/DiyaRootNode.class.st | 23 +++++++++++++++++-- Diya/DiyaText.class.st | 22 ++++++++++-------- Diya/SDL2Image.class.st | 2 +- 10 files changed, 111 insertions(+), 47 deletions(-) diff --git a/Diya/DiyaApplicationLauncher.class.st b/Diya/DiyaApplicationLauncher.class.st index 407e268..4349f65 100644 --- a/Diya/DiyaApplicationLauncher.class.st +++ b/Diya/DiyaApplicationLauncher.class.st @@ -24,7 +24,6 @@ DiyaApplicationLauncher >> bindGlobalEvent [ root on: #quit do: [:e| running := false]. root on: #(fingerdown fingermotion mousemotion) do:[:e| pointer position: e mapped worldPosition. - "Transcript show: e mapped worldPosition asString;cr." DiyaRendererContext uniqueInstance mouse: (e mapped x) @ (e mapped y). ]. ] @@ -34,14 +33,6 @@ DiyaApplicationLauncher >> defaultApplication [ ^DiyaExampleApp ] -{ #category : #accessing } -DiyaApplicationLauncher >> delta: delta [ - |fps| - delta = 0 ifTrue:[^self]. - fps := ((1000/delta) asInteger). - txtFPS data: ('FPS:', fps asString). -] - { #category : #initialization } DiyaApplicationLauncher >> initialize [ super initialize. @@ -58,18 +49,40 @@ DiyaApplicationLauncher >> launch: app [ currapp := app uniqueInstance. self appNode addNode: currapp root. self context assets: currapp am. - currapp setup. + currapp setup ] { #category : #initialization } DiyaApplicationLauncher >> main [ + | fps delta| + delta := DiyaClock uniqueInstance delta asMilliSeconds. + fps := DiyaBoot maxFPS. + delta = 0 ifFalse:[ fps := (1000/ delta) asInteger]. + txtFPS data: ('FPS:', fps asString). [(SDL2 pollEvent: event) > 0] whileTrue: [ root trigger: (DiyaEvent from: event mapped). ]. currapp ifNotNil: [currapp main.]. + "root render." + [ root stepDown ] fork. + self process. root render. ] +{ #category : #initialization } +DiyaApplicationLauncher >> process [ + |Q node maxProcessingTime| + maxProcessingTime := 1000 / DiyaBoot maxFPS - 100. + Q := DiyaRendererContext uniqueInstance processQueue. + Q ifEmpty:[^ self]. + [ + node := Q removeFirst. + node process. + Q isNotEmpty and: DiyaClock uniqueInstance lapDelta asMilliSeconds < maxProcessingTime + ] whileTrue + +] + { #category : #accessing } DiyaApplicationLauncher >> running [ ^ running diff --git a/Diya/DiyaBoot.class.st b/Diya/DiyaBoot.class.st index 3eae063..3010e06 100644 --- a/Diya/DiyaBoot.class.st +++ b/Diya/DiyaBoot.class.st @@ -102,19 +102,18 @@ DiyaBoot >> initialize [ { #category : #events } DiyaBoot >> render [ - |delta launcher| + |launcher| DiyaRendererContext uniqueInstance. launcher := DiyaApplicationLauncher uniqueInstance. launcher setup. self GLinit. [ launcher running ] whileTrue: [ - delta := DiyaClock uniqueInstance delta asMilliSeconds. - launcher delta: delta. DiyaClock uniqueInstance tick. launcher main. SDL2 glSwapWindow: window. - delta := DiyaClock uniqueInstance delta asMilliSeconds. - SDL2 delay: (0 max: (1000/ self class maxFPS) asInteger - delta). + SDL2 delay: + (0 max: + (1000/ self class maxFPS) asInteger - (DiyaClock uniqueInstance lapDelta asMilliSeconds)). ]. ] diff --git a/Diya/DiyaClock.class.st b/Diya/DiyaClock.class.st index 85297f6..203db19 100644 --- a/Diya/DiyaClock.class.st +++ b/Diya/DiyaClock.class.st @@ -3,14 +3,15 @@ Class { #superclass : #DiyaSingleton, #instVars : [ 'monotonic', - 'lastTick' + 'lastTick', + 'lapTime' ], #category : #'Diya-Runtime' } { #category : #initialization } DiyaClock >> delta [ - ^(DateAndTime now) - lastTick + ^ self lapDelta + self lapTime ] { #category : #initialization } @@ -22,9 +23,21 @@ DiyaClock >> elapsedTime [ DiyaClock >> initialize [ monotonic := DateAndTime now. lastTick := monotonic. + lapTime := 0 asDuration. +] + +{ #category : #initialization } +DiyaClock >> lapDelta [ + ^ ((DateAndTime now) - lastTick) +] + +{ #category : #initialization } +DiyaClock >> lapTime [ + ^ lapTime ] { #category : #initialization } DiyaClock >> tick [ + lapTime := (DateAndTime now) - lastTick. lastTick := DateAndTime now. ] diff --git a/Diya/DiyaExampleApp.class.st b/Diya/DiyaExampleApp.class.st index b6afc7e..3459eae 100644 --- a/Diya/DiyaExampleApp.class.st +++ b/Diya/DiyaExampleApp.class.st @@ -11,6 +11,13 @@ DiyaExampleApp >> cleanup [ { #category : #accessing } DiyaExampleApp >> defineStyleSheet [ + |fmgr style| + fmgr := DiyaFontManager uniqueInstance. + #(16 24) do:[:fontSize| + Transcript show: 'Init font size ', fontSize asString, ' of ', fmgr defaultFamily; cr. + style := fmgr style: fmgr defaultStyle from: fmgr defaultFamily. + style textureOf: fontSize. + ]. DiyaUIThemesManager uniqueInstance currentTheme define: #text_icon_1 styles: { #color -> Color orange. diff --git a/Diya/DiyaImageTex.class.st b/Diya/DiyaImageTex.class.st index 84dce7d..1ff393f 100644 --- a/Diya/DiyaImageTex.class.st +++ b/Diya/DiyaImageTex.class.st @@ -142,7 +142,6 @@ DiyaImageTex >> setup [ DiyaImageTex >> surfaceFromFile: aPath [ aPath exists ifFalse: [ ^DiyaCoreAPIError signal:'File not found ', aPath fullName ]. [^ SDL2Image SDLImgLoad: aPath fullName] on: Error do: [ - Transcript show: 'FALLLING BACCCCCCCCCCCCCCCCCCCCCCCCK'; cr. ^ self surfaceFromForm: (ImageReadWriter formFromFileNamed: aPath) ]. ] diff --git a/Diya/DiyaNode.class.st b/Diya/DiyaNode.class.st index 770ade9..3fcf07b 100644 --- a/Diya/DiyaNode.class.st +++ b/Diya/DiyaNode.class.st @@ -10,7 +10,6 @@ Class { 'tf', 'shader', 'context', - 'dirty', 'ehandlers', 'root', 'styleName', @@ -57,7 +56,6 @@ DiyaNode >> addNode: node at: pos [ node position: pos. children add: node. node root: self root. - Transcript show:'Added node #', self id asString; cr. ^ node ] @@ -111,7 +109,6 @@ DiyaNode >> initialize [ shader := nil. context := DiyaRendererContext uniqueInstance. children := OrderedCollection new. - dirty := false. ehandlers := Dictionary new. styleName := nil. style := nil. @@ -124,11 +121,6 @@ DiyaNode >> inner: aPoint [ ^ self subclassResponsibility ] -{ #category : #testing } -DiyaNode >> isDirty [ - ^ dirty -] - { #category : #testing } DiyaNode >> isRoot [ ^ false @@ -178,13 +170,10 @@ DiyaNode >> register: aBlock to: eventName [ { #category : #accessing } DiyaNode >> render [ - self step. - dirty ifTrue:[ - dirty := self process not]. shader ifNotNil: [self setUpShader]. self draw. children ifNil: [ ^self ]. - children do: [:c | c render ]. + children do: [:c| c render ]. ] { #category : #accessing } @@ -194,7 +183,11 @@ DiyaNode >> root [ { #category : #accessing } DiyaNode >> root: anObject [ - root := anObject + root = anObject ifTrue:[^self]. + root := anObject. + children ifNotNil: [ + children do:[:c | c root: root] + ] ] { #category : #accessing } @@ -221,12 +214,16 @@ DiyaNode >> scale: anObject [ { #category : #initialization } DiyaNode >> setClean [ - dirty := false + |Q| + Q := DiyaRendererContext uniqueInstance processQueue. + Q remove: self ifAbsent: [ ] ] { #category : #initialization } DiyaNode >> setDirty [ - dirty := true + |Q| + Q := DiyaRendererContext uniqueInstance processQueue. + (Q includes: self ) ifFalse:[ Q add: self]. ] { #category : #accessing } @@ -265,6 +262,12 @@ DiyaNode >> shader: anObject [ DiyaNode >> step [ ] +{ #category : #stepping } +DiyaNode >> stepDown [ + self step + children ifNotNil: [ children do:[:c | c stepDown ] ] +] + { #category : #accessing } DiyaNode >> styleName [ ^ styleName diff --git a/Diya/DiyaRendererContext.class.st b/Diya/DiyaRendererContext.class.st index f83a4dc..ccc2bab 100644 --- a/Diya/DiyaRendererContext.class.st +++ b/Diya/DiyaRendererContext.class.st @@ -9,7 +9,8 @@ Class { 'texture0', 'projection', 'assets', - 'window' + 'window', + 'rqueue' ], #pools : [ 'OpenGLConstants', @@ -66,6 +67,7 @@ DiyaRendererContext >> initialize [ vbo bind: GL_ARRAY_BUFFER. projection := Array2D identity: 4. assets := AssetManager new. + rqueue := OrderedCollection new. ] { #category : #accessing } @@ -78,12 +80,17 @@ DiyaRendererContext >> mouse: anObject [ mouse := anObject ] +{ #category : #accessing } +DiyaRendererContext >> processQueue [ + ^ rqueue +] + { #category : #accessing } DiyaRendererContext >> projection [ ^ projection ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } DiyaRendererContext >> resolution [ ^ (display w) @ (display h) ] diff --git a/Diya/DiyaRootNode.class.st b/Diya/DiyaRootNode.class.st index a3bb469..d526dff 100644 --- a/Diya/DiyaRootNode.class.st +++ b/Diya/DiyaRootNode.class.st @@ -1,9 +1,22 @@ Class { #name : #DiyaRootNode, #superclass : #DiyaNode, + #instVars : [ + 'Q' + ], #category : #'Diya-Graphics' } +{ #category : #accessing } +DiyaRootNode >> Q [ + ^ Q +] + +{ #category : #accessing } +DiyaRootNode >> Q: v [ + Q := v +] + { #category : #accessing } DiyaRootNode >> boundingBox [ ^ Rectangle origin: 0@0 corner: context resolution @@ -29,10 +42,11 @@ DiyaRootNode >> initialize [ parent := self. shader := nil. root := self. - styleName := #global + styleName := #global. + Q := OrderedCollection new ] -{ #category : #'as yet unclassified' } +{ #category : #accessing } DiyaRootNode >> inner: aPoint [ ^true ] @@ -47,6 +61,11 @@ DiyaRootNode >> process [ ^true ] +{ #category : #accessing } +DiyaRootNode >> processingQueue [ + ^ Q +] + { #category : #accessing } DiyaRootNode >> updateTF [ "donothing" diff --git a/Diya/DiyaText.class.st b/Diya/DiyaText.class.st index d6c7e96..f8461ab 100644 --- a/Diya/DiyaText.class.st +++ b/Diya/DiyaText.class.st @@ -101,7 +101,7 @@ DiyaText >> fontStyle [ ^ self ? #fontStyle ] -{ #category : #accessing } +{ #category : #'text-processing' } DiyaText >> formatText [ |offset index line| lines ifNil: [^self]. @@ -176,7 +176,7 @@ DiyaText >> initialize [ maxLineWidth := 0. ] -{ #category : #'as yet unclassified' } +{ #category : #'text-processing' } DiyaText >> lastSeparatorFrom: index [ index to: 1 by: -1 do: [:i| (data at: i) isSeparator ifTrue:[^i]. @@ -205,6 +205,10 @@ DiyaText >> process [ bbox ifNil: [ ^true ]. data ifNil:[^true]. data ifEmpty:[^true]. + texture ifNil: [ self initTexture ]. + texheight = texture height ifFalse: [ + texheight := texture height. + ]. vbuffer ifNotNil: [vbuffer free]. vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 16. vbuffer autoRelease. @@ -226,14 +230,14 @@ DiyaText >> splitLines [ ] whileTrue. ] +{ #category : #accessing } +DiyaText >> styleName: aName [ + super styleName: aName. + texture := nil. +] + { #category : #accessing } DiyaText >> texture [ - texture ifNil: [ self initTexture ]. - texheight = texture height ifFalse: [ - texheight := texture height. - self process. - self setClean. - ]. ^texture ] @@ -252,5 +256,5 @@ DiyaText >> valignText:h [ { #category : #initialization } DiyaText >> wordWrap: aBool [ wrap := aBool. - dirty := true + self setDirty ] diff --git a/Diya/SDL2Image.class.st b/Diya/SDL2Image.class.st index 4fafc91..9e13f23 100644 --- a/Diya/SDL2Image.class.st +++ b/Diya/SDL2Image.class.st @@ -22,8 +22,8 @@ SDL2Image class >> checkSymbol [ { #category : #accessing } SDL2Image class >> libNames [ ^#( - 'libSDL2_image-2.0.so.0' 'libSDL2_image.so' + 'libSDL2_image-2.0.so.0' 'libSDL2_image-2.0.so' 'libSDL2_image-2.0.so.0.2.3' )