Bläddra i källkod

Optimized Renderer::GetShader() so that caching shader variation pointers becomes unnecessary for the most part.

Lasse Öörni 12 år sedan
förälder
incheckning
07f06563bc

+ 3 - 6
Source/Engine/Graphics/DebugRenderer.cpp

@@ -317,11 +317,8 @@ void DebugRenderer::Render()
 
     PROFILE(RenderDebugGeometry);
 
-    // Cache shaders
-    if (!vs_)
-        vs_ = renderer->GetShader(VS, "Basic", "VERTEXCOLOR");
-    if (!ps_)
-        ps_ = renderer->GetShader(PS, "Basic", "VERTEXCOLOR");
+    ShaderVariation* vs = renderer->GetShader(VS, "Basic", "VERTEXCOLOR");
+    ShaderVariation* ps = renderer->GetShader(PS, "Basic", "VERTEXCOLOR");
     
     unsigned numVertices = (lines_.Size() + noDepthLines_.Size()) * 2;
     // Resize the vertex buffer if too small or much too large
@@ -364,7 +361,7 @@ void DebugRenderer::Render()
     graphics->SetDepthWrite(true);
     graphics->SetScissorTest(false);
     graphics->SetStencilTest(false);
-    graphics->SetShaders(vs_, ps_);
+    graphics->SetShaders(vs, ps);
     graphics->SetShaderParameter(VSP_MODEL, Matrix3x4::IDENTITY);
     graphics->SetShaderParameter(VSP_VIEWPROJ, projection_ * view_);
     graphics->SetShaderParameter(PSP_MATDIFFCOLOR, Color(1.0f, 1.0f, 1.0f, 1.0f));

+ 0 - 5
Source/Engine/Graphics/DebugRenderer.h

@@ -36,7 +36,6 @@ class Drawable;
 class Light;
 class Matrix3x4;
 class Renderer;
-class ShaderVariation;
 class Skeleton;
 class Sphere;
 class VertexBuffer;
@@ -116,10 +115,6 @@ private:
     /// Handle end of frame. Clear debug geometry.
     void HandleEndFrame(StringHash eventType, VariantMap& eventData);
     
-    /// Vertex shader.
-    SharedPtr<ShaderVariation> vs_;
-    /// Pixel shader.
-    SharedPtr<ShaderVariation> ps_;
     /// Lines rendered with depth test.
     PODVector<DebugLine> lines_;
     /// Lines rendered without depth test.

+ 14 - 14
Source/Engine/Graphics/RenderPath.h

@@ -141,6 +141,20 @@ struct RenderPathCommand
     String pass_;
     /// Command/pass metadata.
     String metadata_;
+    /// Vertex shader name.
+    String vertexShaderName_;
+    /// Pixel shader name.
+    String pixelShaderName_;
+    /// Vertex shader defines.
+    String vertexShaderDefines_;
+    /// Pixel shader defines.
+    String pixelShaderDefines_;
+    /// Textures.
+    String textureNames_[MAX_TEXTURE_UNITS];
+    /// %Shader parameters.
+    HashMap<StringHash, Variant> shaderParameters_;
+    /// Output rendertarget names.
+    Vector<String> outputNames_;
     /// Clear flags.
     unsigned clearFlags_;
     /// Clear color.
@@ -161,20 +175,6 @@ struct RenderPathCommand
     bool useScissor_;
     /// Vertex lights flag.
     bool vertexLights_;
-    /// Vertex shader name.
-    String vertexShaderName_;
-    /// Pixel shader name.
-    String pixelShaderName_;
-    /// Vertex shader defines.
-    String vertexShaderDefines_;
-    /// Pixel shader defines.
-    String pixelShaderDefines_;
-    /// Textures.
-    String textureNames_[MAX_TEXTURE_UNITS];
-    /// %Shader parameters.
-    HashMap<StringHash, Variant> shaderParameters_;
-    /// Output rendertarget names.
-    Vector<String> outputNames_;
 };
 
 /// Rendering path definition.

+ 39 - 53
Source/Engine/Graphics/Renderer.cpp

