mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-07 16:54:14 +01:00
[dxvk] Prepare swapchain blitter for compositing HUD and cursor
This will be necessary for non-linear color spaces to get proper blending.
This commit is contained in:
parent
8be30d7d5a
commit
a09d372caf
@ -318,11 +318,36 @@ namespace dxvk {
|
||||
gammaDescriptor.imageLayout = m_gammaView->image()->info().layout;
|
||||
}
|
||||
|
||||
std::array<VkWriteDescriptorSet, 2> descriptorWrites = {{
|
||||
VkDescriptorImageInfo hudDescriptor = { };
|
||||
|
||||
if (m_hudView) {
|
||||
hudDescriptor.imageView = m_hudView->handle();
|
||||
hudDescriptor.imageLayout = m_hudImage->info().layout;
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo cursorDescriptor = { };
|
||||
cursorDescriptor.sampler = m_samplerCursorNearest->handle();
|
||||
|
||||
if (m_cursorView) {
|
||||
VkExtent3D extent = m_cursorImage->info().extent;
|
||||
|
||||
if (m_cursorRect.extent.width != extent.width
|
||||
|| m_cursorRect.extent.height != extent.height)
|
||||
cursorDescriptor.sampler = m_samplerCursorLinear->handle();
|
||||
|
||||
cursorDescriptor.imageLayout = m_cursorImage->info().layout;
|
||||
cursorDescriptor.imageView = m_cursorView->handle();
|
||||
}
|
||||
|
||||
std::array<VkWriteDescriptorSet, 4> descriptorWrites = {{
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
||||
set, 0, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptor },
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
||||
set, 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &gammaDescriptor },
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
||||
set, 2, 0, 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &hudDescriptor },
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
||||
set, 3, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &cursorDescriptor },
|
||||
}};
|
||||
|
||||
ctx.cmd->updateDescriptorSets(
|
||||
@ -474,6 +499,18 @@ namespace dxvk {
|
||||
samplerInfo.setUsePixelCoordinates(false);
|
||||
|
||||
m_samplerGamma = m_device->createSampler(samplerInfo);
|
||||
|
||||
samplerInfo.setAddressModes(
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
|
||||
|
||||
m_samplerCursorLinear = m_device->createSampler(samplerInfo);
|
||||
|
||||
samplerInfo.setFilter(VK_FILTER_NEAREST, VK_FILTER_NEAREST,
|
||||
VK_SAMPLER_MIPMAP_MODE_NEAREST);
|
||||
|
||||
m_samplerCursorNearest = m_device->createSampler(samplerInfo);
|
||||
}
|
||||
|
||||
|
||||
@ -527,10 +564,11 @@ namespace dxvk {
|
||||
VkDescriptorSetLayout DxvkSwapchainBlitter::createSetLayout() {
|
||||
auto vk = m_device->vkd();
|
||||
|
||||
std::array<VkDescriptorSetLayoutBinding, 3> bindings = {{
|
||||
std::array<VkDescriptorSetLayoutBinding, 4> bindings = {{
|
||||
{ 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT },
|
||||
}};
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||
@ -574,13 +612,15 @@ namespace dxvk {
|
||||
const DxvkSwapchainPipelineKey& key) {
|
||||
auto vk = m_device->vkd();
|
||||
|
||||
static const std::array<VkSpecializationMapEntry, 6> specMap = {{
|
||||
static const std::array<VkSpecializationMapEntry, 8> specMap = {{
|
||||
{ 0, offsetof(SpecConstants, sampleCount), sizeof(VkSampleCountFlagBits) },
|
||||
{ 1, offsetof(SpecConstants, gammaBound), sizeof(VkBool32) },
|
||||
{ 2, offsetof(SpecConstants, srcSpace), sizeof(VkColorSpaceKHR) },
|
||||
{ 3, offsetof(SpecConstants, srcIsSrgb), sizeof(VkBool32) },
|
||||
{ 4, offsetof(SpecConstants, dstSpace), sizeof(VkColorSpaceKHR) },
|
||||
{ 5, offsetof(SpecConstants, dstIsSrgb), sizeof(VkBool32) },
|
||||
{ 6, offsetof(SpecConstants, compositeHud), sizeof(VkBool32) },
|
||||
{ 7, offsetof(SpecConstants, compositeCursor),sizeof(VkBool32) },
|
||||
}};
|
||||
|
||||
SpecConstants specConstants = { };
|
||||
@ -590,6 +630,8 @@ namespace dxvk {
|
||||
specConstants.srcIsSrgb = key.srcIsSrgb;
|
||||
specConstants.dstSpace = key.dstSpace;
|
||||
specConstants.dstIsSrgb = lookupFormatInfo(key.dstFormat)->flags.test(DxvkFormatFlag::ColorSpaceSrgb);
|
||||
specConstants.compositeCursor = key.compositeCursor;
|
||||
specConstants.compositeHud = key.compositeHud;
|
||||
|
||||
// Avoid redundant color space conversions if color spaces
|
||||
// and images properties match and we don't do a resolve
|
||||
|
@ -47,6 +47,10 @@ namespace dxvk {
|
||||
VkBool32 needsGamma = VK_FALSE;
|
||||
/// Bit indicating whether alpha blending is required
|
||||
VkBool32 needsBlending = VK_FALSE;
|
||||
/// Bit indicating whether the HUD needs to be composited
|
||||
VkBool32 compositeHud = VK_FALSE;
|
||||
/// Bit indicating whether the software cursor needs to be composited
|
||||
VkBool32 compositeCursor = VK_FALSE;
|
||||
|
||||
size_t hash() const {
|
||||
DxvkHashState hash;
|
||||
@ -58,6 +62,8 @@ namespace dxvk {
|
||||
hash.add(uint32_t(needsBlit));
|
||||
hash.add(uint32_t(needsGamma));
|
||||
hash.add(uint32_t(needsBlending));
|
||||
hash.add(uint32_t(compositeHud));
|
||||
hash.add(uint32_t(compositeCursor));
|
||||
return hash;
|
||||
}
|
||||
|
||||
@ -69,7 +75,9 @@ namespace dxvk {
|
||||
&& dstFormat == other.dstFormat
|
||||
&& needsBlit == other.needsBlit
|
||||
&& needsGamma == other.needsGamma
|
||||
&& needsBlending == other.needsBlending;
|
||||
&& needsBlending == other.needsBlending
|
||||
&& compositeHud == other.compositeHud
|
||||
&& compositeCursor == other.compositeCursor;
|
||||
}
|
||||
};
|
||||
|
||||
@ -155,12 +163,16 @@ namespace dxvk {
|
||||
VkBool32 srcIsSrgb;
|
||||
VkColorSpaceKHR dstSpace;
|
||||
VkBool32 dstIsSrgb;
|
||||
VkBool32 compositeHud;
|
||||
VkBool32 compositeCursor;
|
||||
};
|
||||
|
||||
struct PushConstants {
|
||||
VkOffset2D srcOffset;
|
||||
VkExtent2D srcExtent;
|
||||
VkOffset2D dstOffset;
|
||||
VkOffset2D cursorOffset;
|
||||
VkExtent2D cursorExtent;
|
||||
};
|
||||
|
||||
struct ShaderModule {
|
||||
@ -190,6 +202,11 @@ namespace dxvk {
|
||||
|
||||
Rc<DxvkSampler> m_samplerPresent;
|
||||
Rc<DxvkSampler> m_samplerGamma;
|
||||
Rc<DxvkSampler> m_samplerCursorLinear;
|
||||
Rc<DxvkSampler> m_samplerCursorNearest;
|
||||
|
||||
Rc<DxvkImage> m_hudImage;
|
||||
Rc<DxvkImageView> m_hudView;
|
||||
|
||||
VkDescriptorSetLayout m_setLayout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "dxvk_color_space.glsl"
|
||||
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout(constant_id = 0) const uint c_samples = 0u;
|
||||
layout(constant_id = 1) const bool c_gamma = false;
|
||||
|
||||
@ -7,18 +9,53 @@ layout(constant_id = 2) const uint c_src_color_space = VK_COLOR_SPACE_SRGB_NONLI
|
||||
layout(constant_id = 3) const bool c_src_is_srgb = true;
|
||||
layout(constant_id = 4) const uint c_dst_color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
layout(constant_id = 5) const bool c_dst_is_srgb = true;
|
||||
layout(constant_id = 6) const bool c_composite_hud = false;
|
||||
layout(constant_id = 7) const bool c_composite_cursor = false;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D s_image;
|
||||
layout(set = 0, binding = 0) uniform sampler2DMS s_image_ms;
|
||||
layout(set = 0, binding = 1) uniform sampler1D s_gamma;
|
||||
layout(set = 0, binding = 2) uniform texture2D s_hud;
|
||||
layout(set = 0, binding = 3) uniform sampler2D s_cursor;
|
||||
|
||||
layout(push_constant)
|
||||
uniform present_info_t {
|
||||
ivec2 src_offset;
|
||||
ivec2 src_extent;
|
||||
ivec2 dst_offset;
|
||||
ivec2 cursor_offset;
|
||||
ivec2 cursor_extent;
|
||||
};
|
||||
|
||||
|
||||
vec4 blend_sc_rgb(vec4 dst, vec4 src) {
|
||||
return mix(dst, vec4(src.rgb, 1.0f), src.aaaa);
|
||||
}
|
||||
|
||||
|
||||
vec4 blend_linear_sdr(vec4 dst, vec4 src) {
|
||||
src.rgb = nits_to_sc_rgb(src.rgb * SDR_NITS);
|
||||
return blend_sc_rgb(dst, src);
|
||||
}
|
||||
|
||||
|
||||
vec4 composite_image(vec4 color) {
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
|
||||
if (c_composite_hud)
|
||||
color = blend_linear_sdr(color, texelFetch(s_hud, coord, 0));
|
||||
|
||||
if (c_composite_cursor) {
|
||||
ivec2 rel_ofs = coord - cursor_offset;
|
||||
|
||||
if (max(rel_ofs.x, rel_ofs.y) >= 0 && all(lessThan(rel_ofs, cursor_extent)))
|
||||
color = blend_linear_sdr(color, texture(s_cursor, vec2(rel_ofs) / vec2(cursor_extent)));
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
vec4 input_to_sc_rgb(vec4 color) {
|
||||
switch (c_src_color_space) {
|
||||
default:
|
||||
|
@ -10,5 +10,6 @@ void main() {
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy) + src_offset - dst_offset;
|
||||
|
||||
o_color = input_to_sc_rgb(texelFetch(s_image, coord, 0));
|
||||
o_color = composite_image(o_color);
|
||||
o_color = sc_rgb_to_output(o_color);
|
||||
}
|
||||
|
@ -10,5 +10,6 @@ layout(location = 0) out vec4 o_color;
|
||||
void main() {
|
||||
vec2 coord = vec2(src_offset) + vec2(src_extent) * i_coord;
|
||||
o_color = input_to_sc_rgb(textureLod(s_image, coord, 0.0f));
|
||||
o_color = composite_image(o_color);
|
||||
o_color = sc_rgb_to_output(o_color);
|
||||
}
|
||||
|
@ -13,5 +13,6 @@ void main() {
|
||||
for (uint i = 1; i < c_samples; i++)
|
||||
o_color += input_to_sc_rgb(texelFetch(s_image_ms, coord, int(i)));
|
||||
|
||||
o_color = sc_rgb_to_output(o_color / float(c_samples));
|
||||
o_color = composite_image(o_color / float(c_samples));
|
||||
o_color = sc_rgb_to_output(o_color);
|
||||
}
|
||||
|
@ -31,5 +31,6 @@ void main() {
|
||||
fragCount = bitfieldInsert(fragCount, 0, fragShift, 4);
|
||||
}
|
||||
|
||||
o_color = sc_rgb_to_output(o_color / float(c_samples));
|
||||
o_color = composite_image(o_color / float(c_samples));
|
||||
o_color = sc_rgb_to_output(o_color);
|
||||
}
|
||||
|
@ -61,5 +61,6 @@ void main() {
|
||||
o_color += input_to_sc_rgb(texelFetch(s_image_ms, cint + coffset, int(i)));
|
||||
}
|
||||
|
||||
o_color = sc_rgb_to_output(o_color / float(c_samples));
|
||||
o_color = composite_image(o_color / float(c_samples));
|
||||
o_color = sc_rgb_to_output(o_color);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user