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:
parent
713b76bea5
commit
25076d9220
@ -512,12 +512,12 @@ namespace dxvk {
|
||||
// we'll have to use a fallback using a texel buffer view and buffer copies.
|
||||
bool isViewCompatible = uavFormat == rawFormat;
|
||||
|
||||
if (!isViewCompatible && (imageView->imageInfo().flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
|
||||
uint32_t formatCount = imageView->imageInfo().viewFormatCount;
|
||||
if (!isViewCompatible && (imageView->image()->info().flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)) {
|
||||
uint32_t formatCount = imageView->image()->info().viewFormatCount;
|
||||
isViewCompatible = formatCount == 0;
|
||||
|
||||
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) {
|
||||
@ -5428,8 +5428,8 @@ namespace dxvk {
|
||||
|| curView->info().numLayers != refView->info().numLayers)
|
||||
return false;
|
||||
|
||||
if (curView->imageInfo().sampleCount
|
||||
!= refView->imageInfo().sampleCount)
|
||||
if (curView->image()->info().sampleCount
|
||||
!= refView->image()->info().sampleCount)
|
||||
return false;
|
||||
|
||||
// Color targets must all be the same size
|
||||
|
@ -558,9 +558,7 @@ namespace dxvk {
|
||||
|
||||
Rc<DxvkImage> image = m_device->importImage(imageInfo,
|
||||
imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
m_imageViews[i] = new DxvkImageView(
|
||||
m_device->vkd(), image, viewInfo);
|
||||
m_imageViews[i] = image->createView(viewInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
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)) {
|
||||
default: // case 0
|
||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
@ -67,7 +67,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
UINT GetSampleCount() const {
|
||||
return UINT(m_view->imageInfo().sampleCount);
|
||||
return UINT(m_view->image()->info().sampleCount);
|
||||
}
|
||||
|
||||
VkImageAspectFlags GetWritableAspectMask() const {
|
||||
|
@ -52,13 +52,13 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
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_GENERAL;
|
||||
}
|
||||
|
||||
UINT GetSampleCount() const {
|
||||
return UINT(m_view->imageInfo().sampleCount);
|
||||
return UINT(m_view->image()->info().sampleCount);
|
||||
}
|
||||
|
||||
D3D10RenderTargetView* GetD3D10Iface() {
|
||||
|
@ -985,9 +985,7 @@ namespace dxvk {
|
||||
|
||||
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);
|
||||
m_wctx->imageViews[i] = image->createView(viewInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -730,7 +730,7 @@ namespace dxvk {
|
||||
return;
|
||||
|
||||
// Create one depth view and one stencil view
|
||||
DxvkImageViewCreateInfo dViewInfo;
|
||||
DxvkImageViewCreateInfo dViewInfo = { };
|
||||
dViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
dViewInfo.format = srcImage->info().format;
|
||||
dViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
@ -743,8 +743,8 @@ namespace dxvk {
|
||||
DxvkImageViewCreateInfo sViewInfo = dViewInfo;
|
||||
sViewInfo.aspect = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
Rc<DxvkImageView> dView = m_device->createImageView(srcImage, dViewInfo);
|
||||
Rc<DxvkImageView> sView = m_device->createImageView(srcImage, sViewInfo);
|
||||
Rc<DxvkImageView> dView = srcImage->createView(dViewInfo);
|
||||
Rc<DxvkImageView> sView = srcImage->createView(sViewInfo);
|
||||
|
||||
// Create a descriptor set for the pack operation
|
||||
VkImageLayout layout = srcImage->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
|
||||
@ -817,9 +817,6 @@ namespace dxvk {
|
||||
dstBuffer->info().stages,
|
||||
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::Read>(srcImage);
|
||||
}
|
||||
@ -1662,22 +1659,22 @@ namespace dxvk {
|
||||
VkImageLayout srcLayout = imageView->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
||||
// 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(),
|
||||
mipGenerator->getTopSubresource(),
|
||||
imageView->imageInfo().layout,
|
||||
imageView->imageInfo().stages, 0,
|
||||
imageView->image()->info().layout,
|
||||
imageView->image()->info().stages, 0,
|
||||
srcLayout,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT);
|
||||
}
|
||||
|
||||
// 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(),
|
||||
mipGenerator->getAllTargetSubresources(),
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
imageView->imageInfo().stages, 0,
|
||||
imageView->image()->info().stages, 0,
|
||||
dstLayout,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
|
||||
@ -1785,9 +1782,9 @@ namespace dxvk {
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
imageView->imageInfo().layout,
|
||||
imageView->imageInfo().stages,
|
||||
imageView->imageInfo().access);
|
||||
imageView->image()->info().layout,
|
||||
imageView->image()->info().stages,
|
||||
imageView->image()->info().access);
|
||||
} else {
|
||||
m_execBarriers.accessImage(imageView->image(),
|
||||
mipGenerator->getAllSourceSubresources(),
|
||||
@ -1796,18 +1793,18 @@ namespace dxvk {
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
imageView->imageInfo().layout,
|
||||
imageView->imageInfo().stages,
|
||||
imageView->imageInfo().access);
|
||||
imageView->image()->info().layout,
|
||||
imageView->image()->info().stages,
|
||||
imageView->image()->info().access);
|
||||
|
||||
m_execBarriers.accessImage(imageView->image(),
|
||||
mipGenerator->getBottomSubresource(),
|
||||
dstLayout,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
imageView->imageInfo().layout,
|
||||
imageView->imageInfo().stages,
|
||||
imageView->imageInfo().access);
|
||||
imageView->image()->info().layout,
|
||||
imageView->image()->info().stages,
|
||||
imageView->image()->info().access);
|
||||
}
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::None>(mipGenerator);
|
||||
@ -1971,14 +1968,14 @@ namespace dxvk {
|
||||
VkClearValue clearValue) {
|
||||
DxvkColorAttachmentOps colorOp;
|
||||
colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
colorOp.loadLayout = imageView->imageInfo().layout;
|
||||
colorOp.storeLayout = imageView->imageInfo().layout;
|
||||
colorOp.loadLayout = imageView->image()->info().layout;
|
||||
colorOp.storeLayout = imageView->image()->info().layout;
|
||||
|
||||
DxvkDepthAttachmentOps depthOp;
|
||||
depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthOp.loadLayout = imageView->imageInfo().layout;
|
||||
depthOp.storeLayout = imageView->imageInfo().layout;
|
||||
depthOp.loadLayout = imageView->image()->info().layout;
|
||||
depthOp.storeLayout = imageView->image()->info().layout;
|
||||
|
||||
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
@ -2015,7 +2012,7 @@ namespace dxvk {
|
||||
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) {
|
||||
colorOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
@ -2023,7 +2020,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
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))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
@ -2120,10 +2117,9 @@ namespace dxvk {
|
||||
imageView->imageSubresources(),
|
||||
imageLayout, clearStages, clearAccess,
|
||||
storeLayout,
|
||||
imageView->imageInfo().stages,
|
||||
imageView->imageInfo().access);
|
||||
imageView->image()->info().stages,
|
||||
imageView->image()->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::None>(imageView);
|
||||
m_cmd->trackResource<DxvkAccess::Write>(imageView->image());
|
||||
} else {
|
||||
// Perform the operation when starting the next render pass
|
||||
@ -2221,7 +2217,7 @@ namespace dxvk {
|
||||
|
||||
void DxvkContext::flushSharedImages() {
|
||||
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);
|
||||
i = m_deferredClears.erase(i);
|
||||
} else {
|
||||
@ -3320,11 +3316,11 @@ namespace dxvk {
|
||||
renderingInfo.pStencilAttachment = &attachmentInfo;
|
||||
}
|
||||
|
||||
if (clearLayout != imageView->imageInfo().layout) {
|
||||
if (clearLayout != imageView->image()->info().layout) {
|
||||
m_execAcquires.accessImage(
|
||||
imageView->image(),
|
||||
imageView->imageSubresources(),
|
||||
imageView->imageInfo().layout, clearStages, 0,
|
||||
imageView->image()->info().layout, clearStages, 0,
|
||||
clearLayout, clearStages, clearAccess);
|
||||
m_execAcquires.recordCommands(m_cmd);
|
||||
}
|
||||
@ -3365,11 +3361,10 @@ namespace dxvk {
|
||||
imageView->image(),
|
||||
imageView->imageSubresources(),
|
||||
clearLayout, clearStages, clearAccess,
|
||||
imageView->imageInfo().layout,
|
||||
imageView->imageInfo().stages,
|
||||
imageView->imageInfo().access);
|
||||
imageView->image()->info().layout,
|
||||
imageView->image()->info().stages,
|
||||
imageView->image()->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::None>(imageView);
|
||||
m_cmd->trackResource<DxvkAccess::Write>(imageView->image());
|
||||
}
|
||||
}
|
||||
@ -3399,7 +3394,7 @@ namespace dxvk {
|
||||
VkDescriptorImageInfo viewInfo;
|
||||
viewInfo.sampler = VK_NULL_HANDLE;
|
||||
viewInfo.imageView = imageView->handle();
|
||||
viewInfo.imageLayout = imageView->imageInfo().layout;
|
||||
viewInfo.imageLayout = imageView->image()->info().layout;
|
||||
|
||||
VkWriteDescriptorSet descriptorWrite = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
|
||||
descriptorWrite.dstSet = descriptorSet;
|
||||
@ -3443,14 +3438,13 @@ namespace dxvk {
|
||||
m_execBarriers.accessImage(
|
||||
imageView->image(),
|
||||
imageView->imageSubresources(),
|
||||
imageView->imageInfo().layout,
|
||||
imageView->image()->info().layout,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_ACCESS_SHADER_WRITE_BIT,
|
||||
imageView->imageInfo().layout,
|
||||
imageView->imageInfo().stages,
|
||||
imageView->imageInfo().access);
|
||||
imageView->image()->info().layout,
|
||||
imageView->image()->info().stages,
|
||||
imageView->image()->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::None>(imageView);
|
||||
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_WRITE_BIT,
|
||||
ops.depthOps.storeLayout,
|
||||
depthAttachment.view->imageInfo().stages,
|
||||
depthAttachment.view->imageInfo().access);
|
||||
depthAttachment.view->image()->info().stages,
|
||||
depthAttachment.view->image()->info().access);
|
||||
} else {
|
||||
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_LATE_FRAGMENT_TESTS_BIT,
|
||||
srcAccess,
|
||||
depthAttachment.view->imageInfo().stages,
|
||||
depthAttachment.view->imageInfo().access);
|
||||
depthAttachment.view->image()->info().stages,
|
||||
depthAttachment.view->image()->info().access);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4717,15 +4711,15 @@ namespace dxvk {
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
ops.colorOps[i].storeLayout,
|
||||
colorAttachment.view->imageInfo().stages,
|
||||
colorAttachment.view->imageInfo().access);
|
||||
colorAttachment.view->image()->info().stages,
|
||||
colorAttachment.view->image()->info().access);
|
||||
} else {
|
||||
m_execBarriers.accessMemory(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
colorAttachment.view->imageInfo().stages,
|
||||
colorAttachment.view->imageInfo().access);
|
||||
colorAttachment.view->image()->info().stages,
|
||||
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
|
||||
// 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;
|
||||
|
||||
auto& clear = lateClears[lateClearCount++];
|
||||
@ -4830,10 +4824,8 @@ namespace dxvk {
|
||||
m_cmd->cmdClearAttachments(lateClearCount, lateClears.data(), 1, &clearRect);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < framebufferInfo.numAttachments(); i++) {
|
||||
m_cmd->trackResource<DxvkAccess::None> (framebufferInfo.getAttachment(i).view);
|
||||
for (uint32_t i = 0; i < framebufferInfo.numAttachments(); i++)
|
||||
m_cmd->trackResource<DxvkAccess::Write>(framebufferInfo.getAttachment(i).view->image());
|
||||
}
|
||||
|
||||
m_cmd->addStatCtr(DxvkStatCounter::CmdRenderPassCount, 1);
|
||||
}
|
||||
@ -5258,12 +5250,10 @@ namespace dxvk {
|
||||
if (res.imageView != nullptr && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) {
|
||||
descriptorInfo.image.sampler = VK_NULL_HANDLE;
|
||||
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)) {
|
||||
m_cmd->trackResource<DxvkAccess::None>(res.imageView);
|
||||
if (m_rcTracked.set(binding.resourceBinding))
|
||||
m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image());
|
||||
}
|
||||
} else {
|
||||
descriptorInfo.image.sampler = 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) {
|
||||
descriptorInfo.image.sampler = VK_NULL_HANDLE;
|
||||
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)) {
|
||||
m_cmd->trackResource<DxvkAccess::None>(res.imageView);
|
||||
if (m_rcTracked.set(binding.resourceBinding))
|
||||
m_cmd->trackResource<DxvkAccess::Write>(res.imageView->image());
|
||||
}
|
||||
} else {
|
||||
descriptorInfo.image.sampler = VK_NULL_HANDLE;
|
||||
descriptorInfo.image.imageView = VK_NULL_HANDLE;
|
||||
@ -5297,11 +5285,10 @@ namespace dxvk {
|
||||
&& res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) {
|
||||
descriptorInfo.image.sampler = res.sampler->handle();
|
||||
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)) {
|
||||
m_cmd->trackResource<DxvkAccess::None>(res.sampler);
|
||||
m_cmd->trackResource<DxvkAccess::None>(res.imageView);
|
||||
m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image());
|
||||
}
|
||||
} else {
|
||||
@ -5472,17 +5459,17 @@ namespace dxvk {
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; 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]);
|
||||
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();
|
||||
|
||||
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);
|
||||
m_rtLayouts.depth = depth.view->imageInfo().layout;
|
||||
m_rtLayouts.depth = depth.view->image()->info().layout;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5490,15 +5477,15 @@ namespace dxvk {
|
||||
void DxvkContext::transitionColorAttachment(
|
||||
const DxvkAttachment& attachment,
|
||||
VkImageLayout oldLayout) {
|
||||
if (oldLayout != attachment.view->imageInfo().layout) {
|
||||
if (oldLayout != attachment.view->image()->info().layout) {
|
||||
m_execBarriers.accessImage(
|
||||
attachment.view->image(),
|
||||
attachment.view->imageSubresources(), oldLayout,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
attachment.view->imageInfo().layout,
|
||||
attachment.view->imageInfo().stages,
|
||||
attachment.view->imageInfo().access);
|
||||
attachment.view->image()->info().layout,
|
||||
attachment.view->image()->info().stages,
|
||||
attachment.view->image()->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::Write>(attachment.view->image());
|
||||
}
|
||||
@ -5508,7 +5495,7 @@ namespace dxvk {
|
||||
void DxvkContext::transitionDepthAttachment(
|
||||
const DxvkAttachment& attachment,
|
||||
VkImageLayout oldLayout) {
|
||||
if (oldLayout != attachment.view->imageInfo().layout) {
|
||||
if (oldLayout != attachment.view->image()->info().layout) {
|
||||
m_execBarriers.accessImage(
|
||||
attachment.view->image(),
|
||||
attachment.view->imageSubresources(), oldLayout,
|
||||
@ -5516,9 +5503,9 @@ namespace dxvk {
|
||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
oldLayout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
|
||||
? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : 0,
|
||||
attachment.view->imageInfo().layout,
|
||||
attachment.view->imageInfo().stages,
|
||||
attachment.view->imageInfo().access);
|
||||
attachment.view->image()->info().layout,
|
||||
attachment.view->image()->info().stages,
|
||||
attachment.view->image()->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::Write>(attachment.view->image());
|
||||
}
|
||||
@ -5532,11 +5519,11 @@ namespace dxvk {
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
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)
|
||||
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
|
||||
// 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_COMBINED_IMAGE_SAMPLER:
|
||||
if ((slot.imageView != nullptr)
|
||||
&& (slot.imageView->imageInfo().access & storageImageAccess)) {
|
||||
&& (slot.imageView->image()->info().access & storageImageAccess)) {
|
||||
requiresBarrier = this->checkImageViewBarrier<DoEmit>(slot.imageView,
|
||||
util::pipelineStages(binding.stage), binding.access);
|
||||
}
|
||||
@ -6267,11 +6254,11 @@ namespace dxvk {
|
||||
m_execBarriers.accessImage(
|
||||
imageView->image(),
|
||||
imageView->imageSubresources(),
|
||||
imageView->imageInfo().layout,
|
||||
imageView->image()->info().layout,
|
||||
stages, access,
|
||||
imageView->imageInfo().layout,
|
||||
imageView->imageInfo().stages,
|
||||
imageView->imageInfo().access);
|
||||
imageView->image()->info().layout,
|
||||
imageView->image()->info().stages,
|
||||
imageView->image()->info().access);
|
||||
return false;
|
||||
} else {
|
||||
DxvkAccessFlags dstAccess = DxvkBarrierSet::getAccessTypes(access);
|
||||
|
@ -174,7 +174,7 @@ namespace dxvk {
|
||||
Rc<DxvkImageView> DxvkDevice::createImageView(
|
||||
const Rc<DxvkImage>& image,
|
||||
const DxvkImageViewCreateInfo& createInfo) {
|
||||
return new DxvkImageView(m_vkd, image, createInfo);
|
||||
return image->createView(createInfo);
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,13 +16,13 @@ namespace dxvk {
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
if (m_renderTargets.color[i].view != nullptr) {
|
||||
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) {
|
||||
m_attachments[m_attachmentCount++] = -1;
|
||||
m_sampleCount = m_renderTargets.depth.view->imageInfo().sampleCount;
|
||||
m_sampleCount = m_renderTargets.depth.view->image()->info().sampleCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
const DxvkFormatInfo* formatInfo = lookupFormatInfo(m_info.format);
|
||||
|
||||
@ -195,108 +224,84 @@ namespace dxvk {
|
||||
|
||||
|
||||
DxvkImageView::DxvkImageView(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkImage>& image,
|
||||
const DxvkImageViewCreateInfo& info)
|
||||
: m_vkd(vkd), m_image(image), m_info(info) {
|
||||
for (uint32_t i = 0; i < ViewCount; i++)
|
||||
m_views[i] = VK_NULL_HANDLE;
|
||||
DxvkImage* image,
|
||||
const DxvkImageViewKey& key)
|
||||
: m_image(image), m_key(key) {
|
||||
|
||||
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() {
|
||||
for (uint32_t i = 0; i < ViewCount; i++)
|
||||
m_vkd->vkDestroyImageView(m_vkd->device(), m_views[i], nullptr);
|
||||
|
||||
}
|
||||
|
||||
|
||||
VkImageView DxvkImageView::createView(VkImageViewType type) const {
|
||||
DxvkImageViewKey key = m_key;
|
||||
key.viewType = type;
|
||||
|
||||
// Only use one layer for non-arrayed view types
|
||||
if (type == VK_IMAGE_VIEW_TYPE_1D || type == VK_IMAGE_VIEW_TYPE_2D)
|
||||
key.layerCount = 1u;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return m_image->m_storage->createImageView(key);
|
||||
}
|
||||
|
||||
|
||||
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 };
|
||||
viewUsage.usage = m_info.usage;
|
||||
|
||||
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) {
|
||||
viewInfo.components = {
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
|
||||
void DxvkImageView::updateViews() {
|
||||
// Update all views that are not currently null
|
||||
for (uint32_t i = 0; i < m_views.size(); i++) {
|
||||
if (m_views[i])
|
||||
m_views[i] = createView(VkImageViewType(i));
|
||||
}
|
||||
|
||||
if (m_vkd->vkCreateImageView(m_vkd->device(),
|
||||
&viewInfo, nullptr, &m_views[type]) != VK_SUCCESS) {
|
||||
throw DxvkError(str::format(
|
||||
"DxvkImageView: Failed to create image view:"
|
||||
"\n View type: ", viewInfo.viewType,
|
||||
"\n View format: ", viewInfo.format,
|
||||
"\n Subresources: ",
|
||||
"\n Aspect mask: ", std::hex, viewInfo.subresourceRange.aspectMask,
|
||||
"\n Mip levels: ", viewInfo.subresourceRange.baseMipLevel, " - ",
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
class DxvkImageView;
|
||||
|
||||
/**
|
||||
* \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
|
||||
*
|
||||
@ -114,8 +309,8 @@ namespace dxvk {
|
||||
* memory type and if created with the linear tiling option.
|
||||
*/
|
||||
class DxvkImage : public DxvkPagedResource {
|
||||
friend DxvkImageView;
|
||||
friend class DxvkContext;
|
||||
friend class DxvkImageView;
|
||||
public:
|
||||
|
||||
DxvkImage(
|
||||
@ -348,6 +543,15 @@ namespace dxvk {
|
||||
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:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
@ -365,6 +569,10 @@ namespace dxvk {
|
||||
|
||||
small_vector<VkFormat, 4> m_viewFormats;
|
||||
|
||||
dxvk::mutex m_viewMutex;
|
||||
std::unordered_map<DxvkImageViewKey,
|
||||
DxvkImageView, DxvkHash, DxvkEq> m_views;
|
||||
|
||||
VkImageCreateInfo getImageCreateInfo() const;
|
||||
|
||||
void copyFormatList(
|
||||
@ -379,217 +587,56 @@ namespace dxvk {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief DXVK image view
|
||||
*/
|
||||
class DxvkImageView : public DxvkResource {
|
||||
friend class DxvkImage;
|
||||
constexpr static uint32_t ViewCount = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY + 1;
|
||||
public:
|
||||
|
||||
DxvkImageView(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkImage>& image,
|
||||
const DxvkImageViewCreateInfo& info);
|
||||
|
||||
~DxvkImageView();
|
||||
|
||||
/**
|
||||
* \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() const {
|
||||
return handle(m_info.type);
|
||||
inline void DxvkImageView::incRef() {
|
||||
m_image->incRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* \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];
|
||||
|
||||
inline void DxvkImageView::decRef() {
|
||||
m_image->decRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* \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;
|
||||
}
|
||||
inline VkImageSubresourceRange DxvkImageView::imageSubresources() const {
|
||||
VkImageSubresourceRange result = { };
|
||||
result.aspectMask = m_key.aspects;
|
||||
result.baseMipLevel = m_key.mipIndex;
|
||||
result.levelCount = m_key.mipCount;
|
||||
|
||||
/**
|
||||
* \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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \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;
|
||||
result.baseArrayLayer = m_key.layerIndex;
|
||||
result.layerCount = m_key.layerCount;
|
||||
} else {
|
||||
result.baseArrayLayer = 0;
|
||||
result.layerCount = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Picks an image layout
|
||||
* \see DxvkImage::pickLayout
|
||||
*/
|
||||
VkImageLayout pickLayout(VkImageLayout layout) const {
|
||||
|
||||
inline VkExtent3D DxvkImageView::mipLevelExtent(uint32_t level) const {
|
||||
return m_image->mipLevelExtent(level + m_key.mipIndex, m_key.aspects);
|
||||
}
|
||||
|
||||
|
||||
inline VkImageLayout DxvkImageView::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 VkImageView DxvkImageView::handle(VkImageViewType viewType) {
|
||||
viewType = viewType != VK_IMAGE_VIEW_TYPE_MAX_ENUM ? viewType : m_key.viewType;
|
||||
|
||||
if (unlikely(m_version < m_image->m_version))
|
||||
updateViews();
|
||||
|
||||
if (unlikely(!m_views[viewType]))
|
||||
m_views[viewType] = createView(viewType);
|
||||
|
||||
return m_views[viewType];
|
||||
}
|
||||
|
||||
/**
|
||||
* \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:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
Rc<DxvkImage> m_image;
|
||||
|
||||
DxvkImageViewCreateInfo m_info;
|
||||
VkImageView m_views[ViewCount];
|
||||
|
||||
void createView(VkImageViewType type, uint32_t numLayers);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ namespace dxvk {
|
||||
{ VK_IMAGE_VIEW_TYPE_3D, VK_IMAGE_VIEW_TYPE_2D_ARRAY },
|
||||
}};
|
||||
|
||||
m_srcViewType = viewTypes.at(uint32_t(view->imageInfo().type)).first;
|
||||
m_dstViewType = viewTypes.at(uint32_t(view->imageInfo().type)).second;
|
||||
m_srcViewType = viewTypes.at(uint32_t(view->image()->info().type)).first;
|
||||
m_dstViewType = viewTypes.at(uint32_t(view->image()->info().type)).second;
|
||||
|
||||
// Create image views and framebuffers
|
||||
m_passes.resize(view->info().numLevels - 1);
|
||||
@ -35,7 +35,7 @@ namespace dxvk {
|
||||
VkExtent3D DxvkMetaMipGenRenderPass::computePassExtent(uint32_t passId) const {
|
||||
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;
|
||||
|
||||
return extent;
|
||||
@ -48,7 +48,7 @@ namespace dxvk {
|
||||
VkImageViewUsageCreateInfo usageInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO };
|
||||
|
||||
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;
|
||||
|
||||
// Create source image view, which points to
|
||||
@ -76,7 +76,7 @@ namespace dxvk {
|
||||
dstSubresources.baseMipLevel = m_view->info().minLevel + pass + 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.layerCount = m_view->info().numLayers;
|
||||
} else {
|
||||
|
@ -33,21 +33,21 @@ namespace dxvk {
|
||||
if (!dstRect.extent.width || !dstRect.extent.height) {
|
||||
dstRect.offset = { 0, 0 };
|
||||
dstRect.extent = {
|
||||
dstView->imageInfo().extent.width,
|
||||
dstView->imageInfo().extent.height };
|
||||
dstView->image()->info().extent.width,
|
||||
dstView->image()->info().extent.height };
|
||||
}
|
||||
|
||||
if (!srcRect.extent.width || !srcRect.extent.height) {
|
||||
srcRect.offset = { 0, 0 };
|
||||
srcRect.extent = {
|
||||
srcView->imageInfo().extent.width,
|
||||
srcView->imageInfo().extent.height };
|
||||
srcView->image()->info().extent.width,
|
||||
srcView->image()->info().extent.height };
|
||||
}
|
||||
|
||||
bool sameSize = dstRect.extent == srcRect.extent;
|
||||
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,
|
||||
dstView, dstRect, srcView, srcRect);
|
||||
} else if (sameSize) {
|
||||
@ -55,9 +55,9 @@ namespace dxvk {
|
||||
dstView, dstRect, srcView, srcRect);
|
||||
} else {
|
||||
if (m_resolveImage == nullptr
|
||||
|| m_resolveImage->info().extent != srcView->imageInfo().extent
|
||||
|| m_resolveImage->info().format != srcView->imageInfo().format)
|
||||
this->createResolveImage(srcView->imageInfo());
|
||||
|| m_resolveImage->info().extent != srcView->image()->info().extent
|
||||
|| m_resolveImage->info().format != srcView->image()->info().format)
|
||||
this->createResolveImage(srcView->image()->info());
|
||||
|
||||
this->resolve(ctx, m_resolveView, srcView);
|
||||
this->draw(ctx, m_fsBlit, dstView, dstRect, m_resolveView, srcRect);
|
||||
@ -185,8 +185,8 @@ namespace dxvk {
|
||||
ctx->bindRenderTargets(std::move(renderTargets), 0u);
|
||||
|
||||
VkExtent2D dstExtent = {
|
||||
dstView->imageInfo().extent.width,
|
||||
dstView->imageInfo().extent.height };
|
||||
dstView->image()->info().extent.width,
|
||||
dstView->image()->info().extent.height };
|
||||
|
||||
if (dstRect.extent == dstExtent)
|
||||
ctx->discardImageView(dstView, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
@ -212,7 +212,7 @@ namespace dxvk {
|
||||
|
||||
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->draw(3, 1, 0, 0);
|
||||
}
|
||||
@ -226,7 +226,7 @@ namespace dxvk {
|
||||
resolve.srcOffset = { 0, 0, 0 };
|
||||
resolve.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user