@@ -552,15 +552,17 @@ unsigned Renderer::GetNumOccluders(bool allViews) const
 
 ShaderVariation* Renderer::GetShader(ShaderType type, const String& name, const String& defines) const
 {
-    ResourceCache* cache = GetSubsystem<ResourceCache>();
-    String shaderName = shaderPath_ + name + shaderExtension_;
-    String variationName;
+    if (name != lastShaderName_ || !lastShader_)
+    {
+        ResourceCache* cache = GetSubsystem<ResourceCache>();
+        if (!cache)
+            return 0;
+        
+        lastShader_ = cache->GetResource<Shader>(shaderPath_ + name + shaderExtension_);
+        lastShaderName_ = name;
+    }
     
-    Shader* shader = cache->GetResource<Shader>(shaderName);
-    if (shader)
-        return shader->GetVariation(type, defines);
-    else
-        return 0;
+    return lastShader_ ? lastShader_->GetVariation(type, defines) : (ShaderVariation*)0;
 }
 
 void Renderer::Update(float timeStep)
@@ -789,33 +791,6 @@ void Renderer::QueueViewport(RenderSurface* renderTarget, Viewport* viewport)
     }
 }
 
-void Renderer::GetLightVolumeShaders(PODVector<ShaderVariation*>& lightVS, PODVector<ShaderVariation*>& lightPS,
-    const String& vsName, const String& vsDefines, const String& psName, const String& psDefines)
-{
-    lightVS.Resize(MAX_DEFERRED_LIGHT_VS_VARIATIONS);
-    lightPS.Resize(MAX_DEFERRED_LIGHT_PS_VARIATIONS);
-    
-    unsigned shadows = (graphics_->GetHardwareShadowSupport() ? 1 : 0) | (shadowQuality_ & SHADOWQUALITY_HIGH_16BIT);
-    
-    for (unsigned i = 0; i < MAX_DEFERRED_LIGHT_VS_VARIATIONS; ++i)
-        lightVS[i] = GetShader(VS, vsName, vsDefines + " " + deferredLightVSVariations[i]);
-    
-    for (unsigned i = 0; i < lightPS.Size(); ++i)
-    {
-        String ortho;
-        if (i >= DLPS_ORTHO)
-            ortho = "ORTHO ";
-        
-        if (i & DLPS_SHADOW)
-        {
-            lightPS[i] = GetShader(PS, psName, psDefines + " " + ortho + lightPSVariations[i % DLPS_ORTHO] +
-                shadowVariations[shadows]);
-        }
-        else
-            lightPS[i] = GetShader(PS, psName, psDefines + " " + ortho + lightPSVariations[i % DLPS_ORTHO]);
-    }
-}
-
 Geometry* Renderer::GetLightGeometry(Light* light)
 {
     switch (light->GetLightType())
@@ -1196,8 +1171,10 @@ void Renderer::SetBatchShaders(Batch& batch, Technique* tech, bool allowShadows)
     }
 }
 
