Skip to content

Commit

Permalink
[d3d9] Track dirty regions for UpdateTexture
Browse files Browse the repository at this point in the history
  • Loading branch information
K0bin committed Sep 7, 2020
1 parent 9433d0c commit 4736209
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 9 deletions.
38 changes: 38 additions & 0 deletions src/d3d9/d3d9_common_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,42 @@ namespace dxvk {
void PreLoadAll();
void PreLoadSubresource(UINT Subresource);

void AddUpdateBox(CONST D3DBOX* pDirtyRect, uint32_t layer) {
if (pDirtyRect) {
D3DBOX box = *pDirtyRect;
if (box.Right <= box.Left
|| box.Bottom <= box.Top
|| box.Back <= box.Front)
return;

D3DBOX& updateBox = m_updateBoxes[layer];
if (updateBox.Left == 0 && updateBox.Right == 0
&& updateBox.Top == 0 && updateBox.Bottom == 0
&& updateBox.Front == 0 && updateBox.Back == 0) {
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_updateBoxes[layer] = { 0, 0, m_desc.Width, m_desc.Height };
}
}

void ClearUpdateBoxes() {
for (uint32_t i = 0; i < m_updateBoxes.size(); i++) {
m_updateBoxes[i] = { 0, 0, 0, 0, 0, 0 };
}
}

const D3DBOX& GetUpdateBox(uint32_t layer) const {
return m_updateBoxes[layer];
}

private:

D3D9DeviceEx* m_device;
Expand Down Expand Up @@ -406,6 +442,8 @@ namespace dxvk {

D3DTEXTUREFILTERTYPE m_mipFilter = D3DTEXF_LINEAR;

std::array<D3DBOX, 6> m_updateBoxes;

/**
* \brief Mip level
* \returns Size of packed mip level in bytes
Expand Down
58 changes: 50 additions & 8 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,17 @@ namespace dxvk {
if (unlikely(srcTextureInfo->Desc()->Format != dstTextureInfo->Desc()->Format))
return D3DERR_INVALIDCALL;

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->AddUpdateBox(&updateDirtyRect, dst->GetFace());
} else {
dstTextureInfo->AddUpdateBox(nullptr, dst->GetFace());
}

const DxvkFormatInfo* formatInfo = imageFormatInfo(dstTextureInfo->GetFormatMapping().FormatColor);

VkOffset3D srcBlockOffset = { 0u, 0u, 0u };
Expand Down Expand Up @@ -723,27 +734,52 @@ 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->GetUpdateBox(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);
VkOffset2D srcByteOffset = {
offset.x / int32_t(formatInfo->blockSize.width),
offset.y / int32_t(formatInfo->blockSize.height)
};
VkDeviceSize srcOffset = 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);
});
}
}
Expand All @@ -757,6 +793,8 @@ namespace dxvk {
else
dstTexInfo->MarkAllDirty();

srcTexInfo->ClearUpdateBoxes();

FlushImplicit(false);

return D3D_OK;
Expand Down Expand Up @@ -3920,6 +3958,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->AddUpdateBox(pBox, Face);
}

auto& desc = *(pResource->Desc());

bool alloced = pResource->CreateBufferSubresource(Subresource);
Expand Down
14 changes: 13 additions & 1 deletion src/d3d9/d3d9_texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.AddUpdateBox(&box, 0);
} else {
m_texture.AddUpdateBox(nullptr, 0);
}
return D3D_OK;
}

Expand Down Expand Up @@ -151,8 +157,8 @@ namespace dxvk {
return GetSubresource(Level)->UnlockBox();
}


HRESULT STDMETHODCALLTYPE D3D9Texture3D::AddDirtyBox(CONST D3DBOX* pDirtyBox) {
m_texture.AddUpdateBox(pDirtyBox, 0);
return D3D_OK;
}

Expand Down Expand Up @@ -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.AddUpdateBox(&box, Face);
} else {
m_texture.AddUpdateBox(nullptr, Face);
}
return D3D_OK;
}

Expand Down

0 comments on commit 4736209

Please sign in to comment.