1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-15 16:29:16 +01:00

[d3d9] Use memory mapped files for textures

This commit is contained in:
Robin Kertels 2022-03-16 02:28:22 +01:00 committed by Joshie
parent d598fd3156
commit 6ca6554452
5 changed files with 146 additions and 72 deletions

View File

@ -40,7 +40,8 @@ namespace dxvk {
m_shadow = DetermineShadowState(); m_shadow = DetermineShadowState();
m_supportsFetch4 = DetermineFetch4Compatibility(); m_supportsFetch4 = DetermineFetch4Compatibility();
if (m_mapMode == D3D9_COMMON_TEXTURE_MAP_MODE_BACKED) { const bool createImage = m_desc.Pool != D3DPOOL_SYSTEMMEM && m_desc.Pool != D3DPOOL_SCRATCH && m_desc.Format != D3D9Format::NULL_FORMAT;
if (createImage) {
bool plainSurface = m_type == D3DRTYPE_SURFACE && bool plainSurface = m_type == D3DRTYPE_SURFACE &&
!(m_desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)); !(m_desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL));
@ -73,7 +74,9 @@ namespace dxvk {
} }
} }
if (m_mapMode == D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM) if (m_mapMode == D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE)
AllocData();
else if (m_mapMode != D3D9_COMMON_TEXTURE_MAP_MODE_NONE && m_desc.Pool != D3DPOOL_DEFAULT)
CreateBuffers(); CreateBuffers();
m_exposedMipLevels = m_desc.MipLevels; m_exposedMipLevels = m_desc.MipLevels;
@ -165,11 +168,16 @@ namespace dxvk {
return D3D_OK; return D3D_OK;
} }
void* D3D9CommonTexture::GetData(UINT Subresource) {
if (unlikely(m_mappedSlices[Subresource].mapPtr != nullptr || m_mapMode != D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE))
return m_mappedSlices[Subresource].mapPtr;
bool D3D9CommonTexture::CreateBufferSubresource(UINT Subresource) { D3D9Memory& memory = m_data[Subresource];
if (m_buffers[Subresource] != nullptr) memory.Map();
return false; return memory.Ptr();
}
void D3D9CommonTexture::CreateBufferSubresource(UINT Subresource) {
DxvkBufferCreateInfo info; DxvkBufferCreateInfo info;
info.size = GetMipSize(Subresource); info.size = GetMipSize(Subresource);
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
@ -190,8 +198,6 @@ namespace dxvk {
m_buffers[Subresource] = m_device->GetDXVKDevice()->createBuffer(info, memType); m_buffers[Subresource] = m_device->GetDXVKDevice()->createBuffer(info, memType);
m_mappedSlices[Subresource] = m_buffers[Subresource]->getSliceHandle(); m_mappedSlices[Subresource] = m_buffers[Subresource]->getSliceHandle();
return true;
} }
@ -477,6 +483,20 @@ namespace dxvk {
return VK_IMAGE_LAYOUT_GENERAL; return VK_IMAGE_LAYOUT_GENERAL;
} }
D3D9_COMMON_TEXTURE_MAP_MODE D3D9CommonTexture::DetermineMapMode() const {
if (m_desc.Format == D3D9Format::NULL_FORMAT)
return D3D9_COMMON_TEXTURE_MAP_MODE_NONE;
#ifdef D3D9_ALLOW_UNMAPPING
if (m_desc.Pool != D3DPOOL_DEFAULT)
return D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE;
#endif
if (m_desc.Pool == D3DPOOL_SYSTEMMEM || m_desc.Pool == D3DPOOL_SCRATCH)
return D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM;
return D3D9_COMMON_TEXTURE_MAP_MODE_BACKED;
}
void D3D9CommonTexture::ExportImageInfo() { void D3D9CommonTexture::ExportImageInfo() {
/* From MSDN: /* From MSDN:
@ -606,5 +626,30 @@ namespace dxvk {
m_sampleView.Srgb = CreateView(AllLayers, Lod, VK_IMAGE_USAGE_SAMPLED_BIT, true); m_sampleView.Srgb = CreateView(AllLayers, Lod, VK_IMAGE_USAGE_SAMPLED_BIT, true);
} }
void D3D9CommonTexture::AllocData() {
// D3D9Initializer will handle clearing the data
const uint32_t count = CountSubresources();
for (uint32_t i = 0; i < count; i++) {
m_data[i] = m_device->GetAllocator()->Alloc(GetMipSize(i));
}
}
const Rc<DxvkBuffer>& D3D9CommonTexture::GetBuffer(UINT Subresource, bool Initialize) {
if (unlikely(m_buffers[Subresource] == nullptr)) {
CreateBufferSubresource(Subresource);
if (Initialize) {
if (m_data[Subresource]) {
m_data[Subresource].Map();
memcpy(m_mappedSlices[Subresource].mapPtr, m_data[Subresource].Ptr(), GetMipSize(Subresource));
} else {
memset(m_mappedSlices[Subresource].mapPtr, 0, GetMipSize(Subresource));
}
}
m_data[Subresource] = {};
}
return m_buffers[Subresource];
}
} }

View File

@ -3,6 +3,7 @@
#include "d3d9_format.h" #include "d3d9_format.h"
#include "d3d9_util.h" #include "d3d9_util.h"
#include "d3d9_caps.h" #include "d3d9_caps.h"
#include "d3d9_mem.h"
#include "../dxvk/dxvk_device.h" #include "../dxvk/dxvk_device.h"
@ -22,6 +23,7 @@ namespace dxvk {
D3D9_COMMON_TEXTURE_MAP_MODE_NONE, ///< No mapping available D3D9_COMMON_TEXTURE_MAP_MODE_NONE, ///< No mapping available
D3D9_COMMON_TEXTURE_MAP_MODE_BACKED, ///< Mapped image through buffer D3D9_COMMON_TEXTURE_MAP_MODE_BACKED, ///< Mapped image through buffer
D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM, ///< Only a buffer - no image D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM, ///< Only a buffer - no image
D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE, ///< Non-Vulkan memory that can be unmapped
}; };
/** /**
@ -141,9 +143,17 @@ namespace dxvk {
return m_resolveImage; return m_resolveImage;
} }
const Rc<DxvkBuffer>& GetBuffer(UINT Subresource) { /**
return m_buffers[Subresource]; * \brief Returns a pointer to the internal data used for LockRect/LockBox
} *
* This works regardless of the map mode used by this texture
* and will map the memory if necessary.
* \param [in] Subresource Subresource index
* @return Pointer to locking data
*/
void* GetData(UINT Subresource);
const Rc<DxvkBuffer>& GetBuffer(UINT Subresource, bool Initialize);
DxvkBufferSliceHandle GetMappedSlice(UINT Subresource) { DxvkBufferSliceHandle GetMappedSlice(UINT Subresource) {
@ -215,24 +225,16 @@ namespace dxvk {
return Face * m_desc.MipLevels + MipLevel; return Face * m_desc.MipLevels + MipLevel;
} }
/** void UnmapData(UINT Subresource) {
* \brief Creates buffers m_data[Subresource].Unmap();
* Creates mapping and staging buffers for all subresources
* allocates new buffers if necessary
*/
void CreateBuffers() {
const uint32_t count = CountSubresources();
for (uint32_t i = 0; i < count; i++)
CreateBufferSubresource(i);
} }
/** void UnmapData() {
* \brief Creates a buffer const uint32_t subresources = CountSubresources();
* Creates mapping and staging buffers for a given subresource for (uint32_t i = 0; i < subresources; i++) {
* allocates new buffers if necessary m_data[i].Unmap();
* \returns Whether an allocation happened }
*/ }
bool CreateBufferSubresource(UINT Subresource);
/** /**
* \brief Destroys a buffer * \brief Destroys a buffer
@ -456,6 +458,12 @@ namespace dxvk {
: 0ull; : 0ull;
} }
/**
* \brief Mip level
* \returns Size of packed mip level in bytes
*/
VkDeviceSize GetMipSize(UINT Subresource) const;
private: private:
D3D9DeviceEx* m_device; D3D9DeviceEx* m_device;
@ -468,7 +476,9 @@ namespace dxvk {
D3D9SubresourceArray< D3D9SubresourceArray<
Rc<DxvkBuffer>> m_buffers; Rc<DxvkBuffer>> m_buffers;
D3D9SubresourceArray< D3D9SubresourceArray<
DxvkBufferSliceHandle> m_mappedSlices; DxvkBufferSliceHandle> m_mappedSlices = { };
D3D9SubresourceArray<
D3D9Memory> m_data = { };
D3D9SubresourceArray< D3D9SubresourceArray<
uint64_t> m_seqs = { }; uint64_t> m_seqs = { };
@ -503,12 +513,6 @@ namespace dxvk {
std::array<D3DBOX, 6> m_dirtyBoxes; std::array<D3DBOX, 6> m_dirtyBoxes;
/**
* \brief Mip level
* \returns Size of packed mip level in bytes
*/
VkDeviceSize GetMipSize(UINT Subresource) const;
Rc<DxvkImage> CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT, HANDLE* pSharedHandle) const; Rc<DxvkImage> CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT, HANDLE* pSharedHandle) const;
Rc<DxvkImage> CreateResolveImage() const; Rc<DxvkImage> CreateResolveImage() const;
@ -525,15 +529,7 @@ namespace dxvk {
VkFormat Format, VkFormat Format,
VkImageTiling Tiling) const; VkImageTiling Tiling) const;
D3D9_COMMON_TEXTURE_MAP_MODE DetermineMapMode() const { D3D9_COMMON_TEXTURE_MAP_MODE DetermineMapMode() const;
if (m_desc.Format == D3D9Format::NULL_FORMAT)
return D3D9_COMMON_TEXTURE_MAP_MODE_NONE;
if (m_desc.Pool == D3DPOOL_SYSTEMMEM || m_desc.Pool == D3DPOOL_SCRATCH)
return D3D9_COMMON_TEXTURE_MAP_MODE_SYSTEMMEM;
return D3D9_COMMON_TEXTURE_MAP_MODE_BACKED;
}
VkImageLayout OptimizeLayout( VkImageLayout OptimizeLayout(
VkImageUsageFlags Usage) const; VkImageUsageFlags Usage) const;
@ -544,6 +540,28 @@ namespace dxvk {
D3DRESOURCETYPE Dimension, D3DRESOURCETYPE Dimension,
UINT Layer); UINT Layer);
/**
* \brief Creates a buffer
* Creates mapping and staging buffers for a given subresource
* allocates new buffers if necessary
* \returns Whether an allocation happened
*/
void CreateBufferSubresource(UINT Subresource);
/**
* \brief Creates buffers
* Creates mapping and staging buffers for all subresources
* allocates new buffers if necessary
*/
void CreateBuffers() {
// D3D9Initializer will handle clearing the buffers
const uint32_t count = CountSubresources();
for (uint32_t i = 0; i < count; i++)
CreateBufferSubresource(i);
}
void AllocData();
static constexpr UINT AllLayers = UINT32_MAX; static constexpr UINT AllLayers = UINT32_MAX;
}; };