-void Renderer::SetLightVolumeBatchShaders(Batch& batch, PODVector<ShaderVariation*>& lightVS, PODVector<ShaderVariation*>& lightPS)
+void Renderer::SetLightVolumeBatchShaders(Batch& batch, const String& vsName, const String& psName)
 {
+    assert(deferredLightPSVariations_.Size());
+    
     unsigned vsi = DLVS_NONE;
     unsigned psi = DLPS_NONE;
     Light* light = batch.lightQueue_->light_;
@@ -1207,7 +1184,7 @@ void Renderer::SetLightVolumeBatchShaders(Batch& batch, PODVector<ShaderVariatio
     case LIGHT_DIRECTIONAL:
         vsi += DLVS_DIR;
         break;
-            
+        
     case LIGHT_SPOT:
         psi += DLPS_SPOT;
         break;
@@ -1232,8 +1209,8 @@ void Renderer::SetLightVolumeBatchShaders(Batch& batch, PODVector<ShaderVariatio
         psi += DLPS_ORTHO;
     }
     
-    batch.vertexShader_ = lightVS[vsi];
-    batch.pixelShader_ = lightPS[psi];
+    batch.vertexShader_ = GetShader(VS, vsName, deferredLightVSVariations[vsi]);
+    batch.pixelShader_ = GetShader(PS, psName, deferredLightPSVariations_[psi]);
 }
 
 void Renderer::SetCullMode(CullMode mode, Camera* camera)
@@ -1347,7 +1324,7 @@ void Renderer::OptimizeLightByStencil(Light* light, Camera* camera)
         graphics_->SetColorWrite(false);
         graphics_->SetDepthWrite(false);
         graphics_->SetStencilTest(true, CMP_ALWAYS, OP_REF, OP_KEEP, OP_KEEP, lightStencilValue_);
-        graphics_->SetShaders(stencilVS_, stencilPS_);
+        graphics_->SetShaders(GetShader(VS, "Stencil"), GetShader(PS, "Stencil"));
         graphics_->SetShaderParameter(VSP_VIEWPROJ, projection * view);
         graphics_->SetShaderParameter(VSP_MODEL, light->GetVolumeTransform(camera));
         
@@ -1496,9 +1473,17 @@ void Renderer::LoadShaders()
     ReleaseMaterialShaders();
     shadersChangedFrameNumber_ = GetSubsystem<Time>()->GetFrameNumber();
     
-    // Load inbuilt shaders
-    stencilVS_ = GetShader(VS, "Stencil");
-    stencilPS_ = GetShader(PS, "Stencil");
+    // Construct new names for deferred light volume pixel shaders based on rendering options
+    deferredLightPSVariations_.Resize(MAX_DEFERRED_LIGHT_PS_VARIATIONS);
+    unsigned shadows = (graphics_->GetHardwareShadowSupport() ? 1 : 0) | (shadowQuality_ & SHADOWQUALITY_HIGH_16BIT);
+    for (unsigned i = 0; i < MAX_DEFERRED_LIGHT_PS_VARIATIONS; ++i)
+    {
+        deferredLightPSVariations_[i] = lightPSVariations[i % DLPS_ORTHO];
+        if (i & DLPS_SHADOW)
+            deferredLightPSVariations_[i] += shadowVariations[shadows];
+        if (i & DLPS_ORTHO)
+            deferredLightPSVariations_[i] += "ORTHO";
+    }
     
     shadersDirty_ = false;
 }
@@ -1530,18 +1515,19 @@ void Renderer::LoadPassShaders(Technique* tech, StringHash type)
         {
             unsigned g = j / MAX_LIGHT_VS_VARIATIONS;
             unsigned l = j % MAX_LIGHT_VS_VARIATIONS;
-            vertexShaders[j] = GetShader(VS, pass->GetVertexShader(), pass->GetVertexShaderDefines() + " " + lightVSVariations[l]
-                + geometryVSVariations[g]);
+            vertexShaders[j] = GetShader(VS, pass->GetVertexShader(), Shader::SanitateDefines(pass->GetVertexShaderDefines() + " " +
+                lightVSVariations[l] + geometryVSVariations[g]));
         }
         for (unsigned j = 0; j < MAX_LIGHT_PS_VARIATIONS; ++j)
         {
             if (j & LPS_SHADOW)
             {
-                pixelShaders[j] = GetShader(PS, pass->GetPixelShader(), pass->GetPixelShaderDefines() + " " + lightPSVariations[j]
-                    + shadowVariations[shadows]);
+                pixelShaders[j] = GetShader(PS, pass->GetPixelShader(), Shader::SanitateDefines(pass->GetPixelShaderDefines() +
+                    " " + lightPSVariations[j] + shadowVariations[shadows]));
             }
             else
-                pixelShaders[j] = GetShader(PS, pass->GetPixelShader(), pass->GetPixelShaderDefines() + " " + lightPSVariations[j]);
+                pixelShaders[j] = GetShader(PS, pass->GetPixelShader(), Shader::SanitateDefines(pass->GetPixelShaderDefines() +
+                    " " + lightPSVariations[j]));
         }
     }
     else
@@ -1554,8 +1540,8 @@ void Renderer::LoadPassShaders(Technique* tech, StringHash type)
             {
                 unsigned g = j / MAX_VERTEXLIGHT_VS_VARIATIONS;
                 unsigned l = j % MAX_VERTEXLIGHT_VS_VARIATIONS;
-                vertexShaders[j] = GetShader(VS, pass->GetVertexShader(), pass->GetVertexShaderDefines() + " " +
-                    vertexLightVSVariations[l] + geometryVSVariations[g]);
+                vertexShaders[j] = GetShader(VS, pass->GetVertexShader(), Shader::SanitateDefines(pass->GetVertexShaderDefines() +
+                    " " + vertexLightVSVariations[l] + geometryVSVariations[g]));
             }
         }
         else
