Browse Source

Direct3D9 updates

Josh Engebretson 10 years ago
parent
commit
21bf0cd3f7

+ 124 - 253
Source/Atomic/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -37,6 +37,7 @@
 #include "../../Resource/ResourceCache.h"
 #include "../../Graphics/Shader.h"
 #include "../../Graphics/ShaderPrecache.h"
+#include "../../Graphics/ShaderProgram.h"
 #include "../../Graphics/ShaderVariation.h"
 #include "../../Graphics/Technique.h"
 #include "../../Graphics/Texture2D.h"
@@ -233,6 +234,8 @@ static HWND GetWindowHandle(SDL_Window* window)
 
 static unsigned readableDepthFormat = 0;
 
+const Vector2 Graphics::pixelUVOffset(0.5f, 0.5f);
+
 Graphics::Graphics(Context* context) :
     Object(context),
     impl_(new GraphicsImpl()),
@@ -253,20 +256,18 @@ Graphics::Graphics(Context* context) :
     queryIssued_(false),
     lightPrepassSupport_(false),
     deferredSupport_(false),
-    hardwareShadowSupport_(false),
-    streamOffsetSupport_(false),
+    instancingSupport_(false),
     sRGBSupport_(false),
     sRGBWriteSupport_(false),
-    hasSM3_(false),
-    forceSM2_(false),
     numPrimitives_(0),
     numBatches_(0),
     maxScratchBufferRequest_(0),
     defaultTextureFilterMode_(FILTER_TRILINEAR),
-    currentShaderParameters_(0),
+    shaderProgram_(0),
     shaderPath_("Shaders/HLSL/"),
     shaderExtension_(".hlsl"),
-    orientations_("LandscapeLeft LandscapeRight")
+    orientations_("LandscapeLeft LandscapeRight"),
+    apiName_("D3D9")
 {
     SetTextureUnitMappings();
     
@@ -283,7 +284,7 @@ Graphics::~Graphics()
         MutexLock lock(gpuObjectMutex_);
 
         // Release all GPU objects that still exist
-        for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
+        for (PODVector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
             (*i)->Release();
         gpuObjects_.Clear();
     }
@@ -396,7 +397,6 @@ void Graphics::RaiseWindow()
     if (impl_->window_)
         SDL_RaiseWindow(impl_->window_);
 }
-
 bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, bool resizable, bool vsync, bool tripleBuffer, int multiSample)
 {
     PROFILE(SetScreenMode);
@@ -628,7 +628,7 @@ void Graphics::Close()
     }
 }
 
-bool Graphics::TakeScreenShot(Image* destImage)
+bool Graphics::TakeScreenShot(Image& destImage)
 {
     PROFILE(TakeScreenShot);
     
@@ -696,8 +696,8 @@ bool Graphics::TakeScreenShot(Image* destImage)
         return false;
     }
     
