mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 14:52:11 +01:00
[dxvk] Use dynamic rendering for copies
Significantly reworks framebuffer copies as well. We'll no longer create dummy samplers to work around glslang versions not supporting texture descriptors without samplers, and copyImageFb was cleaned up to factor out the part where a temporary image is created.
This commit is contained in:
parent
a450c88c72
commit
96e102beff
@ -3232,6 +3232,82 @@ namespace dxvk {
|
||||
VkImageSubresourceLayers srcSubresource,
|
||||
VkOffset3D srcOffset,
|
||||
VkExtent3D extent) {
|
||||
VkFormat viewFormat = m_common->metaCopy().getCopyDestinationFormat(
|
||||
dstSubresource.aspectMask,
|
||||
srcSubresource.aspectMask,
|
||||
srcImage->info().format);
|
||||
|
||||
if (!viewFormat) {
|
||||
Logger::err("DxvkContext: copyImageFb: Unsupported format");
|
||||
return;
|
||||
}
|
||||
|
||||
// Usually we should be able to draw directly to the destination image,
|
||||
// but in some cases this might not be possible, e.g. if when copying
|
||||
// from something like D32_SFLOAT to RGBA8_UNORM. In those situations,
|
||||
// create a temporary image to draw to, and then copy to the actual
|
||||
// destination image using a regular Vulkan transfer function.
|
||||
bool useDirectCopy = (dstImage->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
|
||||
&& (dstImage->isViewCompatible(viewFormat));
|
||||
|
||||
if (useDirectCopy) {
|
||||
this->copyImageFbDirect(
|
||||
dstImage, dstSubresource, dstOffset, viewFormat,
|
||||
srcImage, srcSubresource, srcOffset, extent);
|
||||
} else {
|
||||
DxvkImageCreateInfo imageInfo = dstImage->info();
|
||||
imageInfo.format = viewFormat;
|
||||
imageInfo.flags = 0;
|
||||
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
imageInfo.extent = extent;
|
||||
imageInfo.numLayers = dstSubresource.layerCount;
|
||||
imageInfo.mipLevels = 1;
|
||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageInfo.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
imageInfo.viewFormatCount = 0;
|
||||
|
||||
if (dstImage->formatInfo()->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
imageInfo.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
imageInfo.access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
} else {
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
imageInfo.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
||||
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
imageInfo.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
}
|
||||
|
||||
Rc<DxvkImage> tmpImage = m_device->createImage(imageInfo,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
VkImageSubresourceLayers tmpSubresource = dstSubresource;
|
||||
tmpSubresource.mipLevel = 0;
|
||||
tmpSubresource.baseArrayLayer = 0;
|
||||
|
||||
VkOffset3D tmpOffset = { 0, 0, 0 };
|
||||
|
||||
this->copyImageFbDirect(
|
||||
tmpImage, tmpSubresource, tmpOffset, viewFormat,
|
||||
srcImage, srcSubresource, srcOffset, extent);
|
||||
|
||||
this->copyImageHw(
|
||||
dstImage, dstSubresource, dstOffset,
|
||||
tmpImage, tmpSubresource, tmpOffset, extent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copyImageFbDirect(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
VkImageSubresourceLayers dstSubresource,
|
||||
VkOffset3D dstOffset,
|
||||
VkFormat dstFormat,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
VkImageSubresourceLayers srcSubresource,
|
||||
VkOffset3D srcOffset,
|
||||
VkExtent3D extent) {
|
||||
this->invalidateState();
|
||||
|
||||
auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresource);
|
||||
@ -3241,24 +3317,33 @@ namespace dxvk {
|
||||
|| m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
|
||||
// Source image needs to be readable
|
||||
if (!(srcImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
|
||||
Logger::err("DxvkContext: copyImageFb: Source image not readable");
|
||||
return;
|
||||
// Flag used to determine whether we can do an UNDEFINED transition
|
||||
bool doDiscard = dstImage->isFullSubresource(dstSubresource, extent);
|
||||
|
||||
// This function can process both color and depth-stencil images, so
|
||||
// some things change a lot depending on the destination image type
|
||||
VkPipelineStageFlags dstStages;
|
||||
VkAccessFlags dstAccess;
|
||||
VkImageLayout dstLayout;
|
||||
|
||||
if (dstSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
dstLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
dstStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
dstAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
if (!doDiscard)
|
||||
dstAccess |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
|
||||
} else {
|
||||
dstLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
dstStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
||||
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
dstAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
if (!doDiscard)
|
||||
dstAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
|
||||
}
|
||||
|
||||
// Render target format to use for this copy
|
||||
VkFormat viewFormat = m_common->metaCopy().getCopyDestinationFormat(
|
||||
dstSubresource.aspectMask,
|
||||
srcSubresource.aspectMask,
|
||||
srcImage->info().format);
|
||||
|
||||
if (viewFormat == VK_FORMAT_UNDEFINED) {
|
||||
Logger::err("DxvkContext: copyImageFb: Unsupported format");
|
||||
return;
|
||||
}
|
||||
|
||||
// We might have to transition the source image layout
|
||||
// Might have to transition source image as well
|
||||
VkImageLayout srcLayout = (srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
? srcImage->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||
: srcImage->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
|
||||
@ -3271,183 +3356,131 @@ namespace dxvk {
|
||||
srcLayout,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT);
|
||||
|
||||
m_execAcquires.recordCommands(m_cmd);
|
||||
}
|
||||
|
||||
// In some cases, we may be able to render to the destination
|
||||
// image directly, which is faster than using a temporary image
|
||||
VkImageUsageFlagBits tgtUsage = (dstSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
|
||||
: VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
|
||||
bool useDirectRender = (dstImage->isViewCompatible(viewFormat))
|
||||
&& (dstImage->info().usage & tgtUsage);
|
||||
|
||||
// If needed, create a temporary render target for the copy
|
||||
Rc<DxvkImage> tgtImage;
|
||||
VkImageSubresourceLayers tgtSubresource = dstSubresource;
|
||||
VkOffset3D tgtOffset = dstOffset;
|
||||
|
||||
if (!useDirectRender) {
|
||||
DxvkImageCreateInfo info;
|
||||
info.type = dstImage->info().type;
|
||||
info.format = viewFormat;
|
||||
info.flags = 0;
|
||||
info.sampleCount = dstImage->info().sampleCount;
|
||||
info.extent = extent;
|
||||
info.numLayers = dstSubresource.layerCount;
|
||||
info.mipLevels = 1;
|
||||
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | tgtUsage;
|
||||
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
info.access = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
info.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
|
||||
tgtImage = m_device->createImage(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
tgtSubresource.mipLevel = 0;
|
||||
tgtSubresource.baseArrayLayer = 0;
|
||||
|
||||
tgtOffset = { 0, 0, 0 };
|
||||
} else {
|
||||
tgtImage = dstImage;
|
||||
if (dstImage->info().layout != dstLayout) {
|
||||
m_execAcquires.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
doDiscard ? VK_IMAGE_LAYOUT_UNDEFINED
|
||||
: dstImage->info().layout,
|
||||
dstImage->info().stages, 0,
|
||||
dstLayout, dstStages, dstAccess);
|
||||
}
|
||||
|
||||
|
||||
m_execAcquires.recordCommands(m_cmd);
|
||||
|
||||
// Create source and destination image views
|
||||
VkImageViewType viewType = dstImage->info().type == VK_IMAGE_TYPE_1D
|
||||
? VK_IMAGE_VIEW_TYPE_1D_ARRAY
|
||||
: VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
Rc<DxvkMetaCopyViews> views = new DxvkMetaCopyViews(m_device->vkd(),
|
||||
dstImage, dstSubresource, dstFormat,
|
||||
srcImage, srcSubresource);
|
||||
|
||||
DxvkImageViewCreateInfo tgtViewInfo;
|
||||
tgtViewInfo.type = viewType;
|
||||
tgtViewInfo.format = viewFormat;
|
||||
tgtViewInfo.usage = tgtUsage;
|
||||
tgtViewInfo.aspect = tgtSubresource.aspectMask;
|
||||
tgtViewInfo.minLevel = tgtSubresource.mipLevel;
|
||||
tgtViewInfo.numLevels = 1;
|
||||
tgtViewInfo.minLayer = tgtSubresource.baseArrayLayer;
|
||||
tgtViewInfo.numLayers = tgtSubresource.layerCount;
|
||||
// Create pipeline for the copy operation
|
||||
DxvkMetaCopyPipeline pipeInfo = m_common->metaCopy().getPipeline(
|
||||
views->getSrcViewType(), dstFormat, dstImage->info().sampleCount);
|
||||
|
||||
DxvkImageViewCreateInfo srcViewInfo;
|
||||
srcViewInfo.type = viewType;
|
||||
srcViewInfo.format = srcImage->info().format;
|
||||
srcViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
srcViewInfo.aspect = srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
srcViewInfo.minLevel = srcSubresource.mipLevel;
|
||||
srcViewInfo.numLevels = 1;
|
||||
srcViewInfo.minLayer = srcSubresource.baseArrayLayer;
|
||||
srcViewInfo.numLayers = srcSubresource.layerCount;
|
||||
// Create and initialize descriptor set
|
||||
VkDescriptorSet descriptorSet = m_descriptorPool->alloc(pipeInfo.dsetLayout);
|
||||
|
||||
Rc<DxvkImageView> tgtImageView = m_device->createImageView(tgtImage, tgtViewInfo);
|
||||
Rc<DxvkImageView> srcImageView = m_device->createImageView(srcImage, srcViewInfo);
|
||||
Rc<DxvkImageView> srcStencilView;
|
||||
std::array<VkDescriptorImageInfo, 2> descriptorImages = {{
|
||||
{ VK_NULL_HANDLE, views->getSrcView(), srcLayout },
|
||||
{ VK_NULL_HANDLE, views->getSrcStencilView(), srcLayout },
|
||||
}};
|
||||
|
||||
if (srcSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
||||
srcViewInfo.aspect = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
srcStencilView = m_device->createImageView(srcImage, srcViewInfo);
|
||||
std::array<VkWriteDescriptorSet, 2> descriptorWrites;
|
||||
|
||||
for (uint32_t i = 0; i < descriptorWrites.size(); i++) {
|
||||
descriptorWrites[i] = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
|
||||
descriptorWrites[i].dstSet = descriptorSet;
|
||||
descriptorWrites[i].dstBinding = i;
|
||||
descriptorWrites[i].descriptorCount = 1;
|
||||
descriptorWrites[i].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
descriptorWrites[i].pImageInfo = &descriptorImages[i];
|
||||
}
|
||||
|
||||
// Create framebuffer and pipeline for the copy
|
||||
Rc<DxvkMetaCopyRenderPass> fb = new DxvkMetaCopyRenderPass(
|
||||
m_device->vkd(), tgtImageView, srcImageView, srcStencilView,
|
||||
tgtImage->isFullSubresource(tgtSubresource, extent));
|
||||
|
||||
auto pipeInfo = m_common->metaCopy().getPipeline(
|
||||
viewType, viewFormat, tgtImage->info().sampleCount);
|
||||
|
||||
VkDescriptorImageInfo descriptorImage;
|
||||
descriptorImage.sampler = VK_NULL_HANDLE;
|
||||
descriptorImage.imageView = srcImageView->handle();
|
||||
descriptorImage.imageLayout = srcLayout;
|
||||
m_cmd->updateDescriptorSets(
|
||||
descriptorWrites.size(),
|
||||
descriptorWrites.data());
|
||||
|
||||
VkWriteDescriptorSet descriptorWrite;
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.pNext = nullptr;
|
||||
descriptorWrite.dstBinding = 0;
|
||||
descriptorWrite.dstArrayElement = 0;
|
||||
descriptorWrite.descriptorCount = 1;
|
||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
descriptorWrite.pImageInfo = &descriptorImage;
|
||||
descriptorWrite.pBufferInfo = nullptr;
|
||||
descriptorWrite.pTexelBufferView = nullptr;
|
||||
|
||||
descriptorWrite.dstSet = m_descriptorPool->alloc(pipeInfo.dsetLayout);
|
||||
m_cmd->updateDescriptorSets(1, &descriptorWrite);
|
||||
|
||||
if (srcSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
||||
descriptorImage.imageView = srcStencilView->handle();
|
||||
descriptorWrite.dstBinding = 1;
|
||||
m_cmd->updateDescriptorSets(1, &descriptorWrite);
|
||||
}
|
||||
|
||||
// Set up render state
|
||||
VkViewport viewport;
|
||||
viewport.x = float(tgtOffset.x);
|
||||
viewport.y = float(tgtOffset.y);
|
||||
viewport.width = float(extent.width);
|
||||
viewport.height = float(extent.height);
|
||||
viewport.x = float(dstOffset.x);
|
||||
viewport.y = float(dstOffset.y);
|
||||
viewport.width = float(extent.width);
|
||||
viewport.height = float(extent.height);
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
|
||||
VkRect2D scissor;
|
||||
scissor.offset = { tgtOffset.x, tgtOffset.y };
|
||||
scissor.extent = { extent.width, extent.height };
|
||||
scissor.offset = { dstOffset.x, dstOffset.y };
|
||||
scissor.extent = { extent.width, extent.height };
|
||||
|
||||
VkRenderPassBeginInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.renderPass = fb->renderPass();
|
||||
info.framebuffer = fb->framebuffer();
|
||||
info.renderArea.offset = { 0, 0 };
|
||||
info.renderArea.extent = {
|
||||
tgtImage->mipLevelExtent(tgtSubresource.mipLevel).width,
|
||||
tgtImage->mipLevelExtent(tgtSubresource.mipLevel).height };
|
||||
info.clearValueCount = 0;
|
||||
info.pClearValues = nullptr;
|
||||
VkExtent3D mipExtent = dstImage->mipLevelExtent(dstSubresource.mipLevel);
|
||||
|
||||
VkRenderingAttachmentInfoKHR attachmentInfo = { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR };
|
||||
attachmentInfo.imageView = views->getDstView();
|
||||
attachmentInfo.imageLayout = dstLayout;
|
||||
attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
|
||||
if (doDiscard)
|
||||
attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
|
||||
VkRenderingInfoKHR renderingInfo = { VK_STRUCTURE_TYPE_RENDERING_INFO_KHR };
|
||||
renderingInfo.renderArea.offset = VkOffset2D { 0, 0 };
|
||||
renderingInfo.renderArea.extent = VkExtent2D { mipExtent.width, mipExtent.height };
|
||||
renderingInfo.layerCount = dstSubresource.layerCount;
|
||||
|
||||
VkImageAspectFlags dstAspects = dstImage->formatInfo()->aspectMask;
|
||||
|
||||
if (dstAspects & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
renderingInfo.colorAttachmentCount = 1;
|
||||
renderingInfo.pColorAttachments = &attachmentInfo;
|
||||
} else {
|
||||
if (dstAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||
renderingInfo.pDepthAttachment = &attachmentInfo;
|
||||
if (dstAspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
renderingInfo.pStencilAttachment = &attachmentInfo;
|
||||
}
|
||||
|
||||
// Perform the actual copy operation
|
||||
m_cmd->cmdBeginRenderPass(&info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
m_cmd->cmdBeginRendering(&renderingInfo);
|
||||
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle);
|
||||
m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeInfo.pipeLayout, descriptorWrite.dstSet, 0, nullptr);
|
||||
pipeInfo.pipeLayout, descriptorSet, 0, nullptr);
|
||||
|
||||
m_cmd->cmdSetViewport(0, 1, &viewport);
|
||||
m_cmd->cmdSetScissor (0, 1, &scissor);
|
||||
|
||||
VkOffset2D srcCoordOffset = {
|
||||
srcOffset.x - tgtOffset.x,
|
||||
srcOffset.y - tgtOffset.y };
|
||||
srcOffset.x - dstOffset.x,
|
||||
srcOffset.y - dstOffset.y };
|
||||
|
||||
m_cmd->cmdPushConstants(pipeInfo.pipeLayout,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0, sizeof(srcCoordOffset),
|
||||
&srcCoordOffset);
|
||||
|
||||
m_cmd->cmdDraw(3, tgtSubresource.layerCount, 0, 0);
|
||||
m_cmd->cmdEndRenderPass();
|
||||
m_cmd->cmdDraw(3, dstSubresource.layerCount, 0, 0);
|
||||
m_cmd->cmdEndRendering();
|
||||
|
||||
if (srcLayout != srcImage->info().layout) {
|
||||
m_execBarriers.accessImage(
|
||||
srcImage, srcSubresourceRange, srcLayout,
|
||||
srcImage->info().stages,
|
||||
srcImage->info().access,
|
||||
srcImage->info().layout,
|
||||
srcImage->info().stages,
|
||||
srcImage->info().access);
|
||||
}
|
||||
m_execBarriers.accessImage(
|
||||
srcImage, srcSubresourceRange, srcLayout,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
srcImage->info().layout,
|
||||
srcImage->info().stages,
|
||||
srcImage->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::Write>(tgtImage);
|
||||
m_execBarriers.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
dstLayout, dstStages, dstAccess,
|
||||
dstImage->info().layout,
|
||||
dstImage->info().stages,
|
||||
dstImage->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::Write>(dstImage);
|
||||
m_cmd->trackResource<DxvkAccess::Read>(srcImage);
|
||||
m_cmd->trackResource<DxvkAccess::None>(fb);
|
||||
|
||||
// If necessary, copy the temporary image
|
||||
// to the original destination image
|
||||
if (!useDirectRender) {
|
||||
this->copyImageHw(
|
||||
dstImage, dstSubresource, dstOffset,
|
||||
tgtImage, tgtSubresource, tgtOffset,
|
||||
extent);
|
||||
}
|
||||
m_cmd->trackResource<DxvkAccess::None>(views);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1224,6 +1224,16 @@ namespace dxvk {
|
||||
VkOffset3D srcOffset,
|
||||
VkExtent3D extent);
|
||||
|
||||
void copyImageFbDirect(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
VkImageSubresourceLayers dstSubresource,
|
||||
VkOffset3D dstOffset,
|
||||
VkFormat dstFormat,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
VkImageSubresourceLayers srcSubresource,
|
||||
VkOffset3D srcOffset,
|
||||
VkExtent3D extent);
|
||||
|
||||
bool copyImageClear(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
VkImageSubresourceLayers dstSubresource,
|
||||
|
@ -18,143 +18,68 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkMetaCopyRenderPass::DxvkMetaCopyRenderPass(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkImageView>& dstImageView,
|
||||
const Rc<DxvkImageView>& srcImageView,
|
||||
const Rc<DxvkImageView>& srcStencilView,
|
||||
bool discardDst)
|
||||
: m_vkd (vkd),
|
||||
m_dstImageView (dstImageView),
|
||||
m_srcImageView (srcImageView),
|
||||
m_srcStencilView(srcStencilView),
|
||||
m_renderPass (createRenderPass(discardDst)),
|
||||
m_framebuffer (createFramebuffer()) {
|
||||
DxvkMetaCopyViews::DxvkMetaCopyViews(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const VkImageSubresourceLayers& dstSubresources,
|
||||
VkFormat dstFormat,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageSubresourceLayers& srcSubresources)
|
||||
: m_vkd(vkd) {
|
||||
VkImageAspectFlags dstAspects = dstImage->formatInfo()->aspectMask;
|
||||
VkImageAspectFlags srcAspects = srcImage->formatInfo()->aspectMask;
|
||||
|
||||
// We don't support 3D here, so we can safely ignore that case
|
||||
m_dstViewType = dstImage->info().type == VK_IMAGE_TYPE_1D
|
||||
? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
m_srcViewType = srcImage->info().type == VK_IMAGE_TYPE_1D
|
||||
? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
|
||||
VkImageViewUsageCreateInfo usageInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO };
|
||||
usageInfo.usage = (dstAspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
|
||||
: VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
|
||||
// Create destination view
|
||||
VkImageViewCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, &usageInfo };
|
||||
info.image = dstImage->handle();
|
||||
info.viewType = m_dstViewType;
|
||||
info.format = dstFormat;
|
||||
info.subresourceRange = vk::makeSubresourceRange(dstSubresources);
|
||||
|
||||
if ((m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &m_dstImageView)))
|
||||
throw DxvkError("DxvkMetaCopyViews: Failed to create destination image view");
|
||||
|
||||
// Create source image views
|
||||
usageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
|
||||
info.image = srcImage->handle();
|
||||
info.viewType = m_srcViewType;
|
||||
info.format = srcImage->info().format;
|
||||
info.subresourceRange = vk::makeSubresourceRange(srcSubresources);
|
||||
info.subresourceRange.aspectMask = srcAspects & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
|
||||
if ((m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &m_srcImageView)))
|
||||
throw DxvkError("DxvkMetaCopyViews: Failed to create source image view");
|
||||
|
||||
if (srcAspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
||||
info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
if ((m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &m_srcStencilView)))
|
||||
throw DxvkError("DxvkMetaCopyViews: Failed to create source stencil view");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxvkMetaCopyRenderPass::~DxvkMetaCopyRenderPass() {
|
||||
m_vkd->vkDestroyFramebuffer(m_vkd->device(), m_framebuffer, nullptr);
|
||||
m_vkd->vkDestroyRenderPass (m_vkd->device(), m_renderPass, nullptr);
|
||||
DxvkMetaCopyViews::~DxvkMetaCopyViews() {
|
||||
m_vkd->vkDestroyImageView(m_vkd->device(), m_dstImageView, nullptr);
|
||||
m_vkd->vkDestroyImageView(m_vkd->device(), m_srcImageView, nullptr);
|
||||
m_vkd->vkDestroyImageView(m_vkd->device(), m_srcStencilView, nullptr);
|
||||
}
|
||||
|
||||
|
||||
VkRenderPass DxvkMetaCopyRenderPass::createRenderPass(bool discard) const {
|
||||
auto aspect = m_dstImageView->info().aspect;
|
||||
|
||||
VkPipelineStageFlags cpyStages = 0;
|
||||
VkAccessFlags cpyAccess = 0;
|
||||
|
||||
VkAttachmentDescription attachment;
|
||||
attachment.flags = 0;
|
||||
attachment.format = m_dstImageView->info().format;
|
||||
attachment.samples = m_dstImageView->imageInfo().sampleCount;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.initialLayout = m_dstImageView->imageInfo().layout;
|
||||
attachment.finalLayout = m_dstImageView->imageInfo().layout;
|
||||
|
||||
if (discard) {
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
}
|
||||
|
||||
VkAttachmentReference attachmentRef;
|
||||
attachmentRef.attachment = 0;
|
||||
attachmentRef.layout = (aspect & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
? m_dstImageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
|
||||
: m_dstImageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
VkSubpassDescription subpass;
|
||||
subpass.flags = 0;
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.inputAttachmentCount = 0;
|
||||
subpass.pInputAttachments = nullptr;
|
||||
subpass.colorAttachmentCount = 0;
|
||||
subpass.pColorAttachments = nullptr;
|
||||
subpass.pResolveAttachments = nullptr;
|
||||
subpass.pDepthStencilAttachment = nullptr;
|
||||
subpass.preserveAttachmentCount = 0;
|
||||
subpass.pPreserveAttachments = nullptr;
|
||||
|
||||
if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &attachmentRef;
|
||||
|
||||
cpyStages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
cpyAccess |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
if (!discard)
|
||||
cpyAccess |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
|
||||
} else {
|
||||
subpass.pDepthStencilAttachment = &attachmentRef;
|
||||
|
||||
cpyStages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
||||
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
cpyAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
if (!discard)
|
||||
cpyAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
|
||||
}
|
||||
|
||||
// We have to be somewhat conservative here since we cannot assume
|
||||
// that the backend blocks stages that are only used for meta ops
|
||||
VkPipelineStageFlags extStages = m_dstImageView->imageInfo().stages | m_srcImageView->imageInfo().stages;
|
||||
VkAccessFlags extAccess = m_dstImageView->imageInfo().access;
|
||||
|
||||
std::array<VkSubpassDependency, 2> dependencies = {{
|
||||
{ VK_SUBPASS_EXTERNAL, 0, extStages, cpyStages, 0, cpyAccess, 0 },
|
||||
{ 0, VK_SUBPASS_EXTERNAL, cpyStages, extStages, cpyAccess, extAccess, 0 },
|
||||
}};
|
||||
|
||||
VkRenderPassCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
info.attachmentCount = 1;
|
||||
info.pAttachments = &attachment;
|
||||
info.subpassCount = 1;
|
||||
info.pSubpasses = &subpass;
|
||||
info.dependencyCount = dependencies.size();
|
||||
info.pDependencies = dependencies.data();
|
||||
|
||||
VkRenderPass result = VK_NULL_HANDLE;
|
||||
if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkMetaCopyRenderPass: Failed to create render pass");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
VkFramebuffer DxvkMetaCopyRenderPass::createFramebuffer() const {
|
||||
VkImageView dstViewHandle = m_dstImageView->handle();
|
||||
VkImageSubresourceRange dstSubresources = m_dstImageView->subresources();
|
||||
VkExtent3D dstExtent = m_dstImageView->mipLevelExtent(0);
|
||||
|
||||
VkFramebufferCreateInfo fboInfo;
|
||||
fboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
fboInfo.pNext = nullptr;
|
||||
fboInfo.flags = 0;
|
||||
fboInfo.renderPass = m_renderPass;
|
||||
fboInfo.attachmentCount = 1;
|
||||
fboInfo.pAttachments = &dstViewHandle;
|
||||
fboInfo.width = dstExtent.width;
|
||||
fboInfo.height = dstExtent.height;
|
||||
fboInfo.layers = dstSubresources.layerCount;
|
||||
|
||||
VkFramebuffer result = VK_NULL_HANDLE;
|
||||
if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &fboInfo, nullptr, &result) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkMetaCopyRenderPass: Failed to create target framebuffer");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DxvkMetaCopyObjects::DxvkMetaCopyObjects(const DxvkDevice* device)
|
||||
: m_vkd (device->vkd()),
|
||||
m_sampler (createSampler()),
|
||||
m_color {
|
||||
createShaderModule(dxvk_copy_color_1d),
|
||||
createShaderModule(dxvk_copy_color_2d),
|
||||
@ -188,7 +113,6 @@ namespace dxvk {
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), pair.second.pipeHandle, nullptr);
|
||||
m_vkd->vkDestroyPipelineLayout(m_vkd->device(), pair.second.pipeLayout, nullptr);
|
||||
m_vkd->vkDestroyDescriptorSetLayout (m_vkd->device(), pair.second.dsetLayout, nullptr);
|
||||
m_vkd->vkDestroyRenderPass(m_vkd->device(), pair.second.renderPass, nullptr);
|
||||
}
|
||||
|
||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.fragMs, nullptr);
|
||||
@ -202,8 +126,6 @@ namespace dxvk {
|
||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.frag1D, nullptr);
|
||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderGeom, nullptr);
|
||||
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderVert, nullptr);
|
||||
|
||||
m_vkd->vkDestroySampler(m_vkd->device(), m_sampler, nullptr);
|
||||
}
|
||||
|
||||
|
||||
@ -267,34 +189,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
VkSampler DxvkMetaCopyObjects::createSampler() const {
|
||||
VkSamplerCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
info.magFilter = VK_FILTER_NEAREST;
|
||||
info.minFilter = VK_FILTER_NEAREST;
|
||||
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
info.mipLodBias = 0.0f;
|
||||
info.anisotropyEnable = VK_FALSE;
|
||||
info.maxAnisotropy = 1.0f;
|
||||
info.compareEnable = VK_FALSE;
|
||||
info.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
info.minLod = 0.0f;
|
||||
info.maxLod = 0.0f;
|
||||
info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
info.unnormalizedCoordinates = VK_FALSE;
|
||||
|
||||
VkSampler result = VK_NULL_HANDLE;
|
||||
if (m_vkd->vkCreateSampler(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkMetaCopyObjects: Failed to create sampler");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
VkShaderModule DxvkMetaCopyObjects::createShaderModule(
|
||||
const SpirvCodeBuffer& code) const {
|
||||
VkShaderModuleCreateInfo info;
|
||||
@ -313,17 +207,13 @@ namespace dxvk {
|
||||
|
||||
DxvkMetaCopyPipeline DxvkMetaCopyObjects::createCopyBufferImagePipeline() {
|
||||
DxvkMetaCopyPipeline pipeline;
|
||||
pipeline.renderPass = VK_NULL_HANDLE;
|
||||
|
||||
std::array<VkDescriptorSetLayoutBinding, 2> bindings = {{
|
||||
{ 0, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr },
|
||||
}};
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo setLayoutInfo;
|
||||
setLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
setLayoutInfo.pNext = nullptr;
|
||||
setLayoutInfo.flags = 0;
|
||||
VkDescriptorSetLayoutCreateInfo setLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||
setLayoutInfo.bindingCount = bindings.size();
|
||||
setLayoutInfo.pBindings = bindings.data();
|
||||
|
||||
@ -332,10 +222,7 @@ namespace dxvk {
|
||||
|
||||
VkPushConstantRange pushRange = { VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(DxvkCopyBufferImageArgs) };
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo;
|
||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayoutInfo.pNext = nullptr;
|
||||
pipelineLayoutInfo.flags = 0;
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
pipelineLayoutInfo.setLayoutCount = 1;
|
||||
pipelineLayoutInfo.pSetLayouts = &pipeline.dsetLayout;
|
||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
||||
@ -346,19 +233,12 @@ namespace dxvk {
|
||||
|
||||
VkShaderModule shaderModule = createShaderModule(dxvk_copy_buffer_image);
|
||||
|
||||
VkComputePipelineCreateInfo pipelineInfo;
|
||||
pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||
pipelineInfo.pNext = nullptr;
|
||||
pipelineInfo.flags = 0;
|
||||
VkComputePipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
|
||||
pipelineInfo.layout = pipeline.pipeLayout;
|
||||
pipelineInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
pipelineInfo.stage.pNext = nullptr;
|
||||
pipelineInfo.stage.flags = 0;
|
||||
pipelineInfo.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
pipelineInfo.stage.module = shaderModule;
|
||||
pipelineInfo.stage.pName = "main";
|
||||
pipelineInfo.stage.pSpecializationInfo = nullptr;
|
||||
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||
pipelineInfo.basePipelineIndex = -1;
|
||||
|
||||
if (m_vkd->vkCreateComputePipelines(m_vkd->device(), VK_NULL_HANDLE,
|
||||
@ -373,96 +253,24 @@ namespace dxvk {
|
||||
DxvkMetaCopyPipeline DxvkMetaCopyObjects::createPipeline(
|
||||
const DxvkMetaCopyPipelineKey& key) {
|
||||
DxvkMetaCopyPipeline pipeline;
|
||||
pipeline.renderPass = this->createRenderPass(key);
|
||||
pipeline.dsetLayout = this->createDescriptorSetLayout(key);
|
||||
pipeline.pipeLayout = this->createPipelineLayout(pipeline.dsetLayout);
|
||||
pipeline.pipeHandle = this->createPipelineObject(key, pipeline.pipeLayout, pipeline.renderPass);
|
||||
pipeline.pipeHandle = this->createPipelineObject(key, pipeline.pipeLayout);
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
|
||||
VkRenderPass DxvkMetaCopyObjects::createRenderPass(
|
||||
const DxvkMetaCopyPipelineKey& key) const {
|
||||
auto aspect = imageFormatInfo(key.format)->aspectMask;
|
||||
|
||||
VkAttachmentDescription attachment;
|
||||
attachment.flags = 0;
|
||||
attachment.format = key.format;
|
||||
attachment.samples = key.samples;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
attachment.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
VkAttachmentReference attachmentRef;
|
||||
attachmentRef.attachment = 0;
|
||||
attachmentRef.layout = (aspect & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
||||
: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkSubpassDescription subpass;
|
||||
subpass.flags = 0;
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.inputAttachmentCount = 0;
|
||||
subpass.pInputAttachments = nullptr;
|
||||
subpass.colorAttachmentCount = 0;
|
||||
subpass.pColorAttachments = nullptr;
|
||||
subpass.pResolveAttachments = nullptr;
|
||||
subpass.pDepthStencilAttachment = nullptr;
|
||||
subpass.preserveAttachmentCount = 0;
|
||||
subpass.pPreserveAttachments = nullptr;
|
||||
|
||||
if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &attachmentRef;
|
||||
} else {
|
||||
subpass.pDepthStencilAttachment = &attachmentRef;
|
||||
}
|
||||
|
||||
VkRenderPassCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
info.attachmentCount = 1;
|
||||
info.pAttachments = &attachment;
|
||||
info.subpassCount = 1;
|
||||
info.pSubpasses = &subpass;
|
||||
info.dependencyCount = 0;
|
||||
info.pDependencies = nullptr;
|
||||
|
||||
VkRenderPass result = VK_NULL_HANDLE;
|
||||
if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkMetaCopyObjects: Failed to create render pass");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
VkDescriptorSetLayout DxvkMetaCopyObjects::createDescriptorSetLayout(
|
||||
const DxvkMetaCopyPipelineKey& key) const {
|
||||
std::array<VkDescriptorSetLayoutBinding, 2> bindings;
|
||||
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
bindings[i].binding = i;
|
||||
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[i].descriptorCount = 1;
|
||||
bindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[i].pImmutableSamplers = &m_sampler;
|
||||
}
|
||||
std::array<VkDescriptorSetLayoutBinding, 2> bindings = {{
|
||||
{ 0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT },
|
||||
}};
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
info.bindingCount = 1;
|
||||
info.pBindings = bindings.data();
|
||||
VkDescriptorSetLayoutCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||
info.bindingCount = bindings.size();
|
||||
info.pBindings = bindings.data();
|
||||
|
||||
auto format = imageFormatInfo(key.format);
|
||||
|
||||
if (format->aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
info.bindingCount = 2;
|
||||
|
||||
VkDescriptorSetLayout result = VK_NULL_HANDLE;
|
||||
if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkMetaCopyObjects: Failed to create descriptor set layout");
|
||||
@ -472,15 +280,9 @@ namespace dxvk {
|
||||
|
||||
VkPipelineLayout DxvkMetaCopyObjects::createPipelineLayout(
|
||||
VkDescriptorSetLayout descriptorSetLayout) const {
|
||||
VkPushConstantRange push;
|
||||
push.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
push.offset = 0;
|
||||
push.size = sizeof(VkOffset2D);
|
||||
VkPushConstantRange push = { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(VkOffset2D) };
|
||||
|
||||
VkPipelineLayoutCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
VkPipelineLayoutCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
info.setLayoutCount = 1;
|
||||
info.pSetLayouts = &descriptorSetLayout;
|
||||
info.pushConstantRangeCount = 1;
|
||||
@ -495,42 +297,22 @@ namespace dxvk {
|
||||
|
||||
VkPipeline DxvkMetaCopyObjects::createPipelineObject(
|
||||
const DxvkMetaCopyPipelineKey& key,
|
||||
VkPipelineLayout pipelineLayout,
|
||||
VkRenderPass renderPass) {
|
||||
VkPipelineLayout pipelineLayout) {
|
||||
auto aspect = imageFormatInfo(key.format)->aspectMask;
|
||||
|
||||
std::array<VkPipelineShaderStageCreateInfo, 3> stages;
|
||||
uint32_t stageCount = 0;
|
||||
|
||||
VkPipelineShaderStageCreateInfo& vsStage = stages[stageCount++];
|
||||
vsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
vsStage.pNext = nullptr;
|
||||
vsStage.flags = 0;
|
||||
vsStage.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
vsStage.module = m_shaderVert;
|
||||
vsStage.pName = "main";
|
||||
vsStage.pSpecializationInfo = nullptr;
|
||||
stages[stageCount++] = VkPipelineShaderStageCreateInfo {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0,
|
||||
VK_SHADER_STAGE_VERTEX_BIT, m_shaderVert, "main" };
|
||||
|
||||
if (m_shaderGeom) {
|
||||
VkPipelineShaderStageCreateInfo& gsStage = stages[stageCount++];
|
||||
gsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
gsStage.pNext = nullptr;
|
||||
gsStage.flags = 0;
|
||||
gsStage.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||
gsStage.module = m_shaderGeom;
|
||||
gsStage.pName = "main";
|
||||
gsStage.pSpecializationInfo = nullptr;
|
||||
stages[stageCount++] = VkPipelineShaderStageCreateInfo {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0,
|
||||
VK_SHADER_STAGE_GEOMETRY_BIT, m_shaderGeom, "main" };
|
||||
}
|
||||
|
||||
VkPipelineShaderStageCreateInfo& psStage = stages[stageCount++];
|
||||
psStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
psStage.pNext = nullptr;
|
||||
psStage.flags = 0;
|
||||
psStage.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
psStage.module = VK_NULL_HANDLE;
|
||||
psStage.pName = "main";
|
||||
psStage.pSpecializationInfo = nullptr;
|
||||
|
||||
std::array<std::pair<const FragShaders*, VkImageAspectFlags>, 3> shaderSets = {{
|
||||
{ &m_color, VK_IMAGE_ASPECT_COLOR_BIT },
|
||||
{ &m_depth, VK_IMAGE_ASPECT_DEPTH_BIT },
|
||||
@ -545,135 +327,95 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
if (!shaderSet)
|
||||
throw DxvkError("DxvkMetaCopyObjects: Unsupported aspect mask");
|
||||
throw DxvkError(str::format("DxvkMetaCopyObjects: Unsupported aspect mask: ", aspect));
|
||||
|
||||
VkShaderModule psModule = VK_NULL_HANDLE;
|
||||
|
||||
if (key.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
|
||||
psStage.module = shaderSet->frag1D;
|
||||
psModule = shaderSet->frag1D;
|
||||
else if (key.samples == VK_SAMPLE_COUNT_1_BIT)
|
||||
psStage.module = shaderSet->frag2D;
|
||||
psModule = shaderSet->frag2D;
|
||||
else
|
||||
psStage.module = shaderSet->fragMs;
|
||||
psModule = shaderSet->fragMs;
|
||||
|
||||
stages[stageCount++] = VkPipelineShaderStageCreateInfo {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, psModule, "main" };
|
||||
|
||||
std::array<VkDynamicState, 2> dynStates = {{
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR,
|
||||
}};
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dynState;
|
||||
dynState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
dynState.pNext = nullptr;
|
||||
dynState.flags = 0;
|
||||
dynState.dynamicStateCount = dynStates.size();
|
||||
dynState.pDynamicStates = dynStates.data();
|
||||
VkPipelineDynamicStateCreateInfo dynState = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
|
||||
dynState.dynamicStateCount = dynStates.size();
|
||||
dynState.pDynamicStates = dynStates.data();
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo viState;
|
||||
viState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
viState.pNext = nullptr;
|
||||
viState.flags = 0;
|
||||
viState.vertexBindingDescriptionCount = 0;
|
||||
viState.pVertexBindingDescriptions = nullptr;
|
||||
viState.vertexAttributeDescriptionCount = 0;
|
||||
viState.pVertexAttributeDescriptions = nullptr;
|
||||
VkPipelineVertexInputStateCreateInfo viState = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo iaState;
|
||||
iaState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
iaState.pNext = nullptr;
|
||||
iaState.flags = 0;
|
||||
iaState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
iaState.primitiveRestartEnable = VK_FALSE;
|
||||
VkPipelineInputAssemblyStateCreateInfo iaState = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
||||
iaState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
|
||||
VkPipelineViewportStateCreateInfo vpState;
|
||||
vpState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
vpState.pNext = nullptr;
|
||||
vpState.flags = 0;
|
||||
vpState.viewportCount = 1;
|
||||
vpState.pViewports = nullptr;
|
||||
vpState.scissorCount = 1;
|
||||
vpState.pScissors = nullptr;
|
||||
VkPipelineViewportStateCreateInfo vpState = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
|
||||
vpState.viewportCount = 1;
|
||||
vpState.scissorCount = 1;
|
||||
|
||||
VkPipelineRasterizationStateCreateInfo rsState;
|
||||
rsState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
rsState.pNext = nullptr;
|
||||
rsState.flags = 0;
|
||||
rsState.depthClampEnable = VK_TRUE;
|
||||
rsState.rasterizerDiscardEnable = VK_FALSE;
|
||||
rsState.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
rsState.cullMode = VK_CULL_MODE_NONE;
|
||||
rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
rsState.depthBiasEnable = VK_FALSE;
|
||||
rsState.depthBiasConstantFactor = 0.0f;
|
||||
rsState.depthBiasClamp = 0.0f;
|
||||
rsState.depthBiasSlopeFactor = 0.0f;
|
||||
rsState.lineWidth = 1.0f;
|
||||
VkPipelineRasterizationStateCreateInfo rsState = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
|
||||
rsState.depthClampEnable = VK_TRUE;
|
||||
rsState.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
rsState.cullMode = VK_CULL_MODE_NONE;
|
||||
rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
rsState.lineWidth = 1.0f;
|
||||
|
||||
uint32_t msMask = 0xFFFFFFFF;
|
||||
VkPipelineMultisampleStateCreateInfo msState;
|
||||
msState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
msState.pNext = nullptr;
|
||||
msState.flags = 0;
|
||||
msState.rasterizationSamples = key.samples;
|
||||
msState.sampleShadingEnable = key.samples != VK_SAMPLE_COUNT_1_BIT;
|
||||
msState.minSampleShading = 1.0f;
|
||||
msState.pSampleMask = &msMask;
|
||||
msState.alphaToCoverageEnable = VK_FALSE;
|
||||
msState.alphaToOneEnable = VK_FALSE;
|
||||
VkPipelineMultisampleStateCreateInfo msState = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
|
||||
msState.rasterizationSamples = key.samples;
|
||||
msState.sampleShadingEnable = key.samples != VK_SAMPLE_COUNT_1_BIT;
|
||||
msState.minSampleShading = 1.0f;
|
||||
msState.pSampleMask = &msMask;
|
||||
|
||||
VkPipelineColorBlendAttachmentState cbAttachment;
|
||||
cbAttachment.blendEnable = VK_FALSE;
|
||||
cbAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
cbAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
cbAttachment.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
cbAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
cbAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
cbAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
cbAttachment.colorWriteMask =
|
||||
VkPipelineColorBlendAttachmentState cbAttachment = { };
|
||||
cbAttachment.colorWriteMask =
|
||||
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo cbState;
|
||||
cbState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
cbState.pNext = nullptr;
|
||||
cbState.flags = 0;
|
||||
cbState.logicOpEnable = VK_FALSE;
|
||||
cbState.logicOp = VK_LOGIC_OP_NO_OP;
|
||||
cbState.attachmentCount = 1;
|
||||
cbState.pAttachments = &cbAttachment;
|
||||
VkPipelineColorBlendStateCreateInfo cbState = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
|
||||
cbState.attachmentCount = 1;
|
||||
cbState.pAttachments = &cbAttachment;
|
||||
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
cbState.blendConstants[i] = 0.0f;
|
||||
VkStencilOpState stencilOp = { };
|
||||
stencilOp.failOp = VK_STENCIL_OP_REPLACE;
|
||||
stencilOp.passOp = VK_STENCIL_OP_REPLACE;
|
||||
stencilOp.depthFailOp = VK_STENCIL_OP_REPLACE;
|
||||
stencilOp.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
stencilOp.compareMask = 0xFFFFFFFF;
|
||||
stencilOp.writeMask = 0xFFFFFFFF;
|
||||
|
||||
VkStencilOpState stencilOp;
|
||||
stencilOp.failOp = VK_STENCIL_OP_REPLACE;
|
||||
stencilOp.passOp = VK_STENCIL_OP_REPLACE;
|
||||
stencilOp.depthFailOp = VK_STENCIL_OP_REPLACE;
|
||||
stencilOp.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
stencilOp.compareMask = 0xFFFFFFFF;
|
||||
stencilOp.writeMask = 0xFFFFFFFF;
|
||||
stencilOp.reference = 0;
|
||||
VkPipelineDepthStencilStateCreateInfo dsState = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
|
||||
dsState.depthTestEnable = VK_TRUE;
|
||||
dsState.depthWriteEnable = VK_TRUE;
|
||||
dsState.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||
dsState.stencilTestEnable = VK_TRUE;
|
||||
dsState.front = stencilOp;
|
||||
dsState.back = stencilOp;
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo dsState;
|
||||
dsState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||
dsState.pNext = nullptr;
|
||||
dsState.flags = 0;
|
||||
dsState.depthTestEnable = VK_TRUE;
|
||||
dsState.depthWriteEnable = VK_TRUE;
|
||||
dsState.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||
dsState.depthBoundsTestEnable = VK_FALSE;
|
||||
dsState.stencilTestEnable = VK_TRUE;
|
||||
dsState.front = stencilOp;
|
||||
dsState.back = stencilOp;
|
||||
dsState.minDepthBounds = 0.0f;
|
||||
dsState.maxDepthBounds = 1.0f;
|
||||
|
||||
VkGraphicsPipelineCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
VkPipelineRenderingCreateInfoKHR rtState = { VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR };
|
||||
|
||||
if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
rtState.colorAttachmentCount = 1;
|
||||
rtState.pColorAttachmentFormats = &key.format;
|
||||
} else {
|
||||
if (aspect & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||
rtState.depthAttachmentFormat = key.format;
|
||||
if (aspect & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
rtState.stencilAttachmentFormat = key.format;
|
||||
}
|
||||
|
||||
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &rtState };
|
||||
info.stageCount = stageCount;
|
||||
info.pStages = stages.data();
|
||||
info.pVertexInputState = &viState;
|
||||
info.pInputAssemblyState = &iaState;
|
||||
info.pTessellationState = nullptr;
|
||||
info.pViewportState = &vpState;
|
||||
info.pRasterizationState = &rsState;
|
||||
info.pMultisampleState = &msState;
|
||||
@ -681,9 +423,6 @@ namespace dxvk {
|
||||
info.pDepthStencilState = (aspect & VK_IMAGE_ASPECT_COLOR_BIT) ? nullptr : &dsState;
|
||||
info.pDynamicState = &dynState;
|
||||
info.layout = pipelineLayout;
|
||||
info.renderPass = renderPass;
|
||||
info.subpass = 0;
|
||||
info.basePipelineHandle = VK_NULL_HANDLE;
|
||||
info.basePipelineIndex = -1;
|
||||
|
||||
VkPipeline result = VK_NULL_HANDLE;
|
||||
|
@ -32,7 +32,6 @@ namespace dxvk {
|
||||
* that is used for fragment shader copies.
|
||||
*/
|
||||
struct DxvkMetaCopyPipeline {
|
||||
VkRenderPass renderPass;
|
||||
VkDescriptorSetLayout dsetLayout;
|
||||
VkPipelineLayout pipeLayout;
|
||||
VkPipeline pipeHandle;
|
||||
@ -63,46 +62,43 @@ namespace dxvk {
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Copy framebuffer and render pass
|
||||
* \brief Copy view objects
|
||||
*
|
||||
* Creates a framebuffer and render
|
||||
* pass object for an image view.
|
||||
* Creates and manages views used in a
|
||||
* framebuffer-based copy operations.
|
||||
*/
|
||||
class DxvkMetaCopyRenderPass : public DxvkResource {
|
||||
class DxvkMetaCopyViews : public DxvkResource {
|
||||
|
||||
public:
|
||||
|
||||
DxvkMetaCopyRenderPass(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkImageView>& dstImageView,
|
||||
const Rc<DxvkImageView>& srcImageView,
|
||||
const Rc<DxvkImageView>& srcStencilView,
|
||||
bool discardDst);
|
||||
DxvkMetaCopyViews(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const VkImageSubresourceLayers& dstSubresources,
|
||||
VkFormat dstFormat,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageSubresourceLayers& srcSubresources);
|
||||
|
||||
~DxvkMetaCopyRenderPass();
|
||||
~DxvkMetaCopyViews();
|
||||
|
||||
VkRenderPass renderPass() const {
|
||||
return m_renderPass;
|
||||
}
|
||||
VkImageView getDstView() const { return m_dstImageView; }
|
||||
VkImageView getSrcView() const { return m_srcImageView; }
|
||||
VkImageView getSrcStencilView() const { return m_srcStencilView; }
|
||||
|
||||
VkFramebuffer framebuffer() const {
|
||||
return m_framebuffer;
|
||||
VkImageViewType getSrcViewType() const {
|
||||
return m_srcViewType;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
|
||||
Rc<DxvkImageView> m_dstImageView;
|
||||
Rc<DxvkImageView> m_srcImageView;
|
||||
Rc<DxvkImageView> m_srcStencilView;
|
||||
|
||||
VkRenderPass m_renderPass = VK_NULL_HANDLE;
|
||||
VkFramebuffer m_framebuffer = VK_NULL_HANDLE;
|
||||
VkImageViewType m_srcViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
||||
VkImageViewType m_dstViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
||||
|
||||
VkRenderPass createRenderPass(bool discard) const;
|
||||
|
||||
VkFramebuffer createFramebuffer() const;
|
||||
VkImageView m_dstImageView = VK_NULL_HANDLE;
|
||||
VkImageView m_srcImageView = VK_NULL_HANDLE;
|
||||
VkImageView m_srcStencilView = VK_NULL_HANDLE;
|
||||
|
||||
};
|
||||
|
||||
@ -162,8 +158,6 @@ namespace dxvk {
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
|
||||
VkSampler m_sampler;
|
||||
|
||||
VkShaderModule m_shaderVert = VK_NULL_HANDLE;
|
||||
VkShaderModule m_shaderGeom = VK_NULL_HANDLE;
|
||||
|
||||
@ -180,8 +174,6 @@ namespace dxvk {
|
||||
|
||||
DxvkMetaCopyPipeline m_copyBufferImagePipeline = { };
|
||||
|
||||
VkSampler createSampler() const;
|
||||
|
||||
VkShaderModule createShaderModule(
|
||||
const SpirvCodeBuffer& code) const;
|
||||
|
||||
@ -190,9 +182,6 @@ namespace dxvk {
|
||||
DxvkMetaCopyPipeline createPipeline(
|
||||
const DxvkMetaCopyPipelineKey& key);
|
||||
|
||||
VkRenderPass createRenderPass(
|
||||
const DxvkMetaCopyPipelineKey& key) const;
|
||||
|
||||
VkDescriptorSetLayout createDescriptorSetLayout(
|
||||
const DxvkMetaCopyPipelineKey& key) const;
|
||||
|
||||
@ -201,8 +190,7 @@ namespace dxvk {
|
||||
|
||||
VkPipeline createPipelineObject(
|
||||
const DxvkMetaCopyPipelineKey& key,
|
||||
VkPipelineLayout pipelineLayout,
|
||||
VkRenderPass renderPass);
|
||||
VkPipelineLayout pipelineLayout);
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(set = 0, binding = 0)
|
||||
uniform sampler1DArray s_image;
|
||||
uniform texture1DArray s_image;
|
||||
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(set = 0, binding = 0)
|
||||
uniform sampler2DArray s_image;
|
||||
uniform texture2DArray s_image;
|
||||
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(set = 0, binding = 0)
|
||||
uniform sampler2DMSArray s_image;
|
||||
uniform texture2DMSArray s_image;
|
||||
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(set = 0, binding = 0)
|
||||
uniform sampler1DArray s_image;
|
||||
uniform texture1DArray s_image;
|
||||
|
||||
layout(push_constant)
|
||||
uniform u_info_t {
|
||||
|
@ -1,7 +1,9 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(set = 0, binding = 0)
|
||||
uniform sampler2DArray s_image;
|
||||
uniform texture2DArray s_image;
|
||||
|
||||
layout(push_constant)
|
||||
uniform u_info_t {
|
||||
|
@ -1,7 +1,9 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(set = 0, binding = 0)
|
||||
uniform sampler2DMSArray s_image;
|
||||
uniform texture2DMSArray s_image;
|
||||
|
||||
layout(push_constant)
|
||||
uniform u_info_t {
|
||||
|
@ -1,12 +1,13 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_ARB_shader_stencil_export : enable
|
||||
#extension GL_ARB_shader_stencil_export : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(set = 0, binding = 0)
|
||||
uniform sampler1DArray s_depth;
|
||||
uniform texture1DArray s_depth;
|
||||
|
||||
layout(set = 0, binding = 1)
|
||||
uniform usampler1DArray s_stencil;
|
||||
uniform utexture1DArray s_stencil;
|
||||
|
||||
layout(push_constant)
|
||||
uniform u_info_t {
|
||||
|
@ -1,12 +1,13 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_ARB_shader_stencil_export : enable
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(set = 0, binding = 0)
|
||||
uniform sampler2DArray s_depth;
|
||||
uniform texture2DArray s_depth;
|
||||
|
||||
layout(set = 0, binding = 1)
|
||||
uniform usampler2DArray s_stencil;
|
||||
uniform utexture2DArray s_stencil;
|
||||
|
||||
layout(push_constant)
|
||||
uniform u_info_t {
|
||||
|
@ -1,12 +1,13 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_ARB_shader_stencil_export : enable
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(set = 0, binding = 0)
|
||||
uniform sampler2DMSArray s_depth;
|
||||
uniform texture2DMSArray s_depth;
|
||||
|
||||
layout(set = 0, binding = 1)
|
||||
uniform usampler2DMSArray s_stencil;
|
||||
uniform utexture2DMSArray s_stencil;
|
||||
|
||||
layout(push_constant)
|
||||
uniform u_info_t {
|
||||
|
Loading…
x
Reference in New Issue
Block a user