@@ -1563,13 +1549,13 @@ void Renderer::LoadPassShaders(Technique* tech, StringHash type)
             vertexShaders.Resize(MAX_GEOMETRYTYPES);
             for (unsigned j = 0; j < MAX_GEOMETRYTYPES; ++j)
             {
-                vertexShaders[j] = GetShader(VS, pass->GetVertexShader(), pass->GetVertexShaderDefines() + " " +
-                    geometryVSVariations[j]);
+                vertexShaders[j] = GetShader(VS, pass->GetVertexShader(), Shader::SanitateDefines(pass->GetVertexShaderDefines() +
+                    " " + geometryVSVariations[j]));
             }
         }
         
         pixelShaders.Resize(1);
-        pixelShaders[0] = GetShader(PS, pass->GetPixelShader(), pass->GetPixelShaderDefines());
+        pixelShaders[0] = GetShader(PS, pass->GetPixelShader(), Shader::SanitateDefines(pass->GetPixelShaderDefines()));
     }
     
     pass->MarkShadersLoaded(shadersChangedFrameNumber_);

+ 11 - 14
Source/Engine/Graphics/Renderer.h

@@ -43,6 +43,7 @@ class Graphics;
 class RenderPath;
 class RenderSurface;
 class ResourceCache;
+class Shader;
 class Skeleton;
 class OcclusionBuffer;
 class Texture2D;
@@ -286,14 +287,10 @@ public:
     TextureCube* GetIndirectionCubeMap() const { return indirectionCubeMap_; }
     /// Return the instancing vertex buffer
     VertexBuffer* GetInstancingBuffer() const { return dynamicInstancing_ ? instancingBuffer_ : (VertexBuffer*)0; }
-    /// Return a shader by name and defines.
+    /// Return a shader variation by name and defines.
     ShaderVariation* GetShader(ShaderType type, const String& name, const String& defines = String::EMPTY) const;
-    /// Return the stencil vertex shader.
-    ShaderVariation* GetStencilVS() const { return stencilVS_; }
-    /// Return the stencil pixel shader.
-    ShaderVariation* GetStencilPS() const { return stencilPS_; }
     /// Return the frame update parameters.
-    const FrameInfo& GetFrameInfo() { return frame_; }
+    const FrameInfo& GetFrameInfo() const { return frame_; }
     
     /// Update for rendering. Called by HandleRenderUpdate().
     void Update(float timeStep);
@@ -306,8 +303,6 @@ public:
     /// Queue a viewport for rendering. Null surface means backbuffer.
     void QueueViewport(RenderSurface* renderTarget, Viewport* viewport);
     
-    /// Populate light volume shaders.
-    void GetLightVolumeShaders(PODVector<ShaderVariation*>& lightVS, PODVector<ShaderVariation*>& lightPS, const String& vsName, const String& vsDefines, const String& psName, const String& psDefines);
     /// Return volume geometry for a light.
     Geometry* GetLightGeometry(Light* light);
     /// Allocate a shadow map. If shadow map reuse is disabled, a different map is returned each time.
@@ -322,8 +317,8 @@ public:
     Camera* GetShadowCamera();
     /// Choose shaders for a forward rendering batch.
     void SetBatchShaders(Batch& batch, Technique* tech, bool allowShadows = true);
-    /// Choose shaders for a light volume batch.
-    void SetLightVolumeBatchShaders(Batch& batch, PODVector<ShaderVariation*>& lightVS, PODVector<ShaderVariation*>& lightPS);
+    /// Choose shaders for a deferred light volume batch.
+    void SetLightVolumeBatchShaders(Batch& batch, const String& vsName, const String& psName);
     /// Set cull mode while taking possible projection flipping into account.
     void SetCullMode(CullMode mode, Camera* camera);
     /// Ensure sufficient size of the instancing vertex buffer. Return true if successful.
@@ -403,10 +398,6 @@ private:
     SharedPtr<TextureCube> faceSelectCubeMap_;
     /// Indirection cube map for shadowed pointlights.
     SharedPtr<TextureCube> indirectionCubeMap_;
-    /// Stencil rendering vertex shader.
-    SharedPtr<ShaderVariation> stencilVS_;
-    /// Stencil rendering pixel shader.
-    SharedPtr<ShaderVariation> stencilPS_;
     /// Reusable scene nodes with shadow camera components.
     Vector<SharedPtr<Node> > shadowCameraNodes_;
     /// Reusable occlusion buffers.