-    destImage->SetSize(width_, height_, 3);
-    unsigned char* destData = destImage->GetData();
+    destImage.SetSize(width_, height_, 3);
+    unsigned char* destData = destImage.GetData();
     
     if (surfaceDesc.Format == D3DFMT_R5G6B5)
     {
@@ -797,9 +797,6 @@ bool Graphics::BeginFrame()
     for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
         SetTexture(i, 0);
     
-    // Cleanup stream frequencies from previous frame
-    ResetStreamFrequencies();
-    
     numPrimitives_ = 0;
     numBatches_ = 0;
     
@@ -965,7 +962,7 @@ void Graphics::SetVertexBuffer(VertexBuffer* buffer)
 bool Graphics::SetVertexBuffers(const PODVector<VertexBuffer*>& buffers, const PODVector<unsigned>&
     elementMasks, unsigned instanceOffset)
 {
-   if (buffers.Size() > MAX_VERTEX_STREAMS)
+    if (buffers.Size() > MAX_VERTEX_STREAMS)
     {
         LOGERROR("Too many vertex buffers");
         return false;
@@ -1039,73 +1036,7 @@ bool Graphics::SetVertexBuffers(const PODVector<VertexBuffer*>& buffers, const P
 bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers, const PODVector<unsigned>&
     elementMasks, unsigned instanceOffset)
 {
-   if (buffers.Size() > MAX_VERTEX_STREAMS)
-    {
-        LOGERROR("Too many vertex buffers");
-        return false;
-    }
-    if (buffers.Size() != elementMasks.Size())
-    {
-        LOGERROR("Amount of element masks and vertex buffers does not match");
-        return false;
-    }
-    
-    unsigned long long hash = 0;
-    for (unsigned i = 0; i < buffers.Size(); ++i)
-    {
-        if (!buffers[i])
-            continue;
-        
-        hash |= buffers[i]->GetBufferHash(i, elementMasks[i]);
-    }
-    
-    if (hash)
-    {
-        if (!vertexDeclarations_.Contains(hash))
-        {
-            SharedPtr<VertexDeclaration> newDeclaration(new VertexDeclaration(this, buffers, elementMasks));
-            if (!newDeclaration->GetDeclaration())
-            {
-                LOGERROR("Failed to create vertex declaration");
-                return false;
-            }
-            
-            vertexDeclarations_[hash] = newDeclaration;
-        }
-        
-        VertexDeclaration* declaration = vertexDeclarations_[hash];
-        if (declaration != vertexDeclaration_)
-        {
-            impl_->device_->SetVertexDeclaration(declaration->GetDeclaration());
-            vertexDeclaration_ = declaration;
-        }
-    }
-    
-    for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
-    {
-        VertexBuffer* buffer = 0;
-        unsigned offset = 0;
-        
-        if (i < buffers.Size())
-        {
-            buffer = buffers[i];
-            if (buffer && buffer->GetElementMask() & MASK_INSTANCEMATRIX1)
-                offset = instanceOffset * buffer->GetVertexSize();
-        }
-        
-        if (buffer != vertexBuffers_[i] || offset != streamOffsets_[i])
-        {
-            if (buffer)
-                impl_->device_->SetStreamSource(i, (IDirect3DVertexBuffer9*)buffer->GetGPUObject(), offset, buffer->GetVertexSize());
-            else
-                impl_->device_->SetStreamSource(i, 0, 0, 0);
-            
-            vertexBuffers_[i] = buffer;
-            streamOffsets_[i] = offset;
-        }
-    }
-    
-    return true;
+    return SetVertexBuffers(reinterpret_cast<const PODVector<VertexBuffer*>&>(buffers), elementMasks, instanceOffset);
 }
 
 void Graphics::SetIndexBuffer(IndexBuffer* buffer)
@@ -1193,29 +1124,17 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
     if (vertexShader_ && pixelShader_)
     {
         Pair<ShaderVariation*, ShaderVariation*> key = MakePair(vertexShader_, pixelShader_);
-        HashMap<Pair<ShaderVariation*, ShaderVariation*>, HashMap<StringHash, Pair<ShaderType, unsigned> > >::Iterator i =
-            shaderParameters_.Find(key);
-        if (i != shaderParameters_.End())
-            currentShaderParameters_ = &i->second_;
+        ShaderProgramMap::Iterator i = shaderPrograms_.Find(key);
+        if (i != shaderPrograms_.End())
+            shaderProgram_ = i->second_.Get();
         else
         {
-            HashMap<StringHash, Pair<ShaderType, unsigned> >& parameters = shaderParameters_[key];
-
-            const HashMap<StringHash, ShaderParameter>& vsParams = vertexShader_->GetParameters();
-            for (HashMap<StringHash, ShaderParameter>::ConstIterator i = vsParams.Begin(); i != vsParams.End(); ++i)
-                parameters[i->first_] = MakePair(i->second_.type_, i->second_.register_);
-
-            const HashMap<StringHash, ShaderParameter>& psParams = pixelShader_->GetParameters();
-            for (HashMap<StringHash, ShaderParameter>::ConstIterator i = psParams.Begin(); i != psParams.End(); ++i)
-                parameters[i->first_] = MakePair(i->second_.type_, i->second_.register_);
-
-            // Optimize shader parameter lookup by rehashing to next power of two
-            parameters.Rehash(NextPowerOfTwo(parameters.Size()));
-            currentShaderParameters_ = &parameters;
+            ShaderProgram* newProgram = shaderPrograms_[key] = new ShaderProgram(vertexShader_, pixelShader_);
+            shaderProgram_ = newProgram;
         }
     }
     else
-        currentShaderParameters_ = 0;
+        shaderProgram_ = 0;
 
     // Store shader combination if shader dumping in progress
     if (shaderPrecache_)
@@ -1224,161 +1143,148 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
 
 void Graphics::SetShaderParameter(StringHash param, const float* data, unsigned count)
 {
-    HashMap<StringHash, Pair<ShaderType, unsigned> >::Iterator i;
-    if (!currentShaderParameters_ || (i = currentShaderParameters_->Find(param)) == currentShaderParameters_->End())
+    HashMap<StringHash, ShaderParameter>::Iterator i;
+    if (!shaderProgram_ || (i = shaderProgram_->parameters_.Find(param)) == shaderProgram_->parameters_.End())
         return;
     
-    if (i->second_.first_ == VS)
-        impl_->device_->SetVertexShaderConstantF(i->second_.second_, data, count / 4);
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, data, count / 4);
     else
-        impl_->device_->SetPixelShaderConstantF(i->second_.second_, data, count / 4);
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, data, count / 4);
 }
 
 void Graphics::SetShaderParameter(StringHash param, float value)
 {
-    HashMap<StringHash, Pair<ShaderType, unsigned> >::Iterator i;
-    if (!currentShaderParameters_ || (i = currentShaderParameters_->Find(param)) == currentShaderParameters_->End())
+    HashMap<StringHash, ShaderParameter>::Iterator i;
+    if (!shaderProgram_ || (i = shaderProgram_->parameters_.Find(param)) == shaderProgram_->parameters_.End())
         return;
     
-    float data[4];
-    
-    data[0] = value;
-    data[1] = 0.0f;
-    data[2] = 0.0f;
-    data[3] = 0.0f;
+    static Vector4 data(Vector4::ZERO);
+    data.x_ = value;
     
-    if (i->second_.first_ == VS)
-        impl_->device_->SetVertexShaderConstantF(i->second_.second_, &data[0], 1);
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, &data.x_, 1);
     else
-        impl_->device_->SetPixelShaderConstantF(i->second_.second_, &data[0], 1);
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, &data.x_, 1);
 }
 
 void Graphics::SetShaderParameter(StringHash param, bool value)
 {
     /// \todo Bool constants possibly have no effect on Direct3D9
-    HashMap<StringHash, Pair<ShaderType, unsigned> >::Iterator i;
-    if (!currentShaderParameters_ || (i = currentShaderParameters_->Find(param)) == currentShaderParameters_->End())
+    HashMap<StringHash, ShaderParameter>::Iterator i;
+    if (!shaderProgram_ || (i = shaderProgram_->parameters_.Find(param)) == shaderProgram_->parameters_.End())
         return;
 
     BOOL data = value;
 
-    if (i->second_.first_ == VS)
-        impl_->device_->SetVertexShaderConstantB(i->second_.second_, &data, 1);
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantB(i->second_.register_, &data, 1);
     else
-        impl_->device_->SetPixelShaderConstantB(i->second_.second_, &data, 1);
+        impl_->device_->SetPixelShaderConstantB(i->second_.register_, &data, 1);
 }
 
 void Graphics::SetShaderParameter(StringHash param, const Color& color)
 {
-    HashMap<StringHash, Pair<ShaderType, unsigned> >::Iterator i;
-    if (!currentShaderParameters_ || (i = currentShaderParameters_->Find(param)) == currentShaderParameters_->End())
+    HashMap<StringHash, ShaderParameter>::Iterator i;
+    if (!shaderProgram_ || (i = shaderProgram_->parameters_.Find(param)) == shaderProgram_->parameters_.End())
         return;
     
-    if (i->second_.first_ == VS)
-        impl_->device_->SetVertexShaderConstantF(i->second_.second_, color.Data(), 1);
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, color.Data(), 1);
     else
