2018-07-23 15:21:17 +02:00
|
|
|
#include <cstring>
|
|
|
|
|
2019-03-26 17:49:14 +01:00
|
|
|
#include "d3d11_device.h"
|
2018-07-23 15:21:17 +02:00
|
|
|
#include "d3d11_initializer.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
D3D11Initializer::D3D11Initializer(
|
2019-03-26 17:49:14 +01:00
|
|
|
D3D11Device* pParent)
|
|
|
|
: m_parent(pParent),
|
|
|
|
m_device(pParent->GetDXVKDevice()),
|
2022-06-21 23:17:26 +02:00
|
|
|
m_context(m_device->createContext(DxvkContextType::Supplementary)) {
|
2018-07-23 15:21:17 +02:00
|
|
|
m_context->beginRecording(
|
|
|
|
m_device->createCommandList());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
D3D11Initializer::~D3D11Initializer() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void D3D11Initializer::Flush() {
|
2021-06-28 19:19:29 +02:00
|
|
|
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
2018-07-23 15:21:17 +02:00
|
|
|
|
|
|
|
if (m_transferCommands != 0)
|
|
|
|
FlushInternal();
|
|
|
|
}
|
|
|
|
|
|
|
|
void D3D11Initializer::InitBuffer(
|
|
|
|
D3D11Buffer* pBuffer,
|
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData) {
|
|
|
|
VkMemoryPropertyFlags memFlags = pBuffer->GetBuffer()->memFlags();
|
|
|
|
|
|
|
|
(memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
|
|
|
? InitHostVisibleBuffer(pBuffer, pInitialData)
|
|
|
|
: InitDeviceLocalBuffer(pBuffer, pInitialData);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void D3D11Initializer::InitTexture(
|
|
|
|
D3D11CommonTexture* pTexture,
|
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData) {
|
2019-09-19 18:23:07 +02:00
|
|
|
(pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT)
|
2018-07-23 15:21:17 +02:00
|
|
|
? InitHostVisibleTexture(pTexture, pInitialData)
|
|
|
|
: InitDeviceLocalTexture(pTexture, pInitialData);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-11-18 18:38:27 +01:00
|
|
|
void D3D11Initializer::InitUavCounter(
|
|
|
|
D3D11UnorderedAccessView* pUav) {
|
|
|
|
auto counterBuffer = pUav->GetCounterSlice();
|
|
|
|
|
|
|
|
if (!counterBuffer.defined())
|
|
|
|
return;
|
|
|
|
|
2021-06-28 19:19:29 +02:00
|
|
|
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
2020-01-03 13:42:25 +01:00
|
|
|
m_transferCommands += 1;
|
2019-11-18 18:38:27 +01:00
|
|
|
|
|
|
|
const uint32_t zero = 0;
|
|
|
|
m_context->updateBuffer(
|
|
|
|
counterBuffer.buffer(),
|
|
|
|
0, sizeof(zero), &zero);
|
|
|
|
|
|
|
|
FlushImplicit();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-23 15:21:17 +02:00
|
|
|
void D3D11Initializer::InitDeviceLocalBuffer(
|
|
|
|
D3D11Buffer* pBuffer,
|
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData) {
|
2021-06-28 19:19:29 +02:00
|
|
|
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
2018-07-23 15:21:17 +02:00
|
|
|
|
|
|
|
DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice();
|
|
|
|
|
|
|
|
if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
|
|
|
|
m_transferMemory += bufferSlice.length();
|
|
|
|
m_transferCommands += 1;
|
|
|
|
|
2019-06-28 19:02:11 +02:00
|
|
|
m_context->uploadBuffer(
|
2018-07-23 15:21:17 +02:00
|
|
|
bufferSlice.buffer(),
|
|
|
|
pInitialData->pSysMem);
|
|
|
|
} else {
|
|
|
|
m_transferCommands += 1;
|
|
|
|
|
2022-02-17 15:32:53 +01:00
|
|
|
m_context->initBuffer(
|
|
|
|
bufferSlice.buffer());
|
2018-07-23 15:21:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
FlushImplicit();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void D3D11Initializer::InitHostVisibleBuffer(
|
|
|
|
D3D11Buffer* pBuffer,
|
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData) {
|
|
|
|
// 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.
|
|
|
|
DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice();
|
|
|
|
|
|
|
|
if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
|
|
|
|
std::memcpy(
|
|
|
|
bufferSlice.mapPtr(0),
|
|
|
|
pInitialData->pSysMem,
|
|
|
|
bufferSlice.length());
|
|
|
|
} else {
|
|
|
|
std::memset(
|
|
|
|
bufferSlice.mapPtr(0), 0,
|
|
|
|
bufferSlice.length());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void D3D11Initializer::InitDeviceLocalTexture(
|
|
|
|
D3D11CommonTexture* pTexture,
|
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData) {
|
2021-06-28 19:19:29 +02:00
|
|
|
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
2018-07-23 15:21:17 +02:00
|
|
|
|
|
|
|
Rc<DxvkImage> image = pTexture->GetImage();
|
|
|
|
|
2021-06-22 08:04:21 +02:00
|
|
|
auto mapMode = pTexture->GetMapMode();
|
|
|
|
auto desc = pTexture->Desc();
|
|
|
|
|
|
|
|
VkFormat packedFormat = m_parent->LookupPackedFormat(desc->Format, pTexture->GetFormatMode()).Format;
|
2022-07-15 17:23:54 +02:00
|
|
|
auto formatInfo = lookupFormatInfo(packedFormat);
|
2018-07-23 15:21:17 +02:00
|
|
|
|
|
|
|
if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
|
|
|
|
// pInitialData is an array that stores an entry for
|
|
|
|
// every single subresource. Since we will define all
|
|
|
|
// subresources, this counts as initialization.
|
2021-06-22 08:04:21 +02:00
|
|
|
for (uint32_t layer = 0; layer < desc->ArraySize; layer++) {
|
|
|
|
for (uint32_t level = 0; level < desc->MipLevels; level++) {
|
2018-07-23 15:21:17 +02:00
|
|
|
const uint32_t id = D3D11CalcSubresource(
|
2021-06-22 08:04:21 +02:00
|
|
|
level, layer, desc->MipLevels);
|
2021-05-19 18:04:16 +02:00
|
|
|
|
2018-07-23 15:21:17 +02:00
|
|
|
VkOffset3D mipLevelOffset = { 0, 0, 0 };
|
2021-06-22 08:04:21 +02:00
|
|
|
VkExtent3D mipLevelExtent = pTexture->MipLevelExtent(level);
|
|
|
|
|
|
|
|
if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) {
|
|
|
|
m_transferCommands += 1;
|
|
|
|
m_transferMemory += pTexture->GetSubresourceLayout(formatInfo->aspectMask, id).Size;
|
|
|
|
|
|
|
|
VkImageSubresourceLayers subresourceLayers;
|
|
|
|
subresourceLayers.aspectMask = formatInfo->aspectMask;
|
|
|
|
subresourceLayers.mipLevel = level;
|
|
|
|
subresourceLayers.baseArrayLayer = layer;
|
|
|
|
subresourceLayers.layerCount = 1;
|
|
|
|
|
|
|
|
if (formatInfo->aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
|
|
|
m_context->uploadImage(
|
|
|
|
image, subresourceLayers,
|
|
|
|
pInitialData[id].pSysMem,
|
|
|
|
pInitialData[id].SysMemPitch,
|
|
|
|
pInitialData[id].SysMemSlicePitch);
|
|
|
|
} else {
|
|
|
|
m_context->updateDepthStencilImage(
|
|
|
|
image, subresourceLayers,
|
|
|
|
VkOffset2D { mipLevelOffset.x, mipLevelOffset.y },
|
|
|
|
VkExtent2D { mipLevelExtent.width, mipLevelExtent.height },
|
|
|
|
pInitialData[id].pSysMem,
|
|
|
|
pInitialData[id].SysMemPitch,
|
|
|
|
pInitialData[id].SysMemSlicePitch,
|
|
|
|
packedFormat);
|
|
|
|
}
|
2019-03-26 17:49:14 +01:00
|
|
|
}
|
2019-06-25 14:22:47 +02:00
|
|
|
|
2021-06-22 08:04:21 +02:00
|
|
|
if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
|
2021-05-19 18:04:16 +02:00
|
|
|
util::packImageData(pTexture->GetMappedBuffer(id)->mapPtr(0),
|
|
|
|
pInitialData[id].pSysMem, pInitialData[id].SysMemPitch, pInitialData[id].SysMemSlicePitch,
|
2021-07-19 16:53:00 +02:00
|
|
|
0, 0, pTexture->GetVkImageType(), mipLevelExtent, 1, formatInfo, formatInfo->aspectMask);
|
2019-06-25 14:22:47 +02:00
|
|
|
}
|
2018-07-23 15:21:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2021-06-22 08:04:21 +02:00
|
|
|
if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) {
|
|
|
|
m_transferCommands += 1;
|
|
|
|
|
|
|
|
// While the Microsoft docs state that resource contents are
|
|
|
|
// undefined if no initial data is provided, some applications
|
2022-02-17 15:19:05 +01:00
|
|
|
// expect a resource to be pre-cleared.
|
2021-06-22 08:04:21 +02:00
|
|
|
VkImageSubresourceRange subresources;
|
|
|
|
subresources.aspectMask = formatInfo->aspectMask;
|
|
|
|
subresources.baseMipLevel = 0;
|
|
|
|
subresources.levelCount = desc->MipLevels;
|
|
|
|
subresources.baseArrayLayer = 0;
|
|
|
|
subresources.layerCount = desc->ArraySize;
|
|
|
|
|
2022-02-17 15:19:05 +01:00
|
|
|
m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_UNDEFINED);
|
2018-07-23 15:21:17 +02:00
|
|
|
}
|
2021-06-22 08:04:46 +02:00
|
|
|
|
2021-06-22 08:04:21 +02:00
|
|
|
if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
|
2021-06-22 08:04:46 +02:00
|
|
|
for (uint32_t i = 0; i < pTexture->CountSubresources(); i++) {
|
|
|
|
auto buffer = pTexture->GetMappedBuffer(i);
|
|
|
|
std::memset(buffer->mapPtr(0), 0, buffer->info().size);
|
|
|
|
}
|
|
|
|
}
|
2018-07-23 15:21:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
FlushImplicit();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void D3D11Initializer::InitHostVisibleTexture(
|
|
|
|
D3D11CommonTexture* pTexture,
|
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData) {
|
2019-09-19 18:23:07 +02:00
|
|
|
Rc<DxvkImage> image = pTexture->GetImage();
|
|
|
|
|
|
|
|
for (uint32_t layer = 0; layer < image->info().numLayers; layer++) {
|
|
|
|
for (uint32_t level = 0; level < image->info().mipLevels; level++) {
|
|
|
|
VkImageSubresource subresource;
|
|
|
|
subresource.aspectMask = image->formatInfo()->aspectMask;
|
|
|
|
subresource.mipLevel = level;
|
|
|
|
subresource.arrayLayer = layer;
|
|
|
|
|
|
|
|
VkExtent3D blockCount = util::computeBlockCount(
|
|
|
|
image->mipLevelExtent(level),
|
|
|
|
image->formatInfo()->blockSize);
|
|
|
|
|
|
|
|
VkSubresourceLayout layout = image->querySubresourceLayout(subresource);
|
|
|
|
|
|
|
|
auto initialData = pInitialData
|
|
|
|
? &pInitialData[D3D11CalcSubresource(level, layer, image->info().mipLevels)]
|
|
|
|
: nullptr;
|
|
|
|
|
|
|
|
for (uint32_t z = 0; z < blockCount.depth; z++) {
|
|
|
|
for (uint32_t y = 0; y < blockCount.height; y++) {
|
|
|
|
auto size = blockCount.width * image->formatInfo()->elementSize;
|
|
|
|
auto dst = image->mapPtr(layout.offset + y * layout.rowPitch + z * layout.depthPitch);
|
|
|
|
|
|
|
|
if (initialData) {
|
|
|
|
auto src = reinterpret_cast<const char*>(initialData->pSysMem)
|
|
|
|
+ y * initialData->SysMemPitch
|
|
|
|
+ z * initialData->SysMemSlicePitch;
|
|
|
|
std::memcpy(dst, src, size);
|
|
|
|
} else {
|
|
|
|
std::memset(dst, 0, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the image on the GPU
|
2021-06-28 19:19:29 +02:00
|
|
|
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
2019-09-19 18:23:07 +02:00
|
|
|
|
2021-09-17 22:30:49 +02:00
|
|
|
VkImageSubresourceRange subresources = image->getAvailableSubresources();
|
2019-09-19 18:23:07 +02:00
|
|
|
|
|
|
|
m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_PREINITIALIZED);
|
|
|
|
|
|
|
|
m_transferCommands += 1;
|
|
|
|
FlushImplicit();
|
2018-07-23 15:21:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void D3D11Initializer::FlushImplicit() {
|
|
|
|
if (m_transferCommands > MaxTransferCommands
|
|
|
|
|| m_transferMemory > MaxTransferMemory)
|
|
|
|
FlushInternal();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void D3D11Initializer::FlushInternal() {
|
2018-11-28 11:01:18 +01:00
|
|
|
m_context->flushCommandList();
|
2018-07-23 15:21:17 +02:00
|
|
|
|
|
|
|
m_transferCommands = 0;
|
|
|
|
m_transferMemory = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|