Ver código fonte

Make ShaderVariation class header API-agnostic.

Lasse Öörni 9 anos atrás
pai
commit
f8d636426c

+ 17 - 26
Source/Urho3D/Graphics/Direct3D11/D3D11ShaderVariation.cpp

@@ -51,21 +51,9 @@ const char* ShaderVariation::elementSemanticNames[] =
     "OBJECTINDEX"
 };
 
-ShaderVariation::ShaderVariation(Shader* owner, ShaderType type) :
-    GPUObject(owner->GetSubsystem<Graphics>()),
-    owner_(owner),
-    type_(type),
-    elementHash_(0)
+void ShaderVariation::OnDeviceLost()
 {
-    for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
-        useTextureUnit_[i] = false;
-    for (unsigned i = 0; i < MAX_SHADER_PARAMETER_GROUPS; ++i)
-        constantBufferSizes_[i] = 0;
-}
-
-ShaderVariation::~ShaderVariation()
-{
-    Release();
+    // No-op on Direct3D11
 }
 
 bool ShaderVariation::Create()
@@ -166,11 +154,6 @@ void ShaderVariation::Release()
     elementHash_ = 0;
 }
 
-void ShaderVariation::SetName(const String& name)
-{
-    name_ = name;
-}
-
 void ShaderVariation::SetDefines(const String& defines)
 {
     defines_ = defines;
@@ -181,11 +164,6 @@ void ShaderVariation::SetDefines(const String& defines)
         definesClipPlane_ += " CLIPPLANE";
 }
 
-Shader* ShaderVariation::GetOwner() const
-{
-    return owner_;
-}
-
 bool ShaderVariation::LoadByteCode(const String& binaryShaderName)
 {
     ResourceCache* cache = owner_->GetSubsystem<ResourceCache>();
@@ -220,7 +198,13 @@ bool ShaderVariation::LoadByteCode(const String& binaryShaderName)
         unsigned offset = file->ReadUInt();
         unsigned size = file->ReadUInt();
 
-        ShaderParameter parameter(type_, name_, buffer, offset, size);
+        ShaderParameter parameter;
+        parameter.type_ = type_;
+        parameter.name_ = name;
+        parameter.buffer_ = buffer;
+        parameter.offset_ = offset;
+        parameter.size_ = size;
+        parameter.bufferPtr_ = 0;
         parameters_[StringHash(name)] = parameter;
     }
 
@@ -416,7 +400,14 @@ void ShaderVariation::ParseParameters(unsigned char* bufData, unsigned bufSize)
             if (varName[0] == 'c')
             {
                 varName = varName.Substring(1); // Strip the c to follow Urho3D constant naming convention
-                parameters_[varName] = ShaderParameter(type_, varName, cbRegister, varDesc.StartOffset, varDesc.Size);
+                ShaderParameter parameter;
+                parameter.type_ = type_;
+                parameter.name_ = varName;
+                parameter.buffer_ = cbRegister;
+                parameter.offset_ = varDesc.StartOffset;
+                parameter.size_ = varDesc.Size;
+                parameter.bufferPtr_ = 0;
+                parameters_[varName] = parameter;
             }
         }
     }

+ 0 - 172
Source/Urho3D/Graphics/Direct3D11/D3D11ShaderVariation.h

