mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 19:54:19 +01:00
[dxvk] Rework image creation
Uses DxvkResourceAllocation to manage image backing storage, which will allow invalidating images in the future.
This commit is contained in:
parent
d7e1794e29
commit
713b76bea5
@ -95,7 +95,9 @@ namespace dxvk {
|
||||
D3D11CommonTexture* texture = GetCommonTexture(m_resource);
|
||||
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
|
||||
|
||||
VkResult vr = dxvkDevice->vkd()->wine_vkAcquireKeyedMutex(dxvkDevice->handle(), texture->GetImage()->memory().memory(), Key, dwMilliseconds);
|
||||
VkResult vr = dxvkDevice->vkd()->wine_vkAcquireKeyedMutex(
|
||||
dxvkDevice->handle(), texture->GetImage()->getMemoryInfo().memory, Key, dwMilliseconds);
|
||||
|
||||
switch (vr) {
|
||||
case VK_SUCCESS: return S_OK;
|
||||
case VK_TIMEOUT: return WAIT_TIMEOUT;
|
||||
@ -123,9 +125,10 @@ namespace dxvk {
|
||||
context->WaitForResource(texture->GetImage(), DxvkCsThread::SynchronizeAll, D3D11_MAP_READ_WRITE, 0);
|
||||
}
|
||||
|
||||
return dxvkDevice->vkd()->wine_vkReleaseKeyedMutex(dxvkDevice->handle(), texture->GetImage()->memory().memory(), Key) == VK_SUCCESS
|
||||
? S_OK
|
||||
: DXGI_ERROR_INVALID_CALL;
|
||||
VkResult vr = dxvkDevice->vkd()->wine_vkReleaseKeyedMutex(
|
||||
dxvkDevice->handle(), texture->GetImage()->getMemoryInfo().memory, Key);
|
||||
|
||||
return vr == VK_SUCCESS ? S_OK : DXGI_ERROR_INVALID_CALL;
|
||||
}
|
||||
|
||||
D3D11DXGIResource::D3D11DXGIResource(
|
||||
|
@ -556,9 +556,8 @@ namespace dxvk {
|
||||
for (uint32_t i = 0; i < info.imageCount; i++) {
|
||||
VkImage imageHandle = m_presenter->getImage(i).image;
|
||||
|
||||
Rc<DxvkImage> image = new DxvkImage(
|
||||
m_device.ptr(), imageInfo, imageHandle,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
Rc<DxvkImage> image = m_device->importImage(imageInfo,
|
||||
imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
m_imageViews[i] = new DxvkImageView(
|
||||
m_device->vkd(), image, viewInfo);
|
||||
|
@ -76,7 +76,7 @@ namespace dxvk {
|
||||
CreateSampleView(0);
|
||||
|
||||
if (!IsManaged()) {
|
||||
m_size = m_image->memory().length();
|
||||
m_size = m_image->getMemoryInfo().size;
|
||||
if (!m_device->ChangeReportedMemory(-m_size))
|
||||
throw DxvkError("D3D9: Reporting out of memory from tracking.");
|
||||
}
|
||||
|
@ -983,9 +983,8 @@ namespace dxvk {
|
||||
for (uint32_t i = 0; i < info.imageCount; i++) {
|
||||
VkImage imageHandle = m_wctx->presenter->getImage(i).image;
|
||||
|
||||
Rc<DxvkImage> image = new DxvkImage(
|
||||
m_device.ptr(), imageInfo, imageHandle,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
Rc<DxvkImage> image = m_device->importImage(imageInfo,
|
||||
imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
m_wctx->imageViews[i] = new DxvkImageView(
|
||||
m_device->vkd(), image, viewInfo);
|
||||
|
@ -1542,8 +1542,7 @@ namespace dxvk {
|
||||
|
||||
// Bind metadata aspects. Since the image was just created,
|
||||
// we do not need to interrupt our command list for that.
|
||||
VkDeviceMemory imageMemory = image->memory().memory();
|
||||
VkDeviceSize imageOffset = image->memory().offset();
|
||||
DxvkResourceMemoryInfo memoryInfo = image->getMemoryInfo();
|
||||
|
||||
for (const auto& r : req) {
|
||||
if (!(r.formatProperties.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT))
|
||||
@ -1560,13 +1559,13 @@ namespace dxvk {
|
||||
key.flags = VK_SPARSE_MEMORY_BIND_METADATA_BIT;
|
||||
|
||||
DxvkResourceMemoryInfo page;
|
||||
page.memory = imageMemory;
|
||||
page.offset = imageOffset;
|
||||
page.memory = memoryInfo.memory;
|
||||
page.offset = memoryInfo.offset;
|
||||
page.size = r.imageMipTailSize;
|
||||
|
||||
m_cmd->bindImageOpaqueMemory(key, page);
|
||||
|
||||
imageOffset += r.imageMipTailSize;
|
||||
memoryInfo.offset += r.imageMipTailSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,8 @@ namespace dxvk {
|
||||
const DxvkImageCreateInfo& createInfo,
|
||||
VkImage image,
|
||||
VkMemoryPropertyFlags memoryType) {
|
||||
return new DxvkImage(this, createInfo, image, memoryType);
|
||||
return new DxvkImage(this, createInfo, image,
|
||||
m_objects.memoryManager(), memoryType);
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,159 +9,153 @@ namespace dxvk {
|
||||
const DxvkImageCreateInfo& createInfo,
|
||||
DxvkMemoryAllocator& memAlloc,
|
||||
VkMemoryPropertyFlags memFlags)
|
||||
: m_vkd(device->vkd()), m_device(device), m_info(createInfo), m_memFlags(memFlags) {
|
||||
: m_vkd(device->vkd()), m_allocator(&memAlloc), m_properties(memFlags), m_info(createInfo) {
|
||||
copyFormatList(createInfo.viewFormatCount, createInfo.viewFormats);
|
||||
|
||||
// Copy the compatible view formats to a persistent array
|
||||
m_viewFormats.resize(createInfo.viewFormatCount);
|
||||
for (uint32_t i = 0; i < createInfo.viewFormatCount; i++)
|
||||
m_viewFormats[i] = createInfo.viewFormats[i];
|
||||
m_info.viewFormats = m_viewFormats.data();
|
||||
// Determine whether the image is shareable before creating the resource
|
||||
VkImageCreateInfo imageInfo = getImageCreateInfo();
|
||||
m_shared = canShareImage(device, imageInfo, m_info.sharing);
|
||||
|
||||
// If defined, we should provide a format list, which
|
||||
// allows some drivers to enable image compression
|
||||
VkImageFormatListCreateInfo formatList = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO };
|
||||
formatList.viewFormatCount = createInfo.viewFormatCount;
|
||||
formatList.pViewFormats = createInfo.viewFormats;
|
||||
|
||||
VkExternalMemoryImageCreateInfo externalInfo = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO };
|
||||
externalInfo.handleTypes = createInfo.sharing.type;
|
||||
|
||||
VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, &formatList };
|
||||
info.flags = createInfo.flags;
|
||||
info.imageType = createInfo.type;
|
||||
info.format = createInfo.format;
|
||||
info.extent = createInfo.extent;
|
||||
info.mipLevels = createInfo.mipLevels;
|
||||
info.arrayLayers = createInfo.numLayers;
|
||||
info.samples = createInfo.sampleCount;
|
||||
info.tiling = createInfo.tiling;
|
||||
info.usage = createInfo.usage;
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
info.initialLayout = createInfo.initialLayout;
|
||||
|
||||
if ((m_shared = canShareImage(info, createInfo.sharing)))
|
||||
externalInfo.pNext = std::exchange(info.pNext, &externalInfo);
|
||||
|
||||
if (m_vkd->vkCreateImage(m_vkd->device(), &info, nullptr, &m_image.image)) {
|
||||
throw DxvkError(str::format(
|
||||
"DxvkImage: Failed to create image:",
|
||||
"\n Type: ", info.imageType,
|
||||
"\n Format: ", info.format,
|
||||
"\n Flags: ", info.flags,
|
||||
"\n Extent: ", "(", info.extent.width,
|
||||
",", info.extent.height,
|
||||
",", info.extent.depth, ")",
|
||||
"\n Mip levels: ", info.mipLevels,
|
||||
"\n Array layers: ", info.arrayLayers,
|
||||
"\n Samples: ", info.samples,
|
||||
"\n Usage: ", info.usage,
|
||||
"\n Tiling: ", info.tiling));
|
||||
}
|
||||
|
||||
VkImageMemoryRequirementsInfo2 memoryRequirementInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 };
|
||||
memoryRequirementInfo.image = m_image.image;
|
||||
|
||||
if (!(info.flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
|
||||
// Get memory requirements for the image and ask driver
|
||||
// whether we need to use a dedicated allocation.
|
||||
DxvkMemoryRequirements memoryRequirements = { };
|
||||
memoryRequirements.tiling = info.tiling;
|
||||
memoryRequirements.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS };
|
||||
memoryRequirements.core = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &memoryRequirements.dedicated };
|
||||
|
||||
m_vkd->vkGetImageMemoryRequirements2(m_vkd->device(),
|
||||
&memoryRequirementInfo, &memoryRequirements.core);
|
||||
|
||||
// Fill in desired memory properties
|
||||
DxvkMemoryProperties memoryProperties = { };
|
||||
memoryProperties.flags = m_memFlags;
|
||||
|
||||
if (memoryRequirements.dedicated.prefersDedicatedAllocation || m_shared) {
|
||||
memoryProperties.dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO };
|
||||
memoryProperties.dedicated.image = m_image.image;
|
||||
}
|
||||
|
||||
if (m_shared) {
|
||||
memoryRequirements.dedicated.prefersDedicatedAllocation = VK_TRUE;
|
||||
memoryRequirements.dedicated.requiresDedicatedAllocation = VK_TRUE;
|
||||
|
||||
if (createInfo.sharing.mode == DxvkSharedHandleMode::Export) {
|
||||
memoryProperties.sharedExport = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO };
|
||||
memoryProperties.sharedExport.pNext = std::exchange(memoryProperties.dedicated.pNext, &memoryProperties.sharedExport);
|
||||
memoryProperties.sharedExport.handleTypes = createInfo.sharing.type;
|
||||
}
|
||||
|
||||
if (createInfo.sharing.mode == DxvkSharedHandleMode::Import) {
|
||||
memoryProperties.sharedImportWin32 = { VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR };
|
||||
memoryProperties.sharedImportWin32.pNext = std::exchange(memoryProperties.dedicated.pNext, &memoryProperties.sharedImportWin32);
|
||||
memoryProperties.sharedImportWin32.handleType = createInfo.sharing.type;
|
||||
memoryProperties.sharedImportWin32.handle = createInfo.sharing.handle;
|
||||
}
|
||||
}
|
||||
|
||||
m_image.memory = memAlloc.alloc(memoryRequirements, memoryProperties);
|
||||
|
||||
// Try to bind the allocated memory slice to the image
|
||||
if (m_vkd->vkBindImageMemory(m_vkd->device(), m_image.image,
|
||||
m_image.memory.memory(), m_image.memory.offset()) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkImage::DxvkImage: Failed to bind device memory");
|
||||
} else {
|
||||
// Initialize sparse info. We do not immediately bind the metadata
|
||||
// aspects of the image here, the caller needs to explicitly do that.
|
||||
m_sparsePageTable = DxvkSparsePageTable(device, info, m_image.image);
|
||||
|
||||
// Allocate memory for sparse metadata if necessary
|
||||
auto properties = m_sparsePageTable.getProperties();
|
||||
|
||||
if (properties.metadataPageCount) {
|
||||
DxvkMemoryRequirements memoryRequirements = { };
|
||||
memoryRequirements.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
memoryRequirements.core = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 };
|
||||
|
||||
m_vkd->vkGetImageMemoryRequirements2(m_vkd->device(),
|
||||
&memoryRequirementInfo, &memoryRequirements.core);
|
||||
|
||||
DxvkMemoryProperties memoryProperties = { };
|
||||
memoryProperties.flags = m_memFlags;
|
||||
|
||||
// Set size and alignment to match the metadata requirements
|
||||
auto& core = memoryRequirements.core.memoryRequirements;
|
||||
core.size = SparseMemoryPageSize * properties.metadataPageCount;
|
||||
core.alignment = SparseMemoryPageSize;
|
||||
|
||||
m_image.memory = memAlloc.alloc(memoryRequirements, memoryProperties);
|
||||
}
|
||||
}
|
||||
assignResource(createResource());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
DxvkImage::DxvkImage(
|
||||
DxvkDevice* device,
|
||||
const DxvkImageCreateInfo& info,
|
||||
VkImage image,
|
||||
VkImage imageHandle,
|
||||
DxvkMemoryAllocator& memAlloc,
|
||||
VkMemoryPropertyFlags memFlags)
|
||||
: m_vkd(device->vkd()), m_device(device), m_info(info), m_memFlags(memFlags), m_image({ image }) {
|
||||
m_viewFormats.resize(info.viewFormatCount);
|
||||
for (uint32_t i = 0; i < info.viewFormatCount; i++)
|
||||
m_viewFormats[i] = info.viewFormats[i];
|
||||
: m_vkd(device->vkd()), m_allocator(&memAlloc), m_properties(memFlags), m_info(info) {
|
||||
copyFormatList(info.viewFormatCount, info.viewFormats);
|
||||
|
||||
// Create backing storage for existing image resource
|
||||
VkImageCreateInfo imageInfo = getImageCreateInfo();
|
||||
assignResource(m_allocator->importImageResource(imageInfo, imageHandle));
|
||||
}
|
||||
|
||||
|
||||
DxvkImage::~DxvkImage() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
VkSubresourceLayout DxvkImage::querySubresourceLayout(
|
||||
const VkImageSubresource& subresource) const {
|
||||
VkSubresourceLayout result = { };
|
||||
|
||||
m_vkd->vkGetImageSubresourceLayout(m_vkd->device(),
|
||||
m_imageInfo.image, &subresource, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
HANDLE DxvkImage::sharedHandle() const {
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (!m_shared)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
#ifdef _WIN32
|
||||
DxvkResourceMemoryInfo memoryInfo = m_storage->getMemoryInfo();
|
||||
|
||||
VkMemoryGetWin32HandleInfoKHR handleInfo = { VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR };
|
||||
handleInfo.handleType = m_info.sharing.type;
|
||||
handleInfo.memory = memoryInfo.memory;
|
||||
|
||||
if (m_vkd->vkGetMemoryWin32HandleKHR(m_vkd->device(), &handleInfo, &handle) != VK_SUCCESS)
|
||||
Logger::warn("DxvkImage::DxvkImage: Failed to get shared handle for image");
|
||||
#endif
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
DxvkSparsePageTable* DxvkImage::getSparsePageTable() {
|
||||
return m_storage->getSparsePageTable();
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkResourceAllocation> DxvkImage::createResource() {
|
||||
const DxvkFormatInfo* formatInfo = lookupFormatInfo(m_info.format);
|
||||
|
||||
VkImageCreateInfo imageInfo = getImageCreateInfo();
|
||||
|
||||
// Set up view format list so that drivers can better enable
|
||||
// compression. Skip for planar formats due to validation errors.
|
||||
VkImageFormatListCreateInfo formatList = { VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO };
|
||||
|
||||
if (!(formatInfo->aspectMask & VK_IMAGE_ASPECT_PLANE_0_BIT)) {
|
||||
formatList.viewFormatCount = m_info.viewFormatCount;
|
||||
formatList.pViewFormats = m_info.viewFormats;
|
||||
}
|
||||
|
||||
if ((m_info.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && formatList.viewFormatCount)
|
||||
formatList.pNext = std::exchange(imageInfo.pNext, &formatList);
|
||||
|
||||
// Set up external memory parameters for shared images
|
||||
VkExternalMemoryImageCreateInfo externalInfo = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO };
|
||||
|
||||
if (m_shared) {
|
||||
externalInfo.pNext = std::exchange(imageInfo.pNext, &externalInfo);
|
||||
externalInfo.handleTypes = m_info.sharing.type;
|
||||
}
|
||||
|
||||
// Set up shared memory properties
|
||||
void* sharedMemoryInfo = nullptr;
|
||||
|
||||
VkExportMemoryAllocateInfo sharedExport = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO };
|
||||
VkImportMemoryWin32HandleInfoKHR sharedImportWin32= { VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR };
|
||||
|
||||
if (m_shared && m_info.sharing.mode == DxvkSharedHandleMode::Export) {
|
||||
sharedExport.pNext = std::exchange(sharedMemoryInfo, &sharedExport);
|
||||
sharedExport.handleTypes = m_info.sharing.type;
|
||||
}
|
||||
|
||||
if (m_shared && m_info.sharing.mode == DxvkSharedHandleMode::Import) {
|
||||
sharedImportWin32.pNext = std::exchange(sharedMemoryInfo, &sharedImportWin32);
|
||||
sharedImportWin32.handleType = m_info.sharing.type;
|
||||
sharedImportWin32.handle = m_info.sharing.handle;
|
||||
}
|
||||
|
||||
return m_allocator->createImageResource(imageInfo, m_properties, sharedMemoryInfo);
|
||||
}
|
||||
|
||||
|
||||
VkImageCreateInfo DxvkImage::getImageCreateInfo() const {
|
||||
VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
|
||||
info.flags = m_info.flags;
|
||||
info.imageType = m_info.type;
|
||||
info.format = m_info.format;
|
||||
info.extent = m_info.extent;
|
||||
info.mipLevels = m_info.mipLevels;
|
||||
info.arrayLayers = m_info.numLayers;
|
||||
info.samples = m_info.sampleCount;
|
||||
info.tiling = m_info.tiling;
|
||||
info.usage = m_info.usage;
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
info.initialLayout = m_info.initialLayout;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
void DxvkImage::copyFormatList(uint32_t formatCount, const VkFormat* formats) {
|
||||
m_viewFormats.resize(formatCount);
|
||||
|
||||
for (uint32_t i = 0; i < formatCount; i++)
|
||||
m_viewFormats[i] = formats[i];
|
||||
|
||||
m_info.viewFormats = m_viewFormats.data();
|
||||
}
|
||||
|
||||
|
||||
DxvkImage::~DxvkImage() {
|
||||
// This is a bit of a hack to determine whether
|
||||
// the image is implementation-handled or not
|
||||
if ((m_image.memory.memory())
|
||||
|| (m_info.flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT))
|
||||
m_vkd->vkDestroyImage(m_vkd->device(), m_image.image, nullptr);
|
||||
}
|
||||
|
||||
|
||||
bool DxvkImage::canShareImage(const VkImageCreateInfo& createInfo, const DxvkSharedHandleInfo& sharingInfo) const {
|
||||
bool DxvkImage::canShareImage(DxvkDevice* device, const VkImageCreateInfo& createInfo, const DxvkSharedHandleInfo& sharingInfo) const {
|
||||
if (sharingInfo.mode == DxvkSharedHandleMode::None)
|
||||
return false;
|
||||
|
||||
if (!m_device->features().khrExternalMemoryWin32) {
|
||||
if (!device->features().khrExternalMemoryWin32) {
|
||||
Logger::err("Failed to create shared resource: VK_KHR_EXTERNAL_MEMORY_WIN32 not supported");
|
||||
return false;
|
||||
}
|
||||
@ -179,7 +173,7 @@ namespace dxvk {
|
||||
formatQuery.flags = createInfo.flags;
|
||||
formatQuery.handleType = sharingInfo.type;
|
||||
|
||||
auto limits = m_device->getFormatLimits(formatQuery);
|
||||
auto limits = device->getFormatLimits(formatQuery);
|
||||
|
||||
if (!limits)
|
||||
return false;
|
||||
@ -197,27 +191,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
HANDLE DxvkImage::sharedHandle() const {
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (!m_shared)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
#ifdef _WIN32
|
||||
VkMemoryGetWin32HandleInfoKHR handleInfo = { VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR };
|
||||
handleInfo.handleType = m_info.sharing.type;
|
||||
handleInfo.memory = m_image.memory.memory();
|
||||
if (m_vkd->vkGetMemoryWin32HandleKHR(m_vkd->device(), &handleInfo, &handle) != VK_SUCCESS)
|
||||
Logger::warn("DxvkImage::DxvkImage: Failed to get shared handle for image");
|
||||
#endif
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
DxvkSparsePageTable* DxvkImage::getSparsePageTable() {
|
||||
return &m_sparsePageTable;
|
||||
}
|
||||
|
||||
|
||||
DxvkImageView::DxvkImageView(
|
||||
|
@ -19,41 +19,41 @@ namespace dxvk {
|
||||
*/
|
||||
struct DxvkImageCreateInfo {
|
||||
/// Image dimension
|
||||
VkImageType type;
|
||||
VkImageType type = VK_IMAGE_TYPE_2D;
|
||||
|
||||
/// Pixel format
|
||||
VkFormat format;
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
|
||||
/// Flags
|
||||
VkImageCreateFlags flags;
|
||||
VkImageCreateFlags flags = 0u;
|
||||
|
||||
/// Sample count for MSAA
|
||||
VkSampleCountFlagBits sampleCount;
|
||||
VkSampleCountFlagBits sampleCount = VkSampleCountFlagBits(0u);
|
||||
|
||||
/// Image size, in texels
|
||||
VkExtent3D extent;
|
||||
VkExtent3D extent = { };
|
||||
|
||||
/// Number of image array layers
|
||||
uint32_t numLayers;
|
||||
uint32_t numLayers = 0u;
|
||||
|
||||
/// Number of mip levels
|
||||
uint32_t mipLevels;
|
||||
uint32_t mipLevels = 0u;
|
||||
|
||||
/// Image usage flags
|
||||
VkImageUsageFlags usage;
|
||||
VkImageUsageFlags usage = 0u;
|
||||
|
||||
/// Pipeline stages that can access
|
||||
/// the contents of the image
|
||||
VkPipelineStageFlags stages;
|
||||
VkPipelineStageFlags stages = 0u;
|
||||
|
||||
/// Allowed access pattern
|
||||
VkAccessFlags access;
|
||||
VkAccessFlags access = 0u;
|
||||
|
||||
/// Image tiling mode
|
||||
VkImageTiling tiling;
|
||||
VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
|
||||
/// Common image layout
|
||||
VkImageLayout layout;
|
||||
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
// Initial image layout
|
||||
VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
@ -64,11 +64,11 @@ namespace dxvk {
|
||||
|
||||
// Image view formats that can
|
||||
// be used with this image
|
||||
uint32_t viewFormatCount = 0;
|
||||
const VkFormat* viewFormats = nullptr;
|
||||
uint32_t viewFormatCount = 0;
|
||||
const VkFormat* viewFormats = nullptr;
|
||||
|
||||
// Shared handle info
|
||||
DxvkSharedHandleInfo sharing;
|
||||
DxvkSharedHandleInfo sharing = { };
|
||||
};
|
||||
|
||||
|
||||
@ -104,19 +104,10 @@ namespace dxvk {
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Stores an image and its memory slice.
|
||||
*/
|
||||
struct DxvkPhysicalImage {
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
DxvkMemory memory;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief DXVK image
|
||||
* \brief Virtual image resource
|
||||
*
|
||||
* An image resource consisting of various subresources.
|
||||
* Can be accessed by the host if allocated on a suitable
|
||||
@ -143,8 +134,9 @@ namespace dxvk {
|
||||
*/
|
||||
DxvkImage(
|
||||
DxvkDevice* device,
|
||||
const DxvkImageCreateInfo& info,
|
||||
VkImage image,
|
||||
const DxvkImageCreateInfo& createInfo,
|
||||
VkImage imageHandle,
|
||||
DxvkMemoryAllocator& memAlloc,
|
||||
VkMemoryPropertyFlags memFlags);
|
||||
|
||||
/**
|
||||
@ -162,7 +154,7 @@ namespace dxvk {
|
||||
* \returns Image handle
|
||||
*/
|
||||
VkImage handle() const {
|
||||
return m_image.image;
|
||||
return m_imageInfo.image;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -183,7 +175,7 @@ namespace dxvk {
|
||||
* \returns Vulkan memory flags
|
||||
*/
|
||||
VkMemoryPropertyFlags memFlags() const {
|
||||
return m_memFlags;
|
||||
return m_properties;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -196,7 +188,7 @@ namespace dxvk {
|
||||
* \returns Pointer to mapped memory region
|
||||
*/
|
||||
void* mapPtr(VkDeviceSize offset) const {
|
||||
return m_image.memory.mapPtr(offset);
|
||||
return reinterpret_cast<char*>(m_imageInfo.mapPtr) + offset;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -227,23 +219,6 @@ namespace dxvk {
|
||||
return util::computeMipLevelExtent(m_info.extent, level, m_info.format, aspect);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Queries memory layout of a subresource
|
||||
*
|
||||
* Can be used to retrieve the exact pointer to a
|
||||
* subresource of a mapped image with linear tiling.
|
||||
* \param [in] subresource The image subresource
|
||||
* \returns Memory layout of that subresource
|
||||
*/
|
||||
VkSubresourceLayout querySubresourceLayout(
|
||||
const VkImageSubresource& subresource) const {
|
||||
VkSubresourceLayout result;
|
||||
m_vkd->vkGetImageSubresourceLayout(
|
||||
m_vkd->device(), m_image.image,
|
||||
&subresource, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Picks a compatible layout
|
||||
*
|
||||
@ -306,8 +281,8 @@ namespace dxvk {
|
||||
* \brief Memory object
|
||||
* \returns Backing memory
|
||||
*/
|
||||
const DxvkMemory& memory() const {
|
||||
return m_image.memory;
|
||||
DxvkResourceMemoryInfo getMemoryInfo() const {
|
||||
return m_storage->getMemoryInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -325,6 +300,17 @@ namespace dxvk {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Queries memory layout of a subresource
|
||||
*
|
||||
* Can be used to retrieve the exact pointer to a
|
||||
* subresource of a mapped image with linear tiling.
|
||||
* \param [in] subresource The image subresource
|
||||
* \returns Memory layout of that subresource
|
||||
*/
|
||||
VkSubresourceLayout querySubresourceLayout(
|
||||
const VkImageSubresource& subresource) const;
|
||||
|
||||
/**
|
||||
* \brief Create a new shared handle to dedicated memory backing the image
|
||||
* \returns The shared handle with the type given by DxvkSharedHandleInfo::type
|
||||
@ -337,21 +323,58 @@ namespace dxvk {
|
||||
*/
|
||||
DxvkSparsePageTable* getSparsePageTable();
|
||||
|
||||
/**
|
||||
* \brief Creates image resource
|
||||
*
|
||||
* The returned image can be used as backing storage.
|
||||
* \returns New underlying image resource
|
||||
*/
|
||||
Rc<DxvkResourceAllocation> createResource();
|
||||
|
||||
/**
|
||||
* \brief Assigns backing storage to the image
|
||||
*
|
||||
* Implicitly invalidates all image views.
|
||||
* \param [in] resource New backing storage
|
||||
* \returns Previous backing storage
|
||||
*/
|
||||
Rc<DxvkResourceAllocation> assignResource(Rc<DxvkResourceAllocation>&& resource) {
|
||||
Rc<DxvkResourceAllocation> old = std::move(m_storage);
|
||||
|
||||
m_storage = std::move(resource);
|
||||
m_imageInfo = m_storage->getImageInfo();
|
||||
|
||||
m_version += 1u;
|
||||
return old;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
const DxvkDevice* m_device;
|
||||
DxvkImageCreateInfo m_info;
|
||||
VkMemoryPropertyFlags m_memFlags;
|
||||
DxvkPhysicalImage m_image;
|
||||
|
||||
DxvkSparsePageTable m_sparsePageTable;
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
DxvkMemoryAllocator* m_allocator = nullptr;
|
||||
VkMemoryPropertyFlags m_properties = 0u;
|
||||
|
||||
bool m_shared = false;
|
||||
DxvkImageCreateInfo m_info = { };
|
||||
|
||||
small_vector<VkFormat, 4> m_viewFormats;
|
||||
|
||||
bool canShareImage(const VkImageCreateInfo& createInfo, const DxvkSharedHandleInfo& sharingInfo) const;
|
||||
uint32_t m_version = 0u;
|
||||
VkBool32 m_shared = VK_FALSE;
|
||||
|
||||
DxvkResourceImageInfo m_imageInfo = { };
|
||||
|
||||
Rc<DxvkResourceAllocation> m_storage = nullptr;
|
||||
|
||||
small_vector<VkFormat, 4> m_viewFormats;
|
||||
|
||||
VkImageCreateInfo getImageCreateInfo() const;
|
||||
|
||||
void copyFormatList(
|
||||
uint32_t formatCount,
|
||||
const VkFormat* formats);
|
||||
|
||||
bool canShareImage(
|
||||
DxvkDevice* device,
|
||||
const VkImageCreateInfo& createInfo,
|
||||
const DxvkSharedHandleInfo& sharingInfo) const;
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user