1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-02 01:24:11 +01:00

[dxvk] Rework image view creation

This commit is contained in:
Philip Rebohle 2024-09-26 02:57:11 +02:00 committed by Philip Rebohle
parent 713b76bea5
commit 25076d9220
12 changed files with 455 additions and 420 deletions

View File

@ -512,12 +512,12 @@ namespace dxvk {
// we'll have to use a fallback using a texel buffer view and buffer copies. // we'll have to use a fallback using a texel buffer view and buffer copies.
bool isViewCompatible = uavFormat == rawFormat; bool isViewCompatible = uavFormat == rawFormat;
if (!isViewCompatible && (imageView->imageInfo().flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) { if (!isViewCompatible && (imageView->image()->info().flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
uint32_t formatCount = imageView->imageInfo().viewFormatCount; uint32_t formatCount = imageView->image()->info().viewFormatCount;
isViewCompatible = formatCount == 0; isViewCompatible = formatCount == 0;
for (uint32_t i = 0; i < formatCount && !isViewCompatible; i++) for (uint32_t i = 0; i < formatCount && !isViewCompatible; i++)
isViewCompatible = imageView->imageInfo().viewFormats[i] == rawFormat; isViewCompatible = imageView->image()->info().viewFormats[i] == rawFormat;
} }
if (isViewCompatible || isZeroClearValue) { if (isViewCompatible || isZeroClearValue) {
@ -5428,8 +5428,8 @@ namespace dxvk {
|| curView->info().numLayers != refView->info().numLayers) || curView->info().numLayers != refView->info().numLayers)
return false; return false;
if (curView->imageInfo().sampleCount if (curView->image()->info().sampleCount
!= refView->imageInfo().sampleCount) != refView->image()->info().sampleCount)
return false; return false;
// Color targets must all be the same size // Color targets must all be the same size

View File

@ -558,9 +558,7 @@ namespace dxvk {
Rc<DxvkImage> image = m_device->importImage(imageInfo, Rc<DxvkImage> image = m_device->importImage(imageInfo,
imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
m_imageViews[i] = image->createView(viewInfo);
m_imageViews[i] = new DxvkImageView(
m_device->vkd(), image, viewInfo);
} }
} }

View File

@ -50,7 +50,7 @@ namespace dxvk {
} }
VkImageLayout GetRenderLayout() const { VkImageLayout GetRenderLayout() const {
if (m_view->imageInfo().tiling == VK_IMAGE_TILING_OPTIMAL) { if (m_view->image()->info().tiling == VK_IMAGE_TILING_OPTIMAL) {
switch (m_desc.Flags & (D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL)) { switch (m_desc.Flags & (D3D11_DSV_READ_ONLY_DEPTH | D3D11_DSV_READ_ONLY_STENCIL)) {
default: // case 0 default: // case 0
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
@ -67,7 +67,7 @@ namespace dxvk {
} }
UINT GetSampleCount() const { UINT GetSampleCount() const {
return UINT(m_view->imageInfo().sampleCount); return UINT(m_view->image()->info().sampleCount);
} }
VkImageAspectFlags GetWritableAspectMask() const { VkImageAspectFlags GetWritableAspectMask() const {

View File

@ -52,13 +52,13 @@ namespace dxvk {
} }
VkImageLayout GetRenderLayout() const { VkImageLayout GetRenderLayout() const {
return m_view->imageInfo().tiling == VK_IMAGE_TILING_OPTIMAL return m_view->image()->info().tiling == VK_IMAGE_TILING_OPTIMAL
? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
: VK_IMAGE_LAYOUT_GENERAL; : VK_IMAGE_LAYOUT_GENERAL;
} }
UINT GetSampleCount() const { UINT GetSampleCount() const {
return UINT(m_view->imageInfo().sampleCount); return UINT(m_view->image()->info().sampleCount);
} }
D3D10RenderTargetView* GetD3D10Iface() { D3D10RenderTargetView* GetD3D10Iface() {

View File

@ -985,9 +985,7 @@ namespace dxvk {
Rc<DxvkImage> image = m_device->importImage(imageInfo, Rc<DxvkImage> image = m_device->importImage(imageInfo,
imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
m_wctx->imageViews[i] = image->createView(viewInfo);
m_wctx->imageViews[i] = new DxvkImageView(
m_device->vkd(), image, viewInfo);
} }
} }

View File

@ -730,7 +730,7 @@ namespace dxvk {
return; return;
// Create one depth view and one stencil view // Create one depth view and one stencil view
DxvkImageViewCreateInfo dViewInfo; DxvkImageViewCreateInfo dViewInfo = { };
dViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; dViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
dViewInfo.format = srcImage->info().format; dViewInfo.format = srcImage->info().format;
dViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; dViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
@ -743,8 +743,8 @@ namespace dxvk {
DxvkImageViewCreateInfo sViewInfo = dViewInfo; DxvkImageViewCreateInfo sViewInfo = dViewInfo;
sViewInfo.aspect = VK_IMAGE_ASPECT_STENCIL_BIT; sViewInfo.aspect = VK_IMAGE_ASPECT_STENCIL_BIT;
Rc<DxvkImageView> dView = m_device->createImageView(srcImage, dViewInfo); Rc<DxvkImageView> dView = srcImage->createView(dViewInfo);
Rc<DxvkImageView> sView = m_device->createImageView(srcImage, sViewInfo); Rc<DxvkImageView> sView = srcImage->createView(sViewInfo);
// Create a descriptor set for the pack operation // Create a descriptor set for the pack operation
VkImageLayout layout = srcImage->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); VkImageLayout layout = srcImage->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
@ -817,9 +817,6 @@ namespace dxvk {
dstBuffer->info().stages, dstBuffer->info().stages,
dstBuffer->info().access); dstBuffer->info().access);
m_cmd->trackResource<DxvkAccess::None>(dView);
m_cmd->trackResource<DxvkAccess::None>(sView);
m_cmd->trackResource<DxvkAccess::Write>(dstBuffer); m_cmd->trackResource<DxvkAccess::Write>(dstBuffer);
m_cmd->trackResource<DxvkAccess::Read>(srcImage); m_cmd->trackResource<DxvkAccess::Read>(srcImage);
} }
@ -1662,22 +1659,22 @@ namespace dxvk {
VkImageLayout srcLayout = imageView->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); VkImageLayout srcLayout = imageView->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// If necessary, transition first mip level to the read-only layout // If necessary, transition first mip level to the read-only layout
if (imageView->imageInfo().layout != srcLayout) { if (imageView->image()->info().layout != srcLayout) {
m_execAcquires.accessImage(imageView->image(), m_execAcquires.accessImage(imageView->image(),
mipGenerator->getTopSubresource(), mipGenerator->getTopSubresource(),
imageView->imageInfo().layout, imageView->image()->info().layout,
imageView->imageInfo().stages, 0, imageView->image()->info().stages, 0,
srcLayout, srcLayout,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_SHADER_READ_BIT); VK_ACCESS_SHADER_READ_BIT);
} }
// If necessary, initialize all levels that are written to // If necessary, initialize all levels that are written to
if (imageView->imageInfo().layout != dstLayout) { if (imageView->image()->info().layout != dstLayout) {
m_execAcquires.accessImage(imageView->image(), m_execAcquires.accessImage(imageView->image(),
mipGenerator->getAllTargetSubresources(), mipGenerator->getAllTargetSubresources(),
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED,
imageView->imageInfo().stages, 0, imageView->image()->info().stages, 0,
dstLayout, dstLayout,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
@ -1785,9 +1782,9 @@ namespace dxvk {
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
imageView->imageInfo().layout, imageView->image()->info().layout,
imageView->imageInfo().stages, imageView->image()->info().stages,
imageView->imageInfo().access); imageView->image()->info().access);
} else { } else {
m_execBarriers.accessImage(imageView->image(), m_execBarriers.accessImage(imageView->image(),
mipGenerator->getAllSourceSubresources(), mipGenerator->getAllSourceSubresources(),
@ -1796,18 +1793,18 @@ namespace dxvk {
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
imageView->imageInfo().layout, imageView->image()->info().layout,
imageView->imageInfo().stages, imageView->image()->info().stages,
imageView->imageInfo().access); imageView->image()->info().access);
m_execBarriers.accessImage(imageView->image(), m_execBarriers.accessImage(imageView->image(),
mipGenerator->getBottomSubresource(), mipGenerator->getBottomSubresource(),
dstLayout, dstLayout,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
imageView->imageInfo().layout, imageView->image()->info().layout,
imageView->imageInfo().stages, imageView->image()->info().stages,
imageView->imageInfo().access); imageView->image()->info().access);
} }
m_cmd->trackResource<DxvkAccess::None>(mipGenerator); m_cmd->trackResource<DxvkAccess::None>(mipGenerator);
@ -1971,14 +1968,14 @@ namespace dxvk {
VkClearValue clearValue) { VkClearValue clearValue) {
DxvkColorAttachmentOps colorOp; DxvkColorAttachmentOps colorOp;
colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
colorOp.loadLayout = imageView->imageInfo().layout; colorOp.loadLayout = imageView->image()->info().layout;
colorOp.storeLayout = imageView->imageInfo().layout; colorOp.storeLayout = imageView->image()->info().layout;
DxvkDepthAttachmentOps depthOp; DxvkDepthAttachmentOps depthOp;
depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_LOAD; depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_LOAD;
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD; depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD;
depthOp.loadLayout = imageView->imageInfo().layout; depthOp.loadLayout = imageView->image()->info().layout;
depthOp.storeLayout = imageView->imageInfo().layout; depthOp.storeLayout = imageView->image()->info().layout;
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT)
colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
@ -2015,7 +2012,7 @@ namespace dxvk {
attachmentIndex = -1; attachmentIndex = -1;
} }
bool is3D = imageView->imageInfo().type == VK_IMAGE_TYPE_3D; bool is3D = imageView->image()->info().type == VK_IMAGE_TYPE_3D;
if ((clearAspects | discardAspects) == imageView->info().aspect && !is3D) { if ((clearAspects | discardAspects) == imageView->info().aspect && !is3D) {
colorOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; colorOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@ -2023,7 +2020,7 @@ namespace dxvk {
} }
if (attachmentIndex < 0) { if (attachmentIndex < 0) {
bool hasViewFormatMismatch = imageView->info().format != imageView->imageInfo().format; bool hasViewFormatMismatch = imageView->info().format != imageView->image()->info().format;
if (m_execBarriers.isImageDirty(imageView->image(), imageView->imageSubresources(), DxvkAccess::Write)) if (m_execBarriers.isImageDirty(imageView->image(), imageView->imageSubresources(), DxvkAccess::Write))
m_execBarriers.recordCommands(m_cmd); m_execBarriers.recordCommands(m_cmd);
@ -2120,10 +2117,9 @@ namespace dxvk {
imageView->imageSubresources(), imageView->imageSubresources(),
imageLayout, clearStages, clearAccess, imageLayout, clearStages, clearAccess,
storeLayout, storeLayout,
imageView->imageInfo().stages, imageView->image()->info().stages,
imageView->imageInfo().access); imageView->image()->info().access);
m_cmd->trackResource<DxvkAccess::None>(imageView);
m_cmd->trackResource<DxvkAccess::Write>(imageView->image()); m_cmd->trackResource<DxvkAccess::Write>(imageView->image());
} else { } else {
// Perform the operation when starting the next render pass // Perform the operation when starting the next render pass
@ -2221,7 +2217,7 @@ namespace dxvk {
void DxvkContext::flushSharedImages() { void DxvkContext::flushSharedImages() {
for (auto i = m_deferredClears.begin(); i != m_deferredClears.end(); ) { for (auto i = m_deferredClears.begin(); i != m_deferredClears.end(); ) {
if (i->imageView->imageInfo().shared) { if (i->imageView->image()->info().shared) {
this->performClear(i->imageView, -1, i->discardAspects, i->clearAspects, i->clearValue); this->performClear(i->imageView, -1, i->discardAspects, i->clearAspects, i->clearValue);
i = m_deferredClears.erase(i); i = m_deferredClears.erase(i);
} else { } else {
@ -3320,11 +3316,11 @@ namespace dxvk {
renderingInfo.pStencilAttachment = &attachmentInfo; renderingInfo.pStencilAttachment = &attachmentInfo;
} }
if (clearLayout != imageView->imageInfo().layout) { if (clearLayout != imageView->image()->info().layout) {
m_execAcquires.accessImage( m_execAcquires.accessImage(
imageView->image(), imageView->image(),
imageView->imageSubresources(), imageView->imageSubresources(),
imageView->imageInfo().layout, clearStages, 0, imageView->image()->info().layout, clearStages, 0,
clearLayout, clearStages, clearAccess); clearLayout, clearStages, clearAccess);
m_execAcquires.recordCommands(m_cmd); m_execAcquires.recordCommands(m_cmd);
} }
@ -3365,11 +3361,10 @@ namespace dxvk {
imageView->image(), imageView->image(),
imageView->imageSubresources(), imageView->imageSubresources(),
clearLayout, clearStages, clearAccess, clearLayout, clearStages, clearAccess,
imageView->imageInfo().layout, imageView->image()->info().layout,
imageView->imageInfo().stages, imageView->image()->info().stages,
imageView->imageInfo().access); imageView->image()->info().access);
m_cmd->trackResource<DxvkAccess::None>(imageView);
m_cmd->trackResource<DxvkAccess::Write>(imageView->image()); m_cmd->trackResource<DxvkAccess::Write>(imageView->image());
} }
} }
@ -3399,7 +3394,7 @@ namespace dxvk {
VkDescriptorImageInfo viewInfo; VkDescriptorImageInfo viewInfo;
viewInfo.sampler = VK_NULL_HANDLE; viewInfo.sampler = VK_NULL_HANDLE;
viewInfo.imageView = imageView->handle(); viewInfo.imageView = imageView->handle();
viewInfo.imageLayout = imageView->imageInfo().layout; viewInfo.imageLayout = imageView->image()->info().layout;
VkWriteDescriptorSet descriptorWrite = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; VkWriteDescriptorSet descriptorWrite = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
descriptorWrite.dstSet = descriptorSet; descriptorWrite.dstSet = descriptorSet;
@ -3443,14 +3438,13 @@ namespace dxvk {
m_execBarriers.accessImage( m_execBarriers.accessImage(
imageView->image(), imageView->image(),
imageView->imageSubresources(), imageView->imageSubresources(),
imageView->imageInfo().layout, imageView->image()->info().layout,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
imageView->imageInfo().layout, imageView->image()->info().layout,
imageView->imageInfo().stages, imageView->image()->info().stages,
imageView->imageInfo().access); imageView->image()->info().access);
m_cmd->trackResource<DxvkAccess::None>(imageView);
m_cmd->trackResource<DxvkAccess::Write>(imageView->image()); m_cmd->trackResource<DxvkAccess::Write>(imageView->image());
} }
@ -4687,8 +4681,8 @@ namespace dxvk {
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
ops.depthOps.storeLayout, ops.depthOps.storeLayout,
depthAttachment.view->imageInfo().stages, depthAttachment.view->image()->info().stages,
depthAttachment.view->imageInfo().access); depthAttachment.view->image()->info().access);
} else { } else {
VkAccessFlags srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; VkAccessFlags srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
@ -4699,8 +4693,8 @@ namespace dxvk {
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
srcAccess, srcAccess,
depthAttachment.view->imageInfo().stages, depthAttachment.view->image()->info().stages,
depthAttachment.view->imageInfo().access); depthAttachment.view->image()->info().access);
} }
} }
@ -4717,15 +4711,15 @@ namespace dxvk {
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
ops.colorOps[i].storeLayout, ops.colorOps[i].storeLayout,
colorAttachment.view->imageInfo().stages, colorAttachment.view->image()->info().stages,
colorAttachment.view->imageInfo().access); colorAttachment.view->image()->info().access);
} else { } else {
m_execBarriers.accessMemory( m_execBarriers.accessMemory(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
colorAttachment.view->imageInfo().stages, colorAttachment.view->image()->info().stages,
colorAttachment.view->imageInfo().access); colorAttachment.view->image()->info().access);
} }
} }
} }
@ -4764,7 +4758,7 @@ namespace dxvk {
// We can't use LOAD_OP_CLEAR if the view format does not match the // We can't use LOAD_OP_CLEAR if the view format does not match the
// underlying image format, so just discard here and use clear later. // underlying image format, so just discard here and use clear later.
if (colorTarget.view->info().format != colorTarget.view->imageInfo().format) { if (colorTarget.view->info().format != colorTarget.view->image()->info().format) {
colorInfos[i].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; colorInfos[i].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
auto& clear = lateClears[lateClearCount++]; auto& clear = lateClears[lateClearCount++];
@ -4830,10 +4824,8 @@ namespace dxvk {
m_cmd->cmdClearAttachments(lateClearCount, lateClears.data(), 1, &clearRect); m_cmd->cmdClearAttachments(lateClearCount, lateClears.data(), 1, &clearRect);
} }
for (uint32_t i = 0; i < framebufferInfo.numAttachments(); i++) { for (uint32_t i = 0; i < framebufferInfo.numAttachments(); i++)
m_cmd->trackResource<DxvkAccess::None> (framebufferInfo.getAttachment(i).view);
m_cmd->trackResource<DxvkAccess::Write>(framebufferInfo.getAttachment(i).view->image()); m_cmd->trackResource<DxvkAccess::Write>(framebufferInfo.getAttachment(i).view->image());
}
m_cmd->addStatCtr(DxvkStatCounter::CmdRenderPassCount, 1); m_cmd->addStatCtr(DxvkStatCounter::CmdRenderPassCount, 1);
} }
@ -5258,12 +5250,10 @@ namespace dxvk {
if (res.imageView != nullptr && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) { if (res.imageView != nullptr && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) {
descriptorInfo.image.sampler = VK_NULL_HANDLE; descriptorInfo.image.sampler = VK_NULL_HANDLE;
descriptorInfo.image.imageView = res.imageView->handle(binding.viewType); descriptorInfo.image.imageView = res.imageView->handle(binding.viewType);
descriptorInfo.image.imageLayout = res.imageView->imageInfo().layout; descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
if (m_rcTracked.set(binding.resourceBinding)) { if (m_rcTracked.set(binding.resourceBinding))
m_cmd->trackResource<DxvkAccess::None>(res.imageView);
m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image()); m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image());
}
} else { } else {
descriptorInfo.image.sampler = VK_NULL_HANDLE; descriptorInfo.image.sampler = VK_NULL_HANDLE;
descriptorInfo.image.imageView = VK_NULL_HANDLE; descriptorInfo.image.imageView = VK_NULL_HANDLE;
@ -5277,12 +5267,10 @@ namespace dxvk {
if (res.imageView != nullptr && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) { if (res.imageView != nullptr && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) {
descriptorInfo.image.sampler = VK_NULL_HANDLE; descriptorInfo.image.sampler = VK_NULL_HANDLE;
descriptorInfo.image.imageView = res.imageView->handle(binding.viewType); descriptorInfo.image.imageView = res.imageView->handle(binding.viewType);
descriptorInfo.image.imageLayout = res.imageView->imageInfo().layout; descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
if (m_rcTracked.set(binding.resourceBinding)) { if (m_rcTracked.set(binding.resourceBinding))
m_cmd->trackResource<DxvkAccess::None>(res.imageView);
m_cmd->trackResource<DxvkAccess::Write>(res.imageView->image()); m_cmd->trackResource<DxvkAccess::Write>(res.imageView->image());
}
} else { } else {
descriptorInfo.image.sampler = VK_NULL_HANDLE; descriptorInfo.image.sampler = VK_NULL_HANDLE;
descriptorInfo.image.imageView = VK_NULL_HANDLE; descriptorInfo.image.imageView = VK_NULL_HANDLE;
@ -5297,11 +5285,10 @@ namespace dxvk {
&& res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) { && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) {
descriptorInfo.image.sampler = res.sampler->handle(); descriptorInfo.image.sampler = res.sampler->handle();
descriptorInfo.image.imageView = res.imageView->handle(binding.viewType); descriptorInfo.image.imageView = res.imageView->handle(binding.viewType);
descriptorInfo.image.imageLayout = res.imageView->imageInfo().layout; descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
if (m_rcTracked.set(binding.resourceBinding)) { if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->trackResource<DxvkAccess::None>(res.sampler); m_cmd->trackResource<DxvkAccess::None>(res.sampler);
m_cmd->trackResource<DxvkAccess::None>(res.imageView);
m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image()); m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image());
} }
} else { } else {
@ -5472,17 +5459,17 @@ namespace dxvk {
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
const DxvkAttachment& color = m_state.om.framebufferInfo.getColorTarget(i); const DxvkAttachment& color = m_state.om.framebufferInfo.getColorTarget(i);
if (color.view != nullptr && (!sharedOnly || color.view->imageInfo().shared)) { if (color.view != nullptr && (!sharedOnly || color.view->image()->info().shared)) {
this->transitionColorAttachment(color, m_rtLayouts.color[i]); this->transitionColorAttachment(color, m_rtLayouts.color[i]);
m_rtLayouts.color[i] = color.view->imageInfo().layout; m_rtLayouts.color[i] = color.view->image()->info().layout;
} }
} }
const DxvkAttachment& depth = m_state.om.framebufferInfo.getDepthTarget(); const DxvkAttachment& depth = m_state.om.framebufferInfo.getDepthTarget();
if (depth.view != nullptr && (!sharedOnly || depth.view->imageInfo().shared)) { if (depth.view != nullptr && (!sharedOnly || depth.view->image()->info().shared)) {
this->transitionDepthAttachment(depth, m_rtLayouts.depth); this->transitionDepthAttachment(depth, m_rtLayouts.depth);
m_rtLayouts.depth = depth.view->imageInfo().layout; m_rtLayouts.depth = depth.view->image()->info().layout;
} }
} }
@ -5490,15 +5477,15 @@ namespace dxvk {
void DxvkContext::transitionColorAttachment( void DxvkContext::transitionColorAttachment(
const DxvkAttachment& attachment, const DxvkAttachment& attachment,
VkImageLayout oldLayout) { VkImageLayout oldLayout) {
if (oldLayout != attachment.view->imageInfo().layout) { if (oldLayout != attachment.view->image()->info().layout) {
m_execBarriers.accessImage( m_execBarriers.accessImage(
attachment.view->image(), attachment.view->image(),
attachment.view->imageSubresources(), oldLayout, attachment.view->imageSubresources(), oldLayout,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
attachment.view->imageInfo().layout, attachment.view->image()->info().layout,
attachment.view->imageInfo().stages, attachment.view->image()->info().stages,
attachment.view->imageInfo().access); attachment.view->image()->info().access);
m_cmd->trackResource<DxvkAccess::Write>(attachment.view->image()); m_cmd->trackResource<DxvkAccess::Write>(attachment.view->image());
} }
@ -5508,7 +5495,7 @@ namespace dxvk {
void DxvkContext::transitionDepthAttachment( void DxvkContext::transitionDepthAttachment(
const DxvkAttachment& attachment, const DxvkAttachment& attachment,
VkImageLayout oldLayout) { VkImageLayout oldLayout) {
if (oldLayout != attachment.view->imageInfo().layout) { if (oldLayout != attachment.view->image()->info().layout) {
m_execBarriers.accessImage( m_execBarriers.accessImage(
attachment.view->image(), attachment.view->image(),
attachment.view->imageSubresources(), oldLayout, attachment.view->imageSubresources(), oldLayout,
@ -5516,9 +5503,9 @@ namespace dxvk {
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
oldLayout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL oldLayout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : 0, ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : 0,
attachment.view->imageInfo().layout, attachment.view->image()->info().layout,
attachment.view->imageInfo().stages, attachment.view->image()->info().stages,
attachment.view->imageInfo().access); attachment.view->image()->info().access);
m_cmd->trackResource<DxvkAccess::Write>(attachment.view->image()); m_cmd->trackResource<DxvkAccess::Write>(attachment.view->image());
} }
@ -5532,11 +5519,11 @@ namespace dxvk {
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (newFb.getColorTarget(i).view != nullptr) if (newFb.getColorTarget(i).view != nullptr)
layouts.color[i] = newFb.getColorTarget(i).view->imageInfo().layout; layouts.color[i] = newFb.getColorTarget(i).view->image()->info().layout;
} }
if (newFb.getDepthTarget().view != nullptr) if (newFb.getDepthTarget().view != nullptr)
layouts.depth = newFb.getDepthTarget().view->imageInfo().layout; layouts.depth = newFb.getDepthTarget().view->image()->info().layout;
// Check whether any of the previous attachments have been moved // Check whether any of the previous attachments have been moved
// around or been rebound with a different view. This may help // around or been rebound with a different view. This may help
@ -6184,7 +6171,7 @@ namespace dxvk {
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
if ((slot.imageView != nullptr) if ((slot.imageView != nullptr)
&& (slot.imageView->imageInfo().access & storageImageAccess)) { && (slot.imageView->image()->info().access & storageImageAccess)) {
requiresBarrier = this->checkImageViewBarrier<DoEmit>(slot.imageView, requiresBarrier = this->checkImageViewBarrier<DoEmit>(slot.imageView,
util::pipelineStages(binding.stage), binding.access); util::pipelineStages(binding.stage), binding.access);
} }
@ -6267,11 +6254,11 @@ namespace dxvk {
m_execBarriers.accessImage( m_execBarriers.accessImage(
imageView->image(), imageView->image(),
imageView->imageSubresources(), imageView->imageSubresources(),
imageView->imageInfo().layout, imageView->image()->info().layout,
stages, access, stages, access,
imageView->imageInfo().layout, imageView->image()->info().layout,
imageView->imageInfo().stages, imageView->image()->info().stages,
imageView->imageInfo().access); imageView->image()->info().access);
return false; return false;
} else { } else {
DxvkAccessFlags dstAccess = DxvkBarrierSet::getAccessTypes(access); DxvkAccessFlags dstAccess = DxvkBarrierSet::getAccessTypes(access);

View File

@ -174,7 +174,7 @@ namespace dxvk {
Rc<DxvkImageView> DxvkDevice::createImageView( Rc<DxvkImageView> DxvkDevice::createImageView(
const Rc<DxvkImage>& image, const Rc<DxvkImage>& image,
const DxvkImageViewCreateInfo& createInfo) { const DxvkImageViewCreateInfo& createInfo) {
return new DxvkImageView(m_vkd, image, createInfo); return image->createView(createInfo);
} }

View File

@ -16,13 +16,13 @@ namespace dxvk {
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (m_renderTargets.color[i].view != nullptr) { if (m_renderTargets.color[i].view != nullptr) {
m_attachments[m_attachmentCount++] = i; m_attachments[m_attachmentCount++] = i;
m_sampleCount = m_renderTargets.color[i].view->imageInfo().sampleCount; m_sampleCount = m_renderTargets.color[i].view->image()->info().sampleCount;
} }
} }
if (m_renderTargets.depth.view != nullptr) { if (m_renderTargets.depth.view != nullptr) {
m_attachments[m_attachmentCount++] = -1; m_attachments[m_attachmentCount++] = -1;
m_sampleCount = m_renderTargets.depth.view->imageInfo().sampleCount; m_sampleCount = m_renderTargets.depth.view->image()->info().sampleCount;
} }
} }

View File

@ -77,6 +77,35 @@ namespace dxvk {
} }
Rc<DxvkImageView> DxvkImage::createView(
const DxvkImageViewCreateInfo& info) {
DxvkImageViewKey key = { };
key.viewType = info.type;
key.format = info.format;
key.usage = info.usage;
key.aspects = info.aspect;
key.mipIndex = info.minLevel;
key.mipCount = info.numLevels;
key.layerIndex = info.minLayer;
key.layerCount = info.numLayers;
if (info.usage == VK_IMAGE_USAGE_SAMPLED_BIT) {
key.packedSwizzle =
(uint16_t(info.swizzle.r) << 0) |
(uint16_t(info.swizzle.g) << 4) |
(uint16_t(info.swizzle.b) << 8) |
(uint16_t(info.swizzle.a) << 12);
}
std::unique_lock lock(m_viewMutex);
auto entry = m_views.emplace(std::piecewise_construct,
std::make_tuple(key), std::make_tuple(this, key));
return &entry.first->second;
}
Rc<DxvkResourceAllocation> DxvkImage::createResource() { Rc<DxvkResourceAllocation> DxvkImage::createResource() {
const DxvkFormatInfo* formatInfo = lookupFormatInfo(m_info.format); const DxvkFormatInfo* formatInfo = lookupFormatInfo(m_info.format);
@ -195,108 +224,84 @@ namespace dxvk {
DxvkImageView::DxvkImageView( DxvkImageView::DxvkImageView(
const Rc<vk::DeviceFn>& vkd, DxvkImage* image,
const Rc<DxvkImage>& image, const DxvkImageViewKey& key)
const DxvkImageViewCreateInfo& info) : m_image(image), m_key(key) {
: m_vkd(vkd), m_image(image), m_info(info) {
for (uint32_t i = 0; i < ViewCount; i++)
m_views[i] = VK_NULL_HANDLE;
switch (m_info.type) {
case VK_IMAGE_VIEW_TYPE_1D:
case VK_IMAGE_VIEW_TYPE_1D_ARRAY: {
this->createView(VK_IMAGE_VIEW_TYPE_1D, 1);
this->createView(VK_IMAGE_VIEW_TYPE_1D_ARRAY, m_info.numLayers);
} break;
case VK_IMAGE_VIEW_TYPE_2D:
case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
this->createView(VK_IMAGE_VIEW_TYPE_2D, 1);
[[fallthrough]];
case VK_IMAGE_VIEW_TYPE_CUBE:
case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: {
this->createView(VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_info.numLayers);
if (m_image->info().flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) {
uint32_t cubeCount = m_info.numLayers / 6;
if (cubeCount > 0) {
this->createView(VK_IMAGE_VIEW_TYPE_CUBE, 6);
this->createView(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, 6 * cubeCount);
}
}
} break;
case VK_IMAGE_VIEW_TYPE_3D: {
this->createView(VK_IMAGE_VIEW_TYPE_3D, 1);
if (m_image->info().flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT && m_info.numLevels == 1) {
this->createView(VK_IMAGE_VIEW_TYPE_2D, 1);
this->createView(VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_image->mipLevelExtent(m_info.minLevel).depth);
}
} break;
default:
throw DxvkError(str::format("DxvkImageView: Invalid view type: ", m_info.type));
}
} }
DxvkImageView::~DxvkImageView() { DxvkImageView::~DxvkImageView() {
for (uint32_t i = 0; i < ViewCount; i++)
m_vkd->vkDestroyImageView(m_vkd->device(), m_views[i], nullptr);
} }
void DxvkImageView::createView(VkImageViewType type, uint32_t numLayers) {
VkImageSubresourceRange subresourceRange;
subresourceRange.aspectMask = m_info.aspect;
subresourceRange.baseMipLevel = m_info.minLevel;
subresourceRange.levelCount = m_info.numLevels;
subresourceRange.baseArrayLayer = m_info.minLayer;
subresourceRange.layerCount = numLayers;
VkImageViewUsageCreateInfo viewUsage = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO }; VkImageView DxvkImageView::createView(VkImageViewType type) const {
viewUsage.usage = m_info.usage; DxvkImageViewKey key = m_key;
key.viewType = type;
VkImageViewCreateInfo viewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, &viewUsage };
viewInfo.image = m_image->handle();
viewInfo.viewType = type;
viewInfo.format = m_info.format;
viewInfo.components = m_info.swizzle;
viewInfo.subresourceRange = subresourceRange;
if (m_info.usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { // Only use one layer for non-arrayed view types
viewInfo.components = { if (type == VK_IMAGE_VIEW_TYPE_1D || type == VK_IMAGE_VIEW_TYPE_2D)
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, key.layerCount = 1u;
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
switch (m_image->info().type) {
case VK_IMAGE_TYPE_1D: {
// Trivial, just validate that view types are compatible
if (type != VK_IMAGE_VIEW_TYPE_1D && type != VK_IMAGE_VIEW_TYPE_1D_ARRAY)
return VK_NULL_HANDLE;
} break;
case VK_IMAGE_TYPE_2D: {
if (type == VK_IMAGE_VIEW_TYPE_CUBE || type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
// Ensure that the image is compatible with cube maps
if (key.layerCount < 6 || !(m_image->info().flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
return VK_NULL_HANDLE;
// Adjust layer count to make sure it's a multiple of 6
key.layerCount = type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
? key.layerCount - key.layerCount % 6u : 6u;
} else if (type != VK_IMAGE_VIEW_TYPE_2D && type != VK_IMAGE_VIEW_TYPE_2D_ARRAY) {
return VK_NULL_HANDLE;
}
} break;
case VK_IMAGE_TYPE_3D: {
if (type == VK_IMAGE_VIEW_TYPE_2D || type == VK_IMAGE_VIEW_TYPE_2D_ARRAY) {
// Ensure that the image is actually compatible with 2D views
if (!(m_image->info().flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT))
return VK_NULL_HANDLE;
// In case the view's native type is 3D, we can only create 2D compat
// views if there is only one mip and with the full set of array layers.
if (m_key.viewType == VK_IMAGE_VIEW_TYPE_3D) {
if (m_key.mipCount != 1u)
return VK_NULL_HANDLE;
key.layerIndex = 0u;
key.layerCount = type == VK_IMAGE_VIEW_TYPE_2D_ARRAY
? m_image->mipLevelExtent(key.mipIndex).depth : 1u;
}
} else if (type != VK_IMAGE_VIEW_TYPE_3D) {
return VK_NULL_HANDLE;
}
} break;
default:
return VK_NULL_HANDLE;
} }
if (m_vkd->vkCreateImageView(m_vkd->device(), return m_image->m_storage->createImageView(key);
&viewInfo, nullptr, &m_views[type]) != VK_SUCCESS) { }
throw DxvkError(str::format(
"DxvkImageView: Failed to create image view:"
"\n View type: ", viewInfo.viewType, void DxvkImageView::updateViews() {
"\n View format: ", viewInfo.format, // Update all views that are not currently null
"\n Subresources: ", for (uint32_t i = 0; i < m_views.size(); i++) {
"\n Aspect mask: ", std::hex, viewInfo.subresourceRange.aspectMask, if (m_views[i])
"\n Mip levels: ", viewInfo.subresourceRange.baseMipLevel, " - ", m_views[i] = createView(VkImageViewType(i));
viewInfo.subresourceRange.levelCount,
"\n Array layers: ", viewInfo.subresourceRange.baseArrayLayer, " - ",
viewInfo.subresourceRange.layerCount,
"\n Image properties:",
"\n Type: ", m_image->info().type,
"\n Format: ", m_image->info().format,
"\n Extent: ", "(", m_image->info().extent.width,
",", m_image->info().extent.height,
",", m_image->info().extent.depth, ")",
"\n Mip levels: ", m_image->info().mipLevels,
"\n Array layers: ", m_image->info().numLayers,
"\n Samples: ", m_image->info().sampleCount,
"\n Usage: ", std::hex, m_image->info().usage,
"\n Tiling: ", m_image->info().tiling));
} }
m_version = m_image->m_version;
} }
} }

View File

@ -9,8 +9,6 @@
namespace dxvk { namespace dxvk {
class DxvkImageView;
/** /**
* \brief Image create info * \brief Image create info
* *
@ -106,6 +104,203 @@ namespace dxvk {
}; };
/**
* \brief Virtual image view
*
* Stores views for a number of different view types
* that the defined view is compatible with.
*/
class DxvkImageView {
constexpr static uint32_t ViewCount = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY + 1;
public:
DxvkImageView(
DxvkImage* image,
const DxvkImageViewKey& key);
~DxvkImageView();
void incRef();
void decRef();
/**
* \brief Image view handle for the default type
*
* The default view type is guaranteed to be
* supported by the image view, and should be
* preferred over picking a different type.
* \returns Image view handle
*/
VkImageView handle() {
return handle(m_key.viewType);
}
/**
* \brief Image view handle for a given view type
*
* If the view does not support the requested image
* view type, \c VK_NULL_HANDLE will be returned.
* \param [in] viewType The requested view type
* \returns The image view handle
*/
VkImageView handle(VkImageViewType viewType);
/**
* \brief Image view type
*
* Convenience method to query the view type
* in order to check for resource compatibility.
* \returns Image view type
*/
VkImageViewType type() const {
return m_key.viewType;
}
/**
* \brief Image view properties
* \returns Image view properties
*/
DxvkImageViewCreateInfo info() const {
DxvkImageViewCreateInfo info = { };
info.type = m_key.viewType;
info.format = m_key.format;
info.usage = m_key.usage;
info.aspect = m_key.aspects;
info.minLevel = m_key.mipIndex;
info.numLevels = m_key.mipCount;
info.minLayer = m_key.layerIndex;
info.numLayers = m_key.layerCount;
info.swizzle.r = VkComponentSwizzle((m_key.packedSwizzle >> 0) & 0xf);
info.swizzle.g = VkComponentSwizzle((m_key.packedSwizzle >> 4) & 0xf);
info.swizzle.b = VkComponentSwizzle((m_key.packedSwizzle >> 8) & 0xf);
info.swizzle.a = VkComponentSwizzle((m_key.packedSwizzle >> 12) & 0xf);
return info;
}
/**
* \brief Image object
* \returns Image object
*/
DxvkImage* image() const {
return m_image;
}
/**
* \brief View format info
* \returns View format info
*/
const DxvkFormatInfo* formatInfo() const {
return lookupFormatInfo(m_key.format);
}
/**
* \brief Mip level size
*
* Computes the mip level size relative to
* the first mip level that the view includes.
* \param [in] level Mip level
* \returns Size of that level
*/
VkExtent3D mipLevelExtent(uint32_t level) const;
/**
* \brief View subresource range
*
* Returns the subresource range from the image
* description. For 2D views of 3D images, this
* will return the viewed 3D slices.
* \returns View subresource range
*/
VkImageSubresourceRange subresources() const {
VkImageSubresourceRange result;
result.aspectMask = m_key.aspects;
result.baseMipLevel = m_key.mipIndex;
result.levelCount = m_key.mipCount;
result.baseArrayLayer = m_key.layerIndex;
result.layerCount = m_key.layerCount;
return result;
}
/**
* \brief Actual image subresource range
*
* Handles 3D images correctly in that it only
* returns one single array layer. Use this for
* barriers.
* \returns Image subresource range
*/
VkImageSubresourceRange imageSubresources() const;
/**
* \brief Picks an image layout
* \see DxvkImage::pickLayout
*/
VkImageLayout pickLayout(VkImageLayout layout) const;
/**
* \brief Retrieves descriptor info
*
* \param [in] type Exact view type
* \param [in] layout Image layout
* \returns Image descriptor
*/
DxvkDescriptorInfo getDescriptor(VkImageViewType type, VkImageLayout layout) {
DxvkDescriptorInfo result;
result.image.sampler = VK_NULL_HANDLE;
result.image.imageView = handle(type);
result.image.imageLayout = layout;
return result;
}
/**
* \brief Checks whether this view matches another
*
* \param [in] view The other view to check
* \returns \c true if the two views have the same subresources
*/
bool matchesView(const Rc<DxvkImageView>& view) const {
if (this == view.ptr())
return true;
return this->image() == view->image()
&& this->subresources() == view->subresources()
&& this->info().type == view->info().type
&& this->info().format == view->info().format;
}
/**
* \brief Checks whether this view overlaps with another one
*
* Two views overlap if they were created for the same
* image and have at least one subresource in common.
* \param [in] view The other view to check
* \returns \c true if the two views overlap
*/
bool checkSubresourceOverlap(const Rc<DxvkImageView>& view) const {
if (likely(m_image != view->m_image))
return false;
return vk::checkSubresourceRangeOverlap(
this->imageSubresources(),
view->imageSubresources());
}
private:
DxvkImage* m_image = nullptr;
DxvkImageViewKey m_key = { };
uint32_t m_version = 0u;
std::array<VkImageView, ViewCount> m_views = { };
VkImageView createView(VkImageViewType type) const;
void updateViews();
};
/** /**
* \brief Virtual image resource * \brief Virtual image resource
* *
@ -114,8 +309,8 @@ namespace dxvk {
* memory type and if created with the linear tiling option. * memory type and if created with the linear tiling option.
*/ */
class DxvkImage : public DxvkPagedResource { class DxvkImage : public DxvkPagedResource {
friend DxvkImageView;
friend class DxvkContext; friend class DxvkContext;
friend class DxvkImageView;
public: public:
DxvkImage( DxvkImage(
@ -348,6 +543,15 @@ namespace dxvk {
return old; return old;
} }
/**
* \brief Creates or retrieves an image view
*
* \param [in] info Image view create info
* \returns Newly created image view
*/
Rc<DxvkImageView> createView(
const DxvkImageViewCreateInfo& info);
private: private:
Rc<vk::DeviceFn> m_vkd; Rc<vk::DeviceFn> m_vkd;
@ -365,6 +569,10 @@ namespace dxvk {
small_vector<VkFormat, 4> m_viewFormats; small_vector<VkFormat, 4> m_viewFormats;
dxvk::mutex m_viewMutex;
std::unordered_map<DxvkImageViewKey,
DxvkImageView, DxvkHash, DxvkEq> m_views;
VkImageCreateInfo getImageCreateInfo() const; VkImageCreateInfo getImageCreateInfo() const;
void copyFormatList( void copyFormatList(
@ -377,219 +585,58 @@ namespace dxvk {
const DxvkSharedHandleInfo& sharingInfo) const; const DxvkSharedHandleInfo& sharingInfo) const;
}; };
/**
* \brief DXVK image view
*/ inline void DxvkImageView::incRef() {
class DxvkImageView : public DxvkResource { m_image->incRef();
friend class DxvkImage; }
constexpr static uint32_t ViewCount = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY + 1;
public:
inline void DxvkImageView::decRef() {
DxvkImageView( m_image->decRef();
const Rc<vk::DeviceFn>& vkd, }
const Rc<DxvkImage>& image,
const DxvkImageViewCreateInfo& info);
inline VkImageSubresourceRange DxvkImageView::imageSubresources() const {
~DxvkImageView(); VkImageSubresourceRange result = { };
result.aspectMask = m_key.aspects;
/** result.baseMipLevel = m_key.mipIndex;
* \brief Image view handle for the default type result.levelCount = m_key.mipCount;
*
* The default view type is guaranteed to be if (likely(m_image->info().type != VK_IMAGE_TYPE_3D)) {
* supported by the image view, and should be result.baseArrayLayer = m_key.layerIndex;
* preferred over picking a different type. result.layerCount = m_key.layerCount;
* \returns Image view handle } else {
*/ result.baseArrayLayer = 0;
VkImageView handle() const { result.layerCount = 1;
return handle(m_info.type);
}
/**
* \brief Image view handle for a given view type
*
* If the view does not support the requested image
* view type, \c VK_NULL_HANDLE will be returned.
* \param [in] viewType The requested view type
* \returns The image view handle
*/
VkImageView handle(VkImageViewType viewType) const {
if (unlikely(viewType == VK_IMAGE_VIEW_TYPE_MAX_ENUM))
viewType = m_info.type;
return m_views[viewType];
}
/**
* \brief Image view type
*
* Convenience method to query the view type
* in order to check for resource compatibility.
* \returns Image view type
*/
VkImageViewType type() const {
return m_info.type;
}
/**
* \brief Image view properties
* \returns Image view properties
*/
const DxvkImageViewCreateInfo& info() const {
return m_info;
}
/**
* \brief Image handle
* \returns Image handle
*/
VkImage imageHandle() const {
return m_image->handle();
}
/**
* \brief Image properties
* \returns Image properties
*/
const DxvkImageCreateInfo& imageInfo() const {
return m_image->info();
}
/**
* \brief Image object
* \returns Image object
*/
const Rc<DxvkImage>& image() const {
return m_image;
}
/**
* \brief View format info
* \returns View format info
*/
const DxvkFormatInfo* formatInfo() const {
return lookupFormatInfo(m_info.format);
}
/**
* \brief Mip level size
*
* Computes the mip level size relative to
* the first mip level that the view includes.
* \param [in] level Mip level
* \returns Size of that level
*/
VkExtent3D mipLevelExtent(uint32_t level) const {
return m_image->mipLevelExtent(level + m_info.minLevel, m_info.aspect);
}
/**
* \brief View subresource range
*
* Returns the subresource range from the image
* description. For 2D views of 3D images, this
* will return the viewed 3D slices.
* \returns View subresource range
*/
VkImageSubresourceRange subresources() const {
VkImageSubresourceRange result;
result.aspectMask = m_info.aspect;
result.baseMipLevel = m_info.minLevel;
result.levelCount = m_info.numLevels;
result.baseArrayLayer = m_info.minLayer;
result.layerCount = m_info.numLayers;
return result;
} }
/** return result;
* \brief Actual image subresource range }
*
* Handles 3D images correctly in that it only
* returns one single array layer. Use this for
* barriers.
* \returns Image subresource range
*/
VkImageSubresourceRange imageSubresources() const {
VkImageSubresourceRange result;
result.aspectMask = m_info.aspect;
result.baseMipLevel = m_info.minLevel;
result.levelCount = m_info.numLevels;
if (likely(m_image->info().type != VK_IMAGE_TYPE_3D)) {
result.baseArrayLayer = m_info.minLayer;
result.layerCount = m_info.numLayers;
} else {
result.baseArrayLayer = 0;
result.layerCount = 1;
}
return result;
}
/**
* \brief Picks an image layout
* \see DxvkImage::pickLayout
*/
VkImageLayout pickLayout(VkImageLayout layout) const {
return m_image->pickLayout(layout);
}
/**
* \brief Retrieves descriptor info
*
* \param [in] type Exact view type
* \param [in] layout Image layout
* \returns Image descriptor
*/
DxvkDescriptorInfo getDescriptor(VkImageViewType type, VkImageLayout layout) const {
DxvkDescriptorInfo result;
result.image.sampler = VK_NULL_HANDLE;
result.image.imageView = handle(type);
result.image.imageLayout = layout;
return result;
}
/** inline VkExtent3D DxvkImageView::mipLevelExtent(uint32_t level) const {
* \brief Checks whether this view matches another return m_image->mipLevelExtent(level + m_key.mipIndex, m_key.aspects);
* }
* \param [in] view The other view to check
* \returns \c true if the two views have the same subresources
*/
bool matchesView(const Rc<DxvkImageView>& view) const {
if (this == view.ptr())
return true;
return this->image() == view->image()
&& this->subresources() == view->subresources()
&& this->info().type == view->info().type
&& this->info().format == view->info().format;
}
/** inline VkImageLayout DxvkImageView::pickLayout(VkImageLayout layout) const {
* \brief Checks whether this view overlaps with another one return m_image->pickLayout(layout);
* }
* Two views overlap if they were created for the same
* image and have at least one subresource in common.
* \param [in] view The other view to check
* \returns \c true if the two views overlap
*/
bool checkSubresourceOverlap(const Rc<DxvkImageView>& view) const {
if (likely(m_image != view->m_image))
return false;
return vk::checkSubresourceRangeOverlap(
this->imageSubresources(),
view->imageSubresources());
}
private: inline VkImageView DxvkImageView::handle(VkImageViewType viewType) {
viewType = viewType != VK_IMAGE_VIEW_TYPE_MAX_ENUM ? viewType : m_key.viewType;
Rc<vk::DeviceFn> m_vkd;
Rc<DxvkImage> m_image; if (unlikely(m_version < m_image->m_version))
updateViews();
DxvkImageViewCreateInfo m_info;
VkImageView m_views[ViewCount]; if (unlikely(!m_views[viewType]))
m_views[viewType] = createView(viewType);
return m_views[viewType];
}
void createView(VkImageViewType type, uint32_t numLayers);
};
} }

View File

@ -13,8 +13,8 @@ namespace dxvk {
{ VK_IMAGE_VIEW_TYPE_3D, VK_IMAGE_VIEW_TYPE_2D_ARRAY }, { VK_IMAGE_VIEW_TYPE_3D, VK_IMAGE_VIEW_TYPE_2D_ARRAY },
}}; }};
m_srcViewType = viewTypes.at(uint32_t(view->imageInfo().type)).first; m_srcViewType = viewTypes.at(uint32_t(view->image()->info().type)).first;
m_dstViewType = viewTypes.at(uint32_t(view->imageInfo().type)).second; m_dstViewType = viewTypes.at(uint32_t(view->image()->info().type)).second;
// Create image views and framebuffers // Create image views and framebuffers
m_passes.resize(view->info().numLevels - 1); m_passes.resize(view->info().numLevels - 1);
@ -35,7 +35,7 @@ namespace dxvk {
VkExtent3D DxvkMetaMipGenRenderPass::computePassExtent(uint32_t passId) const { VkExtent3D DxvkMetaMipGenRenderPass::computePassExtent(uint32_t passId) const {
VkExtent3D extent = m_view->mipLevelExtent(passId + 1); VkExtent3D extent = m_view->mipLevelExtent(passId + 1);
if (m_view->imageInfo().type != VK_IMAGE_TYPE_3D) if (m_view->image()->info().type != VK_IMAGE_TYPE_3D)
extent.depth = m_view->info().numLayers; extent.depth = m_view->info().numLayers;
return extent; return extent;
@ -48,7 +48,7 @@ namespace dxvk {
VkImageViewUsageCreateInfo usageInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO }; VkImageViewUsageCreateInfo usageInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO };
VkImageViewCreateInfo viewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, &usageInfo }; VkImageViewCreateInfo viewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, &usageInfo };
viewInfo.image = m_view->imageHandle(); viewInfo.image = m_view->image()->handle();
viewInfo.format = m_view->info().format; viewInfo.format = m_view->info().format;
// Create source image view, which points to // Create source image view, which points to
@ -76,7 +76,7 @@ namespace dxvk {
dstSubresources.baseMipLevel = m_view->info().minLevel + pass + 1; dstSubresources.baseMipLevel = m_view->info().minLevel + pass + 1;
dstSubresources.levelCount = 1; dstSubresources.levelCount = 1;
if (m_view->imageInfo().type != VK_IMAGE_TYPE_3D) { if (m_view->image()->info().type != VK_IMAGE_TYPE_3D) {
dstSubresources.baseArrayLayer = m_view->info().minLayer; dstSubresources.baseArrayLayer = m_view->info().minLayer;
dstSubresources.layerCount = m_view->info().numLayers; dstSubresources.layerCount = m_view->info().numLayers;
} else { } else {

View File

@ -33,21 +33,21 @@ namespace dxvk {
if (!dstRect.extent.width || !dstRect.extent.height) { if (!dstRect.extent.width || !dstRect.extent.height) {
dstRect.offset = { 0, 0 }; dstRect.offset = { 0, 0 };
dstRect.extent = { dstRect.extent = {
dstView->imageInfo().extent.width, dstView->image()->info().extent.width,
dstView->imageInfo().extent.height }; dstView->image()->info().extent.height };
} }
if (!srcRect.extent.width || !srcRect.extent.height) { if (!srcRect.extent.width || !srcRect.extent.height) {
srcRect.offset = { 0, 0 }; srcRect.offset = { 0, 0 };
srcRect.extent = { srcRect.extent = {
srcView->imageInfo().extent.width, srcView->image()->info().extent.width,
srcView->imageInfo().extent.height }; srcView->image()->info().extent.height };
} }
bool sameSize = dstRect.extent == srcRect.extent; bool sameSize = dstRect.extent == srcRect.extent;
bool usedResolveImage = false; bool usedResolveImage = false;
if (srcView->imageInfo().sampleCount == VK_SAMPLE_COUNT_1_BIT) { if (srcView->image()->info().sampleCount == VK_SAMPLE_COUNT_1_BIT) {
this->draw(ctx, sameSize ? m_fsCopy : m_fsBlit, this->draw(ctx, sameSize ? m_fsCopy : m_fsBlit,
dstView, dstRect, srcView, srcRect); dstView, dstRect, srcView, srcRect);
} else if (sameSize) { } else if (sameSize) {
@ -55,9 +55,9 @@ namespace dxvk {
dstView, dstRect, srcView, srcRect); dstView, dstRect, srcView, srcRect);
} else { } else {
if (m_resolveImage == nullptr if (m_resolveImage == nullptr
|| m_resolveImage->info().extent != srcView->imageInfo().extent || m_resolveImage->info().extent != srcView->image()->info().extent
|| m_resolveImage->info().format != srcView->imageInfo().format) || m_resolveImage->info().format != srcView->image()->info().format)
this->createResolveImage(srcView->imageInfo()); this->createResolveImage(srcView->image()->info());
this->resolve(ctx, m_resolveView, srcView); this->resolve(ctx, m_resolveView, srcView);
this->draw(ctx, m_fsBlit, dstView, dstRect, m_resolveView, srcRect); this->draw(ctx, m_fsBlit, dstView, dstRect, m_resolveView, srcRect);
@ -185,8 +185,8 @@ namespace dxvk {
ctx->bindRenderTargets(std::move(renderTargets), 0u); ctx->bindRenderTargets(std::move(renderTargets), 0u);
VkExtent2D dstExtent = { VkExtent2D dstExtent = {
dstView->imageInfo().extent.width, dstView->image()->info().extent.width,
dstView->imageInfo().extent.height }; dstView->image()->info().extent.height };
if (dstRect.extent == dstExtent) if (dstRect.extent == dstExtent)
ctx->discardImageView(dstView, VK_IMAGE_ASPECT_COLOR_BIT); ctx->discardImageView(dstView, VK_IMAGE_ASPECT_COLOR_BIT);
@ -212,7 +212,7 @@ namespace dxvk {
ctx->pushConstants(0, sizeof(args), &args); ctx->pushConstants(0, sizeof(args), &args);
ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, srcView->imageInfo().sampleCount); ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, srcView->image()->info().sampleCount);
ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 1, m_gammaView != nullptr); ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 1, m_gammaView != nullptr);
ctx->draw(3, 1, 0, 0); ctx->draw(3, 1, 0, 0);
} }
@ -226,7 +226,7 @@ namespace dxvk {
resolve.srcOffset = { 0, 0, 0 }; resolve.srcOffset = { 0, 0, 0 };
resolve.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; resolve.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
resolve.dstOffset = { 0, 0, 0 }; resolve.dstOffset = { 0, 0, 0 };
resolve.extent = dstView->imageInfo().extent; resolve.extent = dstView->image()->info().extent;
ctx->resolveImage(dstView->image(), srcView->image(), resolve, VK_FORMAT_UNDEFINED); ctx->resolveImage(dstView->image(), srcView->image(), resolve, VK_FORMAT_UNDEFINED);
} }