Skip to content

Commit 64e42ea

Browse files
committed
[dxvk] Add built-in shaders for input attachment copies
1 parent faaaf5b commit 64e42ea

4 files changed

Lines changed: 276 additions & 6 deletions

File tree

src/dxvk/dxvk_meta_copy.cpp

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ namespace dxvk {
2222
};
2323

2424

25+
struct DxvkMetaInputAttachmentImageCopyPushArgs {
26+
ir::SsaDef srcOffset = { };
27+
ir::SsaDef dstOffset = { };
28+
ir::SsaDef srcLayer = { };
29+
ir::SsaDef dstLayer = { };
30+
};
31+
32+
2533
static DxvkMetaImageCopyPushArgs loadImageCopyPushArgs(ir::Builder& builder, DxvkBuiltInShader& helper) {
2634
ir::BasicType coordType(ir::ScalarType::eU32, 3u);
2735

@@ -34,6 +42,18 @@ namespace dxvk {
3442
}
3543

3644

45+
static DxvkMetaInputAttachmentImageCopyPushArgs loadInputAttachmentImageCopyPushArgs(ir::Builder& builder, DxvkBuiltInShader& helper) {
46+
ir::BasicType coordType(ir::ScalarType::eU32, 2u);
47+
48+
DxvkMetaInputAttachmentImageCopyPushArgs result = { };
49+
result.srcOffset = helper.declarePushData(builder, coordType, offsetof(DxvkMetaInputAttachmentImageCopy::Args, srcOffset), "src_offset");
50+
result.dstOffset = helper.declarePushData(builder, coordType, offsetof(DxvkMetaInputAttachmentImageCopy::Args, dstOffset), "dst_offset");
51+
result.srcLayer = helper.declarePushData(builder, ir::ScalarType::eU32, offsetof(DxvkMetaInputAttachmentImageCopy::Args, srcLayer), "src_layer");
52+
result.dstLayer = helper.declarePushData(builder, ir::ScalarType::eU32, offsetof(DxvkMetaInputAttachmentImageCopy::Args, dstLayer), "dst_layer");
53+
return result;
54+
}
55+
56+
3757
static DxvkMetaBufferToImageCopyPushArgs loadBufferToImageCopyPushArgs(ir::Builder& builder, DxvkBuiltInShader& helper) {
3858
ir::BasicType coordType2D(ir::ScalarType::eU32, 2u);
3959
ir::BasicType coordType3D(ir::ScalarType::eU32, 3u);
@@ -190,6 +210,19 @@ namespace dxvk {
190210
}
191211

192212

213+
DxvkMetaInputAttachmentImageCopy DxvkMetaCopyObjects::getPipeline(const DxvkMetaInputAttachmentImageCopy::Key& key) {
214+
std::lock_guard<dxvk::mutex> lock(m_mutex);
215+
216+
auto entry = m_inputAttachmentImageCopyPipelines.find(key);
217+
if (entry != m_inputAttachmentImageCopyPipelines.end())
218+
return entry->second;
219+
220+
DxvkMetaInputAttachmentImageCopy pipeline = createInputAttachmentCopyPipeline(key);
221+
m_inputAttachmentImageCopyPipelines.insert({ key, pipeline });
222+
return pipeline;
223+
}
224+
225+
193226
DxvkMetaBufferToImageCopy DxvkMetaCopyObjects::getPipeline(const DxvkMetaBufferToImageCopy::Key& key) {
194227
std::lock_guard<dxvk::mutex> lock(m_mutex);
195228

@@ -278,6 +311,25 @@ namespace dxvk {
278311
}
279312

280313

314+
std::vector<uint32_t> DxvkMetaCopyObjects::createVsCopyInputAttachment(
315+
const DxvkPipelineLayout* layout,
316+
const DxvkMetaInputAttachmentImageCopy::Key& key) {
317+
dxbc_spv::ir::Builder builder;
318+
DxvkBuiltInShader helper(m_device, layout, getName(key, "vs"));
319+
320+
helper.buildFullscreenVertexShader(builder);
321+
322+
ir::ResourceKind srcKind = helper.determineResourceKind(key.srcViewType, VK_SAMPLE_COUNT_1_BIT);
323+
324+
if (ir::resourceIsLayered(srcKind)) {
325+
DxvkMetaInputAttachmentImageCopyPushArgs pushArgs = loadInputAttachmentImageCopyPushArgs(builder, helper);
326+
helper.exportBuiltIn(builder, ir::BuiltIn::eLayerIndex, pushArgs.srcLayer);
327+
}
328+
329+
return helper.buildShader(builder);
330+
}
331+
332+
281333
std::vector<uint32_t> DxvkMetaCopyObjects::createVsCopyBufferToImage(
282334
const DxvkPipelineLayout* layout,
283335
const DxvkMetaBufferToImageCopy::Key& key) {
@@ -356,6 +408,59 @@ namespace dxvk {
356408
}
357409

358410

411+
std::vector<uint32_t> DxvkMetaCopyObjects::createPsCopyInputAttachment(
412+
const DxvkPipelineLayout* layout,
413+
const DxvkMetaInputAttachmentImageCopy::Key& key) {
414+
dxbc_spv::ir::Builder builder;
415+
416+
DxvkBuiltInShader helper(m_device, layout, getName(key, "ps"));
417+
helper.buildPixelShader(builder);
418+
419+
DxvkMetaInputAttachmentImageCopyPushArgs pushArgs = loadInputAttachmentImageCopyPushArgs(builder, helper);
420+
421+
ir::ResourceKind kind = helper.determineResourceKind(key.dstViewType, VK_SAMPLE_COUNT_1_BIT);
422+
uint32_t coordDims = ir::resourceCoordComponentCount(kind);
423+
424+
ir::BasicType coordTypeF(ir::ScalarType::eF32, 4u);
425+
ir::BasicType coordTypeU(ir::ScalarType::eU32, coordDims);
426+
427+
ir::SsaDef coord = helper.declareBuiltInInput(builder, coordTypeF, ir::BuiltIn::ePosition);
428+
coord = helper.emitExtractVector(builder, coord, 0u, coordDims);
429+
coord = builder.add(ir::Op::ConvertFtoI(coordTypeU, coord));
430+
coord = builder.add(ir::Op::ISub(coordTypeU, coord, helper.emitExtractVector(builder, pushArgs.srcOffset, 0u, coordDims)));
431+
coord = builder.add(ir::Op::IAdd(coordTypeU, coord, helper.emitExtractVector(builder, pushArgs.dstOffset, 0u, coordDims)));
432+
433+
ir::SsaDef layer = resourceIsLayered(kind) ? pushArgs.dstLayer : ir::SsaDef();
434+
ir::BasicType valueType(helper.determineSampledType(key.dstFormat, VK_IMAGE_ASPECT_COLOR_BIT), 4u);
435+
436+
ir::SsaDef imgSrc = helper.declareInputTarget(builder, 0u, "img_src",
437+
key.srcAttachment, key.colorFormats[key.srcAttachment], VK_SAMPLE_COUNT_1_BIT);
438+
ir::SsaDef imgDst = helper.declareImageUav(builder, 1u, "img_dst",
439+
key.dstViewType, key.dstFormat);
440+
441+
ir::SsaDef value = builder.add(ir::Op::InputTargetLoad(valueType, imgSrc, ir::SsaDef()));
442+
value = helper.emitFormatVector(builder, key.dstFormat, value);
443+
444+
auto resultType = builder.getOp(value).getType();
445+
446+
// Emit linear to sRGB conversion as necessary
447+
auto srcFormatInfo = lookupFormatInfo(key.colorFormats[key.srcAttachment]);
448+
auto dstFormatInfo = lookupFormatInfo(key.dstFormat);
449+
450+
ir::SsaDef conversionFunction = { };
451+
452+
if (srcFormatInfo->flags.test(DxvkFormatFlag::ColorSpaceSrgb)
453+
&& !dstFormatInfo->flags.test(DxvkFormatFlag::ColorSpaceSrgb))
454+
conversionFunction = helper.buildLinearToSrgbFn(builder, resultType);
455+
456+
if (conversionFunction)
457+
value = builder.add(ir::Op::FunctionCall(resultType, conversionFunction).addOperand(value));
458+
459+
builder.add(ir::Op::ImageStore(imgDst, layer, coord, value));
460+
return helper.buildShader(builder);
461+
}
462+
463+
359464
std::vector<uint32_t> DxvkMetaCopyObjects::createPsCopyBufferToImage(
360465
const DxvkPipelineLayout* layout,
361466
const DxvkMetaBufferToImageCopy::Key& key) {
@@ -835,6 +940,43 @@ namespace dxvk {
835940
}
836941

837942

943+
DxvkMetaInputAttachmentImageCopy DxvkMetaCopyObjects::createInputAttachmentCopyPipeline(const DxvkMetaInputAttachmentImageCopy::Key& key) {
944+
static const std::array<DxvkDescriptorSetLayoutBinding, 2> bindings = {{
945+
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT },
946+
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT },
947+
}};
948+
949+
// Disable depth-stencil writes
950+
VkPipelineDepthStencilStateCreateInfo dsState = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
951+
dsState.depthTestEnable = VK_FALSE;
952+
dsState.depthWriteEnable = VK_FALSE;
953+
dsState.stencilTestEnable = VK_FALSE;
954+
955+
DxvkMetaInputAttachmentImageCopy pipeline;
956+
pipeline.layout = m_device->createBuiltInPipelineLayout(0u,
957+
VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT,
958+
sizeof(DxvkMetaInputAttachmentImageCopy::Args), bindings.size(), bindings.data());
959+
960+
auto vsSpirv = createVsCopyInputAttachment(pipeline.layout, key);
961+
auto psSpirv = createPsCopyInputAttachment(pipeline.layout, key);
962+
963+
// Disable all color writes
964+
std::array<VkPipelineColorBlendAttachmentState, MaxNumRenderTargets> cbAttachments = { };
965+
966+
util::DxvkBuiltInGraphicsState state = { };
967+
state.vs = vsSpirv;
968+
state.fs = psSpirv;
969+
state.dsState = &dsState;
970+
state.cbAttachment = cbAttachments.data();
971+
state.sampleCount = VK_SAMPLE_COUNT_1_BIT;
972+
state.depthFormat = key.depthFormat;
973+
state.colorFormats = key.colorFormats;
974+
975+
pipeline.pipeline = m_device->createBuiltInGraphicsPipeline(pipeline.layout, state);
976+
return pipeline;
977+
}
978+
979+
838980
DxvkMetaImageCopy DxvkMetaCopyObjects::createImageCopyPipeline(const DxvkMetaImageCopy::Key& key) {
839981
static const std::array<DxvkDescriptorSetLayoutBinding, 2> bindings = {{
840982
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT },
@@ -926,6 +1068,17 @@ namespace dxvk {
9261068
}
9271069

9281070

1071+
std::string DxvkMetaCopyObjects::getName(const DxvkMetaInputAttachmentImageCopy::Key& key, const char* type) {
1072+
std::stringstream name;
1073+
name << "meta_" << type << "_copy_input_attachment";
1074+
name << "_" << str::format(key.srcViewType).substr(std::strlen("VK_IMAGE_VIEW_TYPE_"));
1075+
name << "_to_" << str::format(key.dstViewType).substr(std::strlen("VK_IMAGE_VIEW_TYPE_"));
1076+
name << "_" << str::format(key.colorFormats[key.srcAttachment]).substr(std::strlen("VK_FORMAT_"));
1077+
name << "_rt" << key.srcAttachment;
1078+
return str::tolower(name.str());
1079+
}
1080+
1081+
9291082
std::string DxvkMetaCopyObjects::getName(const DxvkMetaBufferToImageCopy::Key& key, const char* type) {
9301083
std::stringstream name;
9311084
name << "meta_" << type << "_copy_buffer_to_image";

src/dxvk/dxvk_meta_copy.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,58 @@ namespace dxvk {
6262
};
6363

6464

65+
/**
66+
* \brief Input attachment to image copy pipeline
67+
*/
68+
struct DxvkMetaInputAttachmentImageCopy {
69+
/** Shader args for image to image copies */
70+
struct Args {
71+
VkOffset2D srcOffset = { };
72+
VkOffset2D dstOffset = { };
73+
uint32_t srcLayer = { };
74+
uint32_t dstLayer = { };
75+
};
76+
77+
/** Look-up key for input attachment copy pipelines */
78+
struct Key {
79+
VkImageViewType srcViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
80+
VkImageViewType dstViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
81+
VkFormat dstFormat = VK_FORMAT_UNDEFINED;
82+
uint32_t srcAttachment = 0u;
83+
std::array<VkFormat, MaxNumRenderTargets> colorFormats = { };
84+
VkFormat depthFormat = VK_FORMAT_UNDEFINED;
85+
86+
bool eq(const Key& other) const {
87+
bool result = srcViewType == other.srcViewType
88+
&& dstViewType == other.dstViewType
89+
&& dstFormat == other.dstFormat
90+
&& srcAttachment == other.srcAttachment;
91+
92+
for (uint32_t i = 0u; i < MaxNumRenderTargets; i++)
93+
result = result && colorFormats[i] == other.colorFormats[i];
94+
95+
result = result && depthFormat == other.depthFormat;
96+
return result;
97+
}
98+
99+
size_t hash() const {
100+
DxvkHashState hash;
101+
hash.add(uint32_t(srcViewType));
102+
hash.add(uint32_t(dstViewType));
103+
hash.add(uint32_t(dstFormat));
104+
hash.add(uint32_t(srcAttachment));
105+
for (uint32_t i = 0u; i < MaxNumRenderTargets; i++)
106+
hash.add(uint32_t(colorFormats[i]));
107+
hash.add(uint32_t(depthFormat));
108+
return hash;
109+
}
110+
};
111+
112+
const DxvkPipelineLayout* layout = nullptr;
113+
VkPipeline pipeline = VK_NULL_HANDLE;
114+
};
115+
116+
65117
/**
66118
* \brief Buffer-to-image copy pipeline
67119
*
@@ -215,6 +267,14 @@ namespace dxvk {
215267
*/
216268
DxvkMetaImageCopy getPipeline(const DxvkMetaImageCopy::Key& key);
217269

270+
/**
271+
* \brief Gets or creates pipeline for input attachment-based image copies
272+
*
273+
* \param [in] key Pipeline properties
274+
* \returns Pipeline object
275+
*/
276+
DxvkMetaInputAttachmentImageCopy getPipeline(const DxvkMetaInputAttachmentImageCopy::Key& key);
277+
218278
/**
219279
* \brief Gets or creates pipeline for buffer to image copies
220280
*
@@ -264,6 +324,7 @@ namespace dxvk {
264324
dxvk::mutex m_mutex;
265325

266326
std::unordered_map<DxvkMetaImageCopy::Key, DxvkMetaImageCopy, DxvkHash, DxvkEq> m_imageCopyPipelines;
327+
std::unordered_map<DxvkMetaInputAttachmentImageCopy::Key, DxvkMetaInputAttachmentImageCopy, DxvkHash, DxvkEq> m_inputAttachmentImageCopyPipelines;
267328
std::unordered_map<DxvkMetaBufferToImageCopy::Key, DxvkMetaBufferToImageCopy, DxvkHash, DxvkEq> m_bufferImageCopyPipelines;
268329
std::unordered_map<DxvkMetaImageToBufferCopy::Key, DxvkMetaImageToBufferCopy, DxvkHash, DxvkEq> m_imageBufferCopyPipelines;
269330

@@ -273,6 +334,10 @@ namespace dxvk {
273334
const DxvkPipelineLayout* layout,
274335
const DxvkMetaImageCopy::Key& key);
275336

337+
std::vector<uint32_t> createVsCopyInputAttachment(
338+
const DxvkPipelineLayout* layout,
339+
const DxvkMetaInputAttachmentImageCopy::Key& key);
340+
276341
std::vector<uint32_t> createVsCopyBufferToImage(
277342
const DxvkPipelineLayout* layout,
278343
const DxvkMetaBufferToImageCopy::Key& key);
@@ -281,6 +346,10 @@ namespace dxvk {
281346
const DxvkPipelineLayout* layout,
282347
const DxvkMetaImageCopy::Key& key);
283348

349+
std::vector<uint32_t> createPsCopyInputAttachment(
350+
const DxvkPipelineLayout* layout,
351+
const DxvkMetaInputAttachmentImageCopy::Key& key);
352+
284353
std::vector<uint32_t> createPsCopyBufferToImage(
285354
const DxvkPipelineLayout* layout,
286355
const DxvkMetaBufferToImageCopy::Key& key);
@@ -305,6 +374,9 @@ namespace dxvk {
305374
DxvkMetaImageCopy createImageCopyPipeline(
306375
const DxvkMetaImageCopy::Key& key);
307376

377+
DxvkMetaInputAttachmentImageCopy createInputAttachmentCopyPipeline(
378+
const DxvkMetaInputAttachmentImageCopy::Key& key);
379+
308380
DxvkMetaBufferToImageCopy createBufferToImageCopyPipeline(
309381
const DxvkMetaBufferToImageCopy::Key& key);
310382

@@ -316,6 +388,8 @@ namespace dxvk {
316388

317389
static std::string getName(const DxvkMetaImageCopy::Key& key, const char* type);
318390

391+
static std::string getName(const DxvkMetaInputAttachmentImageCopy::Key& key, const char* type);
392+
319393
static std::string getName(const DxvkMetaBufferToImageCopy::Key& key, const char* type);
320394

321395
static std::string getName(const DxvkMetaImageToBufferCopy::Key& key, const char* type);

0 commit comments

Comments
 (0)