-        impl_->device_->SetPixelShaderConstantF(i->second_.second_, color.Data(), 1);
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, color.Data(), 1);
 }
 
 void Graphics::SetShaderParameter(StringHash param, const Vector2& vector)
 {
-    HashMap<StringHash, Pair<ShaderType, unsigned> >::Iterator i;
-    if (!currentShaderParameters_ || (i = currentShaderParameters_->Find(param)) == currentShaderParameters_->End())
+    HashMap<StringHash, ShaderParameter>::Iterator i;
+    if (!shaderProgram_ || (i = shaderProgram_->parameters_.Find(param)) == shaderProgram_->parameters_.End())
         return;
     
-    float data[4];
+    static Vector4 data(Vector4::ZERO);
+    data.x_ = vector.x_;
+    data.y_ = vector.y_;
     
-    data[0] = vector.x_;
-    data[1] = vector.y_;
-    data[2] = 0.0f;
-    data[3] = 0.0f;
-    
-    if (i->second_.first_ == VS)
-        impl_->device_->SetVertexShaderConstantF(i->second_.second_, &data[0], 1);
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, &data.x_, 1);
     else
-        impl_->device_->SetPixelShaderConstantF(i->second_.second_, &data[0], 1);
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, &data.x_, 1);
 }
 
 void Graphics::SetShaderParameter(StringHash param, const Matrix3& matrix)
 {
-    HashMap<StringHash, Pair<ShaderType, unsigned> >::Iterator i;
-    if (!currentShaderParameters_ || (i = currentShaderParameters_->Find(param)) == currentShaderParameters_->End())
+    HashMap<StringHash, ShaderParameter>::Iterator i;
+    if (!shaderProgram_ || (i = shaderProgram_->parameters_.Find(param)) == shaderProgram_->parameters_.End())
         return;
     
-    float data[12];
-    
-    data[0] = matrix.m00_;
-    data[1] = matrix.m01_;
-    data[2] = matrix.m02_;
-    data[3] = 0.0f;
-    data[4] = matrix.m10_;
-    data[5] = matrix.m11_;
-    data[6] = matrix.m12_;
-    data[7] = 0.0f;
-    data[8] = matrix.m20_;
-    data[9] = matrix.m21_;
-    data[10] = matrix.m22_;
-    data[11] = 0.0f;
-    
-    if (i->second_.first_ == VS)
-        impl_->device_->SetVertexShaderConstantF(i->second_.second_, &data[0], 3);
+    static Matrix3x4 data(Matrix3x4::ZERO);
+    data.m00_ = matrix.m00_;
+    data.m01_ = matrix.m01_;
+    data.m02_ = matrix.m02_;
+    data.m10_ = matrix.m10_;
+    data.m11_ = matrix.m11_;
+    data.m12_ = matrix.m12_;
+    data.m20_ = matrix.m20_;
+    data.m21_ = matrix.m21_;
+    data.m22_ = matrix.m22_;
+    
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, &data.m00_, 3);
     else