@@ -1,172 +0,0 @@
-//
-// Copyright (c) 2008-2016 the Urho3D project.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-
-#pragma once
-
-#include "../../Container/HashSet.h"
-#include "../../Container/RefCounted.h"
-#include "../../Container/ArrayPtr.h"
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-
-namespace Urho3D
-{
-
-class ConstantBuffer;
-class Shader;
-
-/// %Shader parameter definition.
-struct ShaderParameter
-{
-    /// Construct with defaults.
-    ShaderParameter() :
-        type_(VS),
-        buffer_(0),
-        offset_(0),
-        size_(0),
-        bufferPtr_(0)
-    {
-    }
-
-    /// Construct with parameters.
-    ShaderParameter(ShaderType type, const String& name, unsigned buffer, unsigned offset, unsigned size, ConstantBuffer* ptr = 0) :
-        type_(type),
-        name_(name),
-        buffer_(buffer),
-        offset_(offset),
-        size_(size),
-        bufferPtr_(ptr)
-    {
-    }
-
-    /// %Shader type.
-    ShaderType type_;
-    /// Name of the parameter.
-    String name_;
-    /// Constant buffer index.
-    unsigned buffer_;
-    /// Offset in constant buffer.
-    unsigned offset_;
-    /// Size of parameter in bytes.
-    unsigned size_;
-    /// Constant buffer pointer. Defined only in shader programs.
-    ConstantBuffer* bufferPtr_;
-};
-
-/// Vertex or pixel shader on the GPU.
-class URHO3D_API ShaderVariation : public RefCounted, public GPUObject
-{
-public:
-    /// Construct.
-    ShaderVariation(Shader* owner, ShaderType type);
-    /// Destruct.
-    virtual ~ShaderVariation();
-
-    /// Release the shader.
-    virtual void Release();
-
-    /// Compile the shader. Return true if successful.
-    bool Create();
-    /// Set name.
-    void SetName(const String& name);
-    /// Set defines.
-    void SetDefines(const String& defines);
-
-    /// Return the owner resource.
-    Shader* GetOwner() const;
-
-    /// Return shader type.
-    ShaderType GetShaderType() const { return type_; }
-
-    /// Return shader name.
-    const String& GetName() const { return name_; }
-
-    /// Return full shader name.
-    String GetFullName() const { return name_ + "(" + defines_ + ")"; }
-
-    /// Return whether uses a parameter.
-    bool HasParameter(StringHash param) const { return parameters_.Contains(param); }
-
-    /// Return whether uses a texture unit (only for pixel shaders.)
-    bool HasTextureUnit(TextureUnit unit) const { return useTextureUnit_[unit]; }
-
-    /// Return all parameter definitions.
-    const HashMap<StringHash, ShaderParameter>& GetParameters() const { return parameters_; }
-
-    /// Return vertex element hash.
-    unsigned long long GetElementHash() const { return elementHash_; }
-
-    /// Return shader bytecode.
-    const PODVector<unsigned char>& GetByteCode() const { return byteCode_; }
-
-    /// Return defines.
-    const String& GetDefines() const { return defines_; }
-
-    /// Return compile error/warning string.
-    const String& GetCompilerOutput() const { return compilerOutput_; }
-
-    /// Return constant buffer data sizes.
-    const unsigned* GetConstantBufferSizes() const { return &constantBufferSizes_[0]; }
-
-    /// Return defines with the CLIPPLANE define appended. Used internally on D3D11 only.
-    const String& GetDefinesClipPlane() { return definesClipPlane_; }
-
-    /// D3D11 vertex semantic names. Used internally.
-    static const char* elementSemanticNames[];
-
-private:
-    /// Load bytecode from a file. Return true if successful.
-    bool LoadByteCode(const String& binaryShaderName);
-    /// Compile from source. Return true if successful.
-    bool Compile();
-    /// Inspect the constant parameters and input layout (if applicable) from the shader bytecode.
-    void ParseParameters(unsigned char* bufData, unsigned bufSize);
-    /// Save bytecode to a file.
-    void SaveByteCode(const String& binaryShaderName);
-    /// Calculate constant buffer sizes from parameters.
-    void CalculateConstantBufferSizes();
-
-    /// Shader this variation belongs to.
-    WeakPtr<Shader> owner_;
-    /// Shader type.
-    ShaderType type_;
-    /// Vertex element hash for vertex shaders. Zero for pixel shaders. Note that hashing is different than vertex buffers.
-    unsigned long long elementHash_;
-    /// Shader parameters.
-    HashMap<StringHash, ShaderParameter> parameters_;
-    /// Texture unit use flags.
-    bool useTextureUnit_[MAX_TEXTURE_UNITS];
-    /// Constant buffer sizes. 0 if a constant buffer slot is not in use.
-    unsigned constantBufferSizes_[MAX_SHADER_PARAMETER_GROUPS];
-    /// Bytecode. Needed for inspecting the input signature and parameters.
-    PODVector<unsigned char> byteCode_;
-    /// Shader name.
-    String name_;
-    /// Defines to use in compiling.
-    String defines_;
-    /// Defines to use in compiling + CLIPPLANE define appended.
-    String definesClipPlane_;
-    /// Shader compile error string.
-    String compilerOutput_;
-};
-
-}

+ 60 - 62
Source/Urho3D/Graphics/Direct3D9/D3D9ShaderVariation.cpp