@@ -441,6 +432,12 @@ private:
     String shaderPath_;
     /// File extension for shaders.
     String shaderExtension_;
+    /// Current variation names for deferred light volume shaders.
+    Vector<String> deferredLightPSVariations_;
+    /// Last used shader in shader variation query.
+    mutable WeakPtr<Shader> lastShader_;
+    /// Last used shader name in shader variation query.
+    mutable String lastShaderName_;
     /// Frame info for rendering.
     FrameInfo frame_;
     /// Texture anisotropy level.

+ 23 - 42
Source/Engine/Graphics/Shader.cpp

@@ -101,9 +101,8 @@ bool Shader::Load(Deserializer& source)
     return true;
 }
 
-ShaderVariation* Shader::GetVariation(ShaderType type, const String& definesIn)
+ShaderVariation* Shader::GetVariation(ShaderType type, const String& defines)
 {
-    String defines = SanitateDefines(definesIn);
     StringHash definesHash(defines);
     
     if (type == VS)
@@ -148,6 +147,28 @@ ShaderVariation* Shader::GetVariation(ShaderType type, const String& definesIn)
     }
 }
 
+String Shader::SanitateDefines(const String& definesIn)
+{
+    String ret;
+    ret.Reserve(definesIn.Length());
+    
+    unsigned numSpaces = 0;
+    
+    for (unsigned i = 0; i < definesIn.Length(); ++i)
+    {
+        // Ensure only one space in a row
+        if (definesIn[i] == ' ')
+            ++numSpaces;
+        else
+            numSpaces = 0;
+        
+        if (numSpaces <= 1)
+            ret += definesIn[i];
+    }
+    
+    return ret.Trimmed();
+}
+
 bool Shader::ProcessSource(String& code, Deserializer& source)
 {
     ResourceCache* cache = GetSubsystem<ResourceCache>();
@@ -187,44 +208,4 @@ bool Shader::ProcessSource(String& code, Deserializer& source)
     return true;
 }
 
-String Shader::SanitateDefines(const String& definesIn)
-{
-    String ret;
-    ret.Reserve(definesIn.Length());
-    
-    unsigned numSpaces = 0;
-    unsigned start = 0, end = definesIn.Length();
-    
-    // Trim spaces from start & begin. Do not use String::Trimmed() as we also need to trim spaces from the middle
-    for (unsigned i = 0; i < definesIn.Length(); ++i)
-    {
-        if (definesIn[i] != ' ')
-        {
-            start = i;
-            break;
-        }
-    }
-    for (unsigned i = definesIn.Length() - 1; i < definesIn.Length(); --i)
-    {
-        if (definesIn[i] != ' ')
-        {
-            end = i + 1;
-            break;
-        }
-    }
-    for (unsigned i = start; i < end; ++i)
-    {
-        // Ensure only one space in a row
-        if (definesIn[i] == ' ')
-            ++numSpaces;
-        else
-            numSpaces = 0;
-        
-        if (numSpaces <= 1)
-            ret += definesIn[i];
-    }
-    
-    return ret;
-}
-
 }

+ 5 - 4
Source/Engine/Graphics/Shader.h

@@ -46,16 +46,17 @@ public:
     /// Load resource. Return true if successful.
     virtual bool Load(Deserializer& source);
     
-    /// Return a variation with defines.
-    ShaderVariation* GetVariation(ShaderType type, const String& definesIn);
+    /// Return a variation with defines, which should be processed with SanitateDefines() if possible.
+    ShaderVariation* GetVariation(ShaderType type, const String& defines);
     /// Return either vertex or pixel shader source code.
     const String& GetSourceCode(ShaderType type) const { return type == VS ? vsSourceCode_ : psSourceCode_; }
     
+    /// Remove extra spaces from a define string to ensure that the same defines are not compiled twice.
+    static String SanitateDefines(const String& definesIn);
+    
 private:
     /// Process source code and include files. Return true if successful.
     bool ProcessSource(String& code, Deserializer& file);
-    /// Remove extra spaces from a define string to ensure that the same defines are not compiled twice.
-    String SanitateDefines(const String& definesIn);
     
     /// Source code adapted for vertex shader.
     String vsSourceCode_;

