diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp index 1742cf0c..a04b5037 100644 --- a/src/d3d11/d3d11_swapchain.cpp +++ b/src/d3d11/d3d11_swapchain.cpp @@ -2,9 +2,6 @@ #include "d3d11_device.h" #include "d3d11_swapchain.h" -#include -#include - namespace dxvk { static uint16_t MapGammaControlPoint(float x) { @@ -32,11 +29,8 @@ namespace dxvk { CreatePresenter(); CreateBackBuffer(); + CreateBlitter(); CreateHud(); - - InitRenderState(); - InitSamplers(); - InitShaders(); } @@ -149,7 +143,7 @@ namespace dxvk { bool isIdentity = true; if (NumControlPoints > 1) { - std::array cp; + std::array cp; if (NumControlPoints > cp.size()) return E_INVALIDARG; @@ -157,22 +151,22 @@ namespace dxvk { for (uint32_t i = 0; i < NumControlPoints; i++) { uint16_t identity = MapGammaControlPoint(float(i) / float(NumControlPoints - 1)); - cp[i].R = MapGammaControlPoint(pControlPoints[i].Red); - cp[i].G = MapGammaControlPoint(pControlPoints[i].Green); - cp[i].B = MapGammaControlPoint(pControlPoints[i].Blue); - cp[i].A = 0; + cp[i].r = MapGammaControlPoint(pControlPoints[i].Red); + cp[i].g = MapGammaControlPoint(pControlPoints[i].Green); + cp[i].b = MapGammaControlPoint(pControlPoints[i].Blue); + cp[i].a = 0; - isIdentity &= cp[i].R == identity - && cp[i].G == identity - && cp[i].B == identity; + isIdentity &= cp[i].r == identity + && cp[i].g == identity + && cp[i].b == identity; } if (!isIdentity) - CreateGammaTexture(NumControlPoints, cp.data()); + m_blitter->setGammaRamp(NumControlPoints, cp.data()); } if (isIdentity) - DestroyGammaTexture(); + m_blitter->setGammaRamp(0, nullptr); return S_OK; } @@ -285,70 +279,9 @@ namespace dxvk { m_context->beginRecording( m_device->createCommandList()); - if (m_swapImageResolve != nullptr && i == 0) { - VkImageSubresourceLayers resolveSubresource; - resolveSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveSubresource.mipLevel = 0; - resolveSubresource.baseArrayLayer = 0; - resolveSubresource.layerCount = 1; - - VkImageResolve resolveRegion; - resolveRegion.srcSubresource = resolveSubresource; - resolveRegion.srcOffset = VkOffset3D { 0, 0, 0 }; - resolveRegion.dstSubresource = resolveSubresource; - resolveRegion.dstOffset = VkOffset3D { 0, 0, 0 }; - resolveRegion.extent = m_swapImage->info().extent; - - m_context->resolveImage( - m_swapImageResolve, m_swapImage, - resolveRegion, VK_FORMAT_UNDEFINED); - } - - // Use an appropriate texture filter depending on whether - // the back buffer size matches the swap image size - bool fitSize = m_swapImage->info().extent.width == info.imageExtent.width - && m_swapImage->info().extent.height == info.imageExtent.height; - - m_context->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_vertShader); - m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_fragShader); - - DxvkRenderTargets renderTargets; - renderTargets.color[0].view = m_imageViews.at(imageIndex); - renderTargets.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - m_context->bindRenderTargets(renderTargets); - m_context->discardImageView(m_imageViews.at(imageIndex), VK_IMAGE_ASPECT_COLOR_BIT); - - VkViewport viewport; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = float(info.imageExtent.width); - viewport.height = float(info.imageExtent.height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor; - scissor.offset.x = 0; - scissor.offset.y = 0; - scissor.extent.width = info.imageExtent.width; - scissor.extent.height = info.imageExtent.height; - - m_context->setViewports(1, &viewport, &scissor); - - m_context->setRasterizerState(m_rsState); - m_context->setMultisampleState(m_msState); - m_context->setDepthStencilState(m_dsState); - m_context->setLogicOpState(m_loState); - m_context->setBlendMode(0, m_blendMode); - - m_context->setInputAssemblyState(m_iaState); - m_context->setInputLayout(0, nullptr, 0, nullptr); - - m_context->bindResourceSampler(BindingIds::Image, fitSize ? m_samplerFitting : m_samplerScaling); - m_context->bindResourceSampler(BindingIds::Gamma, m_gammaSampler); - - m_context->bindResourceView(BindingIds::Image, m_swapImageView, nullptr); - m_context->bindResourceView(BindingIds::Gamma, m_gammaTextureView, nullptr); - m_context->draw(3, 1, 0, 0); + m_blitter->presentImage(m_context.ptr(), + m_imageViews.at(imageIndex), VkRect2D(), + m_swapImageView, VkRect2D()); if (m_hud != nullptr) m_hud->render(m_context, info.format, info.imageExtent); @@ -508,7 +441,6 @@ namespace dxvk { m_backBuffer->ReleasePrivate(); m_swapImage = nullptr; - m_swapImageResolve = nullptr; m_swapImageView = nullptr; m_backBuffer = nullptr; @@ -550,34 +482,6 @@ namespace dxvk { m_swapImage = GetCommonTexture(m_backBuffer)->GetImage(); - // If the image is multisampled, we need to create - // another image which we'll use as a resolve target - if (m_swapImage->info().sampleCount != VK_SAMPLE_COUNT_1_BIT) { - DxvkImageCreateInfo resolveInfo; - resolveInfo.type = VK_IMAGE_TYPE_2D; - resolveInfo.format = m_swapImage->info().format; - resolveInfo.flags = 0; - resolveInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; - resolveInfo.extent = m_swapImage->info().extent; - resolveInfo.numLayers = 1; - resolveInfo.mipLevels = 1; - resolveInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT - | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - resolveInfo.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT - | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT - | VK_PIPELINE_STAGE_TRANSFER_BIT; - resolveInfo.access = VK_ACCESS_SHADER_READ_BIT - | VK_ACCESS_TRANSFER_WRITE_BIT - | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT - | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - resolveInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - resolveInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - m_swapImageResolve = m_device->createImage( - resolveInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - } - // Create an image view that allows the // image to be bound as a shader resource. DxvkImageViewCreateInfo viewInfo; @@ -589,12 +493,7 @@ namespace dxvk { viewInfo.numLevels = 1; viewInfo.minLayer = 0; viewInfo.numLayers = 1; - - m_swapImageView = m_device->createImageView( - m_swapImageResolve != nullptr - ? m_swapImageResolve - : m_swapImage, - viewInfo); + m_swapImageView = m_device->createImageView(m_swapImage, viewInfo); // Initialize the image so that we can use it. Clearing // to black prevents garbled output for the first frame. @@ -624,68 +523,8 @@ namespace dxvk { } - void D3D11SwapChain::CreateGammaTexture( - UINT NumControlPoints, - const D3D11_VK_GAMMA_CP* pControlPoints) { - if (m_gammaTexture == nullptr - || m_gammaTexture->info().extent.width != NumControlPoints) { - 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 = { NumControlPoints, 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_gammaTexture = 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_gammaTextureView = m_device->createImageView(m_gammaTexture, viewInfo); - } - - m_context->beginRecording( - m_device->createCommandList()); - - m_context->updateImage(m_gammaTexture, - VkImageSubresourceLayers { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, - VkOffset3D { 0, 0, 0 }, - VkExtent3D { NumControlPoints, 1, 1 }, - pControlPoints, 0, 0); - - m_device->submitCommandList( - m_context->endRecording(), - VK_NULL_HANDLE, - VK_NULL_HANDLE); - } - - - void D3D11SwapChain::DestroyFrameLatencyEvent() { - CloseHandle(m_frameLatencyEvent); - } - - - void D3D11SwapChain::DestroyGammaTexture() { - m_gammaTexture = nullptr; - m_gammaTextureView = nullptr; + void D3D11SwapChain::CreateBlitter() { + m_blitter = new DxvkSwapchainBlitter(m_device); } @@ -697,103 +536,8 @@ namespace dxvk { } - void D3D11SwapChain::InitRenderState() { - m_iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - m_iaState.primitiveRestart = VK_FALSE; - m_iaState.patchVertexCount = 0; - - m_rsState.polygonMode = VK_POLYGON_MODE_FILL; - m_rsState.cullMode = VK_CULL_MODE_BACK_BIT; - m_rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - m_rsState.depthClipEnable = VK_FALSE; - m_rsState.depthBiasEnable = VK_FALSE; - m_rsState.sampleCount = VK_SAMPLE_COUNT_1_BIT; - - m_msState.sampleMask = 0xffffffff; - m_msState.enableAlphaToCoverage = VK_FALSE; - - 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; - - m_dsState.enableDepthTest = VK_FALSE; - m_dsState.enableDepthWrite = VK_FALSE; - m_dsState.enableStencilTest = VK_FALSE; - m_dsState.depthCompareOp = VK_COMPARE_OP_ALWAYS; - m_dsState.stencilOpFront = stencilOp; - m_dsState.stencilOpBack = stencilOp; - - m_loState.enableLogicOp = VK_FALSE; - m_loState.logicOp = VK_LOGIC_OP_NO_OP; - - m_blendMode.enableBlending = VK_FALSE; - m_blendMode.colorSrcFactor = VK_BLEND_FACTOR_ONE; - m_blendMode.colorDstFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - m_blendMode.colorBlendOp = VK_BLEND_OP_ADD; - m_blendMode.alphaSrcFactor = VK_BLEND_FACTOR_ONE; - m_blendMode.alphaDstFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - m_blendMode.alphaBlendOp = VK_BLEND_OP_ADD; - m_blendMode.writeMask = VK_COLOR_COMPONENT_R_BIT - | VK_COLOR_COMPONENT_G_BIT - | VK_COLOR_COMPONENT_B_BIT - | VK_COLOR_COMPONENT_A_BIT; - } - - - void D3D11SwapChain::InitSamplers() { - DxvkSamplerCreateInfo samplerInfo; - samplerInfo.magFilter = VK_FILTER_NEAREST; - samplerInfo.minFilter = VK_FILTER_NEAREST; - 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_FALSE; - m_samplerFitting = m_device->createSampler(samplerInfo); - - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - m_samplerScaling = 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; - m_gammaSampler = m_device->createSampler(samplerInfo); - } - - - void D3D11SwapChain::InitShaders() { - const SpirvCodeBuffer vsCode(dxgi_presenter_vert); - const SpirvCodeBuffer fsCode(dxgi_presenter_frag); - - const std::array 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_vertShader = m_device->createShader( - VK_SHADER_STAGE_VERTEX_BIT, - 0, nullptr, { 0u, 1u }, - vsCode); - - m_fragShader = m_device->createShader( - VK_SHADER_STAGE_FRAGMENT_BIT, - fsResourceSlots.size(), - fsResourceSlots.data(), - { 1u, 1u }, fsCode); + void D3D11SwapChain::DestroyFrameLatencyEvent() { + CloseHandle(m_frameLatencyEvent); } diff --git a/src/d3d11/d3d11_swapchain.h b/src/d3d11/d3d11_swapchain.h index 4bc23b91..a120689f 100644 --- a/src/d3d11/d3d11_swapchain.h +++ b/src/d3d11/d3d11_swapchain.h @@ -4,6 +4,8 @@ #include "../dxvk/hud/dxvk_hud.h" +#include "../dxvk/dxvk_swapchain_blitter.h" + #include "../util/sync/sync_signal_win32.h" namespace dxvk { @@ -11,17 +13,6 @@ namespace dxvk { class D3D11Device; class D3D11DXGIDevice; - /** - * \brief Gamma control point - * - * Control points are stored as normalized - * 16-bit unsigned integer values that will - * be converted back to floats in the shader. - */ - struct D3D11_VK_GAMMA_CP { - uint16_t R, G, B, A; - }; - class D3D11SwapChain : public ComObject { constexpr static uint32_t DefaultFrameLatency = 1; public: @@ -87,42 +78,24 @@ namespace dxvk { Com m_dxgiDevice; - D3D11Device* m_parent; - HWND m_window; + D3D11Device* m_parent; + HWND m_window; - DXGI_SWAP_CHAIN_DESC1 m_desc; + DXGI_SWAP_CHAIN_DESC1 m_desc; - Rc m_device; - Rc m_context; + Rc m_device; + Rc m_context; - Rc m_presenter; + Rc m_presenter; - Rc m_vertShader; - Rc m_fragShader; + Rc m_swapImage; + Rc m_swapImageView; + Rc m_blitter; - Rc m_samplerFitting; - Rc m_samplerScaling; + Rc m_hud; - Rc m_gammaSampler; - Rc m_gammaTexture; - Rc m_gammaTextureView; - - Rc m_swapImage; - Rc m_swapImageResolve; - Rc m_swapImageView; - - Rc m_hud; - - DxvkInputAssemblyState m_iaState; - DxvkRasterizerState m_rsState; - DxvkMultisampleState m_msState; - DxvkDepthStencilState m_dsState; - DxvkLogicOpState m_loState; - DxvkBlendMode m_blendMode; - - D3D11Texture2D* m_backBuffer = nullptr; - - DxvkSubmitStatus m_presentStatus; + D3D11Texture2D* m_backBuffer = nullptr; + DxvkSubmitStatus m_presentStatus; std::vector> m_imageViews; @@ -155,21 +128,11 @@ namespace dxvk { void CreateBackBuffer(); - void CreateGammaTexture( - UINT NumControlPoints, - const D3D11_VK_GAMMA_CP* pControlPoints); - - void DestroyFrameLatencyEvent(); + void CreateBlitter(); - void DestroyGammaTexture(); - void CreateHud(); - void InitRenderState(); - - void InitSamplers(); - - void InitShaders(); + void DestroyFrameLatencyEvent(); void SignalFrameLatencyEvent(); diff --git a/src/d3d11/meson.build b/src/d3d11/meson.build index c6f93403..7f0d67f3 100644 --- a/src/d3d11/meson.build +++ b/src/d3d11/meson.build @@ -1,10 +1,5 @@ d3d11_res = wrc_generator.process('version.rc') -dxgi_shaders = files([ - '../dxgi/shaders/dxgi_presenter_frag.frag', - '../dxgi/shaders/dxgi_presenter_vert.vert', -]) - dxgi_common_src = [ '../dxgi/dxgi_format.cpp', '../dxgi/dxgi_monitor.cpp', @@ -63,7 +58,7 @@ d3d11_src = [ 'd3d11_view_uav.cpp', ] -d3d11_dll = shared_library('d3d11'+dll_ext, dxgi_common_src + d3d11_src + d3d10_src, glsl_generator.process(dxgi_shaders), d3d11_res, +d3d11_dll = shared_library('d3d11'+dll_ext, dxgi_common_src + d3d11_src + d3d10_src, d3d11_res, name_prefix : '', dependencies : [ lib_dxgi, dxbc_dep, dxvk_dep ], include_directories : dxvk_include_path, diff --git a/src/dxgi/shaders/dxgi_presenter_frag.frag b/src/dxgi/shaders/dxgi_presenter_frag.frag deleted file mode 100644 index e52a0d76..00000000 --- a/src/dxgi/shaders/dxgi_presenter_frag.frag +++ /dev/null @@ -1,21 +0,0 @@ -#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_texcoord; -layout(location = 0) out vec4 o_color; - -void main() { - o_color = texture(s_image, i_texcoord); - - 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); - } -} \ No newline at end of file diff --git a/src/dxgi/shaders/dxgi_presenter_vert.vert b/src/dxgi/shaders/dxgi_presenter_vert.vert deleted file mode 100644 index 1a9cde1d..00000000 --- a/src/dxgi/shaders/dxgi_presenter_vert.vert +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout(location = 0) out vec2 o_texcoord; - -void main() { - vec2 coord = vec2( - float(gl_VertexIndex & 2), - float(gl_VertexIndex & 1) * 2.0f); - - o_texcoord = coord; - gl_Position = vec4(-1.0f + 2.0f * coord, 0.0f, 1.0f); -} \ No newline at end of file