mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-13 19:29:14 +01:00
[dxvk] Introduce DxvkSwapchainBlitter and new presentation shaders
This is meant to provide a common rendering code for D3D9 and D3D11 presentation.
This commit is contained in:
parent
277a4f0206
commit
49f2b4c4a6
372
src/dxvk/dxvk_swapchain_blitter.cpp
Normal file
372
src/dxvk/dxvk_swapchain_blitter.cpp
Normal file
@ -0,0 +1,372 @@
|
||||
#include "dxvk_swapchain_blitter.h"
|
||||
|
||||
#include <dxvk_present_frag.h>
|
||||
#include <dxvk_present_frag_blit.h>
|
||||
#include <dxvk_present_frag_ms.h>
|
||||
#include <dxvk_present_frag_ms_amd.h>
|
||||
#include <dxvk_present_vert.h>
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkSwapchainBlitter::DxvkSwapchainBlitter(const Rc<DxvkDevice>& device)
|
||||
: m_device(device) {
|
||||
this->createSampler();
|
||||
this->createShaders();
|
||||
}
|
||||
|
||||
|
||||
DxvkSwapchainBlitter::~DxvkSwapchainBlitter() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DxvkSwapchainBlitter::presentImage(
|
||||
DxvkContext* ctx,
|
||||
const Rc<DxvkImageView>& dstView,
|
||||
VkRect2D dstRect,
|
||||
const Rc<DxvkImageView>& srcView,
|
||||
VkRect2D srcRect) {
|
||||
if (m_gammaDirty)
|
||||
this->updateGammaTexture(ctx);
|
||||
|
||||
// Fix up default present areas if necessary
|
||||
if (!dstRect.extent.width || !dstRect.extent.height) {
|
||||
dstRect.offset = { 0, 0 };
|
||||
dstRect.extent = {
|
||||
dstView->imageInfo().extent.width,
|
||||
dstView->imageInfo().extent.height };
|
||||
}
|
||||
|
||||
if (!srcRect.extent.width || !srcRect.extent.height) {
|
||||
srcRect.offset = { 0, 0 };
|
||||
srcRect.extent = {
|
||||
srcView->imageInfo().extent.width,
|
||||
srcView->imageInfo().extent.height };
|
||||
}
|
||||
|
||||
bool sameSize = dstRect.extent == srcRect.extent;
|
||||
bool usedResolveImage = false;
|
||||
|
||||
if (srcView->imageInfo().sampleCount == VK_SAMPLE_COUNT_1_BIT) {
|
||||
this->draw(ctx, sameSize ? m_fsCopy : m_fsBlit,
|
||||
dstView, dstRect, srcView, srcRect);
|
||||
} else if (sameSize) {
|
||||
this->draw(ctx, m_fsResolve,
|
||||
dstView, dstRect, srcView, srcRect);
|
||||
} else {
|
||||
if (m_resolveImage == nullptr
|
||||
|| m_resolveImage->info().extent != srcView->imageInfo().extent
|
||||
|| m_resolveImage->info().format != srcView->imageInfo().format)
|
||||
this->createResolveImage(srcView->imageInfo());
|
||||
|
||||
this->resolve(ctx, m_resolveView, srcView);
|
||||
this->draw(ctx, m_fsBlit, dstView, dstRect, m_resolveView, srcRect);
|
||||
|
||||
usedResolveImage = true;
|
||||
}
|
||||
|
||||
if (!usedResolveImage)
|
||||
this->destroyResolveImage();
|
||||
}
|
||||
|
||||
|
||||
void DxvkSwapchainBlitter::setGammaRamp(
|
||||
uint32_t cpCount,
|
||||
const DxvkGammaCp* cpData) {
|
||||
m_gammaRamp.resize(cpCount);
|
||||
|
||||
for (uint32_t i = 0; i < cpCount; i++)
|
||||
m_gammaRamp[i] = cpData[i];
|
||||
|
||||
m_gammaDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void DxvkSwapchainBlitter::draw(
|
||||
DxvkContext* ctx,
|
||||
const Rc<DxvkShader>& fs,
|
||||
const Rc<DxvkImageView>& dstView,
|
||||
VkRect2D dstRect,
|
||||
const Rc<DxvkImageView>& srcView,
|
||||
VkRect2D srcRect) {
|
||||
DxvkInputAssemblyState iaState;
|
||||
iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
iaState.primitiveRestart = VK_FALSE;
|
||||
iaState.patchVertexCount = 0;
|
||||
ctx->setInputAssemblyState(iaState);
|
||||
ctx->setInputLayout(0, nullptr, 0, nullptr);
|
||||
|
||||
DxvkRasterizerState rsState;
|
||||
rsState.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
rsState.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||
rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
rsState.depthClipEnable = VK_FALSE;
|
||||
rsState.depthBiasEnable = VK_FALSE;
|
||||
rsState.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
ctx->setRasterizerState(rsState);
|
||||
|
||||
DxvkMultisampleState msState;
|
||||
msState.sampleMask = 0xffffffff;
|
||||
msState.enableAlphaToCoverage = VK_FALSE;
|
||||
ctx->setMultisampleState(msState);
|
||||
|
||||
VkStencilOpState stencilOp;
|
||||
stencilOp.failOp = VK_STENCIL_OP_KEEP;
|
||||
stencilOp.passOp = VK_STENCIL_OP_KEEP;
|
||||
stencilOp.depthFailOp = VK_STENCIL_OP_KEEP;
|
||||
stencilOp.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
stencilOp.compareMask = 0xFFFFFFFF;
|
||||
stencilOp.writeMask = 0xFFFFFFFF;
|
||||
stencilOp.reference = 0;
|
||||
|
||||
DxvkDepthStencilState dsState;
|
||||
dsState.enableDepthTest = VK_FALSE;
|
||||
dsState.enableDepthWrite = VK_FALSE;
|
||||
dsState.enableStencilTest = VK_FALSE;
|
||||
dsState.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||
dsState.stencilOpFront = stencilOp;
|
||||
dsState.stencilOpBack = stencilOp;
|
||||
ctx->setDepthStencilState(dsState);
|
||||
|
||||
DxvkLogicOpState loState;
|
||||
loState.enableLogicOp = VK_FALSE;
|
||||
loState.logicOp = VK_LOGIC_OP_NO_OP;
|
||||
ctx->setLogicOpState(loState);
|
||||
|
||||
DxvkBlendMode blendMode;
|
||||
blendMode.enableBlending = VK_FALSE;
|
||||
blendMode.colorSrcFactor = VK_BLEND_FACTOR_ONE;
|
||||
blendMode.colorDstFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blendMode.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
blendMode.alphaSrcFactor = VK_BLEND_FACTOR_ONE;
|
||||
blendMode.alphaDstFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blendMode.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
blendMode.writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
|
||||
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
ctx->setBlendMode(0, blendMode);
|
||||
|
||||
VkViewport viewport;
|
||||
viewport.x = float(dstRect.offset.x);
|
||||
viewport.y = float(dstRect.offset.y);
|
||||
viewport.width = float(dstRect.extent.width);
|
||||
viewport.height = float(dstRect.extent.height);
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
|
||||
ctx->setViewports(1, &viewport, &dstRect);
|
||||
|
||||
DxvkRenderTargets renderTargets;
|
||||
renderTargets.color[0].view = dstView;
|
||||
renderTargets.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
ctx->bindRenderTargets(renderTargets);
|
||||
|
||||
VkExtent2D dstExtent = {
|
||||
dstView->imageInfo().extent.width,
|
||||
dstView->imageInfo().extent.height };
|
||||
|
||||
if (dstRect.extent == dstExtent)
|
||||
ctx->discardImageView(dstView, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
else
|
||||
ctx->clearRenderTarget(dstView, VK_IMAGE_ASPECT_COLOR_BIT, VkClearValue());
|
||||
|
||||
ctx->bindResourceSampler(BindingIds::Image, m_samplerPresent);
|
||||
ctx->bindResourceSampler(BindingIds::Gamma, m_samplerGamma);
|
||||
|
||||
ctx->bindResourceView(BindingIds::Image, srcView, nullptr);
|
||||
ctx->bindResourceView(BindingIds::Gamma, m_gammaView, nullptr);
|
||||
|
||||
ctx->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_vs);
|
||||
ctx->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, fs);
|
||||
|
||||
PresenterArgs args;
|
||||
args.srcOffset = srcRect.offset;
|
||||
|
||||
if (dstRect.extent == srcRect.extent)
|
||||
args.dstOffset = dstRect.offset;
|
||||
else
|
||||
args.srcExtent = srcRect.extent;
|
||||
|
||||
ctx->pushConstants(0, sizeof(args), &args);
|
||||
|
||||
ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, srcView->imageInfo().sampleCount);
|
||||
ctx->draw(3, 1, 0, 0);
|
||||
ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0);
|
||||
}
|
||||
|
||||
void DxvkSwapchainBlitter::resolve(
|
||||
DxvkContext* ctx,
|
||||
const Rc<DxvkImageView>& dstView,
|
||||
const Rc<DxvkImageView>& srcView) {
|
||||
VkImageResolve resolve;
|
||||
resolve.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
|
||||
resolve.srcOffset = { 0, 0, 0 };
|
||||
resolve.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
|
||||
resolve.dstOffset = { 0, 0, 0 };
|
||||
resolve.extent = dstView->imageInfo().extent;
|
||||
ctx->resolveImage(dstView->image(), srcView->image(), resolve, VK_FORMAT_UNDEFINED);
|
||||
}
|
||||
|
||||
|
||||
void DxvkSwapchainBlitter::updateGammaTexture(DxvkContext* ctx) {
|
||||
uint32_t n = uint32_t(m_gammaRamp.size());
|
||||
|
||||
if (n) {
|
||||
// Reuse existing image if possible
|
||||
if (m_gammaImage == nullptr || m_gammaImage->info().extent.width != n) {
|
||||
DxvkImageCreateInfo imgInfo;
|
||||
imgInfo.type = VK_IMAGE_TYPE_1D;
|
||||
imgInfo.format = VK_FORMAT_R16G16B16A16_UNORM;
|
||||
imgInfo.flags = 0;
|
||||
imgInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
imgInfo.extent = { n, 1, 1 };
|
||||
imgInfo.numLayers = 1;
|
||||
imgInfo.mipLevels = 1;
|
||||
imgInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||
| VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
imgInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
|
||||
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
imgInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT
|
||||
| VK_ACCESS_SHADER_READ_BIT;
|
||||
imgInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imgInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
m_gammaImage = m_device->createImage(
|
||||
imgInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
DxvkImageViewCreateInfo viewInfo;
|
||||
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
|
||||
viewInfo.format = VK_FORMAT_R16G16B16A16_UNORM;
|
||||
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.minLevel = 0;
|
||||
viewInfo.numLevels = 1;
|
||||
viewInfo.minLayer = 0;
|
||||
viewInfo.numLayers = 1;
|
||||
|
||||
m_gammaView = m_device->createImageView(m_gammaImage, viewInfo);
|
||||
}
|
||||
|
||||
ctx->updateImage(m_gammaImage,
|
||||
VkImageSubresourceLayers { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 },
|
||||
VkOffset3D { 0, 0, 0 },
|
||||
VkExtent3D { n, 1, 1 },
|
||||
m_gammaRamp.data(),
|
||||
sizeof(DxvkGammaCp) * n,
|
||||
sizeof(DxvkGammaCp) * n);
|
||||
} else {
|
||||
m_gammaImage = nullptr;
|
||||
m_gammaView = nullptr;
|
||||
}
|
||||
|
||||
m_gammaDirty = false;
|
||||
}
|
||||
|
||||
|
||||
void DxvkSwapchainBlitter::createSampler() {
|
||||
DxvkSamplerCreateInfo samplerInfo;
|
||||
samplerInfo.magFilter = VK_FILTER_LINEAR;
|
||||
samplerInfo.minFilter = VK_FILTER_LINEAR;
|
||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
samplerInfo.mipmapLodBias = 0.0f;
|
||||
samplerInfo.mipmapLodMin = 0.0f;
|
||||
samplerInfo.mipmapLodMax = 0.0f;
|
||||
samplerInfo.useAnisotropy = VK_FALSE;
|
||||
samplerInfo.maxAnisotropy = 1.0f;
|
||||
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.compareToDepth = VK_FALSE;
|
||||
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
samplerInfo.borderColor = VkClearColorValue();
|
||||
samplerInfo.usePixelCoord = VK_TRUE;
|
||||
m_samplerPresent = m_device->createSampler(samplerInfo);
|
||||
|
||||
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerInfo.usePixelCoord = VK_FALSE;
|
||||
m_samplerGamma = m_device->createSampler(samplerInfo);
|
||||
}
|
||||
|
||||
void DxvkSwapchainBlitter::createShaders() {
|
||||
const SpirvCodeBuffer vsCode(dxvk_present_vert);
|
||||
const SpirvCodeBuffer fsCodeBlit(dxvk_present_frag_blit);
|
||||
const SpirvCodeBuffer fsCodeCopy(dxvk_present_frag);
|
||||
const SpirvCodeBuffer fsCodeResolve(dxvk_present_frag_ms);
|
||||
const SpirvCodeBuffer fsCodeResolveAmd(dxvk_present_frag_ms_amd);
|
||||
|
||||
const std::array<DxvkResourceSlot, 2> fsResourceSlots = {{
|
||||
{ BindingIds::Image, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_IMAGE_VIEW_TYPE_2D },
|
||||
{ BindingIds::Gamma, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_IMAGE_VIEW_TYPE_1D },
|
||||
}};
|
||||
|
||||
m_vs = m_device->createShader(
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0, nullptr, { 0u, 1u },
|
||||
vsCode);
|
||||
|
||||
m_fsBlit = m_device->createShader(
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
fsResourceSlots.size(),
|
||||
fsResourceSlots.data(),
|
||||
{ 1u, 1u, 0u, sizeof(PresenterArgs) },
|
||||
fsCodeBlit);
|
||||
|
||||
m_fsCopy = m_device->createShader(
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
fsResourceSlots.size(),
|
||||
fsResourceSlots.data(),
|
||||
{ 0u, 1u, 0u, sizeof(PresenterArgs) },
|
||||
fsCodeCopy);
|
||||
|
||||
m_fsResolve = m_device->createShader(
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
fsResourceSlots.size(),
|
||||
fsResourceSlots.data(),
|
||||
{ 0u, 1u, 0u, sizeof(PresenterArgs) },
|
||||
m_device->extensions().amdShaderFragmentMask
|
||||
? fsCodeResolveAmd : fsCodeResolve);
|
||||
}
|
||||
|
||||
void DxvkSwapchainBlitter::createResolveImage(const DxvkImageCreateInfo& info) {
|
||||
DxvkImageCreateInfo newInfo;
|
||||
newInfo.type = VK_IMAGE_TYPE_2D;
|
||||
newInfo.format = info.format;
|
||||
newInfo.flags = 0;
|
||||
newInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
newInfo.extent = info.extent;
|
||||
newInfo.numLayers = 1;
|
||||
newInfo.mipLevels = 1;
|
||||
newInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
|
||||
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||
| VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
newInfo.stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
||||
| VK_PIPELINE_STAGE_TRANSFER_BIT
|
||||
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
newInfo.access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
|
||||
| VK_ACCESS_TRANSFER_WRITE_BIT
|
||||
| VK_ACCESS_SHADER_READ_BIT;
|
||||
newInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
newInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
m_resolveImage = m_device->createImage(newInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
DxvkImageViewCreateInfo viewInfo;
|
||||
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format = info.format;
|
||||
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.minLevel = 0;
|
||||
viewInfo.numLevels = 1;
|
||||
viewInfo.minLayer = 0;
|
||||
viewInfo.numLayers = 1;
|
||||
m_resolveView = m_device->createImageView(m_resolveImage, viewInfo);
|
||||
}
|
||||
|
||||
|
||||
void DxvkSwapchainBlitter::destroyResolveImage() {
|
||||
m_resolveImage = nullptr;
|
||||
m_resolveView = nullptr;
|
||||
}
|
||||
|
||||
}
|
116
src/dxvk/dxvk_swapchain_blitter.h
Normal file
116
src/dxvk/dxvk_swapchain_blitter.h
Normal file
@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
#include "../dxvk/dxvk_device.h"
|
||||
#include "../dxvk/dxvk_context.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Gamma control point
|
||||
*/
|
||||
struct DxvkGammaCp {
|
||||
uint16_t r, g, b, a;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Swap chain blitter
|
||||
*
|
||||
* Provides common rendering code for blitting
|
||||
* rendered images to a swap chain image.
|
||||
*/
|
||||
class DxvkSwapchainBlitter : public RcObject {
|
||||
|
||||
public:
|
||||
|
||||
DxvkSwapchainBlitter(const Rc<DxvkDevice>& device);
|
||||
~DxvkSwapchainBlitter();
|
||||
|
||||
/**
|
||||
* \brief Records presentation commands
|
||||
*
|
||||
* \param [in] ctx Context
|
||||
* \param [in] dstView Swap chain image view
|
||||
* \param [in] srcView Image to present
|
||||
* \param [in] dstRect Destination rectangle
|
||||
* \param [in] srcRect Back buffer rectangle
|
||||
*/
|
||||
void presentImage(
|
||||
DxvkContext* ctx,
|
||||
const Rc<DxvkImageView>& dstView,
|
||||
VkRect2D dstRect,
|
||||
const Rc<DxvkImageView>& srcView,
|
||||
VkRect2D srcRect);
|
||||
|
||||
/**
|
||||
* \brief Sets gamma ramp
|
||||
*
|
||||
* If the number of control points is non-zero, this
|
||||
* will create a texture containing a gamma ramp that
|
||||
* will be used for presentation.
|
||||
* \param [in] cpCount Number of control points
|
||||
* \param [in] cpData Control point data
|
||||
*/
|
||||
void setGammaRamp(
|
||||
uint32_t cpCount,
|
||||
const DxvkGammaCp* cpData);
|
||||
|
||||
private:
|
||||
|
||||
enum BindingIds : uint32_t {
|
||||
Image = 0,
|
||||
Gamma = 1,
|
||||
};
|
||||
|
||||
struct PresenterArgs {
|
||||
VkOffset2D srcOffset;
|
||||
union {
|
||||
VkExtent2D srcExtent;
|
||||
VkOffset2D dstOffset;
|
||||
};
|
||||
};
|
||||
|
||||
Rc<DxvkDevice> m_device;
|
||||
|
||||
Rc<DxvkShader> m_fsCopy;
|
||||
Rc<DxvkShader> m_fsBlit;
|
||||
Rc<DxvkShader> m_fsResolve;
|
||||
Rc<DxvkShader> m_vs;
|
||||
|
||||
Rc<DxvkImage> m_gammaImage;
|
||||
Rc<DxvkImageView> m_gammaView;
|
||||
bool m_gammaDirty = false;
|
||||
std::vector<DxvkGammaCp> m_gammaRamp;
|
||||
|
||||
Rc<DxvkImage> m_resolveImage;
|
||||
Rc<DxvkImageView> m_resolveView;
|
||||
|
||||
Rc<DxvkSampler> m_samplerPresent;
|
||||
Rc<DxvkSampler> m_samplerGamma;
|
||||
|
||||
void draw(
|
||||
DxvkContext* ctx,
|
||||
const Rc<DxvkShader>& fs,
|
||||
const Rc<DxvkImageView>& dstView,
|
||||
VkRect2D dstRect,
|
||||
const Rc<DxvkImageView>& srcView,
|
||||
VkRect2D srcRect);
|
||||
|
||||
void resolve(
|
||||
DxvkContext* ctx,
|
||||
const Rc<DxvkImageView>& dstView,
|
||||
const Rc<DxvkImageView>& srcView);
|
||||
|
||||
void updateGammaTexture(DxvkContext* ctx);
|
||||
|
||||
void createSampler();
|
||||
|
||||
void createShaders();
|
||||
|
||||
void createResolveImage(
|
||||
const DxvkImageCreateInfo& info);
|
||||
|
||||
void destroyResolveImage();
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -33,6 +33,12 @@ dxvk_shaders = files([
|
||||
'shaders/dxvk_pack_d24s8.comp',
|
||||
'shaders/dxvk_pack_d32s8.comp',
|
||||
|
||||
'shaders/dxvk_present_frag.frag',
|
||||
'shaders/dxvk_present_frag_blit.frag',
|
||||
'shaders/dxvk_present_frag_ms.frag',
|
||||
'shaders/dxvk_present_frag_ms_amd.frag',
|
||||
'shaders/dxvk_present_vert.vert',
|
||||
|
||||
'shaders/dxvk_resolve_frag_d.frag',
|
||||
'shaders/dxvk_resolve_frag_ds.frag',
|
||||
'shaders/dxvk_resolve_frag_f.frag',
|
||||
@ -97,6 +103,7 @@ dxvk_src = files([
|
||||
'dxvk_staging.cpp',
|
||||
'dxvk_state_cache.cpp',
|
||||
'dxvk_stats.cpp',
|
||||
'dxvk_swapchain_blitter.cpp',
|
||||
'dxvk_unbound.cpp',
|
||||
'dxvk_util.cpp',
|
||||
|
||||
|
27
src/dxvk/shaders/dxvk_present_frag.frag
Normal file
27
src/dxvk/shaders/dxvk_present_frag.frag
Normal file
@ -0,0 +1,27 @@
|
||||
#version 450
|
||||
|
||||
layout(constant_id = 1) const bool s_gamma_bound = true;
|
||||
|
||||
layout(binding = 0) uniform sampler2D s_image;
|
||||
layout(binding = 1) uniform sampler1D s_gamma;
|
||||
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
layout(push_constant)
|
||||
uniform present_info_t {
|
||||
ivec2 src_offset;
|
||||
ivec2 dst_offset;
|
||||
};
|
||||
|
||||
void main() {
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy) + src_offset - dst_offset;
|
||||
o_color = texelFetch(s_image, coord, 0);
|
||||
|
||||
if (s_gamma_bound) {
|
||||
o_color = vec4(
|
||||
texture(s_gamma, o_color.r).r,
|
||||
texture(s_gamma, o_color.g).g,
|
||||
texture(s_gamma, o_color.b).b,
|
||||
o_color.a);
|
||||
}
|
||||
}
|
28
src/dxvk/shaders/dxvk_present_frag_blit.frag
Normal file
28
src/dxvk/shaders/dxvk_present_frag_blit.frag
Normal file
@ -0,0 +1,28 @@
|
||||
#version 450
|
||||
|
||||
layout(constant_id = 1) const bool s_gamma_bound = true;
|
||||
|
||||
layout(binding = 0) uniform sampler2D s_image;
|
||||
layout(binding = 1) uniform sampler1D s_gamma;
|
||||
|
||||
layout(location = 0) in vec2 i_coord;
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
layout(push_constant)
|
||||
uniform present_info_t {
|
||||
ivec2 src_offset;
|
||||
uvec2 src_extent;
|
||||
};
|
||||
|
||||
void main() {
|
||||
vec2 coord = vec2(src_offset) + vec2(src_extent) * i_coord;
|
||||
o_color = textureLod(s_image, coord, 0.0f);
|
||||
|
||||
if (s_gamma_bound) {
|
||||
o_color = vec4(
|
||||
texture(s_gamma, o_color.r).r,
|
||||
texture(s_gamma, o_color.g).g,
|
||||
texture(s_gamma, o_color.b).b,
|
||||
o_color.a);
|
||||
}
|
||||
}
|
33
src/dxvk/shaders/dxvk_present_frag_ms.frag
Normal file
33
src/dxvk/shaders/dxvk_present_frag_ms.frag
Normal file
@ -0,0 +1,33 @@
|
||||
#version 450
|
||||
|
||||
layout(constant_id = 1) const bool s_gamma_bound = true;
|
||||
layout(constant_id = 1225) const uint c_samples = 0;
|
||||
|
||||
layout(binding = 0) uniform sampler2DMS s_image;
|
||||
layout(binding = 1) uniform sampler1D s_gamma;
|
||||
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
layout(push_constant)
|
||||
uniform present_info_t {
|
||||
ivec2 src_offset;
|
||||
ivec2 dst_offset;
|
||||
};
|
||||
|
||||
void main() {
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy) + src_offset - dst_offset;
|
||||
o_color = texelFetch(s_image, coord, 0);
|
||||
|
||||
for (uint i = 1; i < c_samples; i++)
|
||||
o_color += texelFetch(s_image, coord, int(i));
|
||||
|
||||
o_color /= float(c_samples);
|
||||
|
||||
if (s_gamma_bound) {
|
||||
o_color = vec4(
|
||||
texture(s_gamma, o_color.r).r,
|
||||
texture(s_gamma, o_color.g).g,
|
||||
texture(s_gamma, o_color.b).b,
|
||||
o_color.a);
|
||||
}
|
||||
}
|
52
src/dxvk/shaders/dxvk_present_frag_ms_amd.frag
Normal file
52
src/dxvk/shaders/dxvk_present_frag_ms_amd.frag
Normal file
@ -0,0 +1,52 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_AMD_shader_fragment_mask: enable
|
||||
|
||||
layout(constant_id = 1) const bool s_gamma_bound = true;
|
||||
layout(constant_id = 1225) const uint c_samples = 0;
|
||||
|
||||
layout(binding = 0) uniform sampler2DMS s_image;
|
||||
layout(binding = 1) uniform sampler1D s_gamma;
|
||||
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
layout(push_constant)
|
||||
uniform present_info_t {
|
||||
ivec2 src_offset;
|
||||
ivec2 dst_offset;
|
||||
};
|
||||
|
||||
void main() {
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy) + src_offset - dst_offset;
|
||||
|
||||
// check dxvk_resolve_frag_f_amd.frag for documentation
|
||||
uint fragMask = fragmentMaskFetchAMD(s_image, coord);
|
||||
uint fragCount = 0u;
|
||||
|
||||
for (int i = 0; i < 4 * c_samples; i += 4) {
|
||||
uint fragIndex = bitfieldExtract(fragMask, i, 4);
|
||||
fragCount += 1u << (fragIndex << 2);
|
||||
}
|
||||
|
||||
o_color = vec4(0.0f);
|
||||
|
||||
while (fragCount != 0) {
|
||||
int fragIndex = findLSB(fragCount) >> 2;
|
||||
int fragShift = fragIndex << 2;
|
||||
|
||||
o_color += fragmentFetchAMD(s_image, coord, fragIndex)
|
||||
* float(bitfieldExtract(fragCount, fragShift, 4));
|
||||
|
||||
fragCount = bitfieldInsert(fragCount, 0, fragShift, 4);
|
||||
}
|
||||
|
||||
o_color /= float(c_samples);
|
||||
|
||||
if (s_gamma_bound) {
|
||||
o_color = vec4(
|
||||
texture(s_gamma, o_color.r).r,
|
||||
texture(s_gamma, o_color.g).g,
|
||||
texture(s_gamma, o_color.b).b,
|
||||
o_color.a);
|
||||
}
|
||||
}
|
12
src/dxvk/shaders/dxvk_present_vert.vert
Normal file
12
src/dxvk/shaders/dxvk_present_vert.vert
Normal file
@ -0,0 +1,12 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) out vec2 o_coord;
|
||||
|
||||
void main() {
|
||||
vec2 coord = vec2(
|
||||
float(gl_VertexIndex & 2),
|
||||
float(gl_VertexIndex & 1) * 2.0f);
|
||||
|
||||
o_coord = coord;
|
||||
gl_Position = vec4(-1.0f + 2.0f * coord, 0.0f, 1.0f);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user