-        impl_->device_->SetPixelShaderConstantF(i->second_.second_, &data[0], 3);
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, &data.m00_, 3);
 }
 
 void Graphics::SetShaderParameter(StringHash param, const Vector3& vector)
 {
-    HashMap<StringHash, Pair<ShaderType, unsigned> >::Iterator i;
-    if (!currentShaderParameters_ || (i = currentShaderParameters_->Find(param)) == currentShaderParameters_->End())
+    HashMap<StringHash, ShaderParameter>::Iterator i;
+    if (!shaderProgram_ || (i = shaderProgram_->parameters_.Find(param)) == shaderProgram_->parameters_.End())
         return;
     
-    float data[4];
-    
-    data[0] = vector.x_;
-    data[1] = vector.y_;
-    data[2] = vector.z_;
-    data[3] = 0.0f;
-    
-    if (i->second_.first_ == VS)
-        impl_->device_->SetVertexShaderConstantF(i->second_.second_, &data[0], 1);
+    static Vector4 data(Vector4::ZERO);
+    data.x_ = vector.x_;
+    data.y_ = vector.y_;
+    data.z_ = vector.z_;
+
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, &data.x_, 1);
     else
-        impl_->device_->SetPixelShaderConstantF(i->second_.second_, &data[0], 1);
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, &data.x_, 1);
 }
 
 void Graphics::SetShaderParameter(StringHash param, const Matrix4& matrix)
 {
-    HashMap<StringHash, Pair<ShaderType, unsigned> >::Iterator i;
-    if (!currentShaderParameters_ || (i = currentShaderParameters_->Find(param)) == currentShaderParameters_->End())
+    HashMap<StringHash, ShaderParameter>::Iterator i;
+    if (!shaderProgram_ || (i = shaderProgram_->parameters_.Find(param)) == shaderProgram_->parameters_.End())
         return;
     
-    if (i->second_.first_ == VS)
-        impl_->device_->SetVertexShaderConstantF(i->second_.second_, matrix.Data(), 4);
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, matrix.Data(), 4);
     else
-        impl_->device_->SetPixelShaderConstantF(i->second_.second_, matrix.Data(), 4);
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, matrix.Data(), 4);
 }
 
 void Graphics::SetShaderParameter(StringHash param, const Vector4& vector)
 {
-    HashMap<StringHash, Pair<ShaderType, unsigned> >::Iterator i;
-    if (!currentShaderParameters_ || (i = currentShaderParameters_->Find(param)) == currentShaderParameters_->End())
+    HashMap<StringHash, ShaderParameter>::Iterator i;
+    if (!shaderProgram_ || (i = shaderProgram_->parameters_.Find(param)) == shaderProgram_->parameters_.End())
         return;
     
-    if (i->second_.first_ == VS)
-        impl_->device_->SetVertexShaderConstantF(i->second_.second_, vector.Data(), 1);
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, vector.Data(), 1);
     else
-        impl_->device_->SetPixelShaderConstantF(i->second_.second_, vector.Data(), 1);
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, vector.Data(), 1);
 }
 
 void Graphics::SetShaderParameter(StringHash param, const Matrix3x4& matrix)
 {
-    HashMap<StringHash, Pair<ShaderType, unsigned> >::Iterator i;
-    if (!currentShaderParameters_ || (i = currentShaderParameters_->Find(param)) == currentShaderParameters_->End())
+    HashMap<StringHash, ShaderParameter>::Iterator i;
+    if (!shaderProgram_ || (i = shaderProgram_->parameters_.Find(param)) == shaderProgram_->parameters_.End())
         return;
     
-    if (i->second_.first_ == VS)
-        impl_->device_->SetVertexShaderConstantF(i->second_.second_, matrix.Data(), 3);
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, matrix.Data(), 3);
     else
-        impl_->device_->SetPixelShaderConstantF(i->second_.second_, matrix.Data(), 3);
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, matrix.Data(), 3);
 }
 
 void Graphics::SetShaderParameter(StringHash param, const Variant& value)
@@ -1440,7 +1346,7 @@ bool Graphics::NeedParameterUpdate(ShaderParameterGroup group, const void* sourc
 
 bool Graphics::HasShaderParameter(StringHash param)
 {
-    return currentShaderParameters_ && currentShaderParameters_->Find(param) != currentShaderParameters_->End();
+    return shaderProgram_ && shaderProgram_->parameters_.Find(param) != shaderProgram_->parameters_.End();
 }
 
 bool Graphics::HasTextureUnit(TextureUnit unit)
@@ -1462,7 +1368,7 @@ void Graphics::ClearParameterSources()
 void Graphics::ClearTransformSources()
 {
     shaderParameterSources_[SP_CAMERA] = (const void*)M_MAX_UNSIGNED;
-    shaderParameterSources_[SP_OBJECTTRANSFORM] = (const void*)M_MAX_UNSIGNED;
+    shaderParameterSources_[SP_OBJECT] = (const void*)M_MAX_UNSIGNED;
 }
 
 void Graphics::SetTexture(unsigned index, Texture* texture)
@@ -1796,15 +1702,6 @@ void Graphics::SetDepthWrite(bool enable)
     }
 }
 
-void Graphics::SetDrawAntialiased(bool enable)
-{
-    if (enable != drawAntialiased_)
-    {
-        impl_->device_->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, enable ? TRUE : FALSE);
-        drawAntialiased_ = enable;
-    }
-}
-
 void Graphics::SetFillMode(FillMode mode)
 {
     if (mode != fillMode_)
@@ -1971,35 +1868,6 @@ void Graphics::SetClipPlane(bool enable, const Plane& clipPlane, const Matrix3x4
     }
 }
 
