Procházet zdrojové kódy

Reset levelsDirty / resolveDirty when releasing a texture. Resolve multisampled texture in GetData() if necessary. Fix getting multisampled texture data on D3D9/11.

Lasse Öörni před 9 roky
rodič
revize
3d2987c2ba

+ 12 - 1
Source/Urho3D/Graphics/Direct3D11/D3D11Texture2D.cpp

@@ -299,6 +299,15 @@ bool Texture2D::GetData(unsigned level, void* dest) const
         return false;
     }
 
+    if (multiSample_ > 1 && !autoResolve_)
+    {
+        URHO3D_LOGERROR("Can not get data from multisampled texture without autoresolve");
+        return false;
+    }
+
+    if (resolveDirty_)
+        graphics_->ResolveToTexture(const_cast<Texture2D*>(this));
+
     int levelWidth = GetLevelWidth(level);
     int levelHeight = GetLevelHeight(level);
 
@@ -323,7 +332,9 @@ bool Texture2D::GetData(unsigned level, void* dest) const
         return false;
     }
 
+    ID3D11Resource* srcResource = (ID3D11Resource*)(resolveTexture_ ? resolveTexture_ : object_.ptr_);
     unsigned srcSubResource = D3D11CalcSubresource(level, 0, levels_);
+
     D3D11_BOX srcBox;
     srcBox.left = 0;
     srcBox.right = (UINT)levelWidth;
@@ -331,7 +342,7 @@ bool Texture2D::GetData(unsigned level, void* dest) const
     srcBox.bottom = (UINT)levelHeight;
     srcBox.front = 0;
     srcBox.back = 1;
-    graphics_->GetImpl()->GetDeviceContext()->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, (ID3D11Resource*)object_.ptr_,
+    graphics_->GetImpl()->GetDeviceContext()->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, srcResource,
         srcSubResource, &srcBox);
 
     D3D11_MAPPED_SUBRESOURCE mappedData;

+ 2 - 0
Source/Urho3D/Graphics/Direct3D11/D3D11Texture2DArray.cpp

@@ -70,6 +70,8 @@ void Texture2DArray::Release()
     URHO3D_SAFE_RELEASE(object_.ptr_);
     URHO3D_SAFE_RELEASE(shaderResourceView_);
     URHO3D_SAFE_RELEASE(sampler_);
+
+    levelsDirty_ = false;
 }
 
 bool Texture2DArray::SetData(unsigned layer, unsigned level, int x, int y, int width, int height, const void* data)

+ 12 - 1
Source/Urho3D/Graphics/Direct3D11/D3D11TextureCube.cpp

@@ -366,6 +366,15 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
         return false;
     }
 
+    if (multiSample_ > 1 && !autoResolve_)
+    {
+        URHO3D_LOGERROR("Can not get data from multisampled texture without autoresolve");
+        return false;
+    }
+
+    if (resolveDirty_)
+        graphics_->ResolveToTexture(const_cast<TextureCube*>(this));
+
     int levelWidth = GetLevelWidth(level);
     int levelHeight = GetLevelHeight(level);
 
@@ -390,7 +399,9 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
         return false;
     }
 
+    ID3D11Resource* srcResource = (ID3D11Resource*)(resolveTexture_ ? resolveTexture_ : object_.ptr_);
     unsigned srcSubResource = D3D11CalcSubresource(level, face, levels_);
+
     D3D11_BOX srcBox;
     srcBox.left = 0;
     srcBox.right = (UINT)levelWidth;
@@ -398,7 +409,7 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
     srcBox.bottom = (UINT)levelHeight;
     srcBox.front = 0;
     srcBox.back = 1;
-    graphics_->GetImpl()->GetDeviceContext()->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, (ID3D11Resource*)object_.ptr_,
+    graphics_->GetImpl()->GetDeviceContext()->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, srcResource,
         srcSubResource, &srcBox);
 
     D3D11_MAPPED_SUBRESOURCE mappedData;

+ 30 - 5
Source/Urho3D/Graphics/Direct3D9/D3D9Texture2D.cpp

@@ -79,6 +79,9 @@ void Texture2D::Release()
         renderSurface_->Release();
 
     URHO3D_SAFE_RELEASE(object_.ptr_);
