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

[dxvk] Add pipelines for buffer-to-image and image-to-buffer copies

This commit is contained in:
Philip Rebohle 2024-10-05 14:27:09 +02:00 committed by Philip Rebohle
parent 15d5b69d2c
commit 2fac69b7f9
2 changed files with 451 additions and 6 deletions

View File

@ -5,6 +5,13 @@
#include <dxvk_fullscreen_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_color_1d.h>
#include <dxvk_copy_color_2d.h>
@ -88,14 +95,41 @@ namespace dxvk {
createShaderModule(dxvk_copy_depth_stencil_1d),
createShaderModule(dxvk_copy_depth_stencil_2d),
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() {
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->vkDestroyPipelineLayout(m_vkd->device(), m_copyBufferImagePipeline.pipeLayout, nullptr);
m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_copyBufferImagePipeline.dsetLayout, nullptr);
for (const auto& pair : m_pipelines) {
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(
VkImageViewType viewType,
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(
const DxvkMetaCopyPipelineKey& key) const {
std::array<VkDescriptorSetLayoutBinding, 2> bindings = {{

View File

@ -15,7 +15,7 @@ namespace dxvk {
class DxvkDevice;
/**
* \brief Push constants for buffer image copies
* \brief Push constants for formatted buffer copies
*/
struct DxvkFormattedBufferCopyArgs {
VkOffset3D dstOffset; uint32_t pad0;
@ -45,6 +45,19 @@ namespace dxvk {
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
*
@ -52,9 +65,9 @@ namespace dxvk {
* on the copy operation they support.
*/
struct DxvkMetaCopyPipelineKey {
VkImageViewType viewType;
VkFormat format;
VkSampleCountFlagBits samples;
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
VkFormat format = VK_FORMAT_UNDEFINED;
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
bool eq(const DxvkMetaCopyPipelineKey& other) const {
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
*
@ -126,6 +164,33 @@ namespace dxvk {
VkFormat srcFormat,
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
*
@ -158,6 +223,19 @@ namespace dxvk {
VkShaderModule m_shaderVert = 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_depth;
FragShaders m_depthStencil;
@ -169,16 +247,28 @@ namespace dxvk {
DxvkMetaCopyPipeline,
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 = { };
VkShaderModule createShaderModule(
const SpirvCodeBuffer& code) const;
DxvkMetaCopyPipeline createCopyFormattedBufferPipeline();
DxvkMetaCopyPipeline createPipeline(
const DxvkMetaCopyPipelineKey& key);
VkPipeline createCopyBufferToImagePipeline(
const DxvkMetaBufferImageCopyPipelineKey& key);
VkPipeline createCopyImageToBufferPipeline(
const DxvkMetaBufferImageCopyPipelineKey& key);
VkDescriptorSetLayout createDescriptorSetLayout(
const DxvkMetaCopyPipelineKey& key) const;