+ 5 - 10
Source/Engine/Graphics/View.cpp

@@ -391,9 +391,10 @@ bool View::Define(RenderSurface* renderTarget, Viewport* viewport)
         }
     }
     
-    // Get light volume shaders according to the renderpath, if it needs them
+    // Go through commands to check for deferred rendering
     deferred_ = false;
     deferredAmbient_ = false;
+    
     for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
     {
         const RenderPathCommand& command = renderPath_->commands_[i];
@@ -409,17 +410,11 @@ bool View::Define(RenderSurface* renderTarget, Viewport* viewport)
         
         if (command.type_ == CMD_LIGHTVOLUMES)
         {
-            /// \todo Do not re-query each frame, as it involves string manipulation
-            renderer_->GetLightVolumeShaders(lightVS_, lightPS_, command.vertexShaderName_, command.vertexShaderDefines_,
-                command.pixelShaderName_, command.pixelShaderDefines_);
+            lightVolumeVSName_ = command.vertexShaderName_;
+            lightVolumePSName_ = command.pixelShaderName_;
             deferred_ = true;
         }
     }
-    if (!deferred_)
-    {
-        lightVS_.Clear();
-        lightPS_.Clear();
-    }
     
     // Validate the rect and calculate size. If zero rect, use whole rendertarget size
     int rtWidth = renderTarget ? renderTarget->GetWidth() : graphics_->GetWidth();
@@ -928,7 +923,7 @@ void View::GetBatches()
                     volumeBatch.material_ = 0;
                     volumeBatch.pass_ = 0;
                     volumeBatch.zone_ = 0;
-                    renderer_->SetLightVolumeBatchShaders(volumeBatch, lightVS_, lightPS_);
+                    renderer_->SetLightVolumeBatchShaders(volumeBatch, lightVolumeVSName_, lightVolumePSName_);
                     lightQueue.volumeBatches_.Push(volumeBatch);
                 }
             }

+ 4 - 4
Source/Engine/Graphics/View.h

@@ -320,10 +320,6 @@ private:
     PODVector<Drawable*> occluders_;
     /// Lights.
     PODVector<Light*> lights_;
-    /// Light volume vertex shaders.
-    PODVector<ShaderVariation*> lightVS_;
-    /// Light volume pixel shaders.
-    PODVector<ShaderVariation*> lightPS_;
     /// Drawables that limit their maximum light count.
     HashSet<Drawable*> maxLightsDrawables_;
     /// Rendertargets defined by the renderpath.
@@ -350,6 +346,10 @@ private:
     StringHash litBasePassName_;
     /// Hash of the litalpha pass.
     StringHash litAlphaPassName_;
+    /// Name of light volume vertex shader.
+    String lightVolumeVSName_;
+    /// Name of light volume pixel shader.
+    String lightVolumePSName_;
 };
 
 }

+ 18 - 18
Source/Engine/UI/UI.cpp

