Jelajahi Sumber

Threaded renderer fixes

Ivan Safrin 9 tahun lalu
induk
melakukan
a465620176

+ 3 - 3
build/osx/TemplateApp/TemplateApp/Base.lproj/MainMenu.xib

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9532" systemVersion="15C50" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9531" systemVersion="14F27" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
     <dependencies>
         <deployment identifier="macosx"/>
         <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9532"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9531"/>
     </dependencies>
     </dependencies>
     <objects>
     <objects>
         <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
         <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@@ -72,7 +72,7 @@
             <windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
             <windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
             <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
             <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
             <rect key="contentRect" x="335" y="390" width="480" height="360"/>
             <rect key="contentRect" x="335" y="390" width="480" height="360"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
             <view key="contentView" id="EiT-Mj-1SZ">
             <view key="contentView" id="EiT-Mj-1SZ">
                 <rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
                 <rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
                 <autoresizingMask key="autoresizingMask"/>
                 <autoresizingMask key="autoresizingMask"/>

+ 2 - 0
build/osx/TemplateApp/TemplateApp/PolycodeTemplateApp.h

@@ -19,4 +19,6 @@ public:
 private:
 private:
     ScenePrimitive *test ;
     ScenePrimitive *test ;
     Core *core;
     Core *core;
+    std::vector<ScenePrimitive*> tests;
+    SceneLabel *fpsLabel;
 };
 };

+ 29 - 13
build/osx/TemplateApp/TemplateApp/PolycodeTemplateApp.mm

@@ -20,15 +20,25 @@ PolycodeTemplateApp::PolycodeTemplateApp(PolycodeView *view) {
     
     
     Scene *scene = new Scene(Scene::SCENE_2D);
     Scene *scene = new Scene(Scene::SCENE_2D);
     scene->useClearColor = true;
     scene->useClearColor = true;
-    scene->clearColor.setColor(0.0, 0.0, 0.0, 1.0);
-    test = new ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 0.5, 0.5);
-    test->setMaterialByName("Unlit");
-    test->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "main_icon.png");
-//    test->color = Color(2.0, 2.0, 2.0, 1.0);
-    scene->addChild(test);
-
+    scene->clearColor.setColor(0.2, 0.2, 0.2, 1.0);
+    
+    
+    for(int i=0; i  < 5000; i++) {
+        test = new ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 0.5, 0.5);
+        test->setMaterialByName("Unlit");
+        test->getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", "main_icon.png");
+        test->setPosition(RANDOM_NUMBER * 0.5, RANDOM_NUMBER * 0.4);
+        test->setBlendingMode(Renderer::BLEND_MODE_NONE);
+        test->setScale(0.3, 0.3);
+        scene->addChild(test);
+        tests.push_back(test);
+    }
        Camera *camera = scene->getDefaultCamera();
        Camera *camera = scene->getDefaultCamera();
 
 
+    fpsLabel = new SceneLabel("FPS:", 32, "main", Label::ANTIALIAS_FULL, 0.1);
+    scene->addChild(fpsLabel);
+    fpsLabel->setPositionX(-0.6);
+    /*
     scene->getDefaultCamera()->setPostFilterByName("HDRProcessBloom");
     scene->getDefaultCamera()->setPostFilterByName("HDRProcessBloom");
 
 
     camera->getShaderPass(0).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "brightThreshold")->setNumber(0.1);
     camera->getShaderPass(0).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "brightThreshold")->setNumber(0.1);
@@ -36,12 +46,12 @@ PolycodeTemplateApp::PolycodeTemplateApp(PolycodeView *view) {
     camera->getShaderPass(2).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "blurSize")->setNumber(0.01);
     camera->getShaderPass(2).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "blurSize")->setNumber(0.01);
     camera->getShaderPass(3).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "bloomFactor")->setNumber(2.0);
     camera->getShaderPass(3).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "bloomFactor")->setNumber(2.0);
     camera->getShaderPass(3).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "exposure")->setNumber(0.7);
     camera->getShaderPass(3).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "exposure")->setNumber(0.7);
- 
-    /*
+ */
+
     scene->getDefaultCamera()->setPostFilterByName("Blur");
     scene->getDefaultCamera()->setPostFilterByName("Blur");
-    camera->getShaderPass(0).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "blurSize")->setNumber(0.01);
-    camera->getShaderPass(1).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "blurSize")->setNumber(0.01);
-    */
+    camera->getShaderPass(0).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "blurSize")->setNumber(0.003);
+    camera->getShaderPass(1).shaderBinding->addParam(ProgramParam::PARAM_NUMBER, "blurSize")->setNumber(0.003);
+
 //    Sound *music = new Sound("BUGSHUFFLE.ogg");
 //    Sound *music = new Sound("BUGSHUFFLE.ogg");
   //  music->Play();
   //  music->Play();
     
     