+
+    resolveDirty_ = false;
+    levelsDirty_ = false;
 }
 
 bool Texture2D::SetData(unsigned level, int x, int y, int width, int height, const void* data)
@@ -351,6 +354,9 @@ bool Texture2D::GetData(unsigned level, void* dest) const
         return false;
     }
 
+    if (resolveDirty_)
+        graphics_->ResolveToTexture(const_cast<Texture2D*>(this));
+
     int levelWidth = GetLevelWidth(level);
     int levelHeight = GetLevelHeight(level);
 
@@ -371,22 +377,43 @@ bool Texture2D::GetData(unsigned level, void* dest) const
             return false;
         }
 
+        // If multisampled, must copy the surface of the resolve texture instead of the multisampled surface
+        IDirect3DSurface9* resolveSurface = 0;
+        if (multiSample_ > 1)
+        {
+            HRESULT hr = ((IDirect3DTexture9*)object_.ptr_)->GetSurfaceLevel(0, (IDirect3DSurface9**)&resolveSurface);
+            if (FAILED(hr))
+            {
+                URHO3D_LOGD3DERROR("Could not get surface of the resolve texture", hr);
+                URHO3D_SAFE_RELEASE(resolveSurface);
+                return false;
+            }
+        }
+
         IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
         HRESULT hr = device->CreateOffscreenPlainSurface((UINT)width_, (UINT)height_, (D3DFORMAT)format_,
             D3DPOOL_SYSTEMMEM, &offscreenSurface, 0);
         if (FAILED(hr))
         {
             URHO3D_LOGD3DERROR("Could not create surface for getting rendertarget data", hr);
-            URHO3D_SAFE_RELEASE(offscreenSurface);
+            URHO3D_SAFE_RELEASE(offscreenSurface)
+            URHO3D_SAFE_RELEASE(resolveSurface);
             return false;
         }
-        hr = device->GetRenderTargetData((IDirect3DSurface9*)renderSurface_->GetSurface(), offscreenSurface);
+        
+        if (resolveSurface)
+            hr = device->GetRenderTargetData(resolveSurface, offscreenSurface);
+        else
+            hr = device->GetRenderTargetData((IDirect3DSurface9*)renderSurface_->GetSurface(), offscreenSurface);
+        URHO3D_SAFE_RELEASE(resolveSurface);
+
         if (FAILED(hr))
         {
             URHO3D_LOGD3DERROR("Could not get rendertarget data", hr);
             URHO3D_SAFE_RELEASE(offscreenSurface);
             return false;
         }
+
         hr = offscreenSurface->LockRect(&d3dLockedRect, &d3dRect, D3DLOCK_READONLY);
         if (FAILED(hr))
         {
@@ -459,13 +486,11 @@ bool Texture2D::GetData(unsigned level, void* dest) const
     }
 
     if (offscreenSurface)
-    {
         offscreenSurface->UnlockRect();
-        URHO3D_SAFE_RELEASE(offscreenSurface);
-    }
     else
         ((IDirect3DTexture9*)object_.ptr_)->UnlockRect(level);
 
+    URHO3D_SAFE_RELEASE(offscreenSurface);
     return true;
 }
 

+ 29 - 4
Source/Urho3D/Graphics/Direct3D9/D3D9TextureCube.cpp

@@ -86,6 +86,9 @@ void TextureCube::Release()
     }
 
     URHO3D_SAFE_RELEASE(object_.ptr_);
+
+    resolveDirty_ = false;
+    levelsDirty_ = false;
 }
 
 bool TextureCube::SetData(CubeMapFace face, unsigned level, int x, int y, int width, int height, const void* data)
@@ -419,6 +422,9 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
         return false;
     }
 
+    if (resolveDirty_)
+        graphics_->ResolveToTexture(const_cast<TextureCube*>(this));
+
     int levelWidth = GetLevelWidth(level);
     int levelHeight = GetLevelHeight(level);
 
@@ -439,15 +445,36 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
             return false;
         }
 