@@ -595,9 +595,8 @@ bool UI::HasModalElement() const
 void UI::Initialize()
 {
     Graphics* graphics = GetSubsystem<Graphics>();
-    Renderer* renderer = GetSubsystem<Renderer>();
 
-    if (!graphics || !graphics->IsInitialized() || !renderer)
+    if (!graphics || !graphics->IsInitialized())
         return;
 
     PROFILE(InitUI);
@@ -607,13 +606,6 @@ void UI::Initialize()
     rootElement_->SetSize(graphics->GetWidth(), graphics->GetHeight());
     rootModalElement_->SetSize(rootElement_->GetSize());
 
-    noTextureVS_ = renderer->GetShader(VS, "Basic", "VERTEXCOLOR");
-    diffTextureVS_ = renderer->GetShader(VS, "Basic", "DIFFMAP VERTEXCOLOR");
-    noTexturePS_ = renderer->GetShader(PS, "Basic", "VERTEXCOLOR");
-    diffTexturePS_ = renderer->GetShader(PS, "Basic", "DIFFMAP VERTEXCOLOR");
-    diffMaskTexturePS_ = renderer->GetShader(PS, "Basic", "DIFFMAP ALPHAMASK VERTEXCOLOR");
-    alphaTexturePS_ = renderer->GetShader(PS, "Basic", "ALPHAMAP VERTEXCOLOR");
-
     vertexBuffer_ = new VertexBuffer(context_);
     debugVertexBuffer_ = new VertexBuffer(context_);
 
@@ -660,7 +652,8 @@ void UI::Render(VertexBuffer* buffer, const PODVector<UIBatch>& batches, unsigne
     // Engine does not render when window is closed or device is lost
     assert(graphics_ && graphics_->IsInitialized() && !graphics_->IsDeviceLost());
 
-    if (batches.Empty())
+    Renderer* renderer = GetSubsystem<Renderer>();
+    if (!renderer || batches.Empty())
         return;
 
     Vector2 invScreenSize(1.0f / (float)graphics_->GetWidth(), 1.0f / (float)graphics_->GetHeight());
@@ -684,8 +677,12 @@ void UI::Render(VertexBuffer* buffer, const PODVector<UIBatch>& batches, unsigne
     graphics_->ResetRenderTargets();
     graphics_->SetVertexBuffer(buffer);
 
-    ShaderVariation* ps = 0;
-    ShaderVariation* vs = 0;
+    ShaderVariation* noTextureVS = renderer->GetShader(VS, "Basic", "VERTEXCOLOR");
+    ShaderVariation* diffTextureVS = renderer->GetShader(VS, "Basic", "DIFFMAP VERTEXCOLOR");
+    ShaderVariation* noTexturePS = renderer->GetShader(PS, "Basic", "VERTEXCOLOR");
+    ShaderVariation* diffTexturePS = renderer->GetShader(PS, "Basic", "DIFFMAP VERTEXCOLOR");
+    ShaderVariation* diffMaskTexturePS = renderer->GetShader(PS, "Basic", "DIFFMAP ALPHAMASK VERTEXCOLOR");
+    ShaderVariation* alphaTexturePS = renderer->GetShader(PS, "Basic", "ALPHAMAP VERTEXCOLOR");
 
     unsigned alphaFormat = Graphics::GetAlphaFormat();
 
@@ -695,22 +692,25 @@ void UI::Render(VertexBuffer* buffer, const PODVector<UIBatch>& batches, unsigne
         if (batch.vertexStart_ == batch.vertexEnd_)
             continue;
 
+        ShaderVariation* ps;
+        ShaderVariation* vs;
+
         if (!batch.texture_)
         {
-            ps = noTexturePS_;
-            vs = noTextureVS_;
+            ps = noTexturePS;
+            vs = noTextureVS;
         }
         else
         {
             // If texture contains only an alpha channel, use alpha shader (for fonts)
-            vs = diffTextureVS_;
+            vs = diffTextureVS;
 
             if (batch.texture_->GetFormat() == alphaFormat)
-                ps = alphaTexturePS_;
+                ps = alphaTexturePS;
             else if (batch.blendMode_ != BLEND_ALPHA && batch.blendMode_ != BLEND_ADDALPHA && batch.blendMode_ != BLEND_PREMULALPHA)
-                ps = diffMaskTexturePS_;
+                ps = diffMaskTexturePS;
             else
-                ps = diffTexturePS_;
+                ps = diffTexturePS;
         }
 
         graphics_->SetShaders(vs, ps);

+ 0 - 12
Source/Engine/UI/UI.h

@@ -203,18 +203,6 @@ private:
 
     /// Graphics subsystem.
     WeakPtr<Graphics> graphics_;
-    /// Vertex shader for no texture.
-    SharedPtr<ShaderVariation> noTextureVS_;
-    /// Vertex shader for diffuse texture.
-    SharedPtr<ShaderVariation> diffTextureVS_;
-    /// Pixel shader for no texture.
-    SharedPtr<ShaderVariation> noTexturePS_;
-    /// Pixel shader for diffuse texture.
-    SharedPtr<ShaderVariation> diffTexturePS_;
-    /// Pixel shader for diffuse texture masking.
-    SharedPtr<ShaderVariation> diffMaskTexturePS_;
-    /// Pixel shader for alpha texture.
-    SharedPtr<ShaderVariation> alphaTexturePS_;
     /// UI root element.
     SharedPtr<UIElement> rootElement_;
     /// UI root modal element.

+ 0 - 1
Source/Engine/UI/UIBatch.h

@@ -32,7 +32,6 @@ namespace Urho3D
 class PixelShader;
 class Graphics;
 class Matrix3x4;
-class ShaderVariation;
 class Texture;
 class UIElement;