-void Graphics::SetStreamFrequency(unsigned index, unsigned frequency)
-{
-    if (index < MAX_VERTEX_STREAMS && streamFrequencies_[index] != frequency)
-    {
-        impl_->device_->SetStreamSourceFreq(index, frequency);
-        streamFrequencies_[index] = frequency;
-    }
-}
-
-void Graphics::ResetStreamFrequencies()
-{
-    for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
-    {
-        if (streamFrequencies_[i] != 1)
-        {
-            impl_->device_->SetStreamSourceFreq(i, 1);
-            streamFrequencies_[i] = 1;
-        }
-    }
-}
-
-void Graphics::SetForceSM2(bool enable)
-{
-    if (!IsInitialized())
-        forceSM2_ = enable;
-    else
-        LOGERROR("Force Shader Model 2 can not be changed after setting the initial screen mode");
-}
-
 void Graphics::BeginDumpShaders(const String& fileName)
 {
     shaderPrecache_ = new ShaderPrecache(context_, fileName);
@@ -2166,11 +2034,6 @@ RenderSurface* Graphics::GetRenderTarget(unsigned index) const
     return index < MAX_RENDERTARGETS ? renderTargets_[index] : 0;
 }
 
-unsigned Graphics::GetStreamFrequency(unsigned index) const
-{
-    return index < MAX_VERTEX_STREAMS ? streamFrequencies_[index] : 0;
-}
-
 IntVector2 Graphics::GetRenderTargetDimensions() const
 {
     int width, height;
@@ -2225,7 +2088,7 @@ void Graphics::WindowResized()
 
 void Graphics::WindowMoved()
 {
-    if (!impl_->device_ || !impl_->window_)
+    if (!impl_->device_ || !impl_->window_ || fullscreen_)
         return;
 
     int newX, newY;
@@ -2354,19 +2217,18 @@ void Graphics::CleanupScratchBuffers()
     maxScratchBufferRequest_ = 0;
 }
 
-void Graphics::CleanupShaderParameters(ShaderVariation* variation)
+void Graphics::CleanupShaderPrograms(ShaderVariation* variation)
 {
-    for (HashMap<Pair<ShaderVariation*, ShaderVariation*>, HashMap<StringHash, Pair<ShaderType, unsigned> > >::Iterator i =
-        shaderParameters_.Begin(); i != shaderParameters_.End();)
+    for (ShaderProgramMap::Iterator i = shaderPrograms_.Begin(); i != shaderPrograms_.End();)
     {
         if (i->first_.first_ == variation || i->first_.second_ == variation)
-            i = shaderParameters_.Erase(i);
+            i = shaderPrograms_.Erase(i);
         else
             ++i;
     }
 
     if (vertexShader_ == variation || pixelShader_ == variation)
-        currentShaderParameters_ = 0;
+        shaderProgram_ = 0;
 }
 
 unsigned Graphics::GetAlphaFormat()
@@ -2489,6 +2351,27 @@ unsigned Graphics::GetFormat(const String& formatName)
     return GetRGBFormat();
 }
 
+void Graphics::SetStreamFrequency(unsigned index, unsigned frequency)
+{
+    if (index < MAX_VERTEX_STREAMS && streamFrequencies_[index] != frequency)
+    {
+        impl_->device_->SetStreamSourceFreq(index, frequency);
+        streamFrequencies_[index] = frequency;
+    }
+}
+
+void Graphics::ResetStreamFrequencies()
+{
+    for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
+    {
+        if (streamFrequencies_[i] != 1)
+        {
+            impl_->device_->SetStreamSourceFreq(i, 1);
+            streamFrequencies_[i] = 1;
+        }
+    }
+}
+
 bool Graphics::OpenWindow(int width, int height, bool resizable, bool borderless)
 {
     if (!externalWindow_)
@@ -2574,9 +2457,9 @@ bool Graphics::CreateInterface()
         return false;
     }
     
-    if (impl_->deviceCaps_.PixelShaderVersion < D3DPS_VERSION(2, 0))
+    if (impl_->deviceCaps_.PixelShaderVersion < D3DPS_VERSION(3, 0))
     {
-        LOGERROR("Shader model 2.0 display adapter is required");
+        LOGERROR("Shader model 3.0 display adapter is required");
         return false;
     }
     
@@ -2626,8 +2509,7 @@ void Graphics::CheckFeatureSupport()
     lightPrepassSupport_ = false;
     deferredSupport_ = false;
     hardwareShadowSupport_ = false;
-    streamOffsetSupport_ = false;
-    hasSM3_ = false;
+    instancingSupport_ = false;
     readableDepthFormat = 0;
     
     // Check hardware shadow map support: prefer NVIDIA style hardware depth compared shadow maps if available
@@ -2684,14 +2566,6 @@ void Graphics::CheckFeatureSupport()
         dummyColorFormat_ = D3DFMT_R5G6B5;
     else if (impl_->CheckFormatSupport(D3DFMT_A4R4G4B4, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE))
         dummyColorFormat_ = D3DFMT_A4R4G4B4;
-        
-    // Check for Shader Model 3
-    if (!forceSM2_)
-    {
-        if (impl_->deviceCaps_.VertexShaderVersion >= D3DVS_VERSION(3, 0) && impl_->deviceCaps_.PixelShaderVersion >=
-            D3DPS_VERSION(3, 0))
-            hasSM3_ = true;
-    }
     
     // Check for light prepass and deferred rendering support
     if (impl_->deviceCaps_.NumSimultaneousRTs >= 2 && impl_->CheckFormatSupport(D3DFMT_R32F, D3DUSAGE_RENDERTARGET,
@@ -2704,14 +2578,12 @@ void Graphics::CheckFeatureSupport()
     
     // Check for stream offset (needed for instancing)
     if (impl_->deviceCaps_.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET)
-        streamOffsetSupport_ = true;
+        instancingSupport_ = true;
     
     // Check for sRGB read & write
     /// \todo Should be checked for each texture format separately
     sRGBSupport_ = impl_->CheckFormatSupport(D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE);
     sRGBWriteSupport_ = impl_->CheckFormatSupport(D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE);
-    
-    SendEvent(E_GRAPHICSFEATURES);
 }
 
 void Graphics::ResetDevice()
@@ -2748,7 +2620,7 @@ void Graphics::OnDeviceLost()
     {
         MutexLock lock(gpuObjectMutex_);
 
-        for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
+        for (PODVector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
             (*i)->OnDeviceLost();
     }
     
@@ -2760,7 +2632,7 @@ void Graphics::OnDeviceReset()
     {
         MutexLock lock(gpuObjectMutex_);
 
-        for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
+        for (PODVector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
             (*i)->OnDeviceReset();
     }
     
@@ -2834,7 +2706,6 @@ void Graphics::ResetCachedState()
     stencilCompareMask_ = M_MAX_UNSIGNED;
     stencilWriteMask_ = M_MAX_UNSIGNED;
     useClipPlane_ = false;
-    drawAntialiased_ = true;
     impl_->blendEnable_ = FALSE;
     impl_->srcBlend_ = D3DBLEND_ONE;
     impl_->destBlend_ = D3DBLEND_ZERO;

+ 30 - 38
Source/Atomic/Graphics/Direct3D9/D3D9Graphics.h

@@ -43,6 +43,7 @@ class GraphicsImpl;
 class RenderSurface;
 class Shader;
 class ShaderPrecache;
+class ShaderProgram;
 class ShaderVariation;
 class Texture;
 class Texture2D;
@@ -54,6 +55,8 @@ class VertexDeclaration;
 
 struct ShaderParameter;
 
+typedef HashMap<Pair<ShaderVariation*, ShaderVariation*>, SharedPtr<ShaderProgram> > ShaderProgramMap;
+
 /// CPU-side scratch buffer for vertex data updates.
 struct ScratchBuffer
 {
@@ -206,8 +209,6 @@ public:
     void SetDepthTest(CompareMode mode);
     /// Set depth write on/off.
     void SetDepthWrite(bool enable);
-    /// Set antialiased drawing mode on/off. Default is on if the backbuffer is multisampled. Has no effect when backbuffer is not multisampled.
-    void SetDrawAntialiased(bool enable);
     /// Set polygon fill mode.
     void SetFillMode(FillMode mode);
     /// Set scissor test.
@@ -218,12 +219,6 @@ public:
     void SetStencilTest(bool enable, CompareMode mode = CMP_ALWAYS, StencilOp pass = OP_KEEP, StencilOp fail = OP_KEEP, StencilOp zFail = OP_KEEP, unsigned stencilRef = 0, unsigned compareMask = M_MAX_UNSIGNED, unsigned writeMask = M_MAX_UNSIGNED);
     /// Set a custom clipping plane. The plane is specified in world space, but is dependent on the view and projection matrices.
     void SetClipPlane(bool enable, const Plane& clipPlane = Plane::UP, const Matrix3x4& view = Matrix3x4::IDENTITY, const Matrix4& projection = Matrix4::IDENTITY);
-    /// Set vertex buffer stream frequency.
-    void SetStreamFrequency(unsigned index, unsigned frequency);
-    /// Reset stream frequencies.
-    void ResetStreamFrequencies();
-    /// Set force Shader Model 2 flag. Only effective before setting the initial screen mode.
-    void SetForceSM2(bool enable);
     /// Begin dumping shader variation names to an XML file for precaching.
     void BeginDumpShaders(const String& fileName);
     /// End dumping shader variations names.
@@ -239,6 +234,8 @@ public:
     void* GetExternalWindow() const { return externalWindow_; }
     /// Return window title.
     const String& GetWindowTitle() const { return windowTitle_; }
+    /// Return graphics API name.
+    const String& GetApiName() const { return apiName_; }
     /// Return window position.
     IntVector2 GetWindowPosition() const;
     /// Return window width.
@@ -275,10 +272,8 @@ public:
     unsigned GetShadowMapFormat() const { return shadowMapFormat_; }
     /// Return 24-bit shadow map depth texture format, or 0 if not supported.
     unsigned GetHiresShadowMapFormat() const { return hiresShadowMapFormat_; }
-    /// Return whether Shader Model 3 is supported.
-    bool GetSM3Support() const { return hasSM3_; }
-    /// Return whether hardware instancing is supported.
-    bool GetInstancingSupport() const { return hasSM3_; }
+    /// Return whether hardware instancing is supported..
+    bool GetInstancingSupport() const { return instancingSupport_; }
     /// Return whether light pre-pass rendering is supported.
     bool GetLightPrepassSupport() const { return lightPrepassSupport_; }
     /// Return whether deferred rendering is supported.
@@ -287,8 +282,6 @@ public:
     bool GetHardwareShadowSupport() const { return hardwareShadowSupport_; }
     /// Return whether a readable hardware depth format is available.
     bool GetReadableDepthSupport() const { return GetReadableDepthFormat() != 0; }
-    /// Return whether stream offset is supported.
-    bool GetStreamOffsetSupport() const { return streamOffsetSupport_; }
     /// Return whether sRGB conversion on texture sampling is supported.
     bool GetSRGBSupport() const { return sRGBSupport_; }
     /// Return whether sRGB conversion on rendertarget writing is supported.
@@ -309,8 +302,6 @@ public:
     VertexBuffer* GetVertexBuffer(unsigned index) const;
     /// Return current index buffer.
     IndexBuffer* GetIndexBuffer() const { return indexBuffer_; }
-    /// Return current vertex declaration.
-    VertexDeclaration* GetVertexDeclaration() const { return vertexDeclaration_; }
     /// Return current vertex shader.
     ShaderVariation* GetVertexShader() const { return vertexShader_; }
     /// Return current pixel shader.
@@ -345,8 +336,6 @@ public:
     CompareMode GetDepthTest() const { return depthTestMode_; }
     /// Return whether depth write is enabled.
     bool GetDepthWrite() const { return depthWrite_; }
-    /// Return whether antialiased drawing mode is enabled.
-    bool GetDrawAntialiased() const { return drawAntialiased_; }
     /// Return polygon fill mode.
     FillMode GetFillMode() const { return fillMode_; }
     /// Return whether stencil test is enabled.
@@ -371,12 +360,8 @@ public:
     unsigned GetStencilWriteMask() const { return stencilWriteMask_; }
     /// Return whether a custom clipping plane is in use.
     bool GetUseClipPlane() const { return useClipPlane_; }
-    /// Return stream frequency by vertex buffer index.
-    unsigned GetStreamFrequency(unsigned index) const;
     /// Return rendertarget width and height.
     IntVector2 GetRenderTargetDimensions() const;
-    /// Return force Shader Model 2 flag.
-    bool GetForceSM2() const { return forceSM2_; }
     
     /// Window was resized through user interaction. Called by Input subsystem.
     void WindowResized();
@@ -396,8 +381,8 @@ public:
     void FreeScratchBuffer(void* buffer);
     /// Clean up too large scratch buffers.
     void CleanupScratchBuffers();
-    /// Clean up shader parameters when a shader variation is released or destroyed.
-    void CleanupShaderParameters(ShaderVariation* variation);
+    /// Clean up shader programs when a shader variation is released or destroyed.
+    void CleanupShaderPrograms(ShaderVariation* variation);
 
     /// Return the API-specific alpha texture format.
     static unsigned GetAlphaFormat();
@@ -433,8 +418,16 @@ public:
     static unsigned GetReadableDepthFormat();
     /// Return the API-specific texture format from a textual description, for example "rgb".
     static unsigned GetFormat(const String& formatName);
-    
+    /// Return UV offset required for pixel perfect rendering.
+    static const Vector2& GetPixelUVOffset() { return pixelUVOffset; }
+    /// Return maximum number of supported bones for skinning.
+    static unsigned GetMaxBones() { return 64; }
+
 private:
+    /// Set vertex buffer stream frequency.
+    void SetStreamFrequency(unsigned index, unsigned frequency);
+    /// Reset stream frequencies.
+    void ResetStreamFrequencies();
     /// Create the application window.
     bool OpenWindow(int width, int height, bool resizable, bool borderless);
     /// Create the application window icon.
@@ -500,16 +493,12 @@ private:
     bool deferredSupport_;
     /// Hardware shadow map depth compare support flag.
     bool hardwareShadowSupport_;
-    /// Stream offset support flag.
-    bool streamOffsetSupport_;
+    /// Instancing support flag.
+    bool instancingSupport_;
     /// sRGB conversion on read support flag.
     bool sRGBSupport_;
     /// sRGB conversion on write support flag.
     bool sRGBWriteSupport_;
-    /// Shader Model 3 flag.
-    bool hasSM3_;
-    /// Force Shader Model 2 flag.
-    bool forceSM2_;
     /// Number of primitives this frame.
     unsigned numPrimitives_;
     /// Number of batches this frame.
@@ -517,7 +506,7 @@ private:
     /// Largest scratch buffer request this frame.
     unsigned maxScratchBufferRequest_;
     /// GPU objects.
-    Vector<GPUObject*> gpuObjects_;
+    PODVector<GPUObject*> gpuObjects_;
     /// Scratch buffers.
     Vector<ScratchBuffer> scratchBuffers_;
     /// Vertex declarations.
@@ -592,14 +581,12 @@ private:
     bool stencilTest_;
     /// Custom clip plane enable flag.
     bool useClipPlane_;
-    /// Draw antialiased mode flag.
-    bool drawAntialiased_;
     /// Default texture filtering mode.
     TextureFilterMode defaultTextureFilterMode_;
-    /// Shader parameters for all vertex/pixel shader combinations.
-    HashMap<Pair<ShaderVariation*, ShaderVariation*>, HashMap<StringHash, Pair<ShaderType, unsigned> > > shaderParameters_;
-    /// Current active shader parameters.
-    HashMap<StringHash, Pair<ShaderType, unsigned> >* currentShaderParameters_;
+    /// Shader programs.
+    ShaderProgramMap shaderPrograms_;
+    /// Shader program in use.
+    ShaderProgram* shaderProgram_;
     /// Remembered shader parameter sources.
     const void* shaderParameterSources_[MAX_SHADER_PARAMETER_GROUPS];
     /// Base directory for shaders.
@@ -614,6 +601,11 @@ private:
     SharedPtr<ShaderPrecache> shaderPrecache_;
     /// Allowed screen orientations.
     String orientations_;
+    /// Graphics API name.
+    String apiName_;
+
+    /// Pixel perfect UV offset.
+    static const Vector2 pixelUVOffset;
 };
 
 /// Register Graphics library objects.

+ 1 - 1
Source/Atomic/Graphics/Direct3D9/D3D9ShaderProgram.h

@@ -25,7 +25,7 @@
 #include "../../Container/HashMap.h"
 #include "../../Graphics/ShaderVariation.h"
 
-namespace Urho3D
+namespace Atomic
 {
 
 /// Combined information for specific vertex and pixel shaders.

+ 8 - 22
Source/Atomic/Graphics/Direct3D9/D3D9ShaderVariation.cpp

@@ -67,13 +67,9 @@ bool ShaderVariation::Create()
     }
 
     // Check for up-to-date bytecode on disk
-    bool useSM3 = graphics_->GetSM3Support();
     String path, name, extension;
     SplitPath(owner_->GetName(), path, name, extension);
-    if (useSM3)
-        extension = type_ == VS ? ".vs3" : ".ps3";
-    else
-        extension = type_ == VS ? ".vs2" : ".ps2";
+    extension = type_ == VS ? ".vs3" : ".ps3";
     
     String binaryShaderName = path + "Cache/" + name + "_" + StringHash(defines_).ToString() + extension;
     PODVector<unsigned> byteCode;
@@ -115,7 +111,7 @@ void ShaderVariation::Release()
         if (!graphics_)
             return;
         
-        graphics_->CleanupShaderParameters(this);
+        graphics_->CleanupShaderPrograms(this);
 
         if (type_ == VS)
         {
@@ -232,32 +228,22 @@ bool ShaderVariation::Compile(PODVector<unsigned>& byteCode)
     const char* entryPoint = 0;
     const char* profile = 0;
     unsigned flags = D3DCOMPILE_OPTIMIZATION_LEVEL3;
-    bool useSM3 = graphics_->GetSM3Support();
     
     if (type_ == VS)
     {
         entryPoint = "VS";
         defines.Push("COMPILEVS");
-        if (!useSM3)
-            profile = "vs_2_0";
-        else
-            profile = "vs_3_0";
+        profile = "vs_3_0";
     }
     else
     {
         entryPoint = "PS";
         defines.Push("COMPILEPS");
-        if (!useSM3)
-            profile = "ps_2_0";
-        else
-        {
-            profile = "ps_3_0";
-            flags |= D3DCOMPILE_PREFER_FLOW_CONTROL;
-        }
+        profile = "ps_3_0";
+        flags |= D3DCOMPILE_PREFER_FLOW_CONTROL;
     }
-    
-    if (useSM3)
-        defines.Push("SM3");
+
+    defines.Push("MAXBONES=" + String(Graphics::GetMaxBones()));
     
     // Collect defines into macros
     Vector<String> defineValues;
@@ -400,7 +386,7 @@ void ShaderVariation::SaveByteCode(const PODVector<unsigned>& byteCode, const St
     
     file->WriteFileID("USHD");
     file->WriteShort((unsigned short)type_);
-    file->WriteShort(graphics_->GetSM3Support() ? 3 : 2);
+    file->WriteShort(3);
 
     file->WriteUInt(parameters_.Size());
     for (HashMap<StringHash, ShaderParameter>::ConstIterator i = parameters_.Begin(); i != parameters_.End(); ++i)

+ 5 - 1
Source/Atomic/Graphics/Direct3D9/D3D9Texture.h

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2008-2015 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
@@ -50,6 +50,8 @@ public:
     void SetFilterMode(TextureFilterMode filter);
     /// Set addressing mode by texture coordinate.
     void SetAddressMode(TextureCoordinate coord, TextureAddressMode address);
+    /// Set shadow compare mode. No-op on D3D9.
+    void SetShadowCompare(bool enable) {}
     /// Set border color for border addressing mode.
     void SetBorderColor(const Color& color);
     /// Set sRGB sampling and writing mode.
@@ -75,6 +77,8 @@ public:
     TextureFilterMode GetFilterMode() const { return filterMode_; }
     /// Return addressing mode by texture coordinate.
     TextureAddressMode GetAddressMode(TextureCoordinate coord) const { return addressMode_[coord]; }
+    /// Return whether shadow compare is enabled. Always false on D3D9.
+    bool GetShadowCompare() const { return false; }
     /// Return border color.
     const Color& GetBorderColor() const { return borderColor_; }
     /// Return whether is using sRGB sampling and writing.