mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-12 04:08:52 +01:00
[dxvk] Add pipelines for buffer-to-image and image-to-buffer copies
This commit is contained in:
parent
15d5b69d2c
commit
2fac69b7f9
@ -5,6 +5,13 @@
|
|||||||
#include <dxvk_fullscreen_vert.h>
|
#include <dxvk_fullscreen_vert.h>
|
||||||
#include <dxvk_fullscreen_layer_vert.h>
|
#include <dxvk_fullscreen_layer_vert.h>
|
||||||
|
|
||||||
|
#include <dxvk_buffer_to_image_d.h>
|
||||||
|
#include <dxvk_buffer_to_image_ds_export.h>
|
||||||
|
#include <dxvk_buffer_to_image_s_discard.h>
|
||||||
|
|
||||||
|
#include <dxvk_image_to_buffer_ds.h>
|
||||||
|
#include <dxvk_image_to_buffer_f.h>
|
||||||
|
|
||||||
#include <dxvk_copy_buffer_image.h>
|
#include <dxvk_copy_buffer_image.h>
|
||||||
#include <dxvk_copy_color_1d.h>
|
#include <dxvk_copy_color_1d.h>
|
||||||
#include <dxvk_copy_color_2d.h>
|
#include <dxvk_copy_color_2d.h>
|
||||||
@ -88,14 +95,41 @@ namespace dxvk {
|
|||||||
createShaderModule(dxvk_copy_depth_stencil_1d),
|
createShaderModule(dxvk_copy_depth_stencil_1d),
|
||||||
createShaderModule(dxvk_copy_depth_stencil_2d),
|
createShaderModule(dxvk_copy_depth_stencil_2d),
|
||||||
createShaderModule(dxvk_copy_depth_stencil_ms) };
|
createShaderModule(dxvk_copy_depth_stencil_ms) };
|
||||||
|
|
||||||
|
m_shaderBufferToImageDSExport = createShaderModule(dxvk_buffer_to_image_ds_export);
|
||||||
|
} else {
|
||||||
|
m_shaderBufferToImageD = createShaderModule(dxvk_buffer_to_image_d);
|
||||||
|
m_shaderBufferToImageS = createShaderModule(dxvk_buffer_to_image_s_discard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_shaderImageToBufferDS = createShaderModule(dxvk_image_to_buffer_ds);
|
||||||
|
m_shaderImageToBufferF = createShaderModule(dxvk_image_to_buffer_f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DxvkMetaCopyObjects::~DxvkMetaCopyObjects() {
|
DxvkMetaCopyObjects::~DxvkMetaCopyObjects() {
|
||||||
|
for (const auto& p : m_bufferToImagePipelines)
|
||||||
|
m_vkd->vkDestroyPipeline(m_vkd->device(), p.second, nullptr);
|
||||||
|
|
||||||
|
for (const auto& p : m_imageToBufferPipelines)
|
||||||
|
m_vkd->vkDestroyPipeline(m_vkd->device(), p.second, nullptr);
|
||||||
|
|
||||||
|
m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_bufferToImageCopySetLayout, nullptr);
|
||||||
|
m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_imageToBufferCopySetLayout, nullptr);
|
||||||
|
|
||||||
|
m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_bufferToImageCopyPipelineLayout, nullptr);
|
||||||
|
m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_imageToBufferCopyPipelineLayout, nullptr);
|
||||||
|
|
||||||
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderBufferToImageD, nullptr);
|
||||||
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderBufferToImageS, nullptr);
|
||||||
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderBufferToImageDSExport, nullptr);
|
||||||
|
|
||||||
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderImageToBufferF, nullptr);
|
||||||
|
m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderImageToBufferDS, nullptr);
|
||||||
|
|
||||||
|
m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_copyBufferImagePipeline.dsetLayout, nullptr);
|
||||||
m_vkd->vkDestroyPipeline(m_vkd->device(), m_copyBufferImagePipeline.pipeHandle, nullptr);
|
m_vkd->vkDestroyPipeline(m_vkd->device(), m_copyBufferImagePipeline.pipeHandle, nullptr);
|
||||||
m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_copyBufferImagePipeline.pipeLayout, nullptr);
|
m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_copyBufferImagePipeline.pipeLayout, nullptr);
|
||||||
m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_copyBufferImagePipeline.dsetLayout, nullptr);
|
|
||||||
|
|
||||||
for (const auto& pair : m_pipelines) {
|
for (const auto& pair : m_pipelines) {
|
||||||
m_vkd->vkDestroyPipeline(m_vkd->device(), pair.second.pipeHandle, nullptr);
|
m_vkd->vkDestroyPipeline(m_vkd->device(), pair.second.pipeHandle, nullptr);
|
||||||
@ -140,6 +174,70 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkMetaCopyPipeline DxvkMetaCopyObjects::getCopyBufferToImagePipeline(
|
||||||
|
VkImageViewType viewType,
|
||||||
|
VkFormat dstFormat,
|
||||||
|
VkFormat srcFormat,
|
||||||
|
VkImageAspectFlags aspects) {
|
||||||
|
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
DxvkMetaBufferImageCopyPipelineKey key;
|
||||||
|
key.imageViewType = viewType;
|
||||||
|
key.imageFormat = dstFormat;
|
||||||
|
key.bufferFormat = srcFormat;
|
||||||
|
key.imageAspects = aspects;
|
||||||
|
|
||||||
|
auto entry = m_bufferToImagePipelines.find(key);
|
||||||
|
if (entry != m_bufferToImagePipelines.end()) {
|
||||||
|
DxvkMetaCopyPipeline result = { };
|
||||||
|
result.dsetLayout = m_bufferToImageCopySetLayout;
|
||||||
|
result.pipeLayout = m_bufferToImageCopyPipelineLayout;
|
||||||
|
result.pipeHandle = entry->second;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipeline pipeline = createCopyBufferToImagePipeline(key);
|
||||||
|
m_bufferToImagePipelines.insert({ key, pipeline });
|
||||||
|
|
||||||
|
DxvkMetaCopyPipeline result = { };
|
||||||
|
result.dsetLayout = m_bufferToImageCopySetLayout;
|
||||||
|
result.pipeLayout = m_bufferToImageCopyPipelineLayout;
|
||||||
|
result.pipeHandle = pipeline;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkMetaCopyPipeline DxvkMetaCopyObjects::getCopyImageToBufferPipeline(
|
||||||
|
VkImageViewType viewType,
|
||||||
|
VkFormat dstFormat) {
|
||||||
|
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
DxvkMetaBufferImageCopyPipelineKey key;
|
||||||
|
key.imageViewType = viewType;
|
||||||
|
key.imageFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
key.bufferFormat = dstFormat;
|
||||||
|
key.imageAspects = lookupFormatInfo(dstFormat)->aspectMask;
|
||||||
|
|
||||||
|
auto entry = m_bufferToImagePipelines.find(key);
|
||||||
|
if (entry != m_bufferToImagePipelines.end()) {
|
||||||
|
DxvkMetaCopyPipeline result = { };
|
||||||
|
result.dsetLayout = m_imageToBufferCopySetLayout;
|
||||||
|
result.pipeLayout = m_imageToBufferCopyPipelineLayout;
|
||||||
|
result.pipeHandle = entry->second;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipeline pipeline = createCopyImageToBufferPipeline(key);
|
||||||
|
m_bufferToImagePipelines.insert({ key, pipeline });
|
||||||
|
|
||||||
|
DxvkMetaCopyPipeline result = { };
|
||||||
|
result.dsetLayout = m_imageToBufferCopySetLayout;
|
||||||
|
result.pipeLayout = m_imageToBufferCopyPipelineLayout;
|
||||||
|
result.pipeHandle = pipeline;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxvkMetaCopyPipeline DxvkMetaCopyObjects::getCopyImagePipeline(
|
DxvkMetaCopyPipeline DxvkMetaCopyObjects::getCopyImagePipeline(
|
||||||
VkImageViewType viewType,
|
VkImageViewType viewType,
|
||||||
VkFormat dstFormat,
|
VkFormat dstFormat,
|
||||||
@ -239,6 +337,263 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VkPipeline DxvkMetaCopyObjects::createCopyBufferToImagePipeline(
|
||||||
|
const DxvkMetaBufferImageCopyPipelineKey& key) {
|
||||||
|
if (!m_bufferToImageCopySetLayout) {
|
||||||
|
std::array<VkDescriptorSetLayoutBinding, 1> bindings = {{
|
||||||
|
{ 0, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT }
|
||||||
|
}};
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||||
|
info.bindingCount = bindings.size();
|
||||||
|
info.pBindings = bindings.data();
|
||||||
|
|
||||||
|
VkResult vr = m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(),
|
||||||
|
&info, nullptr, &m_bufferToImageCopySetLayout);
|
||||||
|
|
||||||
|
if (vr != VK_SUCCESS)
|
||||||
|
throw DxvkError(str::format("DxvkMetaCopyObjects: Failed to create descriptor set layout: ", vr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_bufferToImageCopyPipelineLayout) {
|
||||||
|
VkPushConstantRange pushConstants = { };
|
||||||
|
pushConstants.offset = 0;
|
||||||
|
pushConstants.size = sizeof(DxvkBufferImageCopyArgs);
|
||||||
|
pushConstants.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
|
||||||
|
VkPipelineLayoutCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||||
|
info.setLayoutCount = 1;
|
||||||
|
info.pSetLayouts = &m_bufferToImageCopySetLayout;
|
||||||
|
info.pushConstantRangeCount = 1;
|
||||||
|
info.pPushConstantRanges = &pushConstants;
|
||||||
|
|
||||||
|
VkResult vr = m_vkd->vkCreatePipelineLayout(m_vkd->device(),
|
||||||
|
&info, nullptr, &m_bufferToImageCopyPipelineLayout);
|
||||||
|
|
||||||
|
if (vr != VK_SUCCESS)
|
||||||
|
throw DxvkError(str::format("DxvkMetaCopyObjects: Failed to create pipeline layout: ", vr));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<VkPipelineShaderStageCreateInfo, 3> stages = { };
|
||||||
|
uint32_t stageCount = 0;
|
||||||
|
|
||||||
|
stages[stageCount++] = VkPipelineShaderStageCreateInfo {
|
||||||
|
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0,
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT, m_shaderVert, "main" };
|
||||||
|
|
||||||
|
if (m_shaderGeom) {
|
||||||
|
stages[stageCount++] = VkPipelineShaderStageCreateInfo {
|
||||||
|
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0,
|
||||||
|
VK_SHADER_STAGE_GEOMETRY_BIT, m_shaderGeom, "main" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't support color right now
|
||||||
|
if (!(key.imageAspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
|
||||||
|
Logger::err(str::format("DxvkMetaCopyObjects: Color images not unsupported"));
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSpecializationMapEntry specMap = { };
|
||||||
|
specMap.size = sizeof(VkFormat);
|
||||||
|
|
||||||
|
VkSpecializationInfo specInfo = { };
|
||||||
|
specInfo.mapEntryCount = 1;
|
||||||
|
specInfo.pMapEntries = &specMap;
|
||||||
|
specInfo.dataSize = sizeof(VkFormat);
|
||||||
|
specInfo.pData = &key.bufferFormat;
|
||||||
|
|
||||||
|
// Always use the DS export shader if possible, it can
|
||||||
|
// support writing to one aspect exclusively.
|
||||||
|
auto& stage = stages[stageCount++];
|
||||||
|
stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
|
stage.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
stage.module = m_shaderBufferToImageDSExport;
|
||||||
|
stage.pName = "main";
|
||||||
|
stage.pSpecializationInfo = &specInfo;
|
||||||
|
|
||||||
|
if (!m_shaderBufferToImageDSExport) {
|
||||||
|
stage.module = key.imageAspects == VK_IMAGE_ASPECT_STENCIL_BIT
|
||||||
|
? m_shaderBufferToImageS
|
||||||
|
: m_shaderBufferToImageD;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<VkDynamicState, 3> dynStates = {{
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT,
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT,
|
||||||
|
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
|
||||||
|
}};
|
||||||
|
|
||||||
|
VkPipelineDynamicStateCreateInfo dynState = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
|
||||||
|
dynState.dynamicStateCount = dynStates.size();
|
||||||
|
dynState.pDynamicStates = dynStates.data();
|
||||||
|
|
||||||
|
if (stage.module != m_shaderBufferToImageS)
|
||||||
|
dynState.dynamicStateCount -= 1;
|
||||||
|
|
||||||
|
VkPipelineVertexInputStateCreateInfo viState = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
||||||
|
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo iaState = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
||||||
|
iaState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
|
||||||
|
VkPipelineViewportStateCreateInfo vpState = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
|
||||||
|
|
||||||
|
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 = 0x1;
|
||||||
|
VkPipelineMultisampleStateCreateInfo msState = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
|
||||||
|
msState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
msState.pSampleMask = &msMask;
|
||||||
|
|
||||||
|
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 = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
|
||||||
|
cbState.attachmentCount = 1;
|
||||||
|
cbState.pAttachments = &cbAttachment;
|
||||||
|
|
||||||
|
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 = 0xff;
|
||||||
|
stencilOp.writeMask = 0xff;
|
||||||
|
stencilOp.reference = 0xff;
|
||||||
|
|
||||||
|
// Clear stencil for depth-only aspect
|
||||||
|
if (stage.module == m_shaderBufferToImageD)
|
||||||
|
stencilOp.reference = 0x00;
|
||||||
|
|
||||||
|
VkPipelineDepthStencilStateCreateInfo dsState = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
|
||||||
|
dsState.depthTestEnable = !!(key.imageAspects & VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||||
|
dsState.depthWriteEnable = dsState.depthTestEnable;
|
||||||
|
dsState.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
|
dsState.stencilTestEnable = !!(key.imageAspects & VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||||
|
dsState.front = stencilOp;
|
||||||
|
dsState.back = stencilOp;
|
||||||
|
|
||||||
|
VkPipelineRenderingCreateInfo rtState = { VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO };
|
||||||
|
|
||||||
|
if (key.imageAspects & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||||
|
rtState.colorAttachmentCount = 1;
|
||||||
|
rtState.pColorAttachmentFormats = &key.imageFormat;
|
||||||
|
} else {
|
||||||
|
auto formatAspects = lookupFormatInfo(key.imageFormat)->aspectMask;
|
||||||
|
|
||||||
|
if (formatAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||||
|
rtState.depthAttachmentFormat = key.imageFormat;
|
||||||
|
if (formatAspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||||
|
rtState.stencilAttachmentFormat = key.imageFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &rtState };
|
||||||
|
info.stageCount = stageCount;
|
||||||
|
info.pStages = stages.data();
|
||||||
|
info.pVertexInputState = &viState;
|
||||||
|
info.pInputAssemblyState = &iaState;
|
||||||
|
info.pViewportState = &vpState;
|
||||||
|
info.pRasterizationState = &rsState;
|
||||||
|
info.pMultisampleState = &msState;
|
||||||
|
info.pColorBlendState = (key.imageAspects & VK_IMAGE_ASPECT_COLOR_BIT) ? &cbState : nullptr;
|
||||||
|
info.pDepthStencilState = (key.imageAspects & VK_IMAGE_ASPECT_COLOR_BIT) ? nullptr : &dsState;
|
||||||
|
info.pDynamicState = &dynState;
|
||||||
|
info.layout = m_bufferToImageCopyPipelineLayout;
|
||||||
|
info.basePipelineIndex = -1;
|
||||||
|
|
||||||
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
|
VkResult vr = m_vkd->vkCreateGraphicsPipelines(m_vkd->device(),
|
||||||
|
VK_NULL_HANDLE, 1, &info, nullptr, &pipeline);
|
||||||
|
|
||||||
|
if (vr != VK_SUCCESS)
|
||||||
|
throw DxvkError(str::format("DxvkMetaCopyObjects: Failed to create graphics pipeline: ", vr));
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VkPipeline DxvkMetaCopyObjects::createCopyImageToBufferPipeline(
|
||||||
|
const DxvkMetaBufferImageCopyPipelineKey& key) {
|
||||||
|
if (!m_imageToBufferCopySetLayout) {
|
||||||
|
std::array<VkDescriptorSetLayoutBinding, 3> bindings = {{
|
||||||
|
{ 0, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
|
||||||
|
{ 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT },
|
||||||
|
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT },
|
||||||
|
}};
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||||
|
info.bindingCount = bindings.size();
|
||||||
|
info.pBindings = bindings.data();
|
||||||
|
|
||||||
|
VkResult vr = m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(),
|
||||||
|
&info, nullptr, &m_imageToBufferCopySetLayout);
|
||||||
|
|
||||||
|
if (vr != VK_SUCCESS)
|
||||||
|
throw DxvkError(str::format("DxvkMetaCopyObjects: Failed to create descriptor set layout: ", vr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_imageToBufferCopyPipelineLayout) {
|
||||||
|
VkPushConstantRange pushConstants = { };
|
||||||
|
pushConstants.offset = 0;
|
||||||
|
pushConstants.size = sizeof(DxvkBufferImageCopyArgs);
|
||||||
|
pushConstants.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
|
|
||||||
|
VkPipelineLayoutCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||||
|
info.setLayoutCount = 1;
|
||||||
|
info.pSetLayouts = &m_imageToBufferCopySetLayout;
|
||||||
|
info.pushConstantRangeCount = 1;
|
||||||
|
info.pPushConstantRanges = &pushConstants;
|
||||||
|
|
||||||
|
VkResult vr = m_vkd->vkCreatePipelineLayout(m_vkd->device(),
|
||||||
|
&info, nullptr, &m_imageToBufferCopyPipelineLayout);
|
||||||
|
|
||||||
|
if (vr != VK_SUCCESS)
|
||||||
|
throw DxvkError(str::format("DxvkMetaCopyObjects: Failed to create pipeline layout: ", vr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.imageViewType != VK_IMAGE_VIEW_TYPE_2D_ARRAY) {
|
||||||
|
Logger::err(str::format("DxvkMetaCopyObjects: Unsupported view type: ", key.imageViewType));
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSpecializationMapEntry specMap = { };
|
||||||
|
specMap.size = sizeof(VkFormat);
|
||||||
|
|
||||||
|
VkSpecializationInfo specInfo = { };
|
||||||
|
specInfo.mapEntryCount = 1;
|
||||||
|
specInfo.pMapEntries = &specMap;
|
||||||
|
specInfo.dataSize = sizeof(VkFormat);
|
||||||
|
specInfo.pData = &key.bufferFormat;
|
||||||
|
|
||||||
|
VkComputePipelineCreateInfo info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
|
||||||
|
info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
|
info.stage.pName = "main";
|
||||||
|
info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
|
info.stage.pSpecializationInfo = &specInfo;
|
||||||
|
info.layout = m_imageToBufferCopyPipelineLayout;
|
||||||
|
info.basePipelineIndex = -1;
|
||||||
|
|
||||||
|
info.stage.module = key.imageAspects & VK_IMAGE_ASPECT_STENCIL_BIT
|
||||||
|
? m_shaderImageToBufferDS
|
||||||
|
: m_shaderImageToBufferF;
|
||||||
|
|
||||||
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
|
VkResult vr = m_vkd->vkCreateComputePipelines(m_vkd->device(),
|
||||||
|
VK_NULL_HANDLE, 1, &info, nullptr, &pipeline);
|
||||||
|
|
||||||
|
if (vr != VK_SUCCESS)
|
||||||
|
throw DxvkError(str::format("DxvkMetaCopyObjects: Failed to create compute pipeline", vr));
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VkDescriptorSetLayout DxvkMetaCopyObjects::createDescriptorSetLayout(
|
VkDescriptorSetLayout DxvkMetaCopyObjects::createDescriptorSetLayout(
|
||||||
const DxvkMetaCopyPipelineKey& key) const {
|
const DxvkMetaCopyPipelineKey& key) const {
|
||||||
std::array<VkDescriptorSetLayoutBinding, 2> bindings = {{
|
std::array<VkDescriptorSetLayoutBinding, 2> bindings = {{
|
||||||
|
@ -15,7 +15,7 @@ namespace dxvk {
|
|||||||
class DxvkDevice;
|
class DxvkDevice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Push constants for buffer image copies
|
* \brief Push constants for formatted buffer copies
|
||||||
*/
|
*/
|
||||||
struct DxvkFormattedBufferCopyArgs {
|
struct DxvkFormattedBufferCopyArgs {
|
||||||
VkOffset3D dstOffset; uint32_t pad0;
|
VkOffset3D dstOffset; uint32_t pad0;
|
||||||
@ -45,6 +45,19 @@ namespace dxvk {
|
|||||||
VkPipeline pipeHandle = VK_NULL_HANDLE;
|
VkPipeline pipeHandle = VK_NULL_HANDLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Push constants for buffer <-> image copies
|
||||||
|
*/
|
||||||
|
struct DxvkBufferImageCopyArgs {
|
||||||
|
VkOffset3D imageOffset;
|
||||||
|
uint32_t bufferOffset;
|
||||||
|
VkExtent3D imageExtent;
|
||||||
|
uint32_t bufferImageWidth;
|
||||||
|
uint32_t bufferImageHeight;
|
||||||
|
uint32_t stencilBitIndex;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Copy pipeline key
|
* \brief Copy pipeline key
|
||||||
*
|
*
|
||||||
@ -52,9 +65,9 @@ namespace dxvk {
|
|||||||
* on the copy operation they support.
|
* on the copy operation they support.
|
||||||
*/
|
*/
|
||||||
struct DxvkMetaCopyPipelineKey {
|
struct DxvkMetaCopyPipelineKey {
|
||||||
VkImageViewType viewType;
|
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
||||||
VkFormat format;
|
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||||
VkSampleCountFlagBits samples;
|
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
|
||||||
|
|
||||||
bool eq(const DxvkMetaCopyPipelineKey& other) const {
|
bool eq(const DxvkMetaCopyPipelineKey& other) const {
|
||||||
return this->viewType == other.viewType
|
return this->viewType == other.viewType
|
||||||
@ -69,6 +82,31 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Buffer to image copy pipeline key
|
||||||
|
*/
|
||||||
|
struct DxvkMetaBufferImageCopyPipelineKey {
|
||||||
|
VkImageViewType imageViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
||||||
|
VkFormat imageFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
VkFormat bufferFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
VkImageAspectFlags imageAspects = 0u;
|
||||||
|
|
||||||
|
bool eq(const DxvkMetaBufferImageCopyPipelineKey& other) const {
|
||||||
|
return this->imageViewType == other.imageViewType
|
||||||
|
&& this->imageFormat == other.imageFormat
|
||||||
|
&& this->imageAspects == other.imageAspects
|
||||||
|
&& this->bufferFormat == other.bufferFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hash() const {
|
||||||
|
return (uint32_t(imageViewType))
|
||||||
|
^ (uint32_t(imageAspects) << 4)
|
||||||
|
^ (uint32_t(imageFormat) << 8)
|
||||||
|
^ (uint32_t(bufferFormat) << 16);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Copy view objects
|
* \brief Copy view objects
|
||||||
*
|
*
|
||||||
@ -126,6 +164,33 @@ namespace dxvk {
|
|||||||
VkFormat srcFormat,
|
VkFormat srcFormat,
|
||||||
VkImageAspectFlags srcAspect) const;
|
VkImageAspectFlags srcAspect) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Creates pipeline for buffer to image copy
|
||||||
|
*
|
||||||
|
* Note that setting both depth and stencil aspects
|
||||||
|
* requires device support for depth-stencil export.
|
||||||
|
* \param [in] viewType Image view type
|
||||||
|
* \param [in] dstFormat Destionation image format
|
||||||
|
* \param [in] srcFormat Source buffer data format
|
||||||
|
* \param [in] aspects Aspect mask to copy
|
||||||
|
*/
|
||||||
|
DxvkMetaCopyPipeline getCopyBufferToImagePipeline(
|
||||||
|
VkImageViewType viewType,
|
||||||
|
VkFormat dstFormat,
|
||||||
|
VkFormat srcFormat,
|
||||||
|
VkImageAspectFlags aspects);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Creates pipeline for image to buffer copy
|
||||||
|
*
|
||||||
|
* This method always returns a compute pipeline.
|
||||||
|
* \param [in] viewType Image view type
|
||||||
|
* \param [in] dstFormat Destionation buffer format
|
||||||
|
*/
|
||||||
|
DxvkMetaCopyPipeline getCopyImageToBufferPipeline(
|
||||||
|
VkImageViewType viewType,
|
||||||
|
VkFormat dstFormat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates pipeline for meta copy operation
|
* \brief Creates pipeline for meta copy operation
|
||||||
*
|
*
|
||||||
@ -158,6 +223,19 @@ namespace dxvk {
|
|||||||
VkShaderModule m_shaderVert = VK_NULL_HANDLE;
|
VkShaderModule m_shaderVert = VK_NULL_HANDLE;
|
||||||
VkShaderModule m_shaderGeom = VK_NULL_HANDLE;
|
VkShaderModule m_shaderGeom = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkDescriptorSetLayout m_bufferToImageCopySetLayout = VK_NULL_HANDLE;
|
||||||
|
VkPipelineLayout m_bufferToImageCopyPipelineLayout = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkShaderModule m_shaderBufferToImageD = VK_NULL_HANDLE;
|
||||||
|
VkShaderModule m_shaderBufferToImageS = VK_NULL_HANDLE;
|
||||||
|
VkShaderModule m_shaderBufferToImageDSExport = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkDescriptorSetLayout m_imageToBufferCopySetLayout = VK_NULL_HANDLE;
|
||||||
|
VkPipelineLayout m_imageToBufferCopyPipelineLayout = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkShaderModule m_shaderImageToBufferF = VK_NULL_HANDLE;
|
||||||
|
VkShaderModule m_shaderImageToBufferDS = VK_NULL_HANDLE;
|
||||||
|
|
||||||
FragShaders m_color;
|
FragShaders m_color;
|
||||||
FragShaders m_depth;
|
FragShaders m_depth;
|
||||||
FragShaders m_depthStencil;
|
FragShaders m_depthStencil;
|
||||||
@ -169,6 +247,12 @@ namespace dxvk {
|
|||||||
DxvkMetaCopyPipeline,
|
DxvkMetaCopyPipeline,
|
||||||
DxvkHash, DxvkEq> m_pipelines;
|
DxvkHash, DxvkEq> m_pipelines;
|
||||||
|
|
||||||
|
std::unordered_map<DxvkMetaBufferImageCopyPipelineKey,
|
||||||
|
VkPipeline, DxvkHash, DxvkEq> m_bufferToImagePipelines;
|
||||||
|
|
||||||
|
std::unordered_map<DxvkMetaBufferImageCopyPipelineKey,
|
||||||
|
VkPipeline, DxvkHash, DxvkEq> m_imageToBufferPipelines;
|
||||||
|
|
||||||
DxvkMetaCopyPipeline m_copyBufferImagePipeline = { };
|
DxvkMetaCopyPipeline m_copyBufferImagePipeline = { };
|
||||||
|
|
||||||
VkShaderModule createShaderModule(
|
VkShaderModule createShaderModule(
|
||||||
@ -179,6 +263,12 @@ namespace dxvk {
|
|||||||
DxvkMetaCopyPipeline createPipeline(
|
DxvkMetaCopyPipeline createPipeline(
|
||||||
const DxvkMetaCopyPipelineKey& key);
|
const DxvkMetaCopyPipelineKey& key);
|
||||||
|
|
||||||
|
VkPipeline createCopyBufferToImagePipeline(
|
||||||
|
const DxvkMetaBufferImageCopyPipelineKey& key);
|
||||||
|
|
||||||
|
VkPipeline createCopyImageToBufferPipeline(
|
||||||
|
const DxvkMetaBufferImageCopyPipelineKey& key);
|
||||||
|
|
||||||
VkDescriptorSetLayout createDescriptorSetLayout(
|
VkDescriptorSetLayout createDescriptorSetLayout(
|
||||||
const DxvkMetaCopyPipelineKey& key) const;
|
const DxvkMetaCopyPipelineKey& key) const;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user