@@ -59,7 +69,13 @@ PolycodeTemplateApp::~PolycodeTemplateApp() {
 bool PolycodeTemplateApp::Update() {
 bool PolycodeTemplateApp::Update() {
     Number elapsed = core->getElapsed();
     Number elapsed = core->getElapsed();
     
     
-    test->Roll(elapsed * 45.0);
+    for(int i=0; i < tests.size(); i++) {
+        tests[i]->Roll(elapsed * 45.0);
+    }
+    
+    if(Services()->getRenderer()->getRenderThread()->getFrameInfo().timeTaken > 0) {
+        fpsLabel->setText("FPS:"+String::IntToString(1000/Services()->getRenderer()->getRenderThread()->getFrameInfo().timeTaken));
+    }
     
     
     return core->updateAndRender();
     return core->updateAndRender();
 }
 }

+ 34 - 3
include/polycode/core/PolyRenderer.h

@@ -38,6 +38,8 @@ THE SOFTWARE.
 #define RENDERER_MAX_LIGHTS 8
 #define RENDERER_MAX_LIGHTS 8
 #define RENDERER_MAX_LIGHT_SHADOWS 2
 #define RENDERER_MAX_LIGHT_SHADOWS 2
 
 
+#define MAX_QUEUED_FRAMES 2
+
 namespace Polycode {
 namespace Polycode {
     
     
     class Texture;
     class Texture;
@@ -91,6 +93,7 @@ namespace Polycode {
         public:
         public:
             int jobType;
             int jobType;
             void *data;
             void *data;
+            void *data2;
     };
     };
     
     
     class RenderThreadDebugInfo {
     class RenderThreadDebugInfo {
@@ -120,20 +123,32 @@ namespace Polycode {
         LocalShaderParam *shadowBuffer;
         LocalShaderParam *shadowBuffer;
     };
     };
     
     
+    class _PolyExport RenderFrame : public PolyBase {
+    public:
+        std::queue<RendererThreadJob> jobQueue;
+    };
+    
     class _PolyExport RenderThread : public Threaded {
     class _PolyExport RenderThread : public Threaded {
         public:
         public:
             RenderThread();
             RenderThread();
              void setGraphicsInterface(Core *core, GraphicsInterface *graphicsInterface);
              void setGraphicsInterface(Core *core, GraphicsInterface *graphicsInterface);
             virtual void runThread();
             virtual void runThread();
-            void enqueueJob(int jobType, void *data);
+        
+            void enqueueFrame(RenderFrame *frame);
+        
+            void enqueueJob(int jobType, void *data, void *data2=NULL);
             void processJob(const RendererThreadJob &job);
             void processJob(const RendererThreadJob &job);
         
         
             ShaderBinding *getShaderBinding();
             ShaderBinding *getShaderBinding();
         
         
             void processDrawBuffer(GPUDrawBuffer *buffer);
             void processDrawBuffer(GPUDrawBuffer *buffer);
-        
             RenderThreadDebugInfo getFrameInfo();
             RenderThreadDebugInfo getFrameInfo();
         
         
+            void initGlobals();
+        
+            void lockRenderMutex();
+            void unlockRenderMutex();
+        
             static const int JOB_REQUEST_CONTEXT_CHANGE = 0;
             static const int JOB_REQUEST_CONTEXT_CHANGE = 0;
             static const int JOB_CREATE_TEXTURE = 1;
             static const int JOB_CREATE_TEXTURE = 1;
             static const int JOB_PROCESS_DRAW_BUFFER = 2;
             static const int JOB_PROCESS_DRAW_BUFFER = 2;
@@ -148,6 +163,10 @@ namespace Polycode {
             static const int JOB_DESTROY_BUFFER = 11;
             static const int JOB_DESTROY_BUFFER = 11;
             static const int JOB_CREATE_RENDER_BUFFER = 12;
             static const int JOB_CREATE_RENDER_BUFFER = 12;
             static const int JOB_DESTROY_RENDER_BUFFER = 13;
             static const int JOB_DESTROY_RENDER_BUFFER = 13;
+            static const int JOB_SET_TEXTURE_PARAM = 14;
+            static const int JOB_ADD_PARAM_TO_BINDING = 15;
+            static const int JOB_DESTROY_SHADER_BINDING = 16;
+            static const int JOB_DESTROY_SHADER_PARAM = 17;
         
         
         protected:
         protected:
         
         
@@ -157,7 +176,10 @@ namespace Polycode {
         
         
             Core *core;
             Core *core;
             CoreMutex *jobQueueMutex;
             CoreMutex *jobQueueMutex;
+            CoreMutex *renderMutex;
+        
             std::queue<RendererThreadJob> jobQueue;
             std::queue<RendererThreadJob> jobQueue;
+            std::queue<RenderFrame*> frameQueue;
             GraphicsInterface *graphicsInterface;
             GraphicsInterface *graphicsInterface;
         
         
             ShaderBinding *rendererShaderBinding;
             ShaderBinding *rendererShaderBinding;
@@ -195,12 +217,20 @@ namespace Polycode {
         Shader *createShader(ShaderProgram *vertexProgram, ShaderProgram *fragmentProgram);
         Shader *createShader(ShaderProgram *vertexProgram, ShaderProgram *fragmentProgram);
         void createVertexBuffers(Mesh *mesh);
         void createVertexBuffers(Mesh *mesh);
         
         
+        void enqueueFrameJob(int jobType, void *data);
+        
         void setExpectedAttributes(Mesh *mesh, Shader *shader);
         void setExpectedAttributes(Mesh *mesh, Shader *shader);
         
         
         void destroyProgram(ShaderProgram *program);
         void destroyProgram(ShaderProgram *program);
         void destroyShader(Shader *shader);
         void destroyShader(Shader *shader);
         void destroyBuffer(RenderDataArray *array);
         void destroyBuffer(RenderDataArray *array);
         
         
+        void destroyShaderBinding(ShaderBinding *binding);
+        void destroyShaderParam(LocalShaderParam *param);
+        
+        void setTextureParam(LocalShaderParam *param, Texture *texture);
+        void addParamToShaderBinding(LocalShaderParam *param, ShaderBinding *binding);
+        
         void setAnisotropyAmount(Number amount);
         void setAnisotropyAmount(Number amount);
         Number getAnisotropyAmount();
         Number getAnisotropyAmount();
         
         
@@ -224,8 +254,9 @@ namespace Polycode {
         
         
         
         
 	protected:
 	protected:
-        
       
       
+        RenderFrame *currentFrame;
+        
         Number backingResolutionScaleX;
         Number backingResolutionScaleX;
         Number backingResolutionScaleY;
         Number backingResolutionScaleY;
         
         

+ 1 - 1
src/core/PolyCocoaCore.mm

@@ -131,7 +131,7 @@ CocoaCore::CocoaCore(PolycodeView *view, int _xRes, int _yRes, bool fullScreen,
     renderer = new Renderer();
     renderer = new Renderer();
     
     
     OpenGLGraphicsInterface *interface = new OpenGLGraphicsInterface();
     OpenGLGraphicsInterface *interface = new OpenGLGraphicsInterface();
-    interface->lineSmooth = true;
+   // interface->lineSmooth = true;
     renderer->setGraphicsInterface(this, interface);
     renderer->setGraphicsInterface(this, interface);
     services->setRenderer(renderer);
     services->setRenderer(renderer);
     setVideoMode(xRes, yRes, fullScreen, vSync, aaLevel, anisotropyLevel, retinaSupport);
     setVideoMode(xRes, yRes, fullScreen, vSync, aaLevel, anisotropyLevel, retinaSupport);

+ 1 - 1
src/core/PolyCore.cpp

@@ -107,7 +107,7 @@ namespace Polycode {
         modeChangeInfo->vSync = vSync;
         modeChangeInfo->vSync = vSync;
         modeChangeInfo->aaLevel = aaLevel;
         modeChangeInfo->aaLevel = aaLevel;
         modeChangeInfo->anisotropyLevel = anisotropyLevel;
         modeChangeInfo->anisotropyLevel = anisotropyLevel;
-        
+
         renderer->getRenderThread()->enqueueJob(RenderThread::JOB_REQUEST_CONTEXT_CHANGE, modeChangeInfo);
         renderer->getRenderThread()->enqueueJob(RenderThread::JOB_REQUEST_CONTEXT_CHANGE, modeChangeInfo);
     }
     }
     
     

+ 1 - 1
src/core/PolyMaterial.cpp

@@ -154,7 +154,7 @@ void Material::clearShaders() {
 	
 	
 	for(int i=0; i < shaderPasses.size(); i++)	{
 	for(int i=0; i < shaderPasses.size(); i++)	{
 		shaderPasses[i].shader->removeAllHandlersForListener(this);
 		shaderPasses[i].shader->removeAllHandlersForListener(this);
-        delete shaderPasses[i].shaderBinding;
+        Services()->getRenderer()->destroyShaderBinding(shaderPasses[i].shaderBinding);
 	}	
 	}	
 	shaderPasses.clear();
 	shaderPasses.clear();
 	
 	

+ 111 - 10
src/core/PolyRenderer.cpp

@@ -34,6 +34,12 @@ GraphicsInterface::GraphicsInterface() {
 
 
 RenderThread::RenderThread() : graphicsInterface(NULL) {
 RenderThread::RenderThread() : graphicsInterface(NULL) {
     
     
+    
+    jobQueueMutex = Services()->getCore()->createMutex();
+    renderMutex = Services()->getCore()->createMutex();
+}
+
+void RenderThread::initGlobals() {
     rendererShaderBinding = new ShaderBinding();
     rendererShaderBinding = new ShaderBinding();
     
     
     projectionMatrixParam = rendererShaderBinding->addParam(ProgramParam::PARAM_MATRIX, "projectionMatrix");
     projectionMatrixParam = rendererShaderBinding->addParam(ProgramParam::PARAM_MATRIX, "projectionMatrix");
@@ -51,7 +57,7 @@ RenderThread::RenderThread() : graphicsInterface(NULL) {
         lights[i].linearAttenuation = rendererShaderBinding->addParam(ProgramParam::PARAM_NUMBER, "lights["+String::IntToString(i)+"].linearAttenuation");
         lights[i].linearAttenuation = rendererShaderBinding->addParam(ProgramParam::PARAM_NUMBER, "lights["+String::IntToString(i)+"].linearAttenuation");
         lights[i].quadraticAttenuation = rendererShaderBinding->addParam(ProgramParam::PARAM_NUMBER, "lights["+String::IntToString(i)+"].quadraticAttenuation");
         lights[i].quadraticAttenuation = rendererShaderBinding->addParam(ProgramParam::PARAM_NUMBER, "lights["+String::IntToString(i)+"].quadraticAttenuation");
         lights[i].shadowEnabled = rendererShaderBinding->addParam(ProgramParam::PARAM_NUMBER, "lights["+String::IntToString(i)+"].shadowEnabled");
         lights[i].shadowEnabled = rendererShaderBinding->addParam(ProgramParam::PARAM_NUMBER, "lights["+String::IntToString(i)+"].shadowEnabled");
-
+        
     }
     }
     
     
     for(int i=0; i < RENDERER_MAX_LIGHT_SHADOWS; i++) {
     for(int i=0; i < RENDERER_MAX_LIGHT_SHADOWS; i++) {
@@ -60,19 +66,38 @@ RenderThread::RenderThread() : graphicsInterface(NULL) {
         lightShadows[i].shadowBuffer->setTexture(NULL);
         lightShadows[i].shadowBuffer->setTexture(NULL);
         
         
     }
     }
-    
-    jobQueueMutex = Services()->getCore()->createMutex();
 }
 }
 
 
+
 void RenderThread::runThread() {
 void RenderThread::runThread() {
-    while(threadRunning) {
+    
+        initGlobals();
+    
+       while(threadRunning) {
         
         
         Services()->getCore()->lockMutex(jobQueueMutex);
         Services()->getCore()->lockMutex(jobQueueMutex);
+        
         if(jobQueue.size() > 0) {
         if(jobQueue.size() > 0) {
             RendererThreadJob nextJob = jobQueue.front();
             RendererThreadJob nextJob = jobQueue.front();
             jobQueue.pop();
             jobQueue.pop();
             processJob(nextJob);
             processJob(nextJob);
         }
         }
+        
+        RenderFrame *nextFrame = NULL;
+        if(frameQueue.size() > 0) {
+            nextFrame = frameQueue.front();
+            frameQueue.pop();
+        }
+        // RENDERER_TODO: Unlock mutex here?
+           
+        if(nextFrame) {
+            while(nextFrame->jobQueue.size() > 0) {
+                RendererThreadJob frameJob = nextFrame->jobQueue.front();
+                nextFrame->jobQueue.pop();
+                processJob(frameJob);
+            }
+            delete nextFrame;
+        }
         Services()->getCore()->unlockMutex(jobQueueMutex);
         Services()->getCore()->unlockMutex(jobQueueMutex);
     }
     }
 }
 }
@@ -299,7 +324,18 @@ void RenderThread::processDrawBuffer(GPUDrawBuffer *buffer) {
     
     
 }
 }
 
 
+void RenderThread::lockRenderMutex() {
+    Services()->getCore()->lockMutex(renderMutex);
+}
+
+void RenderThread::unlockRenderMutex() {
+    Services()->getCore()->unlockMutex(renderMutex);
+}
+
+
 void RenderThread::processJob(const RendererThreadJob &job) {
 void RenderThread::processJob(const RendererThreadJob &job) {
+    
+    lockRenderMutex();
     switch(job.jobType) {
     switch(job.jobType) {
         case JOB_REQUEST_CONTEXT_CHANGE:
         case JOB_REQUEST_CONTEXT_CHANGE:
         {
         {
@@ -331,7 +367,19 @@ void RenderThread::processJob(const RendererThreadJob &job) {
             RenderBuffer *buffer = (RenderBuffer*) job.data;
             RenderBuffer *buffer = (RenderBuffer*) job.data;
             graphicsInterface->destroyRenderBuffer(buffer);
             graphicsInterface->destroyRenderBuffer(buffer);
         }
         }
-            break;
+        break;
+        case JOB_DESTROY_SHADER_BINDING:
+        {
+            ShaderBinding *binding = (ShaderBinding*) job.data;
+            delete binding;
+        }
+        break;
+        case JOB_DESTROY_SHADER_PARAM:
+        {
+            LocalShaderParam *param = (LocalShaderParam*) job.data;
+            delete param;
+        }
+        break;
         case JOB_PROCESS_DRAW_BUFFER:
         case JOB_PROCESS_DRAW_BUFFER:
         {
         {
             GPUDrawBuffer *buffer = (GPUDrawBuffer*) job.data;
             GPUDrawBuffer *buffer = (GPUDrawBuffer*) job.data;
@@ -361,6 +409,20 @@ void RenderThread::processJob(const RendererThreadJob &job) {
             graphicsInterface->createProgram(program);
             graphicsInterface->createProgram(program);
         }
         }
         break;
         break;
+        case JOB_SET_TEXTURE_PARAM:
+        {
+            LocalShaderParam *param = (LocalShaderParam*) job.data;
+            Texture *texture = (Texture*) job.data2;
+            param->data = (void*) texture;
+        }
+        break;
+        case JOB_ADD_PARAM_TO_BINDING:
+        {
+            LocalShaderParam *param = (LocalShaderParam*) job.data;
+            ShaderBinding *binding = (ShaderBinding*) job.data2;
+            binding->localParams.push_back(param);
+        }
+        break;
         case JOB_CREATE_SHADER:
         case JOB_CREATE_SHADER:
         {
         {
             Shader *shader = (Shader*) job.data;
             Shader *shader = (Shader*) job.data;
@@ -391,6 +453,7 @@ void RenderThread::processJob(const RendererThreadJob &job) {
         }
         }
         break;
         break;
     }
     }
+    unlockRenderMutex();
 }
 }
 
 
 RenderThreadDebugInfo RenderThread::getFrameInfo() {
 RenderThreadDebugInfo RenderThread::getFrameInfo() {
@@ -401,11 +464,22 @@ RenderThreadDebugInfo RenderThread::getFrameInfo() {
     return info;
     return info;
 }
 }
 
 
-void RenderThread::enqueueJob(int jobType, void *data) {
+void RenderThread::enqueueFrame(RenderFrame *frame) {
+    Services()->getCore()->lockMutex(jobQueueMutex);
+    frameQueue.push(frame);
+    if(frameQueue.size() > MAX_QUEUED_FRAMES) {
+        // drop frames if necessary
+        frameQueue.pop();
+    }
+    Services()->getCore()->unlockMutex(jobQueueMutex);
+}
+
+void RenderThread::enqueueJob(int jobType, void *data, void *data2) {
     Services()->getCore()->lockMutex(jobQueueMutex);
     Services()->getCore()->lockMutex(jobQueueMutex);
     RendererThreadJob job;
     RendererThreadJob job;
     job.jobType = jobType;
     job.jobType = jobType;
     job.data = data;
     job.data = data;
+    job.data2 = data2;
     jobQueue.push(job);
     jobQueue.push(job);
     Services()->getCore()->unlockMutex(jobQueueMutex);
     Services()->getCore()->unlockMutex(jobQueueMutex);
 }
 }
@@ -419,7 +493,8 @@ Renderer::Renderer() :
     backingResolutionScaleX(1.0),
     backingResolutionScaleX(1.0),
     backingResolutionScaleY(1.0),
     backingResolutionScaleY(1.0),
     cpuBufferIndex(0),
     cpuBufferIndex(0),
-    gpuBufferIndex(1) {
+    gpuBufferIndex(1),
+    currentFrame(NULL) {
         
         
     renderThread = new RenderThread();
     renderThread = new RenderThread();
     Services()->getCore()->createThread(renderThread);
     Services()->getCore()->createThread(renderThread);
@@ -465,15 +540,25 @@ Cubemap *Renderer::createCubemap(Texture *t0, Texture *t1, Texture *t2, Texture
 void Renderer::processDrawBuffer(GPUDrawBuffer *buffer) {
 void Renderer::processDrawBuffer(GPUDrawBuffer *buffer) {
     buffer->backingResolutionScale.x = backingResolutionScaleX;
     buffer->backingResolutionScale.x = backingResolutionScaleX;
     buffer->backingResolutionScale.y = backingResolutionScaleY;
     buffer->backingResolutionScale.y = backingResolutionScaleY;
-    renderThread->enqueueJob(RenderThread::JOB_PROCESS_DRAW_BUFFER, buffer);
+    enqueueFrameJob(RenderThread::JOB_PROCESS_DRAW_BUFFER, buffer);
+}
+
+void Renderer::enqueueFrameJob(int jobType, void *data) {
+    RendererThreadJob job;
+    job.jobType = jobType;
+    job.data = data;
+    currentFrame->jobQueue.push(job);
 }
 }
 
 
 void Renderer::beginFrame() {
 void Renderer::beginFrame() {
-    renderThread->enqueueJob(RenderThread::JOB_BEGIN_FRAME, NULL);
+    currentFrame = new RenderFrame();
+    enqueueFrameJob(RenderThread::JOB_BEGIN_FRAME, NULL);
 }
 }
 
 
 void Renderer::endFrame() {
 void Renderer::endFrame() {
-    renderThread->enqueueJob(RenderThread::JOB_END_FRAME, NULL);
+    enqueueFrameJob(RenderThread::JOB_END_FRAME, NULL);
+    renderThread->enqueueFrame(currentFrame);
+    currentFrame = NULL;
 }
 }
 
 
 Texture *Renderer::createTexture(unsigned int width, unsigned int height, char *textureData, bool clamp, bool createMipmaps, int type, unsigned int filteringMode, unsigned int anisotropy, bool framebufferTexture) {
 Texture *Renderer::createTexture(unsigned int width, unsigned int height, char *textureData, bool clamp, bool createMipmaps, int type, unsigned int filteringMode, unsigned int anisotropy, bool framebufferTexture) {
@@ -529,6 +614,22 @@ void Renderer::destroyProgram(ShaderProgram *program) {
     renderThread->enqueueJob(RenderThread::JOB_DESTROY_PROGRAM, (void*)program);
     renderThread->enqueueJob(RenderThread::JOB_DESTROY_PROGRAM, (void*)program);
 }
 }
 
 
+void Renderer::setTextureParam(LocalShaderParam *param, Texture *texture) {
+    renderThread->enqueueJob(RenderThread::JOB_SET_TEXTURE_PARAM, (void*)param, (void*)texture);
+}
+
+void Renderer::addParamToShaderBinding(LocalShaderParam *param, ShaderBinding *binding) {
+    renderThread->enqueueJob(RenderThread::JOB_ADD_PARAM_TO_BINDING, (void*)param, (void*)binding);
+}
+
+void Renderer::destroyShaderBinding(ShaderBinding *binding) {
+    renderThread->enqueueJob(RenderThread::JOB_DESTROY_SHADER_BINDING, (void*)binding);
+}
+
+void Renderer::destroyShaderParam(LocalShaderParam *param) {
+    renderThread->enqueueJob(RenderThread::JOB_DESTROY_SHADER_PARAM, (void*)param);
+}
+
 void Renderer::destroyShader(Shader *shader) {
 void Renderer::destroyShader(Shader *shader) {
     renderThread->enqueueJob(RenderThread::JOB_DESTROY_SHADER, (void*)shader);
     renderThread->enqueueJob(RenderThread::JOB_DESTROY_SHADER, (void*)shader);
 }
 }

+ 0 - 3
src/core/PolySceneImage.cpp

@@ -37,7 +37,6 @@ SceneImage* SceneImage::SceneImageWithTexture(Texture *texture) {
 
 
 SceneImage::SceneImage(const String& fileName) : ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 1, 1) {
 SceneImage::SceneImage(const String& fileName) : ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 1, 1) {
     
     
-    // RENDERER_TODO
 	setMaterialByName("Unlit");
 	setMaterialByName("Unlit");
 	Texture *texture = getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", fileName);
 	Texture *texture = getShaderPass(0).shaderBinding->loadTextureForParam("diffuse", fileName);
 
 
@@ -50,8 +49,6 @@ SceneImage::SceneImage(const String& fileName) : ScenePrimitive(ScenePrimitive::
 }
 }
 
 
 SceneImage::SceneImage(Image *image) : ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 1, 1) {
 SceneImage::SceneImage(Image *image) : ScenePrimitive(ScenePrimitive::TYPE_VPLANE, 1, 1) {
-    // RENDERER_TODO
-	//loadTextureFromImage(image);
 	setMaterialByName("Unlit");
 	setMaterialByName("Unlit");
     Texture *texture = Services()->getMaterialManager()->createTextureFromImage(image);
     Texture *texture = Services()->getMaterialManager()->createTextureFromImage(image);
     getShaderPass(0).shaderBinding->setTextureForParam("diffuse", texture);
     getShaderPass(0).shaderBinding->setTextureForParam("diffuse", texture);

+ 0 - 1
src/core/PolySceneLabel.cpp

@@ -103,7 +103,6 @@ Number SceneLabel::getLabelActualHeight() {
 void SceneLabel::updateFromLabel() {
 void SceneLabel::updateFromLabel() {
 
 
 	MaterialManager *materialManager = CoreServices::getInstance()->getMaterialManager();
 	MaterialManager *materialManager = CoreServices::getInstance()->getMaterialManager();
-    
     LocalShaderParam *textureParam = getShaderPass(0).shaderBinding->getLocalParamByName("diffuse");
     LocalShaderParam *textureParam = getShaderPass(0).shaderBinding->getLocalParamByName("diffuse");
     if(textureParam) {
     if(textureParam) {
         Texture *currentTexture = textureParam->getTexture();
         Texture *currentTexture = textureParam->getTexture();

+ 3 - 4
src/core/PolySceneMesh.cpp

@@ -186,7 +186,7 @@ Mesh *SceneMesh::getMesh() {
 
 
 void SceneMesh::clearMaterial() {
 void SceneMesh::clearMaterial() {
     for(int i=0; i < shaderPasses.size(); i++)  {
     for(int i=0; i < shaderPasses.size(); i++)  {
-        delete shaderPasses[i].shaderBinding;
+        Services()->getRenderer()->destroyShaderBinding(shaderPasses[i].shaderBinding);
     }
     }
     shaderPasses.clear();
     shaderPasses.clear();
     this->material = NULL;
     this->material = NULL;
@@ -218,8 +218,7 @@ void SceneMesh::setMaterial(Material *material) {
             shaderPass.attributeArrays.push_back(&skeletalVertexNormals);
             shaderPass.attributeArrays.push_back(&skeletalVertexNormals);
         }
         }
         shaderPasses.push_back(shaderPass);
         shaderPasses.push_back(shaderPass);
-    }
-    
+    }    
 }
 }
 
 
 void SceneMesh::setMaterialByName(const String& materialName, ResourcePool *resourcePool) {
 void SceneMesh::setMaterialByName(const String& materialName, ResourcePool *resourcePool) {
@@ -308,7 +307,7 @@ bool SceneMesh::customHitDetection(const Ray &ray) {
 
 
 void SceneMesh::removeShaderPass(int shaderIndex) {
 void SceneMesh::removeShaderPass(int shaderIndex) {
     if(shaderIndex >= 0 && shaderIndex < shaderPasses.size()) {
     if(shaderIndex >= 0 && shaderIndex < shaderPasses.size()) {
-        delete shaderPasses[shaderIndex].shaderBinding;
+        Services()->getRenderer()->destroyShaderBinding(shaderPasses[shaderIndex].shaderBinding);
         shaderPasses.erase(shaderPasses.begin() + shaderIndex);
         shaderPasses.erase(shaderPasses.begin() + shaderIndex);
     }
     }
 }
 }

+ 7 - 7
src/core/PolyShader.cpp

@@ -23,6 +23,7 @@
 #include "polycode/core/PolyShader.h"
 #include "polycode/core/PolyShader.h"
 #include "polycode/core/PolyMatrix4.h"
 #include "polycode/core/PolyMatrix4.h"
 #include "polycode/core/PolyCoreServices.h"
 #include "polycode/core/PolyCoreServices.h"
+#include "polycode/core/PolyRenderer.h"
 
 
 using namespace Polycode;
 using namespace Polycode;
 
 
@@ -108,7 +109,7 @@ ShaderBinding::ShaderBinding() : targetShader(NULL) {
 
 
 ShaderBinding::~ShaderBinding() {
 ShaderBinding::~ShaderBinding() {
 	for(int i=0; i < localParams.size(); i++) {
 	for(int i=0; i < localParams.size(); i++) {
-		delete localParams[i];
+        delete localParams[i]; //Services()->getRenderer()->destroyShaderParam(localParams[i]);
 	}	
 	}	
 	for(int i=0; i < renderTargetBindings.size(); i++) {
 	for(int i=0; i < renderTargetBindings.size(); i++) {
 		delete renderTargetBindings[i];
 		delete renderTargetBindings[i];
@@ -150,8 +151,7 @@ AttributeBinding *ShaderBinding::getAttributeBindingByName(const String &name) {
 }
 }
 
 
 
 
-LocalShaderParam * ShaderBinding::addParam(int type, const String& name) {
-
+LocalShaderParam *ShaderBinding::addParam(int type, const String& name) {
 	void *defaultData = ProgramParam::createParamData(type);
 	void *defaultData = ProgramParam::createParamData(type);
 	LocalShaderParam *newParam = new LocalShaderParam();
 	LocalShaderParam *newParam = new LocalShaderParam();
 	newParam->data = defaultData;
 	newParam->data = defaultData;
@@ -162,7 +162,7 @@ LocalShaderParam * ShaderBinding::addParam(int type, const String& name) {
     if(type == ProgramParam::PARAM_TEXTURE || type == ProgramParam::PARAM_CUBEMAP) {
     if(type == ProgramParam::PARAM_TEXTURE || type == ProgramParam::PARAM_CUBEMAP) {
         newParam->ownsPointer = false;
         newParam->ownsPointer = false;
     }
     }
-	localParams.push_back(newParam);
+    Services()->getRenderer()->addParamToShaderBinding(newParam, this);
 	return newParam;
 	return newParam;
 }
 }
 
 
@@ -173,7 +173,7 @@ LocalShaderParam *ShaderBinding::addParamPointer(int type, const String& name, v
     newParam->type = type;
     newParam->type = type;
     newParam->param = NULL;
     newParam->param = NULL;
     newParam->ownsPointer = false;
     newParam->ownsPointer = false;
-    localParams.push_back(newParam);
+    Services()->getRenderer()->addParamToShaderBinding(newParam, this);
     return newParam;
     return newParam;
 }
 }
 
 
@@ -306,7 +306,7 @@ void ShaderBinding::setCubemapForParam(const String &paramName, Cubemap *cubemap
 void ShaderBinding::removeParam(const String &name) {
 void ShaderBinding::removeParam(const String &name) {
     for(int i=0; i < localParams.size(); i++) {
     for(int i=0; i < localParams.size(); i++) {
         if(localParams[i]->name == name) {
         if(localParams[i]->name == name) {
-            delete localParams[i];
+            Services()->getRenderer()->destroyShaderParam(localParams[i]);
             localParams.erase(localParams.begin()+i);
             localParams.erase(localParams.begin()+i);
         }
         }
     }
     }
@@ -440,7 +440,7 @@ LocalShaderParam::LocalShaderParam() {
 }
 }
 
 
 void LocalShaderParam::setTexture(Texture *texture) {
 void LocalShaderParam::setTexture(Texture *texture) {
-    data = (void*) texture;
+    Services()->getRenderer()->setTextureParam(this, texture);
 }
 }
 
 
 Texture *LocalShaderParam::getTexture() {
 Texture *LocalShaderParam::getTexture() {

+ 2 - 2
src/modules/ui/PolyUIElement.cpp

@@ -276,7 +276,7 @@ void UIRect::initRect(Number width, Number height) {
 
 
 UIRect::~UIRect() {
 UIRect::~UIRect() {
 	delete rectMesh;
 	delete rectMesh;
-    delete shaderPasses[0].shaderBinding;
+    Services()->getRenderer()->destroyShaderBinding(shaderPasses[0].shaderBinding);
 }
 }
 
 
 void UIRect::loadTexture(String fileName) {
 void UIRect::loadTexture(String fileName) {
@@ -314,7 +314,7 @@ void UIRect::setTexture(Texture *texture) {
 void UIRect::setMaterial(Material *material) {
 void UIRect::setMaterial(Material *material) {
     
     
     for(int i=0; i < shaderPasses.size(); i++) {
     for(int i=0; i < shaderPasses.size(); i++) {
-        delete shaderPasses[i].shaderBinding;
+        Services()->getRenderer()->destroyShaderBinding(shaderPasses[i].shaderBinding);
     }
     }
     shaderPasses.clear();
     shaderPasses.clear();