mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-22 07:54:15 +01:00
[d3d11] Implement CopyTiles and UpdateTiles
This commit is contained in:
parent
ca41bb4ea4
commit
0a222aaaf0
@ -2628,10 +2628,25 @@ namespace dxvk {
|
|||||||
ID3D11Buffer* pBuffer,
|
ID3D11Buffer* pBuffer,
|
||||||
UINT64 BufferStartOffsetInBytes,
|
UINT64 BufferStartOffsetInBytes,
|
||||||
UINT Flags) {
|
UINT Flags) {
|
||||||
static bool s_errorShown = false;
|
if (!pTiledResource || !pBuffer)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!std::exchange(s_errorShown, true))
|
auto buffer = static_cast<D3D11Buffer*>(pBuffer);
|
||||||
Logger::err("D3D11DeviceContext::CopyTiles: Not implemented");
|
|
||||||
|
// Get buffer slice and just forward the call
|
||||||
|
VkDeviceSize bufferSize = pTileRegionSize->NumTiles * SparseMemoryPageSize;
|
||||||
|
|
||||||
|
if (buffer->Desc()->ByteWidth < BufferStartOffsetInBytes + bufferSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DxvkBufferSlice slice = buffer->GetBufferSlice(BufferStartOffsetInBytes, bufferSize);
|
||||||
|
|
||||||
|
CopyTiledResourceData(pTiledResource,
|
||||||
|
pTileRegionStartCoordinate,
|
||||||
|
pTileRegionSize, slice, Flags);
|
||||||
|
|
||||||
|
if (buffer->HasSequenceNumber())
|
||||||
|
GetTypedContext()->TrackBufferSequenceNumber(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2927,10 +2942,25 @@ namespace dxvk {
|
|||||||
const D3D11_TILE_REGION_SIZE* pDestTileRegionSize,
|
const D3D11_TILE_REGION_SIZE* pDestTileRegionSize,
|
||||||
const void* pSourceTileData,
|
const void* pSourceTileData,
|
||||||
UINT Flags) {
|
UINT Flags) {
|
||||||
bool s_errorShown = false;
|
if (!pDestTiledResource || !pSourceTileData)
|
||||||
|
return;
|
||||||
|
|
||||||
if (std::exchange(s_errorShown, true))
|
// Allocate staging memory and copy source data into it, at a
|
||||||
Logger::err("D3D11DeviceContext::UpdateTiles: Not implemented");
|
// 64k page granularity. It is not clear whether this behaviour
|
||||||
|
// is correct in case we're writing to incmplete pages.
|
||||||
|
VkDeviceSize bufferSize = pDestTileRegionSize->NumTiles * SparseMemoryPageSize;
|
||||||
|
|
||||||
|
DxvkBufferSlice slice = AllocStagingBuffer(bufferSize);
|
||||||
|
std::memcpy(slice.mapPtr(0), pSourceTileData, bufferSize);
|
||||||
|
|
||||||
|
// Fix up flags. The runtime probably validates this in some
|
||||||
|
// way but our internal function relies on correct flags anyway.
|
||||||
|
Flags &= D3D11_TILE_MAPPING_NO_OVERWRITE;
|
||||||
|
Flags |= D3D11_TILE_COPY_LINEAR_BUFFER_TO_SWIZZLED_TILED_RESOURCE;
|
||||||
|
|
||||||
|
CopyTiledResourceData(pDestTiledResource,
|
||||||
|
pDestTileRegionStartCoordinate,
|
||||||
|
pDestTileRegionSize, slice, Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4016,6 +4046,94 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename ContextType>
|
||||||
|
void D3D11CommonContext<ContextType>::CopyTiledResourceData(
|
||||||
|
ID3D11Resource* pResource,
|
||||||
|
const D3D11_TILED_RESOURCE_COORDINATE* pRegionCoordinate,
|
||||||
|
const D3D11_TILE_REGION_SIZE* pRegionSize,
|
||||||
|
DxvkBufferSlice BufferSlice,
|
||||||
|
UINT Flags) {
|
||||||
|
Rc<DxvkPagedResource> resource = GetPagedResource(pResource);
|
||||||
|
|
||||||
|
// Do some validation based on page table properties
|
||||||
|
auto pageTable = resource->getSparsePageTable();
|
||||||
|
|
||||||
|
if (!pageTable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pRegionSize->bUseBox && pRegionSize->NumTiles !=
|
||||||
|
pRegionSize->Width * pRegionSize->Height * pRegionSize->Depth)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pRegionSize->NumTiles > pageTable->getPageCount())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ignore call if buffer access would be out of bounds
|
||||||
|
VkDeviceSize bufferSize = pRegionSize->NumTiles * SparseMemoryPageSize;
|
||||||
|
|
||||||
|
if (BufferSlice.length() < bufferSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Compute list of tile indices to copy
|
||||||
|
std::vector<uint32_t> tiles(pRegionSize->NumTiles);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < pRegionSize->NumTiles; i++) {
|
||||||
|
VkOffset3D regionOffset = {
|
||||||
|
int32_t(pRegionCoordinate->X),
|
||||||
|
int32_t(pRegionCoordinate->Y),
|
||||||
|
int32_t(pRegionCoordinate->Z) };
|
||||||
|
|
||||||
|
VkExtent3D regionExtent = {
|
||||||
|
uint32_t(pRegionSize->Width),
|
||||||
|
uint32_t(pRegionSize->Height),
|
||||||
|
uint32_t(pRegionSize->Depth) };
|
||||||
|
|
||||||
|
uint32_t tile = pageTable->computePageIndex(
|
||||||
|
pRegionCoordinate->Subresource, regionOffset,
|
||||||
|
regionExtent, !pRegionSize->bUseBox, i);
|
||||||
|
|
||||||
|
// Check that the tile is valid and not part of the mip tail
|
||||||
|
auto tileInfo = pageTable->getPageInfo(tile);
|
||||||
|
|
||||||
|
if (tileInfo.type != DxvkSparsePageType::Buffer
|
||||||
|
&& tileInfo.type != DxvkSparsePageType::Image)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tiles[i] = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If D3D12 is anything to go by, not passing this flag will trigger
|
||||||
|
// the other code path, regardless of whether TO_LINEAR_BUFFER is set.
|
||||||
|
if (Flags & D3D11_TILE_COPY_LINEAR_BUFFER_TO_SWIZZLED_TILED_RESOURCE) {
|
||||||
|
EmitCs([
|
||||||
|
cResource = std::move(resource),
|
||||||
|
cTiles = std::move(tiles),
|
||||||
|
cBuffer = std::move(BufferSlice)
|
||||||
|
] (DxvkContext* ctx) {
|
||||||
|
ctx->copySparsePagesFromBuffer(
|
||||||
|
cResource,
|
||||||
|
cTiles.size(),
|
||||||
|
cTiles.data(),
|
||||||
|
cBuffer.buffer(),
|
||||||
|
cBuffer.offset());
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
EmitCs([
|
||||||
|
cResource = std::move(resource),
|
||||||
|
cTiles = std::move(tiles),
|
||||||
|
cBuffer = std::move(BufferSlice)
|
||||||
|
] (DxvkContext* ctx) {
|
||||||
|
ctx->copySparsePagesToBuffer(
|
||||||
|
cBuffer.buffer(),
|
||||||
|
cBuffer.offset(),
|
||||||
|
cResource,
|
||||||
|
cTiles.size(),
|
||||||
|
cTiles.data());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename ContextType>
|
template<typename ContextType>
|
||||||
void D3D11CommonContext<ContextType>::DiscardBuffer(
|
void D3D11CommonContext<ContextType>::DiscardBuffer(
|
||||||
ID3D11Resource* pResource) {
|
ID3D11Resource* pResource) {
|
||||||
|
@ -885,6 +885,13 @@ namespace dxvk {
|
|||||||
VkOffset3D SrcOffset,
|
VkOffset3D SrcOffset,
|
||||||
VkExtent3D SrcExtent);
|
VkExtent3D SrcExtent);
|
||||||
|
|
||||||
|
void CopyTiledResourceData(
|
||||||
|
ID3D11Resource* pResource,
|
||||||
|
const D3D11_TILED_RESOURCE_COORDINATE* pRegionCoordinate,
|
||||||
|
const D3D11_TILE_REGION_SIZE* pRegionSize,
|
||||||
|
DxvkBufferSlice BufferSlice,
|
||||||
|
UINT Flags);
|
||||||
|
|
||||||
void DiscardBuffer(
|
void DiscardBuffer(
|
||||||
ID3D11Resource* pResource);
|
ID3D11Resource* pResource);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user