summaryrefslogtreecommitdiffstats
path: root/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.cpp
new file mode 100644
index 00000000..d1d66f19
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_initializer.cpp
@@ -0,0 +1,290 @@
+#include <cstring>
+
+#include "d3d11_device.h"
+#include "d3d11_initializer.h"
+
+namespace dxvk {
+
+ D3D11Initializer::D3D11Initializer(
+ D3D11Device* pParent)
+ : m_parent(pParent),
+ m_device(pParent->GetDXVKDevice()),
+ m_context(m_device->createContext()) {
+ m_context->beginRecording(
+ m_device->createCommandList());
+ }
+
+
+ D3D11Initializer::~D3D11Initializer() {
+
+ }
+
+
+ void D3D11Initializer::Flush() {
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+
+ 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) {
+ (pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT)
+ ? InitHostVisibleTexture(pTexture, pInitialData)
+ : InitDeviceLocalTexture(pTexture, pInitialData);
+ }
+
+
+ void D3D11Initializer::InitUavCounter(
+ D3D11UnorderedAccessView* pUav) {
+ auto counterBuffer = pUav->GetCounterSlice();
+
+ if (!counterBuffer.defined())
+ return;
+
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+ m_transferCommands += 1;
+
+ const uint32_t zero = 0;
+ m_context->updateBuffer(
+ counterBuffer.buffer(),
+ 0, sizeof(zero), &zero);
+
+ FlushImplicit();
+ }
+
+
+ void D3D11Initializer::InitDeviceLocalBuffer(
+ D3D11Buffer* pBuffer,
+ const D3D11_SUBRESOURCE_DATA* pInitialData) {
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+
+ DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice();
+
+ if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
+ m_transferMemory += bufferSlice.length();
+ m_transferCommands += 1;
+
+ m_context->uploadBuffer(
+ bufferSlice.buffer(),
+ pInitialData->pSysMem);
+ } else {
+ m_transferCommands += 1;
+
+ m_context->clearBuffer(
+ bufferSlice.buffer(),
+ bufferSlice.offset(),
+ bufferSlice.length(),
+ 0u);
+ }
+
+ 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) {
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+
+ Rc<DxvkImage> image = pTexture->GetImage();
+
+ auto mapMode = pTexture->GetMapMode();
+ auto desc = pTexture->Desc();
+
+ VkFormat packedFormat = m_parent->LookupPackedFormat(desc->Format, pTexture->GetFormatMode()).Format;
+ auto formatInfo = imageFormatInfo(packedFormat);
+
+ 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.
+ for (uint32_t layer = 0; layer < desc->ArraySize; layer++) {
+ for (uint32_t level = 0; level < desc->MipLevels; level++) {
+ const uint32_t id = D3D11CalcSubresource(
+ level, layer, desc->MipLevels);
+
+ VkOffset3D mipLevelOffset = { 0, 0, 0 };
+ 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);
+ }
+ }
+
+ if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
+ util::packImageData(pTexture->GetMappedBuffer(id)->mapPtr(0),
+ pInitialData[id].pSysMem, pInitialData[id].SysMemPitch, pInitialData[id].SysMemSlicePitch,
+ 0, 0, pTexture->GetVkImageType(), mipLevelExtent, 1, formatInfo, formatInfo->aspectMask);
+ }
+ }
+ }
+ } else {
+ 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
+ // expect a resource to be pre-cleared. We can only do that
+ // for non-compressed images, but that should be fine.
+ VkImageSubresourceRange subresources;
+ subresources.aspectMask = formatInfo->aspectMask;
+ subresources.baseMipLevel = 0;
+ subresources.levelCount = desc->MipLevels;
+ subresources.baseArrayLayer = 0;
+ subresources.layerCount = desc->ArraySize;
+
+ if (formatInfo->flags.any(DxvkFormatFlag::BlockCompressed, DxvkFormatFlag::MultiPlane)) {
+ m_context->clearCompressedColorImage(image, subresources);
+ } else {
+ if (subresources.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
+ VkClearColorValue value = { };
+
+ m_context->clearColorImage(
+ image, value, subresources);
+ } else {
+ VkClearDepthStencilValue value;
+ value.depth = 0.0f;
+ value.stencil = 0;
+
+ m_context->clearDepthStencilImage(
+ image, value, subresources);
+ }
+ }
+ }
+
+ if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
+ for (uint32_t i = 0; i < pTexture->CountSubresources(); i++) {
+ auto buffer = pTexture->GetMappedBuffer(i);
+ std::memset(buffer->mapPtr(0), 0, buffer->info().size);
+ }
+ }
+ }
+
+ FlushImplicit();
+ }
+
+
+ void D3D11Initializer::InitHostVisibleTexture(
+ D3D11CommonTexture* pTexture,
+ const D3D11_SUBRESOURCE_DATA* pInitialData) {
+ 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
+ std::lock_guard<dxvk::mutex> lock(m_mutex);
+
+ VkImageSubresourceRange subresources = image->getAvailableSubresources();
+
+ m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_PREINITIALIZED);
+
+ m_transferCommands += 1;
+ FlushImplicit();
+ }
+
+
+ void D3D11Initializer::FlushImplicit() {
+ if (m_transferCommands > MaxTransferCommands
+ || m_transferMemory > MaxTransferMemory)
+ FlushInternal();
+ }
+
+
+ void D3D11Initializer::FlushInternal() {
+ m_context->flushCommandList();
+
+ m_transferCommands = 0;
+ m_transferMemory = 0;
+ }
+
+} \ No newline at end of file