@@ -39,18 +39,39 @@
 namespace Urho3D
 {
 
-ShaderVariation::ShaderVariation(Shader* owner, ShaderType type) :
-    GPUObject(owner->GetSubsystem<Graphics>()),
-    owner_(owner),
-    type_(type)
+void CopyStrippedCode(PODVector<unsigned char>& byteCode, unsigned char* bufData, unsigned bufSize)
 {
-    for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
-        useTextureUnit_[i] = false;
+    unsigned const D3DSIO_COMMENT = 0xFFFE;
+    unsigned* srcWords = (unsigned*)bufData;
+    unsigned srcWordSize = bufSize >> 2;
+    byteCode.Clear();
+
+    for (unsigned i = 0; i < srcWordSize; ++i)
+    {
+        unsigned opcode = srcWords[i] & 0xffff;
+        // unsigned paramLength = (srcWords[i] & 0x0f000000) >> 24;
+        unsigned commentLength = srcWords[i] >> 16;
+
+        // For now, skip comment only at fixed position to prevent false positives
+        if (i == 1 && opcode == D3DSIO_COMMENT)
+        {
+            // Skip the comment
+            i += commentLength;
+        }
+        else
+        {
+            // Not a comment, copy the data
+            unsigned destPos = byteCode.Size();
+            byteCode.Resize(destPos + sizeof(unsigned));
+            unsigned* dest = (unsigned*)&byteCode[destPos];
+            *dest = srcWords[i];
+        }
+    }
 }
 
-ShaderVariation::~ShaderVariation()
+void ShaderVariation::OnDeviceLost()
 {
-    Release();
+    // No-op on Direct3D9, shaders are preserved through a device loss & reset
 }
 
 bool ShaderVariation::Create()
@@ -72,16 +93,15 @@ bool ShaderVariation::Create()
     extension = type_ == VS ? ".vs3" : ".ps3";
 
     String binaryShaderName = path + "Cache/" + name + "_" + StringHash(defines_).ToString() + extension;
-    PODVector<unsigned> byteCode;
 
-    if (!LoadByteCode(byteCode, binaryShaderName))
+    if (!LoadByteCode(binaryShaderName))
     {
         // Compile shader if don't have valid bytecode
-        if (!Compile(byteCode))
+        if (!Compile())
             return false;
         // Save the bytecode after successful compile, but not if the source is from a package
         if (owner_->GetTimeStamp())
-            SaveByteCode(byteCode, binaryShaderName);
+            SaveByteCode(binaryShaderName);
     }
 
     // Then create shader from the bytecode
@@ -89,7 +109,7 @@ bool ShaderVariation::Create()
     if (type_ == VS)
     {
         HRESULT hr = device->CreateVertexShader(
-            (const DWORD*)&byteCode[0],
+            (const DWORD*)&byteCode_[0],
             (IDirect3DVertexShader9**)&object_.ptr_);
         if (FAILED(hr))
         {
@@ -100,7 +120,7 @@ bool ShaderVariation::Create()
     else
     {
         HRESULT hr = device->CreatePixelShader(
-            (const DWORD*)&byteCode[0],
+            (const DWORD*)&byteCode_[0],
             (IDirect3DPixelShader9**)&object_.ptr_);
         if (FAILED(hr))
         {
@@ -109,6 +129,10 @@ bool ShaderVariation::Create()
         }
     }
 
+    // The bytecode is not needed on Direct3D9 after creation, so delete it to save memory
+    byteCode_.Clear();
+    byteCode_.Reserve(0);
+
     return object_.ptr_ != 0;
 }
 
@@ -139,22 +163,12 @@ void ShaderVariation::Release()
     parameters_.Clear();
 }
 
-void ShaderVariation::SetName(const String& name)
-{
-    name_ = name;
-}
-
 void ShaderVariation::SetDefines(const String& defines)
 {
     defines_ = defines;
 }
 
-Shader* ShaderVariation::GetOwner() const
-{
-    return owner_;
-}
-
-bool ShaderVariation::LoadByteCode(PODVector<unsigned>& byteCode, const String& binaryShaderName)
+bool ShaderVariation::LoadByteCode(const String& binaryShaderName)
 {
     ResourceCache* cache = owner_->GetSubsystem<ResourceCache>();
     if (!cache->Exists(binaryShaderName))
@@ -185,7 +199,12 @@ bool ShaderVariation::LoadByteCode(PODVector<unsigned>& byteCode, const String&
         unsigned reg = file->ReadUByte();
         unsigned regCount = file->ReadUByte();
 
-        ShaderParameter parameter(type_, name, reg, regCount);
+        ShaderParameter parameter;
+        parameter.type_ = type_;
+        parameter.name_ = name;
+        parameter.register_ = reg;
+        parameter.regCount_ = regCount;
+        parameter.bufferPtr_ = 0;
         parameters_[StringHash(name)] = parameter;
     }
 
@@ -202,8 +221,8 @@ bool ShaderVariation::LoadByteCode(PODVector<unsigned>& byteCode, const String&
     unsigned byteCodeSize = file->ReadUInt();
     if (byteCodeSize)
     {
-        byteCode.Resize(byteCodeSize >> 2);
-        file->Read(&byteCode[0], byteCodeSize);
+        byteCode_.Resize(byteCodeSize);
+        file->Read(&byteCode_[0], byteCodeSize);
 
         if (type_ == VS)
             URHO3D_LOGDEBUG("Loaded cached vertex shader " + GetFullName());
@@ -219,7 +238,7 @@ bool ShaderVariation::LoadByteCode(PODVector<unsigned>& byteCode, const String&
     }
 }
 
-bool ShaderVariation::Compile(PODVector<unsigned>& byteCode)
+bool ShaderVariation::Compile()
 {
     const String& sourceCode = owner_->GetSourceCode(type_);
     Vector<String> defines = defines_.Split(' ');
@@ -301,13 +320,13 @@ bool ShaderVariation::Compile(PODVector<unsigned>& byteCode)
         unsigned char* bufData = (unsigned char*)shaderCode->GetBufferPointer();
         unsigned bufSize = (unsigned)shaderCode->GetBufferSize();
         ParseParameters(bufData, bufSize);
-        CopyStrippedCode(byteCode, bufData, bufSize);
+        CopyStrippedCode(byteCode_, bufData, bufSize);
     }
 
     URHO3D_SAFE_RELEASE(shaderCode);
     URHO3D_SAFE_RELEASE(errorMsgs);
 
-    return !byteCode.Empty();
+    return !byteCode_.Empty();
 }
 
 void ShaderVariation::ParseParameters(unsigned char* bufData, unsigned bufSize)
@@ -337,41 +356,20 @@ void ShaderVariation::ParseParameters(unsigned char* bufData, unsigned bufSize)
         }
         else
         {
-            ShaderParameter newParam(type_, name, reg, regCount);
-            parameters_[StringHash(name)] = newParam;
+            ShaderParameter parameter;
+            parameter.type_ = type_;
+            parameter.name_ = name;
+            parameter.register_ = reg;
+            parameter.regCount_ = regCount;
+            parameter.bufferPtr_ = 0;
+            parameters_[StringHash(name)] = parameter;
         }
     }
 
     MOJOSHADER_freeParseData(parseData);
 }
 
