Browse Source

GetData() on D3D11 for Texture3D & TextureCube.

Lasse Öörni 10 years ago
parent
commit
e17a88b46f

+ 1 - 1
Docs/Reference.dox

@@ -1134,7 +1134,7 @@ Direct3D9 and Direct3D11 share the same HLSL shader code. Macros and some condit
 - Both textures and samplers are defined for each texture unit. The macros in Samplers.hlsl (Sample2D, SampleCube etc.) can be used to write code that works on both APIs. These take the texture unit name without the 's' prefix.
 - Both textures and samplers are defined for each texture unit. The macros in Samplers.hlsl (Sample2D, SampleCube etc.) can be used to write code that works on both APIs. These take the texture unit name without the 's' prefix.
 - Vertex shader output position and pixel shader output color need to use the SV_POSITION and SV_TARGET semantics. The macros OUTPOSITION and OUTCOLOR0-3 can be used to select the correct semantic on both APIs. In the vertex shader, the output position should be specified last, as otherwise other interpolator outputs may not function correctly.
 - Vertex shader output position and pixel shader output color need to use the SV_POSITION and SV_TARGET semantics. The macros OUTPOSITION and OUTCOLOR0-3 can be used to select the correct semantic on both APIs. In the vertex shader, the output position should be specified last, as otherwise other interpolator outputs may not function correctly.
 - On Direct3D11 the clip plane coordinate must be calculated manually. This is indicated by the CLIPPLANE compilation define, which is added automatically by the Graphics class. See for example the LitSolid.hlsl shader.
 - On Direct3D11 the clip plane coordinate must be calculated manually. This is indicated by the CLIPPLANE compilation define, which is added automatically by the Graphics class. See for example the LitSolid.hlsl shader.
-- Direct3D11 does not support luminance and luminance-alpha texture formats, but rather use the R and RG channels. Therefore be prepared to perform swizzling in the texture reads as appropriate.
+- Direct3D11 does not support luminance and luminance-alpha texture formats, but rather uses the R and RG channels. Therefore be prepared to perform swizzling in the texture reads as appropriate.
 
 
 \section Shaders_Precaching Shader precaching
 \section Shaders_Precaching Shader precaching
 
 

+ 1 - 1
Source/Urho3D/Graphics/Direct3D11/D3D11Graphics.cpp

@@ -2204,7 +2204,7 @@ unsigned Graphics::GetLuminanceFormat()
 
 
 unsigned Graphics::GetLuminanceAlphaFormat()
 unsigned Graphics::GetLuminanceAlphaFormat()
 {
 {
-    /// \todo Not correct
+    // Note: not same sampling behavior as on D3D9; need to sample the RG channels
     return DXGI_FORMAT_R8G8_UNORM;
     return DXGI_FORMAT_R8G8_UNORM;
 }
 }
 
 

+ 53 - 7
Source/Urho3D/Graphics/Direct3D11/D3D11Texture3D.cpp

@@ -462,15 +462,61 @@ bool Texture3D::GetData(unsigned level, void* dest) const
     int levelHeight = GetLevelHeight(level);
     int levelHeight = GetLevelHeight(level);
     int levelDepth = GetLevelDepth(level);
     int levelDepth = GetLevelDepth(level);
     
     
-    int height = levelHeight;
-    if (IsCompressed())
-        height = (height + 3) >> 2;
-    
-    unsigned char* destPtr = (unsigned char*)dest;
+    D3D11_TEXTURE3D_DESC textureDesc;
+    memset(&textureDesc, 0, sizeof textureDesc);
+    textureDesc.Width = levelWidth;
+    textureDesc.Height = levelHeight;
+    textureDesc.Depth = levelDepth;
+    textureDesc.MipLevels = 1;
+    textureDesc.Format = (DXGI_FORMAT)format_;
+    textureDesc.Usage = D3D11_USAGE_STAGING;
+    textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+
+    ID3D11Texture3D* stagingTexture = 0;
+    graphics_->GetImpl()->GetDevice()->CreateTexture3D(&textureDesc, 0, &stagingTexture);
+    if (!stagingTexture)
+    {
+        LOGERROR("Failed to create staging texture for GetData");
+        return false;
+    }
+
+    unsigned srcSubResource = D3D11CalcSubresource(level, 0, levels_);
+    D3D11_BOX srcBox;
+    srcBox.left = 0;
+    srcBox.right = levelWidth;
+    srcBox.top = 0;
+    srcBox.bottom = levelHeight;
+    srcBox.front = 0;
+    srcBox.back = levelDepth;
+    graphics_->GetImpl()->GetDeviceContext()->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, (ID3D11Resource*)object_,
+        srcSubResource, &srcBox);
+
+    D3D11_MAPPED_SUBRESOURCE mappedData;
+    mappedData.pData = 0;
     unsigned rowSize = GetRowDataSize(levelWidth);
     unsigned rowSize = GetRowDataSize(levelWidth);
