mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-03 04:24:11 +01:00
[d3d9] Track dirty regions for UpdateTexture
This commit is contained in:
parent
a0cf5926d8
commit
338f6dfb0e
@ -17,6 +17,10 @@ namespace dxvk {
|
||||
? D3D9Format::D32
|
||||
: D3D9Format::X8R8G8B8;
|
||||
|
||||
for (uint32_t i = 0; i < m_updateDirtyBoxes.size(); i++) {
|
||||
AddUpdateDirtyBox(nullptr, i);
|
||||
}
|
||||
|
||||
m_mapping = pDevice->LookupFormat(m_desc.Format);
|
||||
|
||||
m_mapMode = DetermineMapMode();
|
||||
|
@ -367,6 +367,40 @@ namespace dxvk {
|
||||
void PreLoadAll();
|
||||
void PreLoadSubresource(UINT Subresource);
|
||||
|
||||
void AddUpdateDirtyBox(CONST D3DBOX* pDirtyBox, uint32_t layer) {
|
||||
if (pDirtyBox) {
|
||||
D3DBOX box = *pDirtyBox;
|
||||
if (box.Right <= box.Left
|
||||
|| box.Bottom <= box.Top
|
||||
|| box.Back <= box.Front)
|
||||
return;
|
||||
|
||||
D3DBOX& updateBox = m_updateDirtyBoxes[layer];
|
||||
if (updateBox.Left == updateBox.Right) {
|
||||
updateBox = box;
|
||||
} else {
|
||||
updateBox.Left = std::min(updateBox.Left, box.Left);
|
||||
updateBox.Right = std::max(updateBox.Right, box.Right);
|
||||
updateBox.Top = std::min(updateBox.Top, box.Top);
|
||||
updateBox.Bottom = std::max(updateBox.Bottom, box.Bottom);
|
||||
updateBox.Front = std::min(updateBox.Front, box.Front);
|
||||
updateBox.Back = std::max(updateBox.Back, box.Back);
|
||||
}
|
||||
} else {
|
||||
m_updateDirtyBoxes[layer] = { 0, 0, m_desc.Width, m_desc.Height, 0, m_desc.Depth };
|
||||
}
|
||||
}
|
||||
|
||||
void ClearUpdateDirtyBoxes() {
|
||||
for (uint32_t i = 0; i < m_updateDirtyBoxes.size(); i++) {
|
||||
m_updateDirtyBoxes[i] = { 0, 0, 0, 0, 0, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
const D3DBOX& GetUpdateDirtyBox(uint32_t layer) const {
|
||||
return m_updateDirtyBoxes[layer];
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
D3D9DeviceEx* m_device;
|
||||
@ -407,6 +441,8 @@ namespace dxvk {
|
||||
|
||||
D3DTEXTUREFILTERTYPE m_mipFilter = D3DTEXF_LINEAR;
|
||||
|
||||
std::array<D3DBOX, 6> m_updateDirtyBoxes;
|
||||
|
||||
/**
|
||||
* \brief Mip level
|
||||
* \returns Size of packed mip level in bytes
|
||||
|
@ -649,6 +649,19 @@ namespace dxvk {
|
||||
if (unlikely(srcTextureInfo->Desc()->Format != dstTextureInfo->Desc()->Format))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
if (dst->GetMipLevel() == 0) {
|
||||
if (pSourceRect) {
|
||||
D3DBOX updateDirtyRect = { UINT(pSourceRect->left), UINT(pSourceRect->top), UINT(pSourceRect->right), UINT(pSourceRect->bottom), 0, 1 };
|
||||
if (pDestinationSurface) {
|
||||
updateDirtyRect.Left = pDestPoint->x;
|
||||
updateDirtyRect.Top = pDestPoint->y;
|
||||
}
|
||||
dstTextureInfo->AddUpdateDirtyBox(&updateDirtyRect, dst->GetFace());
|
||||
} else {
|
||||
dstTextureInfo->AddUpdateDirtyBox(nullptr, dst->GetFace());
|
||||
}
|
||||
}
|
||||
|
||||
const DxvkFormatInfo* formatInfo = imageFormatInfo(dstTextureInfo->GetFormatMapping().FormatColor);
|
||||
|
||||
VkOffset3D srcBlockOffset = { 0u, 0u, 0u };
|
||||
@ -726,27 +739,54 @@ namespace dxvk {
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
const Rc<DxvkImage> dstImage = dstTexInfo->GetImage();
|
||||
|
||||
const DxvkFormatInfo* formatInfo = imageFormatInfo(dstTexInfo->GetFormatMapping().FormatColor);
|
||||
uint32_t mipLevels = std::min(srcTexInfo->Desc()->MipLevels, dstTexInfo->Desc()->MipLevels);
|
||||
uint32_t arraySlices = std::min(srcTexInfo->Desc()->ArraySize, dstTexInfo->Desc()->ArraySize);
|
||||
|
||||
for (uint32_t a = 0; a < arraySlices; a++) {
|
||||
const D3DBOX& box = srcTexInfo->GetUpdateDirtyBox(a);
|
||||
for (uint32_t m = 0; m < mipLevels; m++) {
|
||||
Rc<DxvkBuffer> srcBuffer = srcTexInfo->GetBuffer(srcTexInfo->CalcSubresource(a, m));
|
||||
|
||||
VkImageSubresourceLayers dstLayers = { VK_IMAGE_ASPECT_COLOR_BIT, m, a, 1 };
|
||||
|
||||
VkExtent3D extent = dstImage->mipLevelExtent(m);
|
||||
|
||||
|
||||
VkOffset3D offset = {
|
||||
alignDown(int32_t(box.Left) >> m, int32_t(formatInfo->blockSize.width)),
|
||||
alignDown(int32_t(box.Top) >> m, int32_t(formatInfo->blockSize.height)),
|
||||
alignDown(int32_t(box.Front) >> m, int32_t(formatInfo->blockSize.depth))
|
||||
};
|
||||
VkExtent3D extent = {
|
||||
alignDown(uint32_t((box.Right - box.Left) >> m), formatInfo->blockSize.width),
|
||||
alignDown(uint32_t((box.Bottom - box.Top) >> m), formatInfo->blockSize.height),
|
||||
alignDown(uint32_t((box.Back - box.Front) >> m), formatInfo->blockSize.depth),
|
||||
};
|
||||
|
||||
VkExtent3D levelExtent = dstImage->mipLevelExtent(m);
|
||||
VkExtent3D blockCount = util::computeBlockCount(levelExtent, formatInfo->blockSize);
|
||||
VkOffset3D srcByteOffset = {
|
||||
offset.x / int32_t(formatInfo->blockSize.width),
|
||||
offset.y / int32_t(formatInfo->blockSize.height),
|
||||
offset.z / int32_t(formatInfo->blockSize.depth)
|
||||
};
|
||||
VkDeviceSize srcOffset = srcByteOffset.z * formatInfo->elementSize * blockCount.depth
|
||||
+ srcByteOffset.y * formatInfo->elementSize * blockCount.width
|
||||
+ srcByteOffset.x * formatInfo->elementSize;
|
||||
VkExtent2D srcExtent = VkExtent2D{ blockCount.width * formatInfo->blockSize.width,
|
||||
blockCount.height * formatInfo->blockSize.height };
|
||||
|
||||
EmitCs([
|
||||
cDstImage = dstImage,
|
||||
cSrcBuffer = srcBuffer,
|
||||
cDstLayers = dstLayers,
|
||||
cExtent = extent
|
||||
cExtent = extent,
|
||||
cOffset = offset,
|
||||
cSrcOffset = srcOffset,
|
||||
cSrcExtent = srcExtent
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->copyBufferToImage(
|
||||
cDstImage, cDstLayers,
|
||||
VkOffset3D{ 0, 0, 0 }, cExtent,
|
||||
cSrcBuffer, 0, { 0u, 0u });
|
||||
cOffset, cExtent,
|
||||
cSrcBuffer, cSrcOffset,
|
||||
cSrcExtent);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -760,6 +800,8 @@ namespace dxvk {
|
||||
else
|
||||
dstTexInfo->MarkAllDirty();
|
||||
|
||||
srcTexInfo->ClearUpdateDirtyBoxes();
|
||||
|
||||
FlushImplicit(false);
|
||||
|
||||
return D3D_OK;
|
||||
@ -3929,6 +3971,10 @@ namespace dxvk {
|
||||
if (unlikely((Flags & (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE)) == (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE)))
|
||||
Flags &= ~D3DLOCK_DISCARD;
|
||||
|
||||
if (!(Flags & D3DLOCK_NO_DIRTY_UPDATE) && !(Flags & D3DLOCK_READONLY)) {
|
||||
pResource->AddUpdateDirtyBox(pBox, Face);
|
||||
}
|
||||
|
||||
auto& desc = *(pResource->Desc());
|
||||
|
||||
bool alloced = pResource->CreateBufferSubresource(Subresource);
|
||||
|
@ -76,6 +76,12 @@ namespace dxvk {
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9Texture2D::AddDirtyRect(CONST RECT* pDirtyRect) {
|
||||
if (pDirtyRect) {
|
||||
D3DBOX box = { UINT(pDirtyRect->left), UINT(pDirtyRect->top), UINT(pDirtyRect->right), UINT(pDirtyRect->bottom), 0, 1 };
|
||||
m_texture.AddUpdateDirtyBox(&box, 0);
|
||||
} else {
|
||||
m_texture.AddUpdateDirtyBox(nullptr, 0);
|
||||
}
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
@ -151,8 +157,8 @@ namespace dxvk {
|
||||
return GetSubresource(Level)->UnlockBox();
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9Texture3D::AddDirtyBox(CONST D3DBOX* pDirtyBox) {
|
||||
m_texture.AddUpdateDirtyBox(pDirtyBox, 0);
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
@ -230,6 +236,12 @@ namespace dxvk {
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9TextureCube::AddDirtyRect(D3DCUBEMAP_FACES Face, CONST RECT* pDirtyRect) {
|
||||
if (pDirtyRect) {
|
||||
D3DBOX box = { UINT(pDirtyRect->left), UINT(pDirtyRect->top), UINT(pDirtyRect->right), UINT(pDirtyRect->bottom), 0, 1 };
|
||||
m_texture.AddUpdateDirtyBox(&box, Face);
|
||||
} else {
|
||||
m_texture.AddUpdateDirtyBox(nullptr, Face);
|
||||
}
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user