-void ShaderVariation::CopyStrippedCode(PODVector<unsigned>& byteCode, unsigned char* bufData, unsigned bufSize)
-{
-    unsigned const D3DSIO_COMMENT = 0xFFFE;
-    unsigned* srcWords = (unsigned*)bufData;
-    unsigned srcWordSize = bufSize >> 2;
-
-    for (unsigned i = 0; i < srcWordSize; ++i)
-    {
-        unsigned opcode = srcWords[i] & 0xffff;
-        // unsigned paramLength = (srcWords[i] & 0x0f000000) >> 24;
-        unsigned commentLength = srcWords[i] >> 16;
-
-        // For now, skip comment only at fixed position to prevent false positives
-        if (i == 1 && opcode == D3DSIO_COMMENT)
-        {
-            // Skip the comment
-            i += commentLength;
-        }
-        else
-        {
-            // Not a comment, copy the data
-            byteCode.Push(srcWords[i]);
-        }
-    }
-}
-
-void ShaderVariation::SaveByteCode(const PODVector<unsigned>& byteCode, const String& binaryShaderName)
+void ShaderVariation::SaveByteCode(const String& binaryShaderName)
 {
     ResourceCache* cache = owner_->GetSubsystem<ResourceCache>();
     FileSystem* fileSystem = owner_->GetSubsystem<FileSystem>();
@@ -413,10 +411,10 @@ void ShaderVariation::SaveByteCode(const PODVector<unsigned>& byteCode, const St
         }
     }
 
-    unsigned dataSize = byteCode.Size() << 2;
+    unsigned dataSize = byteCode_.Size();
     file->WriteUInt(dataSize);
     if (dataSize)
-        file->Write(&byteCode[0], dataSize);
+        file->Write(&byteCode_[0], dataSize);
 }
 
 }

+ 0 - 140
Source/Urho3D/Graphics/Direct3D9/D3D9ShaderVariation.h