+    unsigned numRows = IsCompressed() ? (levelHeight + 3) >> 2 : levelHeight;
 
 
-    /// \todo Implement
-    return true;
+    graphics_->GetImpl()->GetDeviceContext()->Map((ID3D11Resource*)stagingTexture, 0, D3D11_MAP_READ, 0, &mappedData);
+    if (mappedData.pData)
+    {
+        for (unsigned page = 0; page < levelDepth; ++page)
+        {
+            for (unsigned row = 0; row < numRows; ++row)
+            {
+                memcpy((unsigned char*)dest + (page * numRows + row) * rowSize, (unsigned char*)mappedData.pData + page *
+                    mappedData.DepthPitch + row * mappedData.RowPitch, rowSize);
+            }
+        }
+        graphics_->GetImpl()->GetDeviceContext()->Unmap((ID3D11Resource*)stagingTexture, 0);
+        stagingTexture->Release();
+        return true;
+    }
+    else
+    {
+        LOGERROR("Failed to map staging texture for GetData");
+        stagingTexture->Release();
+        return false;
+    }
 }
 }
 
 
 bool Texture3D::Create()
 bool Texture3D::Create()

+ 50 - 8
Source/Urho3D/Graphics/Direct3D11/D3D11TextureCube.cpp

@@ -604,16 +604,58 @@ bool TextureCube::GetData(CubeMapFace face, unsigned level, void* dest) const
     
     
     int levelWidth = GetLevelWidth(level);
     int levelWidth = GetLevelWidth(level);
     int levelHeight = GetLevelHeight(level);
     int levelHeight = GetLevelHeight(level);
-    
-    int height = levelHeight;
-    if (IsCompressed())
-        height = (height + 3) >> 2;
-    
-    unsigned char* destPtr = (unsigned char*)dest;
+
+    D3D11_TEXTURE2D_DESC textureDesc;
+    memset(&textureDesc, 0, sizeof textureDesc);
+    textureDesc.Width = levelWidth;
+    textureDesc.Height = levelHeight;
+    textureDesc.MipLevels = 1;
+    textureDesc.ArraySize = 1;
+    textureDesc.Format = (DXGI_FORMAT)format_;
+    textureDesc.SampleDesc.Count = 1;
+    textureDesc.SampleDesc.Quality = 0;
+    textureDesc.Usage = D3D11_USAGE_STAGING;
+    textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+
+    ID3D11Texture2D* stagingTexture = 0;
+    graphics_->GetImpl()->GetDevice()->CreateTexture2D(&textureDesc, 0, &stagingTexture);
+    if (!stagingTexture)
+    {
+        LOGERROR("Failed to create staging texture for GetData");
+        return false;
+    }
+
+    unsigned srcSubResource = D3D11CalcSubresource(level, face, levels_);
+    D3D11_BOX srcBox;
+    srcBox.left = 0;
+    srcBox.right = levelWidth;
+    srcBox.top = 0;
+    srcBox.bottom = levelHeight;
+    srcBox.front = 0;
+    srcBox.back = 1;
+    graphics_->GetImpl()->GetDeviceContext()->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, (ID3D11Resource*)object_,
+        srcSubResource, &srcBox);
+
+    D3D11_MAPPED_SUBRESOURCE mappedData;
+    mappedData.pData = 0;
     unsigned rowSize = GetRowDataSize(levelWidth);
     unsigned rowSize = GetRowDataSize(levelWidth);
+    unsigned numRows = IsCompressed() ? (levelHeight + 3) >> 2 : levelHeight;
 
 
-    /// \todo Implement
-    return true;
+    graphics_->GetImpl()->GetDeviceContext()->Map((ID3D11Resource*)stagingTexture, 0, D3D11_MAP_READ, 0, &mappedData);
+    if (mappedData.pData)
+    {
+        for (unsigned row = 0; row < numRows; ++row)
+            memcpy((unsigned char*)dest + row * rowSize, (unsigned char*)mappedData.pData + row * mappedData.RowPitch, rowSize);
+        graphics_->GetImpl()->GetDeviceContext()->Unmap((ID3D11Resource*)stagingTexture, 0);
+        stagingTexture->Release();
+        return true;
+    }
+    else
+    {
+        LOGERROR("Failed to map staging texture for GetData");
+        stagingTexture->Release();
+        return false;
+    }
 }
 }
 
 
 bool TextureCube::Create()
 bool TextureCube::Create()