+        // If multisampled, must copy the surface of the resolve texture instead of the multisampled surface
+        IDirect3DSurface9* resolveSurface = 0;
+        if (multiSample_ > 1)
+        {
+            HRESULT hr = ((IDirect3DCubeTexture9*)object_.ptr_)->GetCubeMapSurface((D3DCUBEMAP_FACES)face, 0,
+                (IDirect3DSurface9**)&resolveSurface);
+            if (FAILED(hr))
+            {
+                URHO3D_LOGD3DERROR("Could not get surface of the resolve texture", hr);
+                URHO3D_SAFE_RELEASE(resolveSurface);
+                return false;
+            }
+        }
+
         IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
         HRESULT hr = device->CreateOffscreenPlainSurface((UINT)width_, (UINT)height_, (D3DFORMAT)format_, D3DPOOL_SYSTEMMEM, &offscreenSurface, 0);
         if (FAILED(hr))
         {
             URHO3D_LOGD3DERROR("Could not create surface for getting rendertarget data", hr);
             URHO3D_SAFE_RELEASE(offscreenSurface);
+            URHO3D_SAFE_RELEASE(resolveSurface);
             return false;
         }
-        hr = device->GetRenderTargetData((IDirect3DSurface9*)renderSurfaces_[face]->GetSurface(), offscreenSurface);
+
+        if (resolveSurface)
+            hr = device->GetRenderTargetData(resolveSurface, offscreenSurface);
+        else
+            hr = device->GetRenderTargetData((IDirect3DSurface9*)renderSurfaces_[face]->GetSurface(), offscreenSurface);
+        URHO3D_SAFE_RELEASE(resolveSurface);
+
         if (FAILED(hr))
         {
             URHO3D_LOGD3DERROR("Could not get rendertarget data", hr);
@@ -525,13 +552,11 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
     }
 
     if (offscreenSurface)
-    {
         offscreenSurface->UnlockRect();
-        URHO3D_SAFE_RELEASE(offscreenSurface);
-    }
     else
         ((IDirect3DCubeTexture9*)object_.ptr_)->UnlockRect((D3DCUBEMAP_FACES)face, level);
 
+    URHO3D_SAFE_RELEASE(offscreenSurface);
     return true;
 }
 

+ 12 - 0
Source/Urho3D/Graphics/OpenGL/OGLTexture2D.cpp

@@ -94,6 +94,9 @@ void Texture2D::Release()
         if (renderSurface_)
             renderSurface_->Release();
     }
+
+    resolveDirty_ = false;
+    levelsDirty_ = false;
 }
 
 bool Texture2D::SetData(unsigned level, int x, int y, int width, int height, const void* data)
@@ -324,6 +327,15 @@ bool Texture2D::GetData(unsigned level, void* dest) const
         return false;
     }
 
+    if (multiSample_ > 1 && !autoResolve_)
+    {
+        URHO3D_LOGERROR("Can not get data from multisampled texture without autoresolve");
+        return false;
+    }
+    
+    if (resolveDirty_)
+        graphics_->ResolveToTexture(const_cast<Texture2D*>(this));
+
     graphics_->SetTextureForUpdate(const_cast<Texture2D*>(this));
 
     if (!IsCompressed())

+ 2 - 0
Source/Urho3D/Graphics/OpenGL/OGLTexture2DArray.cpp

@@ -93,6 +93,8 @@ void Texture2DArray::Release()
 
         object_.name_ = 0;
     }
+
+    levelsDirty_ = false;
 }
 
 bool Texture2DArray::SetData(unsigned layer, unsigned level, int x, int y, int width, int height, const void* data)

+ 12 - 0
Source/Urho3D/Graphics/OpenGL/OGLTextureCube.cpp

@@ -99,6 +99,9 @@ void TextureCube::Release()
 
         object_.name_ = 0;
     }
+
+    resolveDirty_ = false;
+    levelsDirty_ = false;
 }
 
 bool TextureCube::SetData(CubeMapFace face, unsigned level, int x, int y, int width, int height, const void* data)
@@ -390,6 +393,15 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
         return false;
     }
 
+    if (multiSample_ > 1 && !autoResolve_)
+    {
+        URHO3D_LOGERROR("Can not get data from multisampled texture without autoresolve");
+        return false;
+    }
+    
+    if (resolveDirty_)
+        graphics_->ResolveToTexture(const_cast<TextureCube*>(this));
+
     graphics_->SetTextureForUpdate(const_cast<TextureCube*>(this));
 
     if (!IsCompressed())