@@ -1,140 +0,0 @@
-//
-// Copyright (c) 2008-2016 the Urho3D project.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-
-#pragma once
-
-#include "../../Container/HashSet.h"
-#include "../../Container/RefCounted.h"
-#include "../../Container/ArrayPtr.h"
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-
-namespace Urho3D
-{
-
-class Shader;
-
-/// %Shader parameter definition.
-struct ShaderParameter
-{
-    /// Construct with defaults.
-    ShaderParameter() :
-        type_(VS),
-        register_(M_MAX_UNSIGNED),
-        regCount_(0)
-    {
-    }
-
-    /// Construct with parameters.
-    ShaderParameter(ShaderType type, const String& name, unsigned reg, unsigned regCount) :
-        type_(type),
-        name_(name),
-        register_(reg),
-        regCount_(regCount)
-    {
-    }
-
-    /// %Shader type.
-    ShaderType type_;
-    /// Name of the parameter.
-    String name_;
-    /// Hardware register.
-    unsigned register_;
-    /// Number of registers.
-    unsigned regCount_;
-};
-
-/// Vertex or pixel shader on the GPU.
-class URHO3D_API ShaderVariation : public RefCounted, public GPUObject
-{
-public:
-    /// Construct.
-    ShaderVariation(Shader* owner, ShaderType type);
-    /// Destruct.
-    virtual ~ShaderVariation();
-
-    /// Release the shader.
-    virtual void Release();
-
-    /// Compile the shader. Return true if successful.
-    bool Create();
-    /// Set name.
-    void SetName(const String& name);
-    /// Set defines.
-    void SetDefines(const String& defines);
-
-    /// Return the owner resource.
-    Shader* GetOwner() const;
-
-    /// Return shader type.
-    ShaderType GetShaderType() const { return type_; }
-
-    /// Return shader name.
-    const String& GetName() const { return name_; }
-
-    /// Return defines.
-    const String& GetDefines() const { return defines_; }
-
-    /// Return full shader name.
-    String GetFullName() const { return name_ + "(" + defines_ + ")"; }
-
-    /// Return compile error/warning string.
-    const String& GetCompilerOutput() const { return compilerOutput_; }
-
-    /// Return whether uses a parameter.
-    bool HasParameter(StringHash param) const { return parameters_.Contains(param); }
-
-    /// Return whether uses a texture unit (only for pixel shaders.)
-    bool HasTextureUnit(TextureUnit unit) const { return useTextureUnit_[unit]; }
-
-    /// Return all parameter definitions.
-    const HashMap<StringHash, ShaderParameter>& GetParameters() const { return parameters_; }
-
-private:
-    /// Load bytecode from a file. Return true if successful.
-    bool LoadByteCode(PODVector<unsigned>& byteCode, const String& binaryShaderName);
-    /// Compile from source. Return true if successful.
-    bool Compile(PODVector<unsigned>& byteCode);
-    /// Inspect the constant parameters of the shader bytecode using MojoShader.
-    void ParseParameters(unsigned char* bufData, unsigned bufSize);
-    /// Strip comments from shader bytecode and store it.
-    void CopyStrippedCode(PODVector<unsigned>& byteCode, unsigned char* bufData, unsigned bufSize);
-    /// Save bytecode to a file.
-    void SaveByteCode(const PODVector<unsigned>& byteCode, const String& binaryShaderName);
-
-    /// Shader this variation belongs to.
-    WeakPtr<Shader> owner_;
-    /// Shader type.
-    ShaderType type_;
-    /// Shader name.
-    String name_;
-    /// Defines to use in compiling.
-    String defines_;
-    /// Shader compile error string.
-    String compilerOutput_;
-    /// Shader parameters.
-    HashMap<StringHash, ShaderParameter> parameters_;
-    /// Texture unit use flags.
-    bool useTextureUnit_[MAX_TEXTURE_UNITS];
-};
-
-}

+ 3 - 0
Source/Urho3D/Graphics/GraphicsImpl.h

@@ -22,6 +22,9 @@
 
 #pragma once
 
+// Note: GraphicsImpl class is purposefully API-specific. It should not be used by Urho3D client applications,
+// unless required for e.g. integration of 3rd party libraries that interface directly with the graphics device.
+
 #if defined(URHO3D_OPENGL)
 #include "OpenGL/OGLGraphicsImpl.h"
 #elif defined(URHO3D_D3D11)

+ 4 - 4
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -1121,7 +1121,7 @@ void Graphics::SetShaderParameter(StringHash param, const float* data, unsigned
                 return;
             }
 
-            switch (info->type_)
+            switch (info->glType_)
             {
             case GL_FLOAT:
                 glUniform1fv(info->location_, count, data);
@@ -1196,7 +1196,7 @@ void Graphics::SetShaderParameter(StringHash param, const Vector2& vector)
             }
 
             // Check the uniform type to avoid mismatch
-            switch (info->type_)
+            switch (info->glType_)
             {
             case GL_FLOAT:
                 glUniform1fv(info->location_, 1, vector.Data());
@@ -1250,7 +1250,7 @@ void Graphics::SetShaderParameter(StringHash param, const Vector3& vector)
             }
 
             // Check the uniform type to avoid mismatch
-            switch (info->type_)
+            switch (info->glType_)
             {
             case GL_FLOAT:
                 glUniform1fv(info->location_, 1, vector.Data());
@@ -1308,7 +1308,7 @@ void Graphics::SetShaderParameter(StringHash param, const Vector4& vector)
             }
 
             // Check the uniform type to avoid mismatch
