From 6be4608a0d8feaf5966f997c743183ca3a92fce9 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 24 Nov 2015 21:15:19 +1000 Subject: [PATCH 1/2] D3D: Fix crash on some drivers with small textures --- Source/Core/VideoBackends/D3D/D3DTexture.cpp | 14 ++++++++++---- Source/Core/VideoBackends/D3D/D3DTexture.h | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/D3DTexture.cpp index 77293a52d0..eb5d0d594a 100644 --- a/Source/Core/VideoBackends/D3D/D3DTexture.cpp +++ b/Source/Core/VideoBackends/D3D/D3DTexture.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include + #include "Common/CommonTypes.h" #include "Common/MsgHandler.h" #include "VideoBackends/D3D/D3DBase.h" @@ -13,27 +15,31 @@ namespace DX11 namespace D3D { -void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage) +void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level, D3D11_USAGE usage) { + unsigned int src_pitch = 4 * expanded_width; if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING) { D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map); - if (4 * pitch == map.RowPitch) + if (src_pitch == map.RowPitch) { memcpy(map.pData, buffer, map.RowPitch * height); } else { + // Source row size is aligned to texture block size. This can result in a different + // pitch to what the driver returns, so copy whichever is smaller. + unsigned int copy_size = std::min(src_pitch, map.RowPitch); for (unsigned int y = 0; y < height; ++y) - memcpy((u8*)map.pData + y * map.RowPitch, (u32*)buffer + y * pitch, 4 * pitch); + memcpy((u8*)map.pData + y * map.RowPitch, (u8*)buffer + y * src_pitch, copy_size); } D3D::context->Unmap(pTexture, level); } else { D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1); - D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*pitch*height); + D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, src_pitch, src_pitch * height); } } diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.h b/Source/Core/VideoBackends/D3D/D3DTexture.h index 9fb8ea3404..7118d5d979 100644 --- a/Source/Core/VideoBackends/D3D/D3DTexture.h +++ b/Source/Core/VideoBackends/D3D/D3DTexture.h @@ -11,7 +11,7 @@ namespace DX11 namespace D3D { - void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage); + void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level, D3D11_USAGE usage); } class D3DTexture2D From d1b132731dcb81aa4283564a5f9ff40a4c6b2047 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 24 Nov 2015 21:54:19 +1000 Subject: [PATCH 2/2] D3D: Remove redundant cast, move pitch calculation to caller --- Source/Core/VideoBackends/D3D/D3DTexture.cpp | 5 ++--- Source/Core/VideoBackends/D3D/D3DTexture.h | 2 +- Source/Core/VideoBackends/D3D/TextureCache.cpp | 3 ++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/D3DTexture.cpp index eb5d0d594a..b5a65c9a39 100644 --- a/Source/Core/VideoBackends/D3D/D3DTexture.cpp +++ b/Source/Core/VideoBackends/D3D/D3DTexture.cpp @@ -15,9 +15,8 @@ namespace DX11 namespace D3D { -void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level, D3D11_USAGE usage) +void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int src_pitch, unsigned int level, D3D11_USAGE usage) { - unsigned int src_pitch = 4 * expanded_width; if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING) { D3D11_MAPPED_SUBRESOURCE map; @@ -32,7 +31,7 @@ void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned // pitch to what the driver returns, so copy whichever is smaller. unsigned int copy_size = std::min(src_pitch, map.RowPitch); for (unsigned int y = 0; y < height; ++y) - memcpy((u8*)map.pData + y * map.RowPitch, (u8*)buffer + y * src_pitch, copy_size); + memcpy((u8*)map.pData + y * map.RowPitch, buffer + y * src_pitch, copy_size); } D3D::context->Unmap(pTexture, level); } diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.h b/Source/Core/VideoBackends/D3D/D3DTexture.h index 7118d5d979..86d7c188a4 100644 --- a/Source/Core/VideoBackends/D3D/D3DTexture.h +++ b/Source/Core/VideoBackends/D3D/D3DTexture.h @@ -11,7 +11,7 @@ namespace DX11 namespace D3D { - void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level, D3D11_USAGE usage); + void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int src_pitch, unsigned int level, D3D11_USAGE usage); } class D3DTexture2D diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index 1d5141ce0e..0de91068c7 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -142,7 +142,8 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture( void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) { - D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage); + unsigned int src_pitch = 4 * expanded_width; + D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, src_pitch, level, usage); } TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConfig& config)