mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-05 01:24:14 +01:00
[d3d9] Only do one allocation for all texture subresources
This commit is contained in:
parent
145c1ce127
commit
d8933ca175
@ -78,10 +78,16 @@ namespace dxvk {
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < CountSubresources(); i++) {
|
||||
m_memoryOffset[i] = m_totalSize;
|
||||
m_totalSize += GetMipSize(i);
|
||||
}
|
||||
|
||||
// Initialization is handled by D3D9Initializer
|
||||
if (m_mapMode == D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE)
|
||||
AllocData();
|
||||
m_data = m_device->GetAllocator()->Alloc(m_totalSize);
|
||||
else if (m_mapMode != D3D9_COMMON_TEXTURE_MAP_MODE_NONE && m_desc.Pool != D3DPOOL_DEFAULT)
|
||||
CreateBuffers();
|
||||
CreateBuffer(false);
|
||||
|
||||
m_exposedMipLevels = m_desc.MipLevels;
|
||||
|
||||
@ -174,22 +180,24 @@ namespace dxvk {
|
||||
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;
|
||||
|
||||
D3D9Memory& memory = m_data[Subresource];
|
||||
memory.Map();
|
||||
return memory.Ptr();
|
||||
void* D3D9CommonTexture::GetData(UINT Subresource) {
|
||||
if (unlikely(m_buffer != nullptr))
|
||||
return m_buffer->mapPtr(m_memoryOffset[Subresource]);
|
||||
|
||||
m_data.Map();
|
||||
uint8_t* ptr = reinterpret_cast<uint8_t*>(m_data.Ptr());
|
||||
ptr += m_memoryOffset[Subresource];
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void D3D9CommonTexture::CreateBufferSubresource(UINT Subresource, bool Initialize) {
|
||||
if (likely(m_buffers[Subresource] != nullptr)) {
|
||||
|
||||
void D3D9CommonTexture::CreateBuffer(bool Initialize) {
|
||||
if (likely(m_buffer != nullptr))
|
||||
return;
|
||||
}
|
||||
|
||||
DxvkBufferCreateInfo info;
|
||||
info.size = GetMipSize(Subresource);
|
||||
info.size = m_totalSize;
|
||||
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
@ -209,18 +217,17 @@ namespace dxvk {
|
||||
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
|
||||
|
||||
m_buffers[Subresource] = m_device->GetDXVKDevice()->createBuffer(info, memType);
|
||||
m_mappedSlices[Subresource] = m_buffers[Subresource]->getSliceHandle();
|
||||
m_buffer = m_device->GetDXVKDevice()->createBuffer(info, memType);
|
||||
|
||||
if (Initialize) {
|
||||
if (m_data[Subresource]) {
|
||||
m_data[Subresource].Map();
|
||||
memcpy(m_mappedSlices[Subresource].mapPtr, m_data[Subresource].Ptr(), info.size);
|
||||
if (m_data) {
|
||||
m_data.Map();
|
||||
std::memcpy(m_buffer->mapPtr(0), m_data.Ptr(), m_totalSize);
|
||||
} else {
|
||||
memset(m_mappedSlices[Subresource].mapPtr, 0, info.size);
|
||||
std::memset(m_buffer->mapPtr(0), 0, m_totalSize);
|
||||
}
|
||||
}
|
||||
m_data[Subresource] = {};
|
||||
m_data = {};
|
||||
}
|
||||
|
||||
|
||||
@ -233,7 +240,7 @@ namespace dxvk {
|
||||
|
||||
const VkExtent3D mipExtent = util::computeMipLevelExtent(
|
||||
GetExtent(), MipLevel);
|
||||
|
||||
|
||||
const VkExtent3D blockCount = util::computeBlockCount(
|
||||
mipExtent, formatInfo->blockSize);
|
||||
|
||||
@ -661,16 +668,14 @@ namespace dxvk {
|
||||
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() {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
const Rc<DxvkBuffer>& D3D9CommonTexture::GetBuffer(UINT Subresource) {
|
||||
return m_buffers[Subresource];
|
||||
|
||||
DxvkBufferSlice D3D9CommonTexture::GetBufferSlice(UINT Subresource) {
|
||||
return DxvkBufferSlice(GetBuffer(), m_memoryOffset[Subresource], GetMipSize(Subresource));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -155,19 +155,9 @@ namespace dxvk {
|
||||
*/
|
||||
void* GetData(UINT Subresource);
|
||||
|
||||
const Rc<DxvkBuffer>& GetBuffer(UINT Subresource);
|
||||
const Rc<DxvkBuffer>& GetBuffer();
|
||||
|
||||
|
||||
DxvkBufferSliceHandle GetMappedSlice(UINT Subresource) {
|
||||
return m_mappedSlices[Subresource];
|
||||
}
|
||||
|
||||
|
||||
DxvkBufferSliceHandle DiscardMapSlice(UINT Subresource) {
|
||||
DxvkBufferSliceHandle handle = m_buffers[Subresource]->allocSlice();
|
||||
m_mappedSlices[Subresource] = handle;
|
||||
return handle;
|
||||
}
|
||||
DxvkBufferSlice GetBufferSlice(UINT Subresource);
|
||||
|
||||
/**
|
||||
* \brief Computes subresource from the subresource index
|
||||
@ -235,24 +225,17 @@ namespace dxvk {
|
||||
return Face * m_desc.MipLevels + MipLevel;
|
||||
}
|
||||
|
||||
void UnmapData(UINT Subresource) {
|
||||
m_data[Subresource].Unmap();
|
||||
}
|
||||
|
||||
void UnmapData() {
|
||||
const uint32_t subresources = CountSubresources();
|
||||
for (uint32_t i = 0; i < subresources; i++) {
|
||||
m_data[i].Unmap();
|
||||
}
|
||||
m_data.Unmap();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destroys a buffer
|
||||
* Destroys mapping and staging buffers for a given subresource
|
||||
*/
|
||||
void DestroyBufferSubresource(UINT Subresource) {
|
||||
m_buffers[Subresource] = nullptr;
|
||||
SetNeedsReadback(Subresource, true);
|
||||
void DestroyBuffer() {
|
||||
m_buffer = nullptr;
|
||||
MarkAllNeedReadback();
|
||||
}
|
||||
|
||||
bool IsDynamic() const {
|
||||
@ -476,13 +459,17 @@ namespace dxvk {
|
||||
*/
|
||||
VkDeviceSize GetMipSize(UINT Subresource) const;
|
||||
|
||||
uint32_t GetTotalSize() const {
|
||||
return m_totalSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Creates a buffer
|
||||
* Creates mapping and staging buffers for a given subresource
|
||||
* allocates new buffers if necessary
|
||||
* Creates the mapping buffer if necessary
|
||||
* \param [in] Initialize Whether to copy over existing data (or clear if there is no data)
|
||||
* \returns Whether an allocation happened
|
||||
*/
|
||||
void CreateBufferSubresource(UINT Subresource, bool Initialize);
|
||||
void CreateBuffer(bool Initialize);
|
||||
|
||||
ID3D9VkInteropTexture* GetVkInterop() { return &m_d3d9Interop; }
|
||||
|
||||
@ -495,15 +482,17 @@ namespace dxvk {
|
||||
|
||||
Rc<DxvkImage> m_image;
|
||||
Rc<DxvkImage> m_resolveImage;
|
||||
D3D9SubresourceArray<
|
||||
Rc<DxvkBuffer>> m_buffers;
|
||||
D3D9SubresourceArray<
|
||||
DxvkBufferSliceHandle> m_mappedSlices = { };
|
||||
D3D9SubresourceArray<
|
||||
D3D9Memory> m_data = { };
|
||||
Rc<DxvkBuffer> m_buffer;
|
||||
D3D9Memory m_data = { };
|
||||
|
||||
D3D9SubresourceArray<
|
||||
uint64_t> m_seqs = { };
|
||||
|
||||
D3D9SubresourceArray<
|
||||
uint32_t> m_memoryOffset = { };
|
||||
|
||||
uint32_t m_totalSize = 0;
|
||||
|
||||
D3D9_VK_FORMAT_MAPPING m_mapping;
|
||||
|
||||
bool m_shadow; //< Depth Compare-ness
|
||||
@ -561,20 +550,6 @@ namespace dxvk {
|
||||
D3DRESOURCETYPE Dimension,
|
||||
UINT Layer);
|
||||
|
||||
/**
|
||||
* \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, false);
|
||||
}
|
||||
|
||||
void AllocData();
|
||||
|
||||
static constexpr UINT AllLayers = UINT32_MAX;
|
||||
|
||||
};
|
||||
|
@ -911,11 +911,14 @@ namespace dxvk {
|
||||
VkExtent3D dstTexExtent = dstTexInfo->GetExtentMip(dst->GetMipLevel());
|
||||
VkExtent3D srcTexExtent = srcTexInfo->GetExtentMip(src->GetMipLevel());
|
||||
|
||||
dstTexInfo->CreateBufferSubresource(dst->GetSubresource(), dstTexExtent.width > srcTexExtent.width || dstTexExtent.height > srcTexExtent.height);
|
||||
Rc<DxvkBuffer> dstBuffer = dstTexInfo->GetBuffer(dst->GetSubresource());
|
||||
const bool clearDst = dstTexInfo->Desc()->MipLevels > 1
|
||||
|| dstTexExtent.width > srcTexExtent.width
|
||||
|| dstTexExtent.height > srcTexExtent.height;
|
||||
|
||||
Rc<DxvkImage> srcImage = srcTexInfo->GetImage();
|
||||
const DxvkFormatInfo* srcFormatInfo = lookupFormatInfo(srcImage->info().format);
|
||||
dstTexInfo->CreateBuffer(clearDst);
|
||||
DxvkBufferSlice dstBufferSlice = dstTexInfo->GetBufferSlice(dst->GetSubresource());
|
||||
Rc<DxvkImage> srcImage = srcTexInfo->GetImage();
|
||||
const DxvkFormatInfo* srcFormatInfo = lookupFormatInfo(srcImage->info().format);
|
||||
|
||||
const VkImageSubresource srcSubresource = srcTexInfo->GetSubresourceFromIndex(srcFormatInfo->aspectMask, src->GetSubresource());
|
||||
VkImageSubresourceLayers srcSubresourceLayers = {
|
||||
@ -924,12 +927,12 @@ namespace dxvk {
|
||||
srcSubresource.arrayLayer, 1 };
|
||||
|
||||
EmitCs([
|
||||
cBuffer = dstBuffer,
|
||||
cBufferSlice = std::move(dstBufferSlice),
|
||||
cImage = srcImage,
|
||||
cSubresources = srcSubresourceLayers,
|
||||
cLevelExtent = srcTexExtent
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->copyImageToBuffer(cBuffer, 0, 4, 0,
|
||||
ctx->copyImageToBuffer(cBufferSlice.buffer(), cBufferSlice.offset(), 4, 0,
|
||||
cImage, cSubresources, VkOffset3D { 0, 0, 0 },
|
||||
cLevelExtent);
|
||||
});
|
||||
@ -4298,107 +4301,94 @@ namespace dxvk {
|
||||
bool needsReadback = pResource->NeedsReadback(Subresource) || renderable;
|
||||
pResource->SetNeedsReadback(Subresource, false);
|
||||
|
||||
|
||||
if (unlikely(pResource->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_BACKED || needsReadback)) {
|
||||
// Create mapping buffer if it doesn't exist yet. (POOL_DEFAULT)
|
||||
pResource->CreateBufferSubresource(Subresource, !needsReadback);
|
||||
pResource->CreateBuffer(!needsReadback);
|
||||
}
|
||||
|
||||
void* mapPtr;
|
||||
// Don't use MapTexture here to keep the mapped list small while the resource is still locked.
|
||||
void* mapPtr = pResource->GetData(Subresource);
|
||||
|
||||
if ((Flags & D3DLOCK_DISCARD) && needsReadback) {
|
||||
// We do not have to preserve the contents of the
|
||||
// buffer if the entire image gets discarded.
|
||||
const Rc<DxvkBuffer> mappedBuffer = pResource->GetBuffer(Subresource);
|
||||
DxvkBufferSliceHandle physSlice = pResource->DiscardMapSlice(Subresource);
|
||||
mapPtr = physSlice.mapPtr;
|
||||
if (needsReadback) {
|
||||
DxvkBufferSlice mappedBufferSlice = pResource->GetBufferSlice(Subresource);
|
||||
const Rc<DxvkBuffer> mappedBuffer = pResource->GetBuffer();
|
||||
|
||||
EmitCs([
|
||||
cImageBuffer = std::move(mappedBuffer),
|
||||
cBufferSlice = physSlice
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->invalidateBuffer(cImageBuffer, cBufferSlice);
|
||||
});
|
||||
} else {
|
||||
// Don't use MapTexture here to keep the mapped list small while the resource is still locked.
|
||||
mapPtr = pResource->GetData(Subresource);
|
||||
if (unlikely(needsReadback) && pResource->GetImage() != nullptr) {
|
||||
Rc<DxvkImage> resourceImage = pResource->GetImage();
|
||||
|
||||
if (needsReadback) {
|
||||
const Rc<DxvkBuffer> mappedBuffer = pResource->GetBuffer(Subresource);
|
||||
if (unlikely(needsReadback) && pResource->GetImage() != nullptr) {
|
||||
Rc<DxvkImage> resourceImage = pResource->GetImage();
|
||||
Rc<DxvkImage> mappedImage = resourceImage->info().sampleCount != 1
|
||||
? pResource->GetResolveImage()
|
||||
: std::move(resourceImage);
|
||||
|
||||
Rc<DxvkImage> mappedImage = resourceImage->info().sampleCount != 1
|
||||
? pResource->GetResolveImage()
|
||||
: std::move(resourceImage);
|
||||
|
||||
// When using any map mode which requires the image contents
|
||||
// to be preserved, and if the GPU has write access to the
|
||||
// image, copy the current image contents into the buffer.
|
||||
auto subresourceLayers = vk::makeSubresourceLayers(subresource);
|
||||
|
||||
// We need to resolve this, some games
|
||||
// lock MSAA render targets even though
|
||||
// that's entirely illegal and they explicitly
|
||||
// tell us that they do NOT want to lock them...
|
||||
if (resourceImage != nullptr) {
|
||||
EmitCs([
|
||||
cMainImage = resourceImage,
|
||||
cResolveImage = mappedImage,
|
||||
cSubresource = subresourceLayers
|
||||
] (DxvkContext* ctx) {
|
||||
VkImageResolve region;
|
||||
region.srcSubresource = cSubresource;
|
||||
region.srcOffset = VkOffset3D { 0, 0, 0 };
|
||||
region.dstSubresource = cSubresource;
|
||||
region.dstOffset = VkOffset3D { 0, 0, 0 };
|
||||
region.extent = cMainImage->mipLevelExtent(cSubresource.mipLevel);
|
||||
|
||||
if (cSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->resolveImage(
|
||||
cResolveImage, cMainImage, region,
|
||||
cMainImage->info().format);
|
||||
}
|
||||
else {
|
||||
ctx->resolveDepthStencilImage(
|
||||
cResolveImage, cMainImage, region,
|
||||
VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
|
||||
VK_RESOLVE_MODE_SAMPLE_ZERO_BIT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
VkFormat packedFormat = GetPackedDepthStencilFormat(desc.Format);
|
||||
// When using any map mode which requires the image contents
|
||||
// to be preserved, and if the GPU has write access to the
|
||||
// image, copy the current image contents into the buffer.
|
||||
auto subresourceLayers = vk::makeSubresourceLayers(subresource);
|
||||
|
||||
// We need to resolve this, some games
|
||||
// lock MSAA render targets even though
|
||||
// that's entirely illegal and they explicitly
|
||||
// tell us that they do NOT want to lock them...
|
||||
if (resourceImage != nullptr) {
|
||||
EmitCs([
|
||||
cImageBuffer = mappedBuffer,
|
||||
cImage = std::move(mappedImage),
|
||||
cSubresources = subresourceLayers,
|
||||
cLevelExtent = levelExtent,
|
||||
cPackedFormat = packedFormat
|
||||
cMainImage = resourceImage,
|
||||
cResolveImage = mappedImage,
|
||||
cSubresource = subresourceLayers
|
||||
] (DxvkContext* ctx) {
|
||||
if (cSubresources.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyImageToBuffer(cImageBuffer, 0, 4, 0,
|
||||
cImage, cSubresources, VkOffset3D { 0, 0, 0 },
|
||||
cLevelExtent);
|
||||
} else {
|
||||
// Copying DS to a packed buffer is only supported for D24S8 and D32S8
|
||||
// right now so the 4 byte row alignment is guaranteed by the format size
|
||||
ctx->copyDepthStencilImageToPackedBuffer(
|
||||
cImageBuffer, 0,
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { cLevelExtent.width, cLevelExtent.height },
|
||||
cImage, cSubresources,
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { cLevelExtent.width, cLevelExtent.height },
|
||||
cPackedFormat);
|
||||
VkImageResolve region;
|
||||
region.srcSubresource = cSubresource;
|
||||
region.srcOffset = VkOffset3D { 0, 0, 0 };
|
||||
region.dstSubresource = cSubresource;
|
||||
region.dstOffset = VkOffset3D { 0, 0, 0 };
|
||||
region.extent = cMainImage->mipLevelExtent(cSubresource.mipLevel);
|
||||
|
||||
if (cSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->resolveImage(
|
||||
cResolveImage, cMainImage, region,
|
||||
cMainImage->info().format);
|
||||
}
|
||||
else {
|
||||
ctx->resolveDepthStencilImage(
|
||||
cResolveImage, cMainImage, region,
|
||||
VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
|
||||
VK_RESOLVE_MODE_SAMPLE_ZERO_BIT);
|
||||
}
|
||||
});
|
||||
TrackTextureMappingBufferSequenceNumber(pResource, Subresource);
|
||||
}
|
||||
|
||||
if (!WaitForResource(mappedBuffer, pResource->GetMappingBufferSequenceNumber(Subresource), Flags))
|
||||
return D3DERR_WASSTILLDRAWING;
|
||||
VkFormat packedFormat = GetPackedDepthStencilFormat(desc.Format);
|
||||
|
||||
EmitCs([
|
||||
cImageBufferSlice = std::move(mappedBufferSlice),
|
||||
cImage = std::move(mappedImage),
|
||||
cSubresources = subresourceLayers,
|
||||
cLevelExtent = levelExtent,
|
||||
cPackedFormat = packedFormat
|
||||
] (DxvkContext* ctx) {
|
||||
if (cSubresources.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyImageToBuffer(cImageBufferSlice.buffer(),
|
||||
cImageBufferSlice.offset(), 4, 0, cImage,
|
||||
cSubresources, VkOffset3D { 0, 0, 0 },
|
||||
cLevelExtent);
|
||||
} else {
|
||||
// Copying DS to a packed buffer is only supported for D24S8 and D32S8
|
||||
// right now so the 4 byte row alignment is guaranteed by the format size
|
||||
ctx->copyDepthStencilImageToPackedBuffer(
|
||||
cImageBufferSlice.buffer(), cImageBufferSlice.offset(),
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { cLevelExtent.width, cLevelExtent.height },
|
||||
cImage, cSubresources,
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { cLevelExtent.width, cLevelExtent.height },
|
||||
cPackedFormat);
|
||||
}
|
||||
});
|
||||
TrackTextureMappingBufferSequenceNumber(pResource, Subresource);
|
||||
}
|
||||
|
||||
if (!WaitForResource(mappedBuffer, pResource->GetMappingBufferSequenceNumber(Subresource), Flags))
|
||||
return D3DERR_WASSTILLDRAWING;
|
||||
}
|
||||
|
||||
const bool atiHack = desc.Format == D3D9Format::ATI1 || desc.Format == D3D9Format::ATI2;
|
||||
@ -4496,11 +4486,10 @@ namespace dxvk {
|
||||
bool shouldToss = pResource->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_BACKED;
|
||||
shouldToss &= !pResource->IsDynamic();
|
||||
shouldToss &= !pResource->IsManaged();
|
||||
shouldToss &= !pResource->IsAnySubresourceLocked();
|
||||
|
||||
if (shouldToss) {
|
||||
pResource->DestroyBufferSubresource(Subresource);
|
||||
pResource->SetNeedsReadback(Subresource, true);
|
||||
}
|
||||
if (shouldToss)
|
||||
pResource->DestroyBuffer();
|
||||
|
||||
UnmapTextures();
|
||||
return D3D_OK;
|
||||
@ -4561,8 +4550,10 @@ namespace dxvk {
|
||||
auto convertFormat = pDestTexture->GetFormatMapping().ConversionFormatInfo;
|
||||
|
||||
if (unlikely(pSrcTexture->NeedsReadback(SrcSubresource))) {
|
||||
pSrcTexture->CreateBufferSubresource(SrcSubresource, true);
|
||||
const Rc<DxvkBuffer>& buffer = pSrcTexture->GetBuffer(SrcSubresource);
|
||||
// The src texutre has to be in POOL_SYSTEMEM, so it cannot use AUTOMIPGEN.
|
||||
// That means that NeedsReadback is only true if the texture has been used with GetRTData or GetFrontbufferData before.
|
||||
// Those functions create a buffer, so the buffer always exists here.
|
||||
const Rc<DxvkBuffer>& buffer = pSrcTexture->GetBuffer();
|
||||
WaitForResource(buffer, pSrcTexture->GetMappingBufferSequenceNumber(SrcSubresource), 0);
|
||||
pSrcTexture->SetNeedsReadback(SrcSubresource, false);
|
||||
}
|
||||
|
@ -113,41 +113,35 @@ namespace dxvk {
|
||||
// If the buffer is mapped, we can write data directly
|
||||
// to the mapped memory region instead of doing it on
|
||||
// the GPU. Same goes for zero-initialization.
|
||||
const D3D9_COMMON_TEXTURE_DESC* desc = pTexture->Desc();
|
||||
for (uint32_t a = 0; a < desc->ArraySize; a++) {
|
||||
for (uint32_t m = 0; m < desc->MipLevels; m++) {
|
||||
uint32_t subresource = pTexture->CalcSubresource(a, m);
|
||||
void* mapPtr = pTexture->GetData(subresource);
|
||||
uint32_t length = pTexture->GetMipSize(subresource);
|
||||
void* mapPtr = pTexture->GetData(0);
|
||||
if (pInitialData) {
|
||||
// Initial data is only supported for textures with 1 subresource
|
||||
VkExtent3D mipExtent = pTexture->GetExtentMip(0);
|
||||
const DxvkFormatInfo* formatInfo = lookupFormatInfo(pTexture->GetFormatMapping().FormatColor);
|
||||
VkExtent3D blockCount = util::computeBlockCount(mipExtent, formatInfo->blockSize);
|
||||
uint32_t pitch = blockCount.width * formatInfo->elementSize;
|
||||
uint32_t alignedPitch = align(pitch, 4);
|
||||
|
||||
if (pInitialData != nullptr) {
|
||||
VkExtent3D mipExtent = pTexture->GetExtentMip(m);
|
||||
const DxvkFormatInfo* formatInfo = lookupFormatInfo(pTexture->GetFormatMapping().FormatColor);
|
||||
VkExtent3D blockCount = util::computeBlockCount(mipExtent, formatInfo->blockSize);
|
||||
uint32_t pitch = blockCount.width * formatInfo->elementSize;
|
||||
uint32_t alignedPitch = align(pitch, 4);
|
||||
|
||||
util::packImageData(
|
||||
mapPtr,
|
||||
pInitialData,
|
||||
pitch,
|
||||
pitch * blockCount.height,
|
||||
alignedPitch,
|
||||
alignedPitch * blockCount.height,
|
||||
D3D9CommonTexture::GetImageTypeFromResourceType(pTexture->GetType()),
|
||||
mipExtent,
|
||||
pTexture->Desc()->ArraySize,
|
||||
formatInfo,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
} else {
|
||||
std::memset(
|
||||
mapPtr, 0,
|
||||
length);
|
||||
}
|
||||
}
|
||||
util::packImageData(
|
||||
mapPtr,
|
||||
pInitialData,
|
||||
pitch,
|
||||
pitch * blockCount.height,
|
||||
alignedPitch,
|
||||
alignedPitch * blockCount.height,
|
||||
D3D9CommonTexture::GetImageTypeFromResourceType(pTexture->GetType()),
|
||||
mipExtent,
|
||||
pTexture->Desc()->ArraySize,
|
||||
formatInfo,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
} else {
|
||||
// All subresources are allocated in one chunk of memory.
|
||||
// So we can just get the pointer for subresource 0 and memset all of them at once.
|
||||
std::memset(
|
||||
mapPtr, 0,
|
||||
pTexture->GetTotalSize());
|
||||
}
|
||||
if (pTexture->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE)
|
||||
pTexture->UnmapData();
|
||||
pTexture->UnmapData();
|
||||
}
|
||||
|
||||
|
||||
|
@ -180,9 +180,13 @@ namespace dxvk {
|
||||
VkExtent3D dstTexExtent = dstTexInfo->GetExtentMip(dst->GetMipLevel());
|
||||
VkExtent3D srcTexExtent = srcTexInfo->GetExtentMip(0);
|
||||
|
||||
dstTexInfo->CreateBufferSubresource(dst->GetSubresource(), dstTexExtent.width > srcTexExtent.width || dstTexExtent.height > srcTexExtent.height);
|
||||
Rc<DxvkBuffer> dstBuffer = dstTexInfo->GetBuffer(dst->GetSubresource());
|
||||
Rc<DxvkImage> srcImage = srcTexInfo->GetImage();
|
||||
const bool clearDst = dstTexInfo->Desc()->MipLevels > 1
|
||||
|| dstTexExtent.width > srcTexExtent.width
|
||||
|| dstTexExtent.height > srcTexExtent.height;
|
||||
|
||||
dstTexInfo->CreateBuffer(clearDst);
|
||||
DxvkBufferSlice dstBufferSlice = dstTexInfo->GetBufferSlice(dst->GetSubresource());
|
||||
Rc<DxvkImage> srcImage = srcTexInfo->GetImage();
|
||||
|
||||
if (srcImage->info().sampleCount != VK_SAMPLE_COUNT_1_BIT) {
|
||||
DxvkImageCreateInfo resolveInfo;
|
||||
@ -316,13 +320,14 @@ namespace dxvk {
|
||||
VkExtent3D srcExtent = srcImage->mipLevelExtent(srcSubresource.mipLevel);
|
||||
|
||||
m_parent->EmitCs([
|
||||
cBuffer = dstBuffer,
|
||||
cImage = srcImage,
|
||||
cBufferSlice = std::move(dstBufferSlice),
|
||||
cImage = std::move(srcImage),
|
||||
cSubresources = srcSubresourceLayers,
|
||||
cLevelExtent = srcExtent
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->copyImageToBuffer(cBuffer, 0, 4, 0,
|
||||
cImage, cSubresources, VkOffset3D { 0, 0, 0 },
|
||||
ctx->copyImageToBuffer(cBufferSlice.buffer(),
|
||||
cBufferSlice.offset(), 4, 0, cImage,
|
||||
cSubresources, VkOffset3D { 0, 0, 0 },
|
||||
cLevelExtent);
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user