View File

@ -876,7 +876,10 @@ namespace dxvk {
if (dstTexInfo->Desc()->Pool == D3DPOOL_DEFAULT) if (dstTexInfo->Desc()->Pool == D3DPOOL_DEFAULT)
return this->StretchRect(pRenderTarget, nullptr, pDestSurface, nullptr, D3DTEXF_NONE); return this->StretchRect(pRenderTarget, nullptr, pDestSurface, nullptr, D3DTEXF_NONE);
Rc<DxvkBuffer> dstBuffer = dstTexInfo->GetBuffer(dst->GetSubresource()); VkExtent3D dstTexExtent = dstTexInfo->GetExtentMip(dst->GetMipLevel());
VkExtent3D srcTexExtent = srcTexInfo->GetExtentMip(src->GetMipLevel());
Rc<DxvkBuffer> dstBuffer = dstTexInfo->GetBuffer(dst->GetSubresource(), dstTexExtent.width > srcTexExtent.width || dstTexExtent.height > srcTexExtent.height);
Rc<DxvkImage> srcImage = srcTexInfo->GetImage(); Rc<DxvkImage> srcImage = srcTexInfo->GetImage();
const DxvkFormatInfo* srcFormatInfo = lookupFormatInfo(srcImage->info().format); const DxvkFormatInfo* srcFormatInfo = lookupFormatInfo(srcImage->info().format);
@ -887,9 +890,8 @@ namespace dxvk {
srcSubresource.mipLevel, srcSubresource.mipLevel,
srcSubresource.arrayLayer, 1 }; srcSubresource.arrayLayer, 1 };
VkExtent3D srcExtent = srcTexInfo->GetExtentMip(src->GetMipLevel());
VkExtent3D texLevelExtentBlockCount = util::computeBlockCount(srcExtent, srcFormatInfo->blockSize); VkExtent3D texLevelExtentBlockCount = util::computeBlockCount(srcTexExtent, srcFormatInfo->blockSize);
VkDeviceSize pitch = align(texLevelExtentBlockCount.width * uint32_t(srcFormatInfo->elementSize), 4); VkDeviceSize pitch = align(texLevelExtentBlockCount.width * uint32_t(srcFormatInfo->elementSize), 4);
uint32_t pitchBlocks = uint32_t(pitch / srcFormatInfo->elementSize); uint32_t pitchBlocks = uint32_t(pitch / srcFormatInfo->elementSize);
VkExtent2D dstExtent = VkExtent2D{ pitchBlocks, VkExtent2D dstExtent = VkExtent2D{ pitchBlocks,
@ -899,7 +901,7 @@ namespace dxvk {
cBuffer = dstBuffer, cBuffer = dstBuffer,
cImage = srcImage, cImage = srcImage,
cSubresources = srcSubresourceLayers, cSubresources = srcSubresourceLayers,
cLevelExtent = srcExtent, cLevelExtent = srcTexExtent,
cDstExtent = dstExtent cDstExtent = dstExtent
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
ctx->copyImageToBuffer(cBuffer, 0, 4, 0, ctx->copyImageToBuffer(cBuffer, 0, 4, 0,
@ -4128,10 +4130,6 @@ namespace dxvk {
auto& desc = *(pResource->Desc()); auto& desc = *(pResource->Desc());
bool alloced = pResource->CreateBufferSubresource(Subresource);
const Rc<DxvkBuffer> mappedBuffer = pResource->GetBuffer(Subresource);
auto& formatMapping = pResource->GetFormatMapping(); auto& formatMapping = pResource->GetFormatMapping();
const DxvkFormatInfo* formatInfo = formatMapping.IsValid() const DxvkFormatInfo* formatInfo = formatMapping.IsValid()
@ -4182,12 +4180,14 @@ namespace dxvk {
bool needsReadback = pResource->NeedsReachback(Subresource) || renderable; bool needsReadback = pResource->NeedsReachback(Subresource) || renderable;
pResource->SetNeedsReadback(Subresource, false); pResource->SetNeedsReadback(Subresource, false);
DxvkBufferSliceHandle physSlice; void* mapPtr;
if ((Flags & D3DLOCK_DISCARD) && needsReadback) { if ((Flags & D3DLOCK_DISCARD) && needsReadback) {
// We do not have to preserve the contents of the // We do not have to preserve the contents of the
// buffer if the entire image gets discarded. // buffer if the entire image gets discarded.
physSlice = pResource->DiscardMapSlice(Subresource); const Rc<DxvkBuffer> mappedBuffer = pResource->GetBuffer(Subresource, false);
DxvkBufferSliceHandle physSlice = pResource->DiscardMapSlice(Subresource);
mapPtr = physSlice.mapPtr;
EmitCs([ EmitCs([
cImageBuffer = std::move(mappedBuffer), cImageBuffer = std::move(mappedBuffer),
@ -4196,10 +4196,15 @@ namespace dxvk {
ctx->invalidateBuffer(cImageBuffer, cBufferSlice); ctx->invalidateBuffer(cImageBuffer, cBufferSlice);
}); });
} else { } else {
physSlice = pResource->GetMappedSlice(Subresource); if (unlikely(pResource->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_BACKED)) {
// Create mapping buffer if it doesn't exist yet. (POOL_DEFAULT)
pResource->GetBuffer(Subresource, !needsReadback);
}
mapPtr = pResource->GetData(Subresource);
if (needsReadback) { if (needsReadback) {
const Rc<DxvkBuffer> mappedBuffer = pResource->GetBuffer(Subresource); const Rc<DxvkBuffer> mappedBuffer = pResource->GetBuffer(Subresource, false);
if (unlikely(needsReadback) && pResource->GetImage() != nullptr) { if (unlikely(needsReadback) && pResource->GetImage() != nullptr) {
Rc<DxvkImage> resourceImage = pResource->GetImage(); Rc<DxvkImage> resourceImage = pResource->GetImage();
@ -4274,8 +4279,6 @@ namespace dxvk {
if (!WaitForResource(mappedBuffer, pResource->GetMappingBufferSequenceNumber(Subresource), Flags)) if (!WaitForResource(mappedBuffer, pResource->GetMappingBufferSequenceNumber(Subresource), Flags))
return D3DERR_WASSTILLDRAWING; return D3DERR_WASSTILLDRAWING;
} else if (alloced) {
std::memset(physSlice.mapPtr, 0, physSlice.length);
} }
} }
@ -4332,8 +4335,7 @@ namespace dxvk {
(!atiHack) ? formatInfo : nullptr, (!atiHack) ? formatInfo : nullptr,
pBox); pBox);
uint8_t* data = reinterpret_cast<uint8_t*>(mapPtr);
uint8_t* data = reinterpret_cast<uint8_t*>(physSlice.mapPtr);
data += offset; data += offset;
pLockedBox->pBits = data; pLockedBox->pBits = data;
return D3D_OK; return D3D_OK;
@ -4419,7 +4421,6 @@ namespace dxvk {
// Now that data has been written into the buffer, // Now that data has been written into the buffer,
// we need to copy its contents into the image // we need to copy its contents into the image
const DxvkBufferSliceHandle srcSlice = pSrcTexture->GetMappedSlice(SrcSubresource);
auto formatInfo = lookupFormatInfo(image->info().format); auto formatInfo = lookupFormatInfo(image->info().format);
auto srcSubresource = pSrcTexture->GetSubresourceFromIndex( auto srcSubresource = pSrcTexture->GetSubresourceFromIndex(
@ -4462,9 +4463,10 @@ namespace dxvk {
+ srcOffsetBlockCount.y * pitch + srcOffsetBlockCount.y * pitch
+ srcOffsetBlockCount.x * formatInfo->elementSize; + srcOffsetBlockCount.x * formatInfo->elementSize;
const void* mapPtr = pSrcTexture->GetData(SrcSubresource);
VkDeviceSize dirtySize = extentBlockCount.width * extentBlockCount.height * extentBlockCount.depth * formatInfo->elementSize; VkDeviceSize dirtySize = extentBlockCount.width * extentBlockCount.height * extentBlockCount.depth * formatInfo->elementSize;
D3D9BufferSlice slice = AllocStagingBuffer(dirtySize); D3D9BufferSlice slice = AllocStagingBuffer(dirtySize);
const void* srcData = reinterpret_cast<const uint8_t*>(srcSlice.mapPtr) + copySrcOffset; const void* srcData = reinterpret_cast<const uint8_t*>(mapPtr) + copySrcOffset;
util::packImageData( util::packImageData(
slice.mapPtr, srcData, extentBlockCount, formatInfo->elementSize, slice.mapPtr, srcData, extentBlockCount, formatInfo->elementSize,
pitch, pitch * srcTexLevelExtentBlockCount.height); pitch, pitch * srcTexLevelExtentBlockCount.height);
@ -4487,6 +4489,7 @@ namespace dxvk {
} }
else { else {
const DxvkFormatInfo* formatInfo = lookupFormatInfo(pDestTexture->GetFormatMapping().FormatColor); const DxvkFormatInfo* formatInfo = lookupFormatInfo(pDestTexture->GetFormatMapping().FormatColor);
const void* mapPtr = pSrcTexture->GetData(SrcSubresource);
// Add more blocks for the other planes that we might have. // Add more blocks for the other planes that we might have.
// TODO: PLEASE CLEAN ME // TODO: PLEASE CLEAN ME
@ -4504,11 +4507,11 @@ namespace dxvk {
} }
// the converter can not handle the 4 aligned pitch so we always repack into a staging buffer // the converter can not handle the 4 aligned pitch so we always repack into a staging buffer
D3D9BufferSlice slice = AllocStagingBuffer(srcSlice.length); D3D9BufferSlice slice = AllocStagingBuffer(pSrcTexture->GetMipSize(SrcSubresource));
VkDeviceSize pitch = align(srcTexLevelExtentBlockCount.width * formatInfo->elementSize, 4); VkDeviceSize pitch = align(srcTexLevelExtentBlockCount.width * formatInfo->elementSize, 4);
util::packImageData( util::packImageData(
slice.mapPtr, srcSlice.mapPtr, srcTexLevelExtentBlockCount, formatInfo->elementSize, slice.mapPtr, mapPtr, srcTexLevelExtentBlockCount, formatInfo->elementSize,
pitch, std::min(convertFormat.PlaneCount, 2u) * pitch * srcTexLevelExtentBlockCount.height); pitch, std::min(convertFormat.PlaneCount, 2u) * pitch * srcTexLevelExtentBlockCount.height);
Flush(); Flush();
@ -5214,7 +5217,7 @@ namespace dxvk {
void D3D9DeviceEx::UploadManagedTexture(D3D9CommonTexture* pResource) { void D3D9DeviceEx::UploadManagedTexture(D3D9CommonTexture* pResource) {
for (uint32_t subresource = 0; subresource < pResource->CountSubresources(); subresource++) { for (uint32_t subresource = 0; subresource < pResource->CountSubresources(); subresource++) {
if (!pResource->NeedsUpload(subresource) || pResource->GetBuffer(subresource) == nullptr) if (!pResource->NeedsUpload(subresource))
continue; continue;
this->FlushImage(pResource, subresource); this->FlushImage(pResource, subresource);

View File

@ -44,9 +44,11 @@ namespace dxvk {
if (pTexture->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_NONE) if (pTexture->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_NONE)
return; return;
(pTexture->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_BACKED) if (pTexture->GetImage() != nullptr)
? InitDeviceLocalTexture(pTexture) InitDeviceLocalTexture(pTexture);
: InitHostVisibleTexture(pTexture, pInitialData);
if (pTexture->Desc()->Pool != D3DPOOL_DEFAULT)
InitHostVisibleTexture(pTexture, pInitialData);
} }
@ -115,7 +117,8 @@ namespace dxvk {
for (uint32_t a = 0; a < desc->ArraySize; a++) { for (uint32_t a = 0; a < desc->ArraySize; a++) {
for (uint32_t m = 0; m < desc->MipLevels; m++) { for (uint32_t m = 0; m < desc->MipLevels; m++) {
uint32_t subresource = pTexture->CalcSubresource(a, m); uint32_t subresource = pTexture->CalcSubresource(a, m);
DxvkBufferSliceHandle mapSlice = pTexture->GetBuffer(subresource)->getSliceHandle(); void* mapPtr = pTexture->GetData(subresource);
uint32_t length = pTexture->GetMipSize(subresource);
if (pInitialData != nullptr) { if (pInitialData != nullptr) {
VkExtent3D mipExtent = pTexture->GetExtentMip(m); VkExtent3D mipExtent = pTexture->GetExtentMip(m);
@ -125,7 +128,7 @@ namespace dxvk {
uint32_t alignedPitch = align(pitch, 4); uint32_t alignedPitch = align(pitch, 4);
util::packImageData( util::packImageData(
mapSlice.mapPtr, mapPtr,
pInitialData, pInitialData,
pitch, pitch,
pitch * blockCount.height, pitch * blockCount.height,
@ -138,11 +141,13 @@ namespace dxvk {
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
} else { } else {
std::memset( std::memset(
mapSlice.mapPtr, 0, mapPtr, 0,
mapSlice.length); length);
} }
} }
} }
if (pTexture->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE)
pTexture->UnmapData();
} }

View File

@ -341,7 +341,10 @@ namespace dxvk {
if (unlikely(dstTexInfo->Desc()->Pool != D3DPOOL_SYSTEMMEM && dstTexInfo->Desc()->Pool != D3DPOOL_SCRATCH)) if (unlikely(dstTexInfo->Desc()->Pool != D3DPOOL_SYSTEMMEM && dstTexInfo->Desc()->Pool != D3DPOOL_SCRATCH))
return D3DERR_INVALIDCALL; return D3DERR_INVALIDCALL;
Rc<DxvkBuffer> dstBuffer = dstTexInfo->GetBuffer(dst->GetSubresource()); VkExtent3D dstTexExtent = dstTexInfo->GetExtentMip(dst->GetMipLevel());
VkExtent3D srcTexExtent = srcTexInfo->GetExtentMip(0);
Rc<DxvkBuffer> dstBuffer = dstTexInfo->GetBuffer(dst->GetSubresource(), dstTexExtent.width > srcTexExtent.width || dstTexExtent.height > srcTexExtent.height);
Rc<DxvkImage> srcImage = srcTexInfo->GetImage(); Rc<DxvkImage> srcImage = srcTexInfo->GetImage();
if (srcImage->info().sampleCount != VK_SAMPLE_COUNT_1_BIT) { if (srcImage->info().sampleCount != VK_SAMPLE_COUNT_1_BIT) {