From 4c1deabcd30cafadae8fbe3270d42f22552917f6 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Tue, 26 May 2020 13:11:24 +0100 Subject: [PATCH] [d3d9] Don't expose surfaces for autogenned mips --- src/d3d9/d3d9_common_texture.cpp | 5 ++ src/d3d9/d3d9_common_texture.h | 4 ++ src/d3d9/d3d9_texture.cpp | 84 +++++++++++++++----------------- src/d3d9/d3d9_texture.h | 5 +- 4 files changed, 50 insertions(+), 48 deletions(-) diff --git a/src/d3d9/d3d9_common_texture.cpp b/src/d3d9/d3d9_common_texture.cpp index 524fa76b..61cf6fa9 100644 --- a/src/d3d9/d3d9_common_texture.cpp +++ b/src/d3d9/d3d9_common_texture.cpp @@ -55,6 +55,11 @@ namespace dxvk { if (m_mapMode == D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM) CreateBuffers(); + + m_exposedMipLevels = m_desc.MipLevels; + + if (m_desc.Usage & D3DUSAGE_AUTOGENMIPMAP) + m_exposedMipLevels = 1; } diff --git a/src/d3d9/d3d9_common_texture.h b/src/d3d9/d3d9_common_texture.h index 7e13d0d9..73e49b5b 100644 --- a/src/d3d9/d3d9_common_texture.h +++ b/src/d3d9/d3d9_common_texture.h @@ -354,6 +354,8 @@ namespace dxvk { bool NeedsAnyUpload() { return m_needsUpload.any(); } void ClearNeedsUpload() { return m_needsUpload.clearAll(); } + DWORD ExposedMipLevels() { return m_exposedMipLevels; } + private: D3D9DeviceEx* m_device; @@ -391,6 +393,8 @@ namespace dxvk { D3D9SubresourceBitset m_uploading = { }; D3D9SubresourceBitset m_needsUpload = { }; + DWORD m_exposedMipLevels = 0; + /** * \brief Mip level * \returns Size of packed mip level in bytes diff --git a/src/d3d9/d3d9_texture.cpp b/src/d3d9/d3d9_texture.cpp index 6331e8c0..38fd450c 100644 --- a/src/d3d9/d3d9_texture.cpp +++ b/src/d3d9/d3d9_texture.cpp @@ -38,41 +38,43 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D9Texture2D::GetLevelDesc(UINT Level, D3DSURFACE_DESC *pDesc) { - auto* surface = GetSubresource(Level); - if (surface == nullptr) + if (unlikely(Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - return surface->GetDesc(pDesc); + return GetSubresource(Level)->GetDesc(pDesc); } HRESULT STDMETHODCALLTYPE D3D9Texture2D::GetSurfaceLevel(UINT Level, IDirect3DSurface9** ppSurfaceLevel) { InitReturnPtr(ppSurfaceLevel); - auto* surface = GetSubresource(Level); - if (ppSurfaceLevel == nullptr || surface == nullptr) + if (unlikely(Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - *ppSurfaceLevel = ref(surface); + if (unlikely(ppSurfaceLevel == nullptr)) + return D3DERR_INVALIDCALL; + + *ppSurfaceLevel = ref(GetSubresource(Level)); return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D9Texture2D::LockRect(UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { - auto* surface = GetSubresource(Level); - if (surface == nullptr || pLockedRect == nullptr) + if (unlikely(Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - return surface->LockRect(pLockedRect, pRect, Flags); + if (unlikely(pLockedRect == nullptr)) + return D3DERR_INVALIDCALL; + + return GetSubresource(Level)->LockRect(pLockedRect, pRect, Flags); } HRESULT STDMETHODCALLTYPE D3D9Texture2D::UnlockRect(UINT Level) { - auto* surface = GetSubresource(Level); - if (surface == nullptr) + if (unlikely(Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - return surface->UnlockRect(); + return GetSubresource(Level)->UnlockRect(); } @@ -116,41 +118,43 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D9Texture3D::GetLevelDesc(UINT Level, D3DVOLUME_DESC *pDesc) { - auto* volume = GetSubresource(Level); - if (volume == nullptr) + if (unlikely(Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - return volume->GetDesc(pDesc); + return GetSubresource(Level)->GetDesc(pDesc); } HRESULT STDMETHODCALLTYPE D3D9Texture3D::GetVolumeLevel(UINT Level, IDirect3DVolume9** ppVolumeLevel) { InitReturnPtr(ppVolumeLevel); - auto* volume = GetSubresource(Level); - if (ppVolumeLevel == nullptr || volume == nullptr) + if (unlikely(Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - *ppVolumeLevel = ref(volume); + if (unlikely(ppVolumeLevel == nullptr)) + return D3DERR_INVALIDCALL; + + *ppVolumeLevel = ref(GetSubresource(Level)); return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D9Texture3D::LockBox(UINT Level, D3DLOCKED_BOX* pLockedBox, CONST D3DBOX* pBox, DWORD Flags) { - auto* volume = GetSubresource(Level); - if (volume == nullptr || pLockedBox == nullptr) + if (unlikely(Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - return volume->LockBox(pLockedBox, pBox, Flags); + if (unlikely(pLockedBox == nullptr)) + return D3DERR_INVALIDCALL; + + return GetSubresource(Level)->LockBox(pLockedBox, pBox, Flags); } HRESULT STDMETHODCALLTYPE D3D9Texture3D::UnlockBox(UINT Level) { - auto* volume = GetSubresource(Level); - if (volume == nullptr) + if (unlikely(Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - return volume->UnlockBox(); + return GetSubresource(Level)->UnlockBox(); } @@ -194,51 +198,43 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D9TextureCube::GetLevelDesc(UINT Level, D3DSURFACE_DESC *pDesc) { - auto* surface = GetSubresource(Level); - - if (surface == nullptr) + if (unlikely(Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - return surface->GetDesc(pDesc); + return GetSubresource(Level)->GetDesc(pDesc); } HRESULT STDMETHODCALLTYPE D3D9TextureCube::GetCubeMapSurface(D3DCUBEMAP_FACES Face, UINT Level, IDirect3DSurface9** ppSurfaceLevel) { InitReturnPtr(ppSurfaceLevel); - if (Level >= m_texture.Desc()->MipLevels) + if (unlikely(Level >= m_texture.ExposedMipLevels() || Face >= D3DCUBEMAP_FACES(6))) return D3DERR_INVALIDCALL; - auto* surface = GetSubresource( - m_texture.CalcSubresource(UINT(Face), Level)); - - if (ppSurfaceLevel == nullptr || surface == nullptr) + if (unlikely(ppSurfaceLevel == nullptr)) return D3DERR_INVALIDCALL; - *ppSurfaceLevel = ref(surface); + *ppSurfaceLevel = ref(GetSubresource(m_texture.CalcSubresource(UINT(Face), Level))); return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D9TextureCube::LockRect(D3DCUBEMAP_FACES Face, UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { - auto* surface = GetSubresource( - m_texture.CalcSubresource(UINT(Face), Level)); - - if (surface == nullptr || pLockedRect == nullptr) + if (unlikely(Face > D3DCUBEMAP_FACE_NEGATIVE_Z || Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - return surface->LockRect(pLockedRect, pRect, Flags); + if (unlikely(pLockedRect == nullptr)) + return D3DERR_INVALIDCALL; + + return GetSubresource(m_texture.CalcSubresource(UINT(Face), Level))->LockRect(pLockedRect, pRect, Flags); } HRESULT STDMETHODCALLTYPE D3D9TextureCube::UnlockRect(D3DCUBEMAP_FACES Face, UINT Level) { - auto* surface = GetSubresource( - m_texture.CalcSubresource(UINT(Face), Level)); - - if (surface == nullptr) + if (unlikely(Face > D3DCUBEMAP_FACE_NEGATIVE_Z || Level >= m_texture.ExposedMipLevels())) return D3DERR_INVALIDCALL; - return surface->UnlockRect(); + return GetSubresource(m_texture.CalcSubresource(UINT(Face), Level))->UnlockRect(); } diff --git a/src/d3d9/d3d9_texture.h b/src/d3d9/d3d9_texture.h index be19d327..5ea08938 100644 --- a/src/d3d9/d3d9_texture.h +++ b/src/d3d9/d3d9_texture.h @@ -71,7 +71,7 @@ namespace dxvk { } DWORD STDMETHODCALLTYPE GetLevelCount() final { - return m_texture.Desc()->MipLevels; + return m_texture.ExposedMipLevels(); } HRESULT STDMETHODCALLTYPE SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType) final { @@ -93,9 +93,6 @@ namespace dxvk { } SubresourceType* GetSubresource(UINT Subresource) { - if (unlikely(Subresource >= m_subresources.size())) - return nullptr; - return reinterpret_cast(&m_subresources[Subresource]); }