-            switch (info->type_)
+            switch (info->glType_)
             {
             case GL_FLOAT:
                 glUniform1fv(info->location_, 1, vector.Data());

+ 4 - 15
Source/Urho3D/Graphics/OpenGL/OGLShaderProgram.cpp

@@ -44,19 +44,6 @@ static const char* shaderParameterGroups[] = {
     "custom"
 };
 
-static const char* elementSemanticNames[] =
-{
-    "POS",
-    "NORMAL",
-    "BINORMAL",
-    "TANGENT",
-    "TEXCOORD",
-    "COLOR",
-    "BLENDWEIGHT",
-    "BLENDINDICES",
-    "OBJECTINDEX"
-};
-
 static unsigned NumberPostfix(const String& str)
 {
     for (unsigned i = 0; i < str.Length(); ++i)
@@ -182,7 +169,7 @@ bool ShaderProgram::Link()
         // Go in reverse order so that "binormal" is detected before "normal"
         for (unsigned j = MAX_VERTEX_ELEMENT_SEMANTICS - 1; j < MAX_VERTEX_ELEMENT_SEMANTICS; --j)
         {
-            if (name.Contains(elementSemanticNames[j], false))
+            if (name.Contains(ShaderVariation::elementSemanticNames[j], false))
             {
                 semantic = (VertexElementSemantic)j;
                 unsigned index = NumberPostfix(name);
@@ -287,8 +274,10 @@ bool ShaderProgram::Link()
             // Store constant uniform
             String paramName = name.Substring(1);
             ShaderParameter newParam;
-            newParam.type_ = type;
+            newParam.name_ = paramName;
+            newParam.glType_ = type;
             newParam.location_ = location;
+            newParam.bufferPtr_ = 0;
 
 #ifndef GL_ES_VERSION_2_0
             // If running OpenGL 3, the uniform may be inside a constant buffer

+ 1 - 18
Source/Urho3D/Graphics/OpenGL/OGLShaderProgram.h

@@ -26,30 +26,13 @@
 #include "../../Container/RefCounted.h"
 #include "../../Graphics/GPUObject.h"
 #include "../../Graphics/GraphicsDefs.h"
+#include "../../Graphics/ShaderVariation.h"
 
 namespace Urho3D
 {
 
 class ConstantBuffer;
 class Graphics;
-class ShaderVariation;
-
-/// %Shader parameter definition.
-struct ShaderParameter
-{
-    /// Construct with defaults.
-    ShaderParameter() :
-        bufferPtr_(0)
-    {
-    }
-
-    /// Uniform location or byte offset in constant buffer.
-    int location_;
-    /// Element type.
-    unsigned type_;
-    /// Constant buffer pointer.
-    ConstantBuffer* bufferPtr_;
-};
 
 /// Linked shader program on the GPU.
 class URHO3D_API ShaderProgram : public RefCounted, public GPUObject

+ 11 - 20
Source/Urho3D/Graphics/OpenGL/OGLShaderVariation.cpp

@@ -34,17 +34,18 @@
 namespace Urho3D
 {
 
-ShaderVariation::ShaderVariation(Shader* owner, ShaderType type) :
-    GPUObject(owner->GetSubsystem<Graphics>()),
-    owner_(owner),
-    type_(type)
+const char* ShaderVariation::elementSemanticNames[] =
 {
-}
-
-ShaderVariation::~ShaderVariation()
-{
-    Release();
-}
+    "POS",
+    "NORMAL",
+    "BINORMAL",
+    "TANGENT",
+    "TEXCOORD",
+    "COLOR",
+    "BLENDWEIGHT",
+    "BLENDINDICES",
+    "OBJECTINDEX"
+};
 
 void ShaderVariation::OnDeviceLost()
 {
@@ -186,19 +187,9 @@ bool ShaderVariation::Create()
     return object_.name_ != 0;
 }
 
-void ShaderVariation::SetName(const String& name)
-{
-    name_ = name;
-}
-
 void ShaderVariation::SetDefines(const String& defines)
 {
     defines_ = defines;
 }
 
-Shader* ShaderVariation::GetOwner() const
-{
-    return owner_;
-}
-
 }

+ 0 - 88
Source/Urho3D/Graphics/OpenGL/OGLShaderVariation.h

@@ -1,88 +0,0 @@
-//
-// Copyright (c) 2008-2016 the Urho3D project.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-
-#pragma once
-
-#include "../../Container/RefCounted.h"
-#include "../../Container/ArrayPtr.h"
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-
-namespace Urho3D
-{
-
-class Shader;
-class ShaderProgram;
-
-/// Vertex or pixel shader on the GPU.
-class URHO3D_API ShaderVariation : public RefCounted, public GPUObject
-{
-public:
-    /// Construct.
-    ShaderVariation(Shader* owner, ShaderType type);
-    /// Destruct.
-    virtual ~ShaderVariation();
-
-    /// Mark the GPU resource destroyed on context destruction.
-    virtual void OnDeviceLost();
-    /// Release the shader.
-    virtual void Release();
-
-    /// Compile the shader. Return true if successful.
-    bool Create();
-    /// Set name.
-    void SetName(const String& name);
-    /// Set defines.
-    void SetDefines(const String& defines);
-
-    /// Return the owner resource.
-    Shader* GetOwner() const;
-
-    /// Return shader type.
-    ShaderType GetShaderType() const { return type_; }
-
-    /// Return name.
-    const String& GetName() const { return name_; }
-
-    /// Return defines.
-    const String& GetDefines() const { return defines_; }
-
-    /// Return full shader name.
-    String GetFullName() const { return name_ + "(" + defines_ + ")"; }
-
-    /// Return compile error/warning string.
-    const String& GetCompilerOutput() const { return compilerOutput_; }
-
-private:
-    /// Shader this variation belongs to.
-    WeakPtr<Shader> owner_;
-    /// Shader type.
-    ShaderType type_;
-    /// Shader name.
-    String name_;
-    /// Defines to use in compiling.
-    String defines_;
-    /// Shader compile error string.
-    String compilerOutput_;
-};
-
-}

+ 2 - 0
Source/Urho3D/Graphics/ShaderProgram.h

@@ -22,6 +22,8 @@
 
 #pragma once
 
+// Note: ShaderProgram class is purposefully API-specific. It should not be used by Urho3D client applications.
+
 #if defined(URHO3D_OPENGL)
 #include "OpenGL/OGLShaderProgram.h"
 #elif defined(URHO3D_D3D11)

+ 61 - 0
Source/Urho3D/Graphics/ShaderVariation.cpp

@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "../Precompiled.h"
+
+#include "../Graphics/Graphics.h"
+#include "../Graphics/Shader.h"
+#include "../Graphics/ShaderVariation.h"
+
+#include "../DebugNew.h"
+
+namespace Urho3D
+{
+
+ShaderVariation::ShaderVariation(Shader* owner, ShaderType type) :
+    GPUObject(owner->GetSubsystem<Graphics>()),
+    owner_(owner),
+    type_(type),
+    elementHash_(0)
+{
+    for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
+        useTextureUnit_[i] = false;
+    for (unsigned i = 0; i < MAX_SHADER_PARAMETER_GROUPS; ++i)
+        constantBufferSizes_[i] = 0;
+}
+
+ShaderVariation::~ShaderVariation()
+{
+    Release();
+}
+
+void ShaderVariation::SetName(const String& name)
+{
+    name_ = name;
+}
+
+Shader* ShaderVariation::GetOwner() const
+{
+    return owner_;
+}
+
+}

+ 146 - 7
Source/Urho3D/Graphics/ShaderVariation.h

@@ -22,10 +22,149 @@
 
 #pragma once
 
-#if defined(URHO3D_OPENGL)
-#include "OpenGL/OGLShaderVariation.h"
-#elif defined(URHO3D_D3D11)
-#include "Direct3D11/D3D11ShaderVariation.h"
-#else
-#include "Direct3D9/D3D9ShaderVariation.h"
-#endif
+#include "../Container/HashMap.h"
+#include "../Container/RefCounted.h"
+#include "../Container/ArrayPtr.h"
+#include "../Graphics/GPUObject.h"
+#include "../Graphics/GraphicsDefs.h"
+
+namespace Urho3D
+{
+
+class ConstantBuffer;
+class Shader;
+
+/// %Shader parameter definition.
+struct ShaderParameter
+{
+    /// %Shader type.
+    ShaderType type_;
+    /// Name of the parameter.
+    String name_;
+    /// Constant buffer index.
+    unsigned buffer_;
+
+    union
+    {
+        /// Offset in constant buffer.
+        unsigned offset_;
+        /// OpenGL Uniform location.
+        int location_;
+        /// Direct3D9 register index.
+        unsigned register_;
+    };
+
+    union
+    {
+        /// Parameter size.
+        unsigned size_;
+        /// Parameter OpenGL type.
+        unsigned glType_;
+        /// Number of registers on Direct3D9.
+        unsigned regCount_;
+    };
+
+    /// Constant buffer pointer. Defined only in shader programs.
+    ConstantBuffer* bufferPtr_;
+};
+
+/// Vertex or pixel shader on the GPU.
+class URHO3D_API ShaderVariation : public RefCounted, public GPUObject
+{
+public:
+    /// Construct.
+    ShaderVariation(Shader* owner, ShaderType type);
+    /// Destruct.
+    virtual ~ShaderVariation();
+
+    /// Mark the GPU resource destroyed on graphics context destruction.
+    virtual void OnDeviceLost();
+    /// Release the shader.
+    virtual void Release();
+
+    /// Compile the shader. Return true if successful.
+    bool Create();
+    /// Set name.
+    void SetName(const String& name);
+    /// Set defines.
+    void SetDefines(const String& defines);
+
+    /// Return the owner resource.
+    Shader* GetOwner() const;
+
+    /// Return shader type.
+    ShaderType GetShaderType() const { return type_; }
+
+    /// Return shader name.
+    const String& GetName() const { return name_; }
+
+    /// Return full shader name.
+    String GetFullName() const { return name_ + "(" + defines_ + ")"; }
+
+    /// Return whether uses a parameter. Not applicable on OpenGL, where this information is contained in ShaderProgram instead.
+    bool HasParameter(StringHash param) const { return parameters_.Contains(param); }
+
+    /// Return whether uses a texture unit (only for pixel shaders.) Not applicable on OpenGL, where this information is contained in ShaderProgram instead.
+    bool HasTextureUnit(TextureUnit unit) const { return useTextureUnit_[unit]; }
+
+    /// Return all parameter definitions. Not applicable on OpenGL, where this information is contained in ShaderProgram instead.
+    const HashMap<StringHash, ShaderParameter>& GetParameters() const { return parameters_; }
+
+    /// Return vertex element hash.
+    unsigned long long GetElementHash() const { return elementHash_; }
+
+    /// Return shader bytecode. Stored persistently on Direct3D11 only.
+    const PODVector<unsigned char>& GetByteCode() const { return byteCode_; }
+
+    /// Return defines.
+    const String& GetDefines() const { return defines_; }
+
+    /// Return compile error/warning string.
+    const String& GetCompilerOutput() const { return compilerOutput_; }
+
+    /// Return constant buffer data sizes.
+    const unsigned* GetConstantBufferSizes() const { return &constantBufferSizes_[0]; }
+
+    /// Return defines with the CLIPPLANE define appended. Used internally on Direct3D11 only, will be empty on other APIs.
+    const String& GetDefinesClipPlane() { return definesClipPlane_; }
+
+    /// D3D11 vertex semantic names. Used internally.
+    static const char* elementSemanticNames[];
+
+private:
+    /// Load bytecode from a file. Return true if successful.
+    bool LoadByteCode(const String& binaryShaderName);
+    /// Compile from source. Return true if successful.
+    bool Compile();
+    /// Inspect the constant parameters and input layout (if applicable) from the shader bytecode.
+    void ParseParameters(unsigned char* bufData, unsigned bufSize);
+    /// Save bytecode to a file.
+    void SaveByteCode(const String& binaryShaderName);
+    /// Calculate constant buffer sizes from parameters.
+    void CalculateConstantBufferSizes();
+
+    /// Shader this variation belongs to.
+    WeakPtr<Shader> owner_;
+    /// Shader type.
+    ShaderType type_;
+    /// Vertex element hash for vertex shaders. Zero for pixel shaders. Note that hashing is different than vertex buffers.
+    unsigned long long elementHash_;
+    /// Shader parameters.
+    HashMap<StringHash, ShaderParameter> parameters_;
+    /// Texture unit use flags.
+    bool useTextureUnit_[MAX_TEXTURE_UNITS];
+    /// Constant buffer sizes. 0 if a constant buffer slot is not in use.
+    unsigned constantBufferSizes_[MAX_SHADER_PARAMETER_GROUPS];
+    /// Shader bytecode. Needed for inspecting the input signature and parameters. Not used on OpenGL.
+    PODVector<unsigned char> byteCode_;
+    /// Shader name.
+    String name_;
+    /// Defines to use in compiling.
+    String defines_;
+    /// Defines to use in compiling + CLIPPLANE define appended. Used only on Direct3D11.
+    String definesClipPlane_;
+    /// Shader compile error string.
+    String compilerOutput_;
+};
+
+}

+ 2 - 5
Source/Urho3D/Graphics/View.cpp

@@ -603,11 +603,8 @@ void View::Render()
 
     // It is possible, though not recommended, that the same camera is used for multiple main views. Set automatic aspect ratio
     // to ensure correct projection will be used
-    if (camera_)
-    {
-        if (camera_->GetAutoAspectRatio())
-            camera_->SetAspectRatioInternal((float)(viewSize_.x_) / (float)(viewSize_.y_));
-    }
+    if (camera_ && camera_->GetAutoAspectRatio())
+        camera_->SetAspectRatioInternal((float)(viewSize_.x_) / (float)(viewSize_.y_));
 
     // Bind the face selection and indirection cube maps for point light shadows
 #ifndef GL_ES_VERSION_2_0