Browse Source

Unify IndexBuffer & VertexBuffer headers for all APIs. Move API-independent parts of vertex / index buffers to their own implementation files to eliminate code duplication.

Lasse Öörni 9 years ago
parent
commit
51b026f33d

+ 4 - 62
Source/Urho3D/Graphics/Direct3D11/D3D11IndexBuffer.cpp

@@ -33,26 +33,14 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-IndexBuffer::IndexBuffer(Context* context, bool forceHeadless) :
-    Object(context),
-    GPUObject(forceHeadless ? (Graphics*)0 : GetSubsystem<Graphics>()),
-    indexCount_(0),
-    indexSize_(0),
-    lockState_(LOCK_NONE),
-    lockStart_(0),
-    lockCount_(0),
-    lockScratchData_(0),
-    dynamic_(false),
-    shadowed_(false)
+void IndexBuffer::OnDeviceLost()
 {
 {
-    // Force shadowing mode if graphics subsystem does not exist
-    if (!graphics_)
-        shadowed_ = true;
+    // No-op on Direct3D11
 }
 }
 
 
-IndexBuffer::~IndexBuffer()
+void IndexBuffer::OnDeviceReset()
 {
 {
-    Release();
+    // No-op on Direct3D11
 }
 }
 
 
 void IndexBuffer::Release()
 void IndexBuffer::Release()
@@ -273,52 +261,6 @@ void IndexBuffer::Unlock()
     }
     }
 }
 }
 
 
-bool IndexBuffer::GetUsedVertexRange(unsigned start, unsigned count, unsigned& minVertex, unsigned& vertexCount)
-{
-    if (!shadowData_)
-    {
-        URHO3D_LOGERROR("Used vertex range can only be queried from an index buffer with shadow data");
-        return false;
-    }
-
-    if (start + count > indexCount_)
-    {
-        URHO3D_LOGERROR("Illegal index range for querying used vertices");
-        return false;
-    }
-
-    minVertex = M_MAX_UNSIGNED;
-    unsigned maxVertex = 0;
-
-    if (indexSize_ == sizeof(unsigned))
-    {
-        unsigned* indices = ((unsigned*)shadowData_.Get()) + start;
-
-        for (unsigned i = 0; i < count; ++i)
-        {
-            if (indices[i] < minVertex)
-                minVertex = indices[i];
-            if (indices[i] > maxVertex)
-                maxVertex = indices[i];
-        }
-    }
-    else
-    {
-        unsigned short* indices = ((unsigned short*)shadowData_.Get()) + start;
-
-        for (unsigned i = 0; i < count; ++i)
-        {
-            if (indices[i] < minVertex)
-                minVertex = indices[i];
-            if (indices[i] > maxVertex)
-                maxVertex = indices[i];
-        }
-    }
-
-    vertexCount = maxVertex - minVertex + 1;
-    return true;
-}
-
 bool IndexBuffer::Create()
 bool IndexBuffer::Create()
 {
 {
     Release();
     Release();

+ 0 - 114
Source/Urho3D/Graphics/Direct3D11/D3D11IndexBuffer.h

@@ -1,114 +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 "../../Core/Object.h"
-#include "../../Container/ArrayPtr.h"
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-
-namespace Urho3D
-{
-
-/// Hardware index buffer.
-class URHO3D_API IndexBuffer : public Object, public GPUObject
-{
-    URHO3D_OBJECT(IndexBuffer, Object);
-
-public:
-    /// Construct.
-    IndexBuffer(Context* context, bool forceHeadless = false);
-    /// Destruct.
-    virtual ~IndexBuffer();
-
-    /// Release buffer.
-    virtual void Release();
-
-    /// Enable shadowing in CPU memory. Shadowing is forced on if the graphics subsystem does not exist.
-    void SetShadowed(bool enable);
-    /// Set size and vertex elements and dynamic mode. Previous data will be lost.
-    bool SetSize(unsigned indexCount, bool largeIndices, bool dynamic = false);
-    /// Set all data in the buffer.
-    bool SetData(const void* data);
-    /// Set a data range in the buffer. Optionally discard data outside the range.
-    bool SetDataRange(const void* data, unsigned start, unsigned count, bool discard = false);
-    /// Lock the buffer for write-only editing. Return data pointer if successful. Optionally discard data outside the range.
-    void* Lock(unsigned start, unsigned count, bool discard = false);
-    /// Unlock the buffer and apply changes to the GPU buffer.
-    void Unlock();
-
-    /// Return whether CPU memory shadowing is enabled.
-    bool IsShadowed() const { return shadowed_; }
-
-    /// Return whether is dynamic.
-    bool IsDynamic() const { return dynamic_; }
-
-    /// Return whether is currently locked.
-    bool IsLocked() const { return lockState_ != LOCK_NONE; }
-
-    /// Return number of indices.
-    unsigned GetIndexCount() const { return indexCount_; }
-
-    /// Return index size in bytes.
-    unsigned GetIndexSize() const { return indexSize_; }
-
-    /// Return used vertex range from index range.
-    bool GetUsedVertexRange(unsigned start, unsigned count, unsigned& minVertex, unsigned& vertexCount);
-
-    /// Return CPU memory shadow data.
-    unsigned char* GetShadowData() const { return shadowData_.Get(); }
-
-    /// Return shared array pointer to the CPU memory shadow data.
-    SharedArrayPtr<unsigned char> GetShadowDataShared() const { return shadowData_; }
-
-private:
-    /// Create buffer.
-    bool Create();
-    /// Update the shadow data to the GPU buffer.
-    bool UpdateToGPU();
-    /// Map the GPU buffer into CPU memory.
-    void* MapBuffer(unsigned start, unsigned count, bool discard);
-    /// Unmap the GPU buffer.
-    void UnmapBuffer();
-
-    /// Shadow data.
-    SharedArrayPtr<unsigned char> shadowData_;
-    /// Number of indices.
-    unsigned indexCount_;
-    /// Index size.
-    unsigned indexSize_;
-    /// Buffer locking state.
-    LockState lockState_;
-    /// Lock start vertex.
-    unsigned lockStart_;
-    /// Lock number of vertices.
-    unsigned lockCount_;
-    /// Scratch buffer for fallback locking.
-    void* lockScratchData_;
-    /// Dynamic flag.
-    bool dynamic_;
-    /// Shadowed flag.
-    bool shadowed_;
-};
-
-}

+ 4 - 120
Source/Urho3D/Graphics/Direct3D11/D3D11VertexBuffer.cpp

@@ -32,28 +32,14 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-VertexBuffer::VertexBuffer(Context* context, bool forceHeadless) :
-    Object(context),
-    GPUObject(forceHeadless ? (Graphics*)0 : GetSubsystem<Graphics>()),
-    vertexCount_(0),
-    elementMask_(0),
-    lockState_(LOCK_NONE),
-    lockStart_(0),
-    lockCount_(0),
-    lockScratchData_(0),
-    dynamic_(false),
-    shadowed_(false)
+void VertexBuffer::OnDeviceLost()
 {
 {
-    UpdateOffsets();
-
-    // Force shadowing mode if graphics subsystem does not exist
-    if (!graphics_)
-        shadowed_ = true;
+    // No-op on Direct3D11
 }
 }
 
 
-VertexBuffer::~VertexBuffer()
+void VertexBuffer::OnDeviceReset()
 {
 {
-    Release();
+    // No-op on Direct3D11
 }
 }
 
 
 void VertexBuffer::Release()
 void VertexBuffer::Release()
@@ -287,109 +273,7 @@ void VertexBuffer::Unlock()
     }
     }
 }
 }
 
 
-void VertexBuffer::UpdateOffsets()
-{
-    unsigned elementOffset = 0;
-    elementHash_ = 0;
-    elementMask_ = 0;
-
-    for (PODVector<VertexElement>::Iterator i = elements_.Begin(); i != elements_.End(); ++i)
-    {
-        i->offset_ = elementOffset;
-        elementOffset += ELEMENT_TYPESIZES[i->type_];
-        elementHash_ <<= 6;
-        elementHash_ += (((int)i->type_ + 1) * ((int)i->semantic_ + 1) + i->index_);
-
-        for (unsigned j = 0; j < MAX_LEGACY_VERTEX_ELEMENTS; ++j)
-        {
-            const VertexElement& legacy = LEGACY_VERTEXELEMENTS[j];
-            if (i->type_ == legacy.type_ && i->semantic_ == legacy.semantic_ && i->index_ == legacy.index_)
-                elementMask_ |= (1 << j);
-        }
-    }
-
-    vertexSize_ = elementOffset;
-}
-
-const VertexElement* VertexBuffer::GetElement(VertexElementSemantic semantic, unsigned char index) const
-{
-    for (PODVector<VertexElement>::ConstIterator i = elements_.Begin(); i != elements_.End(); ++i)
-    {
-        if (i->semantic_ == semantic && i->index_ == index)
-            return &(*i);
-    }
-
-    return 0;
-}
-
-const VertexElement* VertexBuffer::GetElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index) const
-{
-    for (PODVector<VertexElement>::ConstIterator i = elements_.Begin(); i != elements_.End(); ++i)
-    {
-        if (i->type_ == type && i->semantic_ == semantic && i->index_ == index)
-            return &(*i);
-    }
-
-    return 0;
-}
 
 
-const VertexElement* VertexBuffer::GetElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
-{
-    for (PODVector<VertexElement>::ConstIterator i = elements.Begin(); i != elements.End(); ++i)
-    {
-        if (i->type_ == type && i->semantic_ == semantic && i->index_ == index)
-            return &(*i);
-    }
-
-    return 0;
-}
-
-bool VertexBuffer::HasElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
-{
-    return GetElement(elements, type, semantic, index) != 0;
-}
-
-unsigned VertexBuffer::GetElementOffset(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
-{
-    const VertexElement* element = GetElement(elements, type, semantic, index);
-    return element ? element->offset_ : M_MAX_UNSIGNED;
-}
-
-PODVector<VertexElement> VertexBuffer::GetElements(unsigned elementMask)
-{
-    PODVector<VertexElement> ret;
-
-    for (unsigned i = 0; i < MAX_LEGACY_VERTEX_ELEMENTS; ++i)
-    {
-        if (elementMask & (1 << i))
-            ret.Push(LEGACY_VERTEXELEMENTS[i]);
-    }
-
-    return ret;
-}
-
-unsigned VertexBuffer::GetVertexSize(const PODVector<VertexElement>& elements)
-{
-    unsigned size = 0;
-
-    for (unsigned i = 0; i < elements.Size(); ++i)
-        size += ELEMENT_TYPESIZES[elements[i].type_];
-
-    return size;
-}
-
-unsigned VertexBuffer::GetVertexSize(unsigned elementMask)
-{
-    unsigned size = 0;
-
-    for (unsigned i = 0; i < MAX_LEGACY_VERTEX_ELEMENTS; ++i)
-    {
-        if (elementMask & (1 << i))
-            size += ELEMENT_TYPESIZES[LEGACY_VERTEXELEMENTS[i].type_];
-    }
-
-    return size;
-}
 
 
 bool VertexBuffer::Create()
 bool VertexBuffer::Create()
 {
 {

+ 0 - 165
Source/Urho3D/Graphics/Direct3D11/D3D11VertexBuffer.h

@@ -1,165 +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/ArrayPtr.h"
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-
-namespace Urho3D
-{
-
-/// Hardware vertex buffer.
-class URHO3D_API VertexBuffer : public Object, public GPUObject
-{
-    URHO3D_OBJECT(VertexBuffer, Object);
-
-public:
-    /// Construct.
-    VertexBuffer(Context* context, bool forceHeadless = false);
-    /// Destruct.
-    virtual ~VertexBuffer();
-
-    /// Release buffer.
-    virtual void Release();
-
-    /// Enable shadowing in CPU memory. Shadowing is forced on if the graphics subsystem does not exist.
-    void SetShadowed(bool enable);
-    /// Set size, vertex elements and dynamic mode. Previous data will be lost.
-    bool SetSize(unsigned vertexCount, const PODVector<VertexElement>& elements, bool dynamic = false);
-    /// Set size and vertex elements and dynamic mode using legacy element bitmask. Previous data will be lost.
-    bool SetSize(unsigned vertexCount, unsigned elementMask, bool dynamic = false);
-    /// Set all data in the buffer.
-    bool SetData(const void* data);
-    /// Set a data range in the buffer. Optionally discard data outside the range.
-    bool SetDataRange(const void* data, unsigned start, unsigned count, bool discard = false);
-    /// Lock the buffer for write-only editing. Return data pointer if successful. Optionally discard data outside the range.
-    void* Lock(unsigned start, unsigned count, bool discard = false);
-    /// Unlock the buffer and apply changes to the GPU buffer.
-    void Unlock();
-
-    /// Return whether CPU memory shadowing is enabled.
-    bool IsShadowed() const { return shadowed_; }
-
-    /// Return whether is dynamic.
-    bool IsDynamic() const { return dynamic_; }
-
-    /// Return whether is currently locked.
-    bool IsLocked() const { return lockState_ != LOCK_NONE; }
-
-    /// Return number of vertices.
-    unsigned GetVertexCount() const { return vertexCount_; }
-
-    /// Return vertex size in bytes.
-    unsigned GetVertexSize() const { return vertexSize_; }
-
-    /// Return vertex elements.
-    const PODVector<VertexElement>& GetElements() const { return elements_; }
-
-    /// Return vertex element, or null if does not exist.
-    const VertexElement* GetElement(VertexElementSemantic semantic, unsigned char index = 0) const;
-
-    /// Return vertex element with specific type, or null if does not exist.
-    const VertexElement* GetElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const;
-
-    /// Return whether has a specified element semantic.
-    bool HasElement(VertexElementSemantic semantic, unsigned char index = 0) const { return GetElement(semantic, index) != 0; }
-
-    /// Return whether has an element semantic with specific type.
-    bool HasElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const { return GetElement(type, semantic, index) != 0; }
-
-    /// Return offset of a element within vertex, or M_MAX_UNSIGNED if does not exist.
-    unsigned GetElementOffset(VertexElementSemantic semantic, unsigned char index = 0) const { const VertexElement* element = GetElement(semantic, index); return element ? element->offset_ : M_MAX_UNSIGNED; }
-
-    /// Return offset of a element with specific type within vertex, or M_MAX_UNSIGNED if element does not exist.
-    unsigned GetElementOffset(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const { const VertexElement* element = GetElement(type, semantic, index); return element ? element->offset_ : M_MAX_UNSIGNED; }
-
-    /// Return legacy vertex element mask. Note that both semantic and type must match the legacy element for a mask bit to be set.
-    unsigned GetElementMask() const { return elementMask_; }
-
-    /// Return CPU memory shadow data.
-    unsigned char* GetShadowData() const { return shadowData_.Get(); }
-
-    /// Return shared array pointer to the CPU memory shadow data.
-    SharedArrayPtr<unsigned char> GetShadowDataShared() const { return shadowData_; }
-
-    /// Return buffer hash for building vertex declarations. Used internally.
-    unsigned long long GetBufferHash(unsigned streamIndex) { return elementHash_ << (streamIndex * 16); }
-
-    /// Return element with specified type and semantic from a vertex element list, or null if does not exist.
-    static const VertexElement* GetElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
-
-    /// Return whether element list has a specified element type and semantic.
-    static bool HasElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
-
-    /// Return element offset for specified type and semantic from a vertex element list, or M_MAX_UNSIGNED if does not exist.
-    static unsigned GetElementOffset(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
-
-    /// Return a vertex element list from a legacy element bitmask.
-    static PODVector<VertexElement> GetElements(unsigned elementMask);
-
-    /// Return vertex size from an element list.
-    static unsigned GetVertexSize(const PODVector<VertexElement>& elements);
-
-    /// Return vertex size for a legacy vertex element bitmask.
-    static unsigned GetVertexSize(unsigned elementMask);
-
-private:
-    /// Update offsets of vertex elements.
-    void UpdateOffsets();
-    /// Create buffer.
-    bool Create();
-    /// Update the shadow data to the GPU buffer.
-    bool UpdateToGPU();
-    /// Map the GPU buffer into CPU memory.
-    void* MapBuffer(unsigned start, unsigned count, bool discard);
-    /// Unmap the GPU buffer.
-    void UnmapBuffer();
-
-    /// Shadow data.
-    SharedArrayPtr<unsigned char> shadowData_;
-    /// Number of vertices.
-    unsigned vertexCount_;
-    /// Vertex size.
-    unsigned vertexSize_;
-    /// Vertex elements.
-    PODVector<VertexElement> elements_;
-    /// Vertex element hash.
-    unsigned long long elementHash_;
-    /// Vertex element legacy bitmask.
-    unsigned elementMask_;
-    /// Buffer locking state.
-    LockState lockState_;
-    /// Lock start vertex.
-    unsigned lockStart_;
-    /// Lock number of vertices.
-    unsigned lockCount_;
-    /// Scratch buffer for fallback locking.
-    void* lockScratchData_;
-    /// Dynamic flag.
-    bool dynamic_;
-    /// Shadowed flag.
-    bool shadowed_;
-};
-
-}

+ 11 - 90
Source/Urho3D/Graphics/Direct3D9/D3D9IndexBuffer.cpp

@@ -33,38 +33,17 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-IndexBuffer::IndexBuffer(Context* context, bool forceHeadless) :
-    Object(context),
-    GPUObject(forceHeadless ? (Graphics*)0 : GetSubsystem<Graphics>()),
-    indexCount_(0),
-    indexSize_(0),
-    pool_(D3DPOOL_MANAGED),
-    usage_(0),
-    lockState_(LOCK_NONE),
-    lockStart_(0),
-    lockCount_(0),
-    lockScratchData_(0),
-    shadowed_(false)
-{
-    // Force shadowing mode if graphics subsystem does not exist
-    if (!graphics_)
-        shadowed_ = true;
-}
-
-IndexBuffer::~IndexBuffer()
-{
-    Release();
-}
-
 void IndexBuffer::OnDeviceLost()
 void IndexBuffer::OnDeviceLost()
 {
 {
-    if (pool_ == D3DPOOL_DEFAULT)
+    // Dynamic buffers are in the default pool and need to be released on device loss
+    if (dynamic_)
         Release();
         Release();
 }
 }
 
 
 void IndexBuffer::OnDeviceReset()
 void IndexBuffer::OnDeviceReset()
 {
 {
-    if (pool_ == D3DPOOL_DEFAULT || !object_.ptr_)
+    // Dynamic buffers are in the default pool and need to be recreated after device reset
+    if (dynamic_ || !object_.ptr_)
     {
     {
         Create();
         Create();
         dataLost_ = !UpdateToGPU();
         dataLost_ = !UpdateToGPU();
@@ -106,19 +85,9 @@ bool IndexBuffer::SetSize(unsigned indexCount, bool largeIndices, bool dynamic)
 {
 {
     Unlock();
     Unlock();
 
 
-    if (dynamic)
-    {
-        pool_ = D3DPOOL_DEFAULT;
-        usage_ = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
-    }
-    else
-    {
-        pool_ = D3DPOOL_MANAGED;
-        usage_ = 0;
-    }
-
     indexCount_ = indexCount;
     indexCount_ = indexCount;
     indexSize_ = (unsigned)(largeIndices ? sizeof(unsigned) : sizeof(unsigned short));
     indexSize_ = (unsigned)(largeIndices ? sizeof(unsigned) : sizeof(unsigned short));
+    dynamic_ = dynamic;
 
 
     if (shadowed_ && indexCount_ && indexSize_)
     if (shadowed_ && indexCount_ && indexSize_)
         shadowData_ = new unsigned char[indexCount_ * indexSize_];
         shadowData_ = new unsigned char[indexCount_ * indexSize_];
@@ -288,57 +257,6 @@ void IndexBuffer::Unlock()
     }
     }
 }
 }
 
 
-bool IndexBuffer::IsDynamic() const
-{
-    return pool_ == D3DPOOL_DEFAULT;
-}
-
-bool IndexBuffer::GetUsedVertexRange(unsigned start, unsigned count, unsigned& minVertex, unsigned& vertexCount)
-{
-    if (!shadowData_)
-    {
-        URHO3D_LOGERROR("Used vertex range can only be queried from an index buffer with shadow data");
-        return false;
-    }
-
-    if (start + count > indexCount_)
-    {
-        URHO3D_LOGERROR("Illegal index range for querying used vertices");
-        return false;
-    }
-
-    minVertex = M_MAX_UNSIGNED;
-    unsigned maxVertex = 0;
-
-    if (indexSize_ == sizeof(unsigned))
-    {
-        unsigned* indices = ((unsigned*)shadowData_.Get()) + start;
-
-        for (unsigned i = 0; i < count; ++i)
-        {
-            if (indices[i] < minVertex)
-                minVertex = indices[i];
-            if (indices[i] > maxVertex)
-                maxVertex = indices[i];
-        }
-    }
-    else
-    {
-        unsigned short* indices = ((unsigned short*)shadowData_.Get()) + start;
-
-        for (unsigned i = 0; i < count; ++i)
-        {
-            if (indices[i] < minVertex)
-                minVertex = indices[i];
-            if (indices[i] > maxVertex)
-                maxVertex = indices[i];
-        }
-    }
-
-    vertexCount = maxVertex - minVertex + 1;
-    return true;
-}
-
 bool IndexBuffer::Create()
 bool IndexBuffer::Create()
 {
 {
     Release();
     Release();
@@ -354,12 +272,15 @@ bool IndexBuffer::Create()
             return true;
             return true;
         }
         }
 
 
+        unsigned pool = dynamic_ ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
+        unsigned usage = dynamic_ ? D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY : 0;
+
         IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
         IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
         HRESULT hr = device->CreateIndexBuffer(
         HRESULT hr = device->CreateIndexBuffer(
             indexCount_ * indexSize_,
             indexCount_ * indexSize_,
-            usage_,
+            usage,
             indexSize_ == sizeof(unsigned) ? D3DFMT_INDEX32 : D3DFMT_INDEX16,
             indexSize_ == sizeof(unsigned) ? D3DFMT_INDEX32 : D3DFMT_INDEX16,
-            (D3DPOOL)pool_,
+            (D3DPOOL)pool,
             (IDirect3DIndexBuffer9**)&object_,
             (IDirect3DIndexBuffer9**)&object_,
             0);
             0);
         if (FAILED(hr))
         if (FAILED(hr))
@@ -389,7 +310,7 @@ void* IndexBuffer::MapBuffer(unsigned start, unsigned count, bool discard)
     {
     {
         DWORD flags = 0;
         DWORD flags = 0;
 
 
-        if (discard && usage_ & D3DUSAGE_DYNAMIC)
+        if (discard && dynamic_)
             flags = D3DLOCK_DISCARD;
             flags = D3DLOCK_DISCARD;
 
 
         HRESULT hr = ((IDirect3DIndexBuffer9*)object_.ptr_)->Lock(start * indexSize_, count * indexSize_, &hwData, flags);
         HRESULT hr = ((IDirect3DIndexBuffer9*)object_.ptr_)->Lock(start * indexSize_, count * indexSize_, &hwData, flags);

+ 0 - 120
Source/Urho3D/Graphics/Direct3D9/D3D9IndexBuffer.h

@@ -1,120 +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 "../../Core/Object.h"
-#include "../../Container/ArrayPtr.h"
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-
-namespace Urho3D
-{
-
-/// Hardware index buffer.
-class URHO3D_API IndexBuffer : public Object, public GPUObject
-{
-    URHO3D_OBJECT(IndexBuffer, Object);
-
-public:
-    /// Construct.
-    IndexBuffer(Context* context, bool forceHeadless = false);
-    /// Destruct.
-    virtual ~IndexBuffer();
-
-    /// Release default pool resources.
-    virtual void OnDeviceLost();
-    /// Recreate default pool resources.
-    virtual void OnDeviceReset();
-    /// Release buffer.
-    virtual void Release();
-
-    /// Enable shadowing in CPU memory. Shadowing is forced on if the graphics subsystem does not exist.
-    void SetShadowed(bool enable);
-    /// Set size and vertex elements and dynamic mode. Previous data will be lost.
-    bool SetSize(unsigned indexCount, bool largeIndices, bool dynamic = false);
-    /// Set all data in the buffer.
-    bool SetData(const void* data);
-    /// Set a data range in the buffer. Optionally discard data outside the range.
-    bool SetDataRange(const void* data, unsigned start, unsigned count, bool discard = false);
-    /// Lock the buffer for write-only editing. Return data pointer if successful. Optionally discard data outside the range.
-    void* Lock(unsigned start, unsigned count, bool discard = false);
-    /// Unlock the buffer and apply changes to the GPU buffer.
-    void Unlock();
-
-    /// Return whether CPU memory shadowing is enabled.
-    bool IsShadowed() const { return shadowed_; }
-
-    /// Return whether is dynamic.
-    bool IsDynamic() const;
-
-    /// Return whether is currently locked.
-    bool IsLocked() const { return lockState_ != LOCK_NONE; }
-
-    /// Return number of indices.
-    unsigned GetIndexCount() const { return indexCount_; }
-
-    /// Return index size in bytes.
-    unsigned GetIndexSize() const { return indexSize_; }
-
-    /// Return used vertex range from index range.
-    bool GetUsedVertexRange(unsigned start, unsigned count, unsigned& minVertex, unsigned& vertexCount);
-
-    /// Return CPU memory shadow data.
-    unsigned char* GetShadowData() const { return shadowData_.Get(); }
-
-    /// Return shared array pointer to the CPU memory shadow data.
-    SharedArrayPtr<unsigned char> GetShadowDataShared() const { return shadowData_; }
-
-private:
-    /// Create buffer.
-    bool Create();
-    /// Update the shadow data to the GPU buffer.
-    bool UpdateToGPU();
-    /// Map the GPU buffer into CPU memory.
-    void* MapBuffer(unsigned start, unsigned count, bool discard);
-    /// Unmap the GPU buffer.
-    void UnmapBuffer();
-
-    /// Shadow data.
-    SharedArrayPtr<unsigned char> shadowData_;
-    /// Number of indices.
-    unsigned indexCount_;
-    /// Index size.
-    unsigned indexSize_;
-    /// Memory pool.
-    unsigned pool_;
-    /// Usage type.
-    unsigned usage_;
-    /// Buffer locking state.
-    LockState lockState_;
-    /// Lock start vertex.
-    unsigned lockStart_;
-    /// Lock number of vertices.
-    unsigned lockCount_;
-    /// Scratch buffer for fallback locking.
-    void* lockScratchData_;
-    /// Shadowed flag.
-    bool shadowed_;
-};
-
-}

+ 10 - 149
Source/Urho3D/Graphics/Direct3D9/D3D9VertexBuffer.cpp

@@ -32,39 +32,17 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-VertexBuffer::VertexBuffer(Context* context, bool forceHeadless) :
-    Object(context),
-    GPUObject(forceHeadless ? (Graphics*)0 : GetSubsystem<Graphics>()),
-    vertexCount_(0),
-    elementHash_(0),
-    elementMask_(0),
-    pool_(D3DPOOL_MANAGED),
-    usage_(0),
-    lockState_(LOCK_NONE),
-    lockStart_(0),
-    lockCount_(0),
-    lockScratchData_(0),
-    shadowed_(false)
-{
-    // Force shadowing mode if graphics subsystem does not exist
-    if (!graphics_)
-        shadowed_ = true;
-}
-
-VertexBuffer::~VertexBuffer()
-{
-    Release();
-}
-
 void VertexBuffer::OnDeviceLost()
 void VertexBuffer::OnDeviceLost()
 {
 {
-    if (pool_ == D3DPOOL_DEFAULT)
+    // Dynamic buffers are in the default pool and need to be released on device loss
+    if (dynamic_)
         Release();
         Release();
 }
 }
 
 
 void VertexBuffer::OnDeviceReset()
 void VertexBuffer::OnDeviceReset()
 {
 {
-    if (pool_ == D3DPOOL_DEFAULT || !object_.ptr_)
+    // Dynamic buffers are in the default pool and need to be recreated after device reset
+    if (dynamic_ || !object_.ptr_)
     {
     {
         Create();
         Create();
         dataLost_ = !UpdateToGPU();
         dataLost_ = !UpdateToGPU();
@@ -117,17 +95,6 @@ bool VertexBuffer::SetSize(unsigned vertexCount, const PODVector<VertexElement>&
 {
 {
     Unlock();
     Unlock();
 
 
-    if (dynamic)
-    {
-        pool_ = D3DPOOL_DEFAULT;
-        usage_ = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
-    }
-    else
-    {
-        pool_ = D3DPOOL_MANAGED;
-        usage_ = 0;
-    }
-
     vertexCount_ = vertexCount;
     vertexCount_ = vertexCount;
     elements_ = elements;
     elements_ = elements;
 
 
@@ -301,115 +268,6 @@ void VertexBuffer::Unlock()
     }
     }
 }
 }
 
 
-bool VertexBuffer::IsDynamic() const
-{
-    return pool_ == D3DPOOL_DEFAULT;
-}
-
-void VertexBuffer::UpdateOffsets()
-{
-    unsigned elementOffset = 0;
-    elementHash_ = 0;
-    elementMask_ = 0;
-
-    for (PODVector<VertexElement>::Iterator i = elements_.Begin(); i != elements_.End(); ++i)
-    {
-        i->offset_ = elementOffset;
-        elementOffset += ELEMENT_TYPESIZES[i->type_];
-        elementHash_ <<= 6;
-        elementHash_ += (((int)i->type_ + 1) * ((int)i->semantic_ + 1) + i->index_);
-
-        for (unsigned j = 0; j < MAX_LEGACY_VERTEX_ELEMENTS; ++j)
-        {
-            const VertexElement& legacy = LEGACY_VERTEXELEMENTS[j];
-            if (i->type_ == legacy.type_ && i->semantic_ == legacy.semantic_ && i->index_ == legacy.index_)
-                elementMask_ |= (1 << j);
-        }
-    }
-
-    vertexSize_ = elementOffset;
-}
-
-const VertexElement* VertexBuffer::GetElement(VertexElementSemantic semantic, unsigned char index) const
-{
-    for (PODVector<VertexElement>::ConstIterator i = elements_.Begin(); i != elements_.End(); ++i)
-    {
-        if (i->semantic_ == semantic && i->index_ == index)
-            return &(*i);
-    }
-
-    return 0;
-}
-
-const VertexElement* VertexBuffer::GetElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index) const
-{
-    for (PODVector<VertexElement>::ConstIterator i = elements_.Begin(); i != elements_.End(); ++i)
-    {
-        if (i->type_ == type && i->semantic_ == semantic && i->index_ == index)
-            return &(*i);
-    }
-
-    return 0;
-}
-
-const VertexElement* VertexBuffer::GetElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
-{
-    for (PODVector<VertexElement>::ConstIterator i = elements.Begin(); i != elements.End(); ++i)
-    {
-        if (i->type_ == type && i->semantic_ == semantic && i->index_ == index)
-            return &(*i);
-    }
-
-    return 0;
-}
-
-bool VertexBuffer::HasElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
-{
-    return GetElement(elements, type, semantic, index) != 0;
-}
-
-unsigned VertexBuffer::GetElementOffset(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
-{
-    const VertexElement* element = GetElement(elements, type, semantic, index);
-    return element ? element->offset_ : M_MAX_UNSIGNED;
-}
-
-PODVector<VertexElement> VertexBuffer::GetElements(unsigned elementMask)
-{
-    PODVector<VertexElement> ret;
-
-    for (unsigned i = 0; i < MAX_LEGACY_VERTEX_ELEMENTS; ++i)
-    {
-        if (elementMask & (1 << i))
-            ret.Push(LEGACY_VERTEXELEMENTS[i]);
-    }
-
-    return ret;
-}
-
-unsigned VertexBuffer::GetVertexSize(const PODVector<VertexElement>& elements)
-{
-    unsigned size = 0;
-
-    for (unsigned i = 0; i < elements.Size(); ++i)
-        size += ELEMENT_TYPESIZES[elements[i].type_];
-
-    return size;
-}
-
-unsigned VertexBuffer::GetVertexSize(unsigned elementMask)
-{
-    unsigned size = 0;
-
-    for (unsigned i = 0; i < MAX_LEGACY_VERTEX_ELEMENTS; ++i)
-    {
-        if (elementMask & (1 << i))
-            size += ELEMENT_TYPESIZES[LEGACY_VERTEXELEMENTS[i].type_];
-    }
-
-    return size;
-}
-
 bool VertexBuffer::Create()
 bool VertexBuffer::Create()
 {
 {
     Release();
     Release();
@@ -425,12 +283,15 @@ bool VertexBuffer::Create()
             return true;
             return true;
         }
         }
 
 
+        unsigned pool = dynamic_ ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
+        unsigned usage = dynamic_ ? D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY : 0;
+
         IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
         IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
         HRESULT hr = device->CreateVertexBuffer(
         HRESULT hr = device->CreateVertexBuffer(
             vertexCount_ * vertexSize_,
             vertexCount_ * vertexSize_,
-            usage_,
+            usage,
             0,
             0,
-            (D3DPOOL)pool_,
+            (D3DPOOL)pool,
             (IDirect3DVertexBuffer9**)&object_.ptr_,
             (IDirect3DVertexBuffer9**)&object_.ptr_,
             0);
             0);
         if (FAILED(hr))
         if (FAILED(hr))
@@ -460,7 +321,7 @@ void* VertexBuffer::MapBuffer(unsigned start, unsigned count, bool discard)
     {
     {
         DWORD flags = 0;
         DWORD flags = 0;
 
 
-        if (discard && usage_ & D3DUSAGE_DYNAMIC)
+        if (discard && dynamic_)
             flags = D3DLOCK_DISCARD;
             flags = D3DLOCK_DISCARD;
 
 
         HRESULT hr = ((IDirect3DVertexBuffer9*)object_.ptr_)->Lock(start * vertexSize_, count * vertexSize_, &hwData, flags);
         HRESULT hr = ((IDirect3DVertexBuffer9*)object_.ptr_)->Lock(start * vertexSize_, count * vertexSize_, &hwData, flags);

+ 0 - 171
Source/Urho3D/Graphics/Direct3D9/D3D9VertexBuffer.h

@@ -1,171 +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/ArrayPtr.h"
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-
-namespace Urho3D
-{
-
-/// Hardware vertex buffer.
-class URHO3D_API VertexBuffer : public Object, public GPUObject
-{
-    URHO3D_OBJECT(VertexBuffer, Object);
-
-public:
-    /// Construct.
-    VertexBuffer(Context* context, bool forceHeadless = false);
-    /// Destruct.
-    virtual ~VertexBuffer();
-
-    /// Release default pool resources.
-    virtual void OnDeviceLost();
-    /// ReCreate default pool resources.
-    virtual void OnDeviceReset();
-    /// Release buffer.
-    virtual void Release();
-
-    /// Enable shadowing in CPU memory. Shadowing is forced on if the graphics subsystem does not exist.
-    void SetShadowed(bool enable);
-    /// Set size, vertex elements and dynamic mode. Previous data will be lost.
-    bool SetSize(unsigned vertexCount, const PODVector<VertexElement>& elements, bool dynamic = false);
-    /// Set size and vertex elements and dynamic mode using legacy element bitmask. Previous data will be lost.
-    bool SetSize(unsigned vertexCount, unsigned elementMask, bool dynamic = false);
-    /// Set all data in the buffer.
-    bool SetData(const void* data);
-    /// Set a data range in the buffer. Optionally discard data outside the range.
-    bool SetDataRange(const void* data, unsigned start, unsigned count, bool discard = false);
-    /// Lock the buffer for write-only editing. Return data pointer if successful. Optionally discard data outside the range.
-    void* Lock(unsigned start, unsigned count, bool discard = false);
-    /// Unlock the buffer and apply changes to the GPU buffer.
-    void Unlock();
-
-    /// Return whether CPU memory shadowing is enabled.
-    bool IsShadowed() const { return shadowed_; }
-
-    /// Return whether is dynamic.
-    bool IsDynamic() const;
-
-    /// Return whether is currently locked.
-    bool IsLocked() const { return lockState_ != LOCK_NONE; }
-
-    /// Return number of vertices.
-    unsigned GetVertexCount() const { return vertexCount_; }
-
-    /// Return vertex size in bytes.
-    unsigned GetVertexSize() const { return vertexSize_; }
-
-    /// Return vertex elements.
-    const PODVector<VertexElement>& GetElements() const { return elements_; }
-
-    /// Return vertex element, or null if does not exist.
-    const VertexElement* GetElement(VertexElementSemantic semantic, unsigned char index = 0) const;
-
-    /// Return vertex element with specific type, or null if does not exist.
-    const VertexElement* GetElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const;
-
-    /// Return whether has a specified element semantic.
-    bool HasElement(VertexElementSemantic semantic, unsigned char index = 0) const { return GetElement(semantic, index) != 0; }
-
-    /// Return whether has an element semantic with specific type.
-    bool HasElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const { return GetElement(type, semantic, index) != 0; }
-
-    /// Return offset of a element within vertex, or M_MAX_UNSIGNED if does not exist.
-    unsigned GetElementOffset(VertexElementSemantic semantic, unsigned char index = 0) const { const VertexElement* element = GetElement(semantic, index); return element ? element->offset_ : M_MAX_UNSIGNED; }
-
-    /// Return offset of a element with specific type within vertex, or M_MAX_UNSIGNED if element does not exist.
-    unsigned GetElementOffset(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const { const VertexElement* element = GetElement(type, semantic, index); return element ? element->offset_ : M_MAX_UNSIGNED; }
-
-    /// Return legacy vertex element mask. Note that both semantic and type must match the legacy element for a mask bit to be set.
-    unsigned GetElementMask() const { return elementMask_; }
-
-    /// Return CPU memory shadow data.
-    unsigned char* GetShadowData() const { return shadowData_.Get(); }
-
-    /// Return shared array pointer to the CPU memory shadow data.
-    SharedArrayPtr<unsigned char> GetShadowDataShared() const { return shadowData_; }
-
-    /// Return buffer hash for building vertex declarations. Used internally.
-    unsigned long long GetBufferHash(unsigned streamIndex) { return elementHash_ << (streamIndex * 16); }
-
-    /// Return element with specified type and semantic from a vertex element list, or null if does not exist.
-    static const VertexElement* GetElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
-
-    /// Return whether element list has a specified element type and semantic.
-    static bool HasElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
-
-    /// Return element offset for specified type and semantic from a vertex element list, or M_MAX_UNSIGNED if does not exist.
-    static unsigned GetElementOffset(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
-
-    /// Return a vertex element list from a legacy element bitmask.
-    static PODVector<VertexElement> GetElements(unsigned elementMask);
-
-    /// Return vertex size from an element list.
-    static unsigned GetVertexSize(const PODVector<VertexElement>& elements);
-
-    /// Return vertex size for a legacy vertex element bitmask.
-    static unsigned GetVertexSize(unsigned elementMask);
-
-private:
-    /// Update vertex size, offsets of vertex elements and the element hash.
-    void UpdateOffsets();
-    /// Create buffer.
-    bool Create();
-    /// Update the shadow data to the GPU buffer.
-    bool UpdateToGPU();
-    /// Map the GPU buffer into CPU memory.
-    void* MapBuffer(unsigned start, unsigned count, bool discard);
-    /// Unmap the GPU buffer.
-    void UnmapBuffer();
-
-    /// Shadow data.
-    SharedArrayPtr<unsigned char> shadowData_;
-    /// Number of vertices.
-    unsigned vertexCount_;
-    /// Vertex size.
-    unsigned vertexSize_;
-    /// Vertex elements.
-    PODVector<VertexElement> elements_;
-    /// Vertex element hash.
-    unsigned long long elementHash_;
-    /// Vertex element legacy bitmask.
-    unsigned elementMask_;
-    /// Memory pool.
-    unsigned pool_;
-    /// Usage type.
-    unsigned usage_;
-    /// Buffer locking state.
-    LockState lockState_;
-    /// Lock start vertex.
-    unsigned lockStart_;
-    /// Lock number of vertices.
-    unsigned lockCount_;
-    /// Scratch buffer for fallback locking.
-    void* lockScratchData_;
-    /// Shadowed flag.
-    bool shadowed_;
-};
-
-}

+ 4 - 1
Source/Urho3D/Graphics/GPUObject.cpp

@@ -35,8 +35,11 @@ GPUObject::GPUObject(Graphics* graphics) :
     dataLost_(false),
     dataLost_(false),
     dataPending_(false)
     dataPending_(false)
 {
 {
-    object_.ptr_ = 0;
+#ifdef URHO3D_OPENGL
     object_.name_ = 0;
     object_.name_ = 0;
+#else
+    object_.ptr_ = 0;
+#endif
 
 
     if (graphics_)
     if (graphics_)
         graphics->AddGPUObject(this);
         graphics->AddGPUObject(this);

+ 104 - 0
Source/Urho3D/Graphics/IndexBuffer.cpp

@@ -0,0 +1,104 @@
+//
+// 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.
+//
+
+// This file contains IndexBuffer code common to all graphics APIs.
+
+#include "../Precompiled.h"
+
+#include "../Graphics/Graphics.h"
+#include "../Graphics/IndexBuffer.h"
+#include "../IO/Log.h"
+
+#include "../DebugNew.h"
+
+namespace Urho3D
+{
+
+IndexBuffer::IndexBuffer(Context* context, bool forceHeadless) :
+    Object(context),
+    GPUObject(forceHeadless ? (Graphics*)0 : GetSubsystem<Graphics>()),
+    indexCount_(0),
+    indexSize_(0),
+    lockState_(LOCK_NONE),
+    lockStart_(0),
+    lockCount_(0),
+    lockScratchData_(0),
+    shadowed_(false),
+    dynamic_(false)
+{
+    // Force shadowing mode if graphics subsystem does not exist
+    if (!graphics_)
+        shadowed_ = true;
+}
+
+IndexBuffer::~IndexBuffer()
+{
+    Release();
+}
+
+bool IndexBuffer::GetUsedVertexRange(unsigned start, unsigned count, unsigned& minVertex, unsigned& vertexCount)
+{
+    if (!shadowData_)
+    {
+        URHO3D_LOGERROR("Used vertex range can only be queried from an index buffer with shadow data");
+        return false;
+    }
+
+    if (start + count > indexCount_)
+    {
+        URHO3D_LOGERROR("Illegal index range for querying used vertices");
+        return false;
+    }
+
+    minVertex = M_MAX_UNSIGNED;
+    unsigned maxVertex = 0;
+
+    if (indexSize_ == sizeof(unsigned))
+    {
+        unsigned* indices = ((unsigned*)shadowData_.Get()) + start;
+
+        for (unsigned i = 0; i < count; ++i)
+        {
+            if (indices[i] < minVertex)
+                minVertex = indices[i];
+            if (indices[i] > maxVertex)
+                maxVertex = indices[i];
+        }
+    }
+    else
+    {
+        unsigned short* indices = ((unsigned short*)shadowData_.Get()) + start;
+
+        for (unsigned i = 0; i < count; ++i)
+        {
+            if (indices[i] < minVertex)
+                minVertex = indices[i];
+            if (indices[i] > maxVertex)
+                maxVertex = indices[i];
+        }
+    }
+
+    vertexCount = maxVertex - minVertex + 1;
+    return true;
+}
+
+}

+ 96 - 7
Source/Urho3D/Graphics/IndexBuffer.h

@@ -22,10 +22,99 @@
 
 
 #pragma once
 #pragma once
 
 
-#if defined(URHO3D_OPENGL)
-#include "OpenGL/OGLIndexBuffer.h"
-#elif defined(URHO3D_D3D11)
-#include "Direct3D11/D3D11IndexBuffer.h"
-#else
-#include "Direct3D9/D3D9IndexBuffer.h"
-#endif
+#include "../Core/Object.h"
+#include "../Container/ArrayPtr.h"
+#include "../Graphics/GPUObject.h"
+#include "../Graphics/GraphicsDefs.h"
+
+namespace Urho3D
+{
+
+/// Hardware index buffer.
+class URHO3D_API IndexBuffer : public Object, public GPUObject
+{
+    URHO3D_OBJECT(IndexBuffer, Object);
+
+public:
+    /// Construct. Optionally force headless (no GPU-side buffer) operation.
+    IndexBuffer(Context* context, bool forceHeadless = false);
+    /// Destruct.
+    virtual ~IndexBuffer();
+
+    /// Mark the buffer destroyed on graphics context destruction. May be a no-op depending on the API.
+    virtual void OnDeviceLost();
+
+    /// Recreate the buffer and restore data if applicable. May be a no-op depending on the API.
+    virtual void OnDeviceReset();
+
+    /// Release buffer.
+    virtual void Release();
+
+    /// Enable shadowing in CPU memory. Shadowing is forced on if the graphics subsystem does not exist.
+    void SetShadowed(bool enable);
+    /// Set size and vertex elements and dynamic mode. Previous data will be lost.
+    bool SetSize(unsigned indexCount, bool largeIndices, bool dynamic = false);
+    /// Set all data in the buffer.
+    bool SetData(const void* data);
+    /// Set a data range in the buffer. Optionally discard data outside the range.
+    bool SetDataRange(const void* data, unsigned start, unsigned count, bool discard = false);
+    /// Lock the buffer for write-only editing. Return data pointer if successful. Optionally discard data outside the range.
+    void* Lock(unsigned start, unsigned count, bool discard = false);
+    /// Unlock the buffer and apply changes to the GPU buffer.
+    void Unlock();
+
+    /// Return whether CPU memory shadowing is enabled.
+    bool IsShadowed() const { return shadowed_; }
+
+    /// Return whether is dynamic.
+    bool IsDynamic() const { return dynamic_; }
+
+    /// Return whether is currently locked.
+    bool IsLocked() const { return lockState_ != LOCK_NONE; }
+
+    /// Return number of indices.
+    unsigned GetIndexCount() const { return indexCount_; }
+
+    /// Return index size in bytes.
+    unsigned GetIndexSize() const { return indexSize_; }
+
+    /// Return used vertex range from index range.
+    bool GetUsedVertexRange(unsigned start, unsigned count, unsigned& minVertex, unsigned& vertexCount);
+
+    /// Return CPU memory shadow data.
+    unsigned char* GetShadowData() const { return shadowData_.Get(); }
+
+    /// Return shared array pointer to the CPU memory shadow data.
+    SharedArrayPtr<unsigned char> GetShadowDataShared() const { return shadowData_; }
+
+private:
+    /// Create buffer.
+    bool Create();
+    /// Update the shadow data to the GPU buffer.
+    bool UpdateToGPU();
+    /// Map the GPU buffer into CPU memory. Not used on OpenGL.
+    void* MapBuffer(unsigned start, unsigned count, bool discard);
+    /// Unmap the GPU buffer. Not used on OpenGL.
+    void UnmapBuffer();
+
+    /// Shadow data.
+    SharedArrayPtr<unsigned char> shadowData_;
+    /// Number of indices.
+    unsigned indexCount_;
+    /// Index size.
+    unsigned indexSize_;
+    /// Buffer locking state.
+    LockState lockState_;
+    /// Lock start vertex.
+    unsigned lockStart_;
+    /// Lock number of vertices.
+    unsigned lockCount_;
+    /// Scratch buffer for fallback locking.
+    void* lockScratchData_;
+    /// Dynamic flag.
+    bool dynamic_;
+    /// Shadowed flag.
+    bool shadowed_;
+};
+
+}

+ 13 - 65
Source/Urho3D/Graphics/OpenGL/OGLIndexBuffer.cpp

@@ -33,26 +33,9 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-IndexBuffer::IndexBuffer(Context* context, bool forceHeadless) :
-    Object(context),
-    GPUObject(forceHeadless ? (Graphics*)0 : GetSubsystem<Graphics>()),
-    indexCount_(0),
-    indexSize_(0),
-    lockState_(LOCK_NONE),
-    lockStart_(0),
-    lockCount_(0),
-    lockScratchData_(0),
-    shadowed_(false),
-    dynamic_(false)
+void IndexBuffer::OnDeviceLost()
 {
 {
-    // Force shadowing mode if graphics subsystem does not exist
-    if (!graphics_)
-        shadowed_ = true;
-}
-
-IndexBuffer::~IndexBuffer()
-{
-    Release();
+    GPUObject::OnDeviceLost();
 }
 }
 
 
 void IndexBuffer::OnDeviceReset()
 void IndexBuffer::OnDeviceReset()
@@ -269,52 +252,6 @@ void IndexBuffer::Unlock()
     }
     }
 }
 }
 
 
-bool IndexBuffer::GetUsedVertexRange(unsigned start, unsigned count, unsigned& minVertex, unsigned& vertexCount)
-{
-    if (!shadowData_)
-    {
-        URHO3D_LOGERROR("Used vertex range can only be queried from an index buffer with shadow data");
-        return false;
-    }
-
-    if (start + count > indexCount_)
-    {
-        URHO3D_LOGERROR("Illegal index range for querying used vertices");
-        return false;
-    }
-
-    minVertex = M_MAX_UNSIGNED;
-    unsigned maxVertex = 0;
-
-    if (indexSize_ == sizeof(unsigned))
-    {
-        unsigned* indices = ((unsigned*)shadowData_.Get()) + start;
-
-        for (unsigned i = 0; i < count; ++i)
-        {
-            if (indices[i] < minVertex)
-                minVertex = indices[i];
-            if (indices[i] > maxVertex)
-                maxVertex = indices[i];
-        }
-    }
-    else
-    {
-        unsigned short* indices = ((unsigned short*)shadowData_.Get()) + start;
-
-        for (unsigned i = 0; i < count; ++i)
-        {
-            if (indices[i] < minVertex)
-                minVertex = indices[i];
-            if (indices[i] > maxVertex)
-                maxVertex = indices[i];
-        }
-    }
-
-    vertexCount = maxVertex - minVertex + 1;
-    return true;
-}
-
 bool IndexBuffer::Create()
 bool IndexBuffer::Create()
 {
 {
     if (!indexCount_)
     if (!indexCount_)
@@ -354,4 +291,15 @@ bool IndexBuffer::UpdateToGPU()
         return false;
         return false;
 }
 }
 
 
+void* IndexBuffer::MapBuffer(unsigned start, unsigned count, bool discard)
+{
+    // Never called on OpenGL
+    return 0;
+}
+
+void IndexBuffer::UnmapBuffer()
+{
+    // Never called on OpenGL
+}
+
 }
 }

+ 0 - 112
Source/Urho3D/Graphics/OpenGL/OGLIndexBuffer.h

@@ -1,112 +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/ArrayPtr.h"
-#include "../../Core/Object.h"
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-
-namespace Urho3D
-{
-
-/// Hardware index buffer.
-class URHO3D_API IndexBuffer : public Object, public GPUObject
-{
-    URHO3D_OBJECT(IndexBuffer, Object);
-
-public:
-    /// Construct.
-    IndexBuffer(Context* context, bool forceHeadless = false);
-    /// Destruct.
-    virtual ~IndexBuffer();
-
-    /// Recreate the GPU resource and restore data if applicable.
-    virtual void OnDeviceReset();
-    /// Release the buffer.
-    virtual void Release();
-
-    /// Enable shadowing in CPU memory. Shadowing is forced on if the graphics subsystem does not exist.
-    void SetShadowed(bool enable);
-    /// Set buffer size and dynamic mode. Previous data will be lost.
-    bool SetSize(unsigned indexCount, bool largeIndices, bool dynamic = false);
-    /// Set all data in the buffer.
-    bool SetData(const void* data);
-    /// Set a data range in the buffer. Optionally discard data outside the range.
-    bool SetDataRange(const void* data, unsigned start, unsigned count, bool discard = false);
-    /// Lock the buffer for write-only editing. Return data pointer if successful. Optionally discard data outside the range.
-    void* Lock(unsigned start, unsigned count, bool discard = false);
-    /// Unlock the buffer and apply changes to the GPU buffer.
-    void Unlock();
-
-    /// Return whether CPU memory shadowing is enabled.
-    bool IsShadowed() const { return shadowed_; }
-
-    /// Return whether is dynamic.
-    bool IsDynamic() const { return dynamic_; }
-
-    /// Return whether is currently locked.
-    bool IsLocked() const { return lockState_ != LOCK_NONE; }
-
-    /// Return number of indices.
-    unsigned GetIndexCount() const { return indexCount_; }
-
-    /// Return index size in bytes.
-    unsigned GetIndexSize() const { return indexSize_; }
-
-    /// Return used vertex range from index range. Only supported for shadowed buffers.
-    bool GetUsedVertexRange(unsigned start, unsigned count, unsigned& minVertex, unsigned& vertexCount);
-
-    /// Return CPU memory shadow data.
-    unsigned char* GetShadowData() const { return shadowData_.Get(); }
-
-    /// Return shared array pointer to the CPU memory shadow data.
-    SharedArrayPtr<unsigned char> GetShadowDataShared() const { return shadowData_; }
-
-private:
-    /// Create buffer.
-    bool Create();
-    /// Update the shadow data to the GPU buffer.
-    bool UpdateToGPU();
-
-    /// Shadow data.
-    SharedArrayPtr<unsigned char> shadowData_;
-    /// Number of indices.
-    unsigned indexCount_;
-    /// Index size.
-    unsigned indexSize_;
-    /// Buffer locking state.
-    LockState lockState_;
-    /// Lock start vertex.
-    unsigned lockStart_;
-    /// Lock number of vertices.
-    unsigned lockCount_;
-    /// Scratch buffer for fallback locking.
-    void* lockScratchData_;
-    /// Shadowed flag.
-    bool shadowed_;
-    /// Dynamic flag.
-    bool dynamic_;
-};
-
-}

+ 13 - 125
Source/Urho3D/Graphics/OpenGL/OGLVertexBuffer.cpp

@@ -32,28 +32,9 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-VertexBuffer::VertexBuffer(Context* context, bool forceHeadless) :
-    Object(context),
-    GPUObject(forceHeadless ? (Graphics*)0 : GetSubsystem<Graphics>()),
-    vertexCount_(0),
-    elementMask_(0),
-    lockState_(LOCK_NONE),
-    lockStart_(0),
-    lockCount_(0),
-    lockScratchData_(0),
-    shadowed_(false),
-    dynamic_(false)
+void VertexBuffer::OnDeviceLost()
 {
 {
-    UpdateOffsets();
-
-    // Force shadowing mode if graphics subsystem does not exist
-    if (!graphics_)
-        shadowed_ = true;
-}
-
-VertexBuffer::~VertexBuffer()
-{
-    Release();
+    GPUObject::OnDeviceLost();
 }
 }
 
 
 void VertexBuffer::OnDeviceReset()
 void VertexBuffer::OnDeviceReset()
@@ -281,110 +262,6 @@ void VertexBuffer::Unlock()
     }
     }
 }
 }
 
 
-void VertexBuffer::UpdateOffsets()
-{
-    unsigned elementOffset = 0;
-    elementHash_ = 0;
-    elementMask_ = 0;
-
-    for (PODVector<VertexElement>::Iterator i = elements_.Begin(); i != elements_.End(); ++i)
-    {
-        i->offset_ = elementOffset;
-        elementOffset += ELEMENT_TYPESIZES[i->type_];
-        elementHash_ <<= 6;
-        elementHash_ += (((int)i->type_ + 1) * ((int)i->semantic_ + 1) + i->index_);
-
-        for (unsigned j = 0; j < MAX_LEGACY_VERTEX_ELEMENTS; ++j)
-        {
-            const VertexElement& legacy = LEGACY_VERTEXELEMENTS[j];
-            if (i->type_ == legacy.type_ && i->semantic_ == legacy.semantic_ && i->index_ == legacy.index_)
-                elementMask_ |= (1 << j);
-        }
-    }
-
-    vertexSize_ = elementOffset;
-}
-
-const VertexElement* VertexBuffer::GetElement(VertexElementSemantic semantic, unsigned char index) const
-{
-    for (PODVector<VertexElement>::ConstIterator i = elements_.Begin(); i != elements_.End(); ++i)
-    {
-        if (i->semantic_ == semantic && i->index_ == index)
-            return &(*i);
-    }
-
-    return 0;
-}
-
-const VertexElement* VertexBuffer::GetElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index) const
-{
-    for (PODVector<VertexElement>::ConstIterator i = elements_.Begin(); i != elements_.End(); ++i)
-    {
-        if (i->type_ == type && i->semantic_ == semantic && i->index_ == index)
-            return &(*i);
-    }
-
-    return 0;
-}
-
-const VertexElement* VertexBuffer::GetElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
-{
-    for (PODVector<VertexElement>::ConstIterator i = elements.Begin(); i != elements.End(); ++i)
-    {
-        if (i->type_ == type && i->semantic_ == semantic && i->index_ == index)
-            return &(*i);
-    }
-
-    return 0;
-}
-
-bool VertexBuffer::HasElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
-{
-    return GetElement(elements, type, semantic, index) != 0;
-}
-
-unsigned VertexBuffer::GetElementOffset(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
-{
-    const VertexElement* element = GetElement(elements, type, semantic, index);
-    return element ? element->offset_ : M_MAX_UNSIGNED;
-}
-
-PODVector<VertexElement> VertexBuffer::GetElements(unsigned elementMask)
-{
-    PODVector<VertexElement> ret;
-
-    for (unsigned i = 0; i < MAX_LEGACY_VERTEX_ELEMENTS; ++i)
-    {
-        if (elementMask & (1 << i))
-            ret.Push(LEGACY_VERTEXELEMENTS[i]);
-    }
-
-    return ret;
-}
-
-unsigned VertexBuffer::GetVertexSize(const PODVector<VertexElement>& elements)
-{
-    unsigned size = 0;
-
-    for (unsigned i = 0; i < elements.Size(); ++i)
-        size += ELEMENT_TYPESIZES[elements[i].type_];
-
-    return size;
-}
-
-unsigned VertexBuffer::GetVertexSize(unsigned elementMask)
-{
-    unsigned size = 0;
-
-    for (unsigned i = 0; i < MAX_LEGACY_VERTEX_ELEMENTS; ++i)
-    {
-        if (elementMask & (1 << i))
-            size += ELEMENT_TYPESIZES[LEGACY_VERTEXELEMENTS[i].type_];
-    }
-
-    return size;
-}
-
 bool VertexBuffer::Create()
 bool VertexBuffer::Create()
 {
 {
     if (!vertexCount_ || !elementMask_)
     if (!vertexCount_ || !elementMask_)
@@ -424,4 +301,15 @@ bool VertexBuffer::UpdateToGPU()
         return false;
         return false;
 }
 }
 
 
+void* VertexBuffer::MapBuffer(unsigned start, unsigned count, bool discard)
+{
+    // Never called on OpenGL
+    return 0;
+}
+
+void VertexBuffer::UnmapBuffer()
+{
+    // Never called on OpenGL
+}
+
 }
 }

+ 0 - 163
Source/Urho3D/Graphics/OpenGL/OGLVertexBuffer.h

@@ -1,163 +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/ArrayPtr.h"
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-
-namespace Urho3D
-{
-
-/// Hardware vertex buffer.
-class URHO3D_API VertexBuffer : public Object, public GPUObject
-{
-    URHO3D_OBJECT(VertexBuffer, Object);
-
-public:
-    /// Construct.
-    VertexBuffer(Context* context, bool forceHeadless = false);
-    /// Destruct.
-    virtual ~VertexBuffer();
-
-    /// Recreate the GPU resource and restore data if applicable.
-    virtual void OnDeviceReset();
-    /// Release the buffer.
-    virtual void Release();
-
-    /// Enable shadowing in CPU memory. Shadowing is forced on if the graphics subsystem does not exist.
-    void SetShadowed(bool enable);
-    /// Set size, vertex elements and dynamic mode. Previous data will be lost.
-    bool SetSize(unsigned vertexCount, const PODVector<VertexElement>& elements, bool dynamic = false);
-    /// Set size and vertex elements and dynamic mode using legacy element bitmask. Previous data will be lost.
-    bool SetSize(unsigned vertexCount, unsigned elementMask, bool dynamic = false);
-    /// Set all data in the buffer.
-    bool SetData(const void* data);
-    /// Set a data range in the buffer. Optionally discard data outside the range.
-    bool SetDataRange(const void* data, unsigned start, unsigned count, bool discard = false);
-    /// Lock the buffer for write-only editing. Return data pointer if successful. Optionally discard data outside the range.
-    void* Lock(unsigned start, unsigned count, bool discard = false);
-    /// Unlock the buffer and apply changes to the GPU buffer.
-    void Unlock();
-
-    /// Return whether CPU memory shadowing is enabled.
-    bool IsShadowed() const { return shadowed_; }
-
-    /// Return whether is dynamic.
-    bool IsDynamic() const { return dynamic_; }
-
-    /// Return whether is currently locked.
-    bool IsLocked() const { return lockState_ != LOCK_NONE; }
-
-    /// Return number of vertices.
-    unsigned GetVertexCount() const { return vertexCount_; }
-
-    /// Return vertex size in bytes.
-    unsigned GetVertexSize() const { return vertexSize_; }
-
-    /// Return vertex elements.
-    const PODVector<VertexElement>& GetElements() const { return elements_; }
-
-    /// Return vertex element, or null if does not exist.
-    const VertexElement* GetElement(VertexElementSemantic semantic, unsigned char index = 0) const;
-
-    /// Return vertex element with specific type, or null if does not exist.
-    const VertexElement* GetElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const;
-
-    /// Return whether has a specified element semantic.
-    bool HasElement(VertexElementSemantic semantic, unsigned char index = 0) const { return GetElement(semantic, index) != 0; }
-
-    /// Return whether has an element semantic with specific type.
-    bool HasElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const { return GetElement(type, semantic, index) != 0; }
-
-    /// Return offset of a element within vertex, or M_MAX_UNSIGNED if does not exist.
-    unsigned GetElementOffset(VertexElementSemantic semantic, unsigned char index = 0) const { const VertexElement* element = GetElement(semantic, index); return element ? element->offset_ : M_MAX_UNSIGNED; }
-
-    /// Return offset of a element with specific type within vertex, or M_MAX_UNSIGNED if element does not exist.
-    unsigned GetElementOffset(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const { const VertexElement* element = GetElement(type, semantic, index); return element ? element->offset_ : M_MAX_UNSIGNED; }
-
-    /// Return legacy vertex element mask. Note that both semantic and type must match the legacy element for a mask bit to be set.
-    unsigned GetElementMask() const { return elementMask_; }
-
-    /// Return CPU memory shadow data.
-    unsigned char* GetShadowData() const { return shadowData_.Get(); }
-
-    /// Return shared array pointer to the CPU memory shadow data.
-    SharedArrayPtr<unsigned char> GetShadowDataShared() const { return shadowData_; }
-
-    /// Return buffer hash for building vertex declarations. Used internally.
-    unsigned long long GetBufferHash(unsigned streamIndex) { return elementHash_ << (streamIndex * 16); }
-
-    /// Return element with specified type and semantic from a vertex element list, or null if does not exist.
-    static const VertexElement* GetElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
-
-    /// Return whether element list has a specified element type and semantic.
-    static bool HasElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
-
-    /// Return element offset for specified type and semantic from a vertex element list, or M_MAX_UNSIGNED if does not exist.
-    static unsigned GetElementOffset(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
-
-    /// Return a vertex element list from a legacy element bitmask.
-    static PODVector<VertexElement> GetElements(unsigned elementMask);
-
-    /// Return vertex size from an element list.
-    static unsigned GetVertexSize(const PODVector<VertexElement>& elements);
-
-    /// Return vertex size for a legacy vertex element bitmask.
-    static unsigned GetVertexSize(unsigned elementMask);
-
-private:
-    /// Update offsets of vertex elements.
-    void UpdateOffsets();
-    /// Create buffer.
-    bool Create();
-    /// Update the shadow data to the GPU buffer.
-    bool UpdateToGPU();
-
-    /// Shadow data.
-    SharedArrayPtr<unsigned char> shadowData_;
-    /// Number of vertices.
-    unsigned vertexCount_;
-    /// Vertex size.
-    unsigned vertexSize_;
-    /// Vertex elements.
-    PODVector<VertexElement> elements_;
-    /// Vertex element hash.
-    unsigned long long elementHash_;
-    /// Vertex element legacy bitmask.
-    unsigned elementMask_;
-    /// Buffer locking state.
-    LockState lockState_;
-    /// Lock start vertex.
-    unsigned lockStart_;
-    /// Lock number of vertices.
-    unsigned lockCount_;
-    /// Scratch buffer for fallback locking.
-    void* lockScratchData_;
-    /// Shadowed flag.
-    bool shadowed_;
-    /// Dynamic flag.
-    bool dynamic_;
-};
-
-}

+ 164 - 0
Source/Urho3D/Graphics/VertexBuffer.cpp

@@ -0,0 +1,164 @@
+//
+// 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.
+//
+
+// This file contains VertexBuffer code common to all graphics APIs.
+
+#include "../Precompiled.h"
+
+#include "../Graphics/Graphics.h"
+#include "../Graphics/VertexBuffer.h"
+#include "../Math/MathDefs.h"
+
+#include "../DebugNew.h"
+
+namespace Urho3D
+{
+
+VertexBuffer::VertexBuffer(Context* context, bool forceHeadless) :
+    Object(context),
+    GPUObject(forceHeadless ? (Graphics*)0 : GetSubsystem<Graphics>()),
+    vertexCount_(0),
+    elementMask_(0),
+    lockState_(LOCK_NONE),
+    lockStart_(0),
+    lockCount_(0),
+    lockScratchData_(0),
+    shadowed_(false),
+    dynamic_(false)
+{
+    UpdateOffsets();
+
+    // Force shadowing mode if graphics subsystem does not exist
+    if (!graphics_)
+        shadowed_ = true;
+}
+
+VertexBuffer::~VertexBuffer()
+{
+    Release();
+}
+
+void VertexBuffer::UpdateOffsets()
+{
+    unsigned elementOffset = 0;
+    elementHash_ = 0;
+    elementMask_ = 0;
+
+    for (PODVector<VertexElement>::Iterator i = elements_.Begin(); i != elements_.End(); ++i)
+    {
+        i->offset_ = elementOffset;
+        elementOffset += ELEMENT_TYPESIZES[i->type_];
+        elementHash_ <<= 6;
+        elementHash_ += (((int)i->type_ + 1) * ((int)i->semantic_ + 1) + i->index_);
+
+        for (unsigned j = 0; j < MAX_LEGACY_VERTEX_ELEMENTS; ++j)
+        {
+            const VertexElement& legacy = LEGACY_VERTEXELEMENTS[j];
+            if (i->type_ == legacy.type_ && i->semantic_ == legacy.semantic_ && i->index_ == legacy.index_)
+                elementMask_ |= (1 << j);
+        }
+    }
+
+    vertexSize_ = elementOffset;
+}
+
+const VertexElement* VertexBuffer::GetElement(VertexElementSemantic semantic, unsigned char index) const
+{
+    for (PODVector<VertexElement>::ConstIterator i = elements_.Begin(); i != elements_.End(); ++i)
+    {
+        if (i->semantic_ == semantic && i->index_ == index)
+            return &(*i);
+    }
+
+    return 0;
+}
+
+const VertexElement* VertexBuffer::GetElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index) const
+{
+    for (PODVector<VertexElement>::ConstIterator i = elements_.Begin(); i != elements_.End(); ++i)
+    {
+        if (i->type_ == type && i->semantic_ == semantic && i->index_ == index)
+            return &(*i);
+    }
+
+    return 0;
+}
+
+const VertexElement* VertexBuffer::GetElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
+{
+    for (PODVector<VertexElement>::ConstIterator i = elements.Begin(); i != elements.End(); ++i)
+    {
+        if (i->type_ == type && i->semantic_ == semantic && i->index_ == index)
+            return &(*i);
+    }
+
+    return 0;
+}
+
+bool VertexBuffer::HasElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
+{
+    return GetElement(elements, type, semantic, index) != 0;
+}
+
+unsigned VertexBuffer::GetElementOffset(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index)
+{
+    const VertexElement* element = GetElement(elements, type, semantic, index);
+    return element ? element->offset_ : M_MAX_UNSIGNED;
+}
+
+PODVector<VertexElement> VertexBuffer::GetElements(unsigned elementMask)
+{
+    PODVector<VertexElement> ret;
+
+    for (unsigned i = 0; i < MAX_LEGACY_VERTEX_ELEMENTS; ++i)
+    {
+        if (elementMask & (1 << i))
+            ret.Push(LEGACY_VERTEXELEMENTS[i]);
+    }
+
+    return ret;
+}
+
+unsigned VertexBuffer::GetVertexSize(const PODVector<VertexElement>& elements)
+{
+    unsigned size = 0;
+
+    for (unsigned i = 0; i < elements.Size(); ++i)
+        size += ELEMENT_TYPESIZES[elements[i].type_];
+
+    return size;
+}
+
+unsigned VertexBuffer::GetVertexSize(unsigned elementMask)
+{
+    unsigned size = 0;
+
+    for (unsigned i = 0; i < MAX_LEGACY_VERTEX_ELEMENTS; ++i)
+    {
+        if (elementMask & (1 << i))
+            size += ELEMENT_TYPESIZES[LEGACY_VERTEXELEMENTS[i].type_];
+    }
+
+    return size;
+}
+
+}

+ 148 - 7
Source/Urho3D/Graphics/VertexBuffer.h

@@ -22,10 +22,151 @@
 
 
 #pragma once
 #pragma once
 
 
-#if defined(URHO3D_OPENGL)
-#include "OpenGL/OGLVertexBuffer.h"
-#elif defined(URHO3D_D3D11)
-#include "Direct3D11/D3D11VertexBuffer.h"
-#else
-#include "Direct3D9/D3D9VertexBuffer.h"
-#endif
+#include "../Container/ArrayPtr.h"
+#include "../Core/Object.h"
+#include "../Graphics/GPUObject.h"
+#include "../Graphics/GraphicsDefs.h"
+
+namespace Urho3D
+{
+
+/// Hardware vertex buffer.
+class URHO3D_API VertexBuffer : public Object, public GPUObject
+{
+    URHO3D_OBJECT(VertexBuffer, Object);
+
+public:
+    /// Construct. Optionally force headless (no GPU-side buffer) operation.
+    VertexBuffer(Context* context, bool forceHeadless = false);
+    /// Destruct.
+    virtual ~VertexBuffer();
+
+    /// Mark the buffer destroyed on graphics context destruction. May be a no-op depending on the API.
+    virtual void OnDeviceLost();
+
+    /// Recreate the buffer and restore data if applicable. May be a no-op depending on the API.
+    virtual void OnDeviceReset();
+
+    /// Release buffer.
+    virtual void Release();
+
+    /// Enable shadowing in CPU memory. Shadowing is forced on if the graphics subsystem does not exist.
+    void SetShadowed(bool enable);
+    /// Set size, vertex elements and dynamic mode. Previous data will be lost.
+    bool SetSize(unsigned vertexCount, const PODVector<VertexElement>& elements, bool dynamic = false);
+    /// Set size and vertex elements and dynamic mode using legacy element bitmask. Previous data will be lost.
+    bool SetSize(unsigned vertexCount, unsigned elementMask, bool dynamic = false);
+    /// Set all data in the buffer.
+    bool SetData(const void* data);
+    /// Set a data range in the buffer. Optionally discard data outside the range.
+    bool SetDataRange(const void* data, unsigned start, unsigned count, bool discard = false);
+    /// Lock the buffer for write-only editing. Return data pointer if successful. Optionally discard data outside the range.
+    void* Lock(unsigned start, unsigned count, bool discard = false);
+    /// Unlock the buffer and apply changes to the GPU buffer.
+    void Unlock();
+
+    /// Return whether CPU memory shadowing is enabled.
+    bool IsShadowed() const { return shadowed_; }
+
+    /// Return whether is dynamic.
+    bool IsDynamic() const { return dynamic_; }
+
+    /// Return whether is currently locked.
+    bool IsLocked() const { return lockState_ != LOCK_NONE; }
+
+    /// Return number of vertices.
+    unsigned GetVertexCount() const { return vertexCount_; }
+
+    /// Return vertex size in bytes.
+    unsigned GetVertexSize() const { return vertexSize_; }
+
+    /// Return vertex elements.
+    const PODVector<VertexElement>& GetElements() const { return elements_; }
+
+    /// Return vertex element, or null if does not exist.
+    const VertexElement* GetElement(VertexElementSemantic semantic, unsigned char index = 0) const;
+
+    /// Return vertex element with specific type, or null if does not exist.
+    const VertexElement* GetElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const;
+
+    /// Return whether has a specified element semantic.
+    bool HasElement(VertexElementSemantic semantic, unsigned char index = 0) const { return GetElement(semantic, index) != 0; }
+
+    /// Return whether has an element semantic with specific type.
+    bool HasElement(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const { return GetElement(type, semantic, index) != 0; }
+
+    /// Return offset of a element within vertex, or M_MAX_UNSIGNED if does not exist.
+    unsigned GetElementOffset(VertexElementSemantic semantic, unsigned char index = 0) const { const VertexElement* element = GetElement(semantic, index); return element ? element->offset_ : M_MAX_UNSIGNED; }
+
+    /// Return offset of a element with specific type within vertex, or M_MAX_UNSIGNED if element does not exist.
+    unsigned GetElementOffset(VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0) const { const VertexElement* element = GetElement(type, semantic, index); return element ? element->offset_ : M_MAX_UNSIGNED; }
+
+    /// Return legacy vertex element mask. Note that both semantic and type must match the legacy element for a mask bit to be set.
+    unsigned GetElementMask() const { return elementMask_; }
+
+    /// Return CPU memory shadow data.
+    unsigned char* GetShadowData() const { return shadowData_.Get(); }
+
+    /// Return shared array pointer to the CPU memory shadow data.
+    SharedArrayPtr<unsigned char> GetShadowDataShared() const { return shadowData_; }
+
+    /// Return buffer hash for building vertex declarations. Used internally.
+    unsigned long long GetBufferHash(unsigned streamIndex) { return elementHash_ << (streamIndex * 16); }
+
+    /// Return element with specified type and semantic from a vertex element list, or null if does not exist.
+    static const VertexElement* GetElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
+
+    /// Return whether element list has a specified element type and semantic.
+    static bool HasElement(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
+
+    /// Return element offset for specified type and semantic from a vertex element list, or M_MAX_UNSIGNED if does not exist.
+    static unsigned GetElementOffset(const PODVector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, unsigned char index = 0);
+
+    /// Return a vertex element list from a legacy element bitmask.
+    static PODVector<VertexElement> GetElements(unsigned elementMask);
+
+    /// Return vertex size from an element list.
+    static unsigned GetVertexSize(const PODVector<VertexElement>& elements);
+
+    /// Return vertex size for a legacy vertex element bitmask.
+    static unsigned GetVertexSize(unsigned elementMask);
+
+private:
+    /// Update offsets of vertex elements.
+    void UpdateOffsets();
+    /// Create buffer.
+    bool Create();
+    /// Update the shadow data to the GPU buffer.
+    bool UpdateToGPU();
+    /// Map the GPU buffer into CPU memory. Not used on OpenGL.
+    void* MapBuffer(unsigned start, unsigned count, bool discard);
+    /// Unmap the GPU buffer. Not used on OpenGL.
+    void UnmapBuffer();
+
+    /// Shadow data.
+    SharedArrayPtr<unsigned char> shadowData_;
+    /// Number of vertices.
+    unsigned vertexCount_;
+    /// Vertex size.
+    unsigned vertexSize_;
+    /// Vertex elements.
+    PODVector<VertexElement> elements_;
+    /// Vertex element hash.
+    unsigned long long elementHash_;
+    /// Vertex element legacy bitmask.
+    unsigned elementMask_;
+    /// Buffer locking state.
+    LockState lockState_;
+    /// Lock start vertex.
+    unsigned lockStart_;
+    /// Lock number of vertices.
+    unsigned lockCount_;
+    /// Scratch buffer for fallback locking.
+    void* lockScratchData_;
+    /// Dynamic flag.
+    bool dynamic_;
+    /// Shadowed flag.
+    bool shadowed_;
+};
+
+}