From 832b3a9dba8329f06df9fdcdd2d9f0935e704b4c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 28 Jun 2018 01:00:07 +0200 Subject: [PATCH] [hud] Render HUD directly to swap chain image Saves a fullscreen render target, render pass, and a queue submission. --- src/dxgi/dxgi_presenter.cpp | 107 +++++-------- src/dxgi/dxgi_presenter.h | 10 +- src/dxvk/hud/dxvk_hud.cpp | 249 ++++++++--------------------- src/dxvk/hud/dxvk_hud.h | 57 +++---- src/dxvk/hud/dxvk_hud_renderer.cpp | 11 +- src/dxvk/hud/dxvk_hud_renderer.h | 6 +- 6 files changed, 145 insertions(+), 295 deletions(-) diff --git a/src/dxgi/dxgi_presenter.cpp b/src/dxgi/dxgi_presenter.cpp index b4885b28..c20b34af 100644 --- a/src/dxgi/dxgi_presenter.cpp +++ b/src/dxgi/dxgi_presenter.cpp @@ -42,31 +42,22 @@ namespace dxvk { // Set up context state. The shader bindings and the // constant state objects will never be modified. - DxvkInputAssemblyState iaState; - iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - iaState.primitiveRestart = VK_FALSE; - iaState.patchVertexCount = 0; - m_context->setInputAssemblyState(iaState); + m_iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + m_iaState.primitiveRestart = VK_FALSE; + m_iaState.patchVertexCount = 0; - m_context->setInputLayout( - 0, nullptr, 0, nullptr); + 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.depthClampEnable = VK_FALSE; + m_rsState.depthBiasEnable = VK_FALSE; + m_rsState.depthBiasConstant = 0.0f; + m_rsState.depthBiasClamp = 0.0f; + m_rsState.depthBiasSlope = 0.0f; - DxvkRasterizerState rsState; - rsState.polygonMode = VK_POLYGON_MODE_FILL; - rsState.cullMode = VK_CULL_MODE_BACK_BIT; - rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rsState.depthClampEnable = VK_FALSE; - rsState.depthBiasEnable = VK_FALSE; - rsState.depthBiasConstant = 0.0f; - rsState.depthBiasClamp = 0.0f; - rsState.depthBiasSlope = 0.0f; - m_context->setRasterizerState(rsState); - - DxvkMultisampleState msState; - msState.sampleMask = 0xffffffff; - msState.enableAlphaToCoverage = VK_FALSE; - msState.enableAlphaToOne = VK_FALSE; - m_context->setMultisampleState(msState); + m_msState.sampleMask = 0xffffffff; + m_msState.enableAlphaToCoverage = VK_FALSE; + m_msState.enableAlphaToOne = VK_FALSE; VkStencilOpState stencilOp; stencilOp.failOp = VK_STENCIL_OP_KEEP; @@ -77,19 +68,15 @@ namespace dxvk { 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; - m_context->setDepthStencilState(dsState); + 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; - DxvkLogicOpState loState; - loState.enableLogicOp = VK_FALSE; - loState.logicOp = VK_LOGIC_OP_NO_OP; - m_context->setLogicOpState(loState); + 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; @@ -102,14 +89,9 @@ namespace dxvk { | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - - m_context->bindShader( - VK_SHADER_STAGE_VERTEX_BIT, - CreateVertexShader()); - - m_context->bindShader( - VK_SHADER_STAGE_FRAGMENT_BIT, - CreateFragmentShader()); + + m_vertShader = CreateVertexShader(); + m_fragShader = CreateFragmentShader(); m_hud = hud::Hud::createHud(m_device); } @@ -140,12 +122,8 @@ namespace dxvk { void DxgiVkPresenter::PresentImage(UINT SyncInterval) { - if (m_hud != nullptr) { - m_hud->render({ - m_options.preferredBufferSize.width, - m_options.preferredBufferSize.height, - }); - } + if (m_hud != nullptr) + m_hud->update(); // Check whether the back buffer size is the same // as the window size, in which case we should use @@ -176,6 +154,9 @@ namespace dxvk { auto swapSemas = m_swapchain->getSemaphorePair(); auto swapImage = m_swapchain->getImageView(swapSemas.acquireSync); + 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 = swapImage; renderTargets.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; @@ -197,25 +178,25 @@ namespace dxvk { m_context->setViewports(1, &viewport, &scissor); - m_context->bindResourceSampler(BindingIds::Sampler, - fitSize ? m_samplerFitting : m_samplerScaling); - - m_blendMode.enableBlending = VK_FALSE; + 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::Sampler, fitSize ? m_samplerFitting : m_samplerScaling); + m_context->bindResourceSampler(BindingIds::GammaSmp, m_gammaSampler); + m_context->bindResourceView(BindingIds::Texture, m_backBufferView, nullptr); + m_context->bindResourceView(BindingIds::GammaTex, m_gammaTextureView, nullptr); + m_context->draw(4, 1, 0, 0); - m_context->bindResourceSampler(BindingIds::GammaSmp, m_gammaSampler); - m_context->bindResourceView (BindingIds::GammaTex, m_gammaTextureView, nullptr); - - if (m_hud != nullptr) { - m_blendMode.enableBlending = VK_TRUE; - m_context->setBlendMode(0, m_blendMode); - - m_context->bindResourceView(BindingIds::Texture, m_hud->texture(), nullptr); - m_context->draw(4, 1, 0, 0); - } + if (m_hud != nullptr) + m_hud->render(m_context, m_options.preferredBufferSize); m_device->submitCommandList( m_context->endRecording(), diff --git a/src/dxgi/dxgi_presenter.h b/src/dxgi/dxgi_presenter.h index b13b50c1..980ea56e 100644 --- a/src/dxgi/dxgi_presenter.h +++ b/src/dxgi/dxgi_presenter.h @@ -136,6 +136,9 @@ namespace dxvk { Rc m_surface; Rc m_swapchain; + + Rc m_vertShader; + Rc m_fragShader; Rc m_samplerFitting; Rc m_samplerScaling; @@ -149,7 +152,12 @@ namespace dxvk { Rc m_gammaTextureView; Rc m_hud; - + + DxvkInputAssemblyState m_iaState; + DxvkRasterizerState m_rsState; + DxvkMultisampleState m_msState; + DxvkDepthStencilState m_dsState; + DxvkLogicOpState m_loState; DxvkBlendMode m_blendMode; DxvkSwapchainProperties m_options; diff --git a/src/dxvk/hud/dxvk_hud.cpp b/src/dxvk/hud/dxvk_hud.cpp index 5b7858fc..f7e43605 100644 --- a/src/dxvk/hud/dxvk_hud.cpp +++ b/src/dxvk/hud/dxvk_hud.cpp @@ -9,13 +9,32 @@ namespace dxvk::hud { const HudConfig& config) : m_config (config), m_device (device), - m_context (m_device->createContext()), - m_renderer (m_device, m_context), m_uniformBuffer (createUniformBuffer()), + m_renderer (device), m_hudDeviceInfo (device), m_hudFramerate (config.elements), m_hudStats (config.elements) { - this->setupConstantState(); + // Set up constant state + m_rsState.polygonMode = VK_POLYGON_MODE_FILL; + m_rsState.cullMode = VK_CULL_MODE_BACK_BIT; + m_rsState.frontFace = VK_FRONT_FACE_CLOCKWISE; + m_rsState.depthClampEnable = VK_FALSE; + m_rsState.depthBiasEnable = VK_FALSE; + m_rsState.depthBiasConstant = 0.0f; + m_rsState.depthBiasClamp = 0.0f; + m_rsState.depthBiasSlope = 0.0f; + + m_blendMode.enableBlending = VK_TRUE; + 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; } @@ -24,21 +43,20 @@ namespace dxvk::hud { } - void Hud::render(VkExtent2D size) { - bool recreateFbo = m_surfaceSize != size; - - if (recreateFbo) { - m_surfaceSize = size; - this->setupFramebuffer(size); - } - + void Hud::update() { m_hudFramerate.update(); m_hudStats.update(m_device); + } + + + void Hud::render(const Rc& ctx, VkExtent2D surfaceSize) { + HudUniformData uniformData; + uniformData.surfaceSize = surfaceSize; - this->beginRenderPass(recreateFbo); - this->updateUniformBuffer(); - this->render(); - this->endRenderPass(); + this->updateUniformBuffer(ctx, uniformData); + + this->setupRendererState(ctx); + this->renderHudElements(ctx); } @@ -49,8 +67,40 @@ namespace dxvk::hud { ? new Hud(device, config) : nullptr; } + + + void Hud::setupRendererState(const Rc& ctx) { + ctx->setRasterizerState(m_rsState); + ctx->setBlendMode(0, m_blendMode); + + ctx->bindResourceBuffer(0, + DxvkBufferSlice(m_uniformBuffer)); + + m_renderer.beginFrame(ctx); + } + + + void Hud::renderHudElements(const Rc& ctx) { + HudPos position = { 8.0f, 24.0f }; + + if (m_config.elements.test(HudElement::DeviceInfo)) { + position = m_hudDeviceInfo.render( + ctx, m_renderer, position); + } + + position = m_hudFramerate.render(ctx, m_renderer, position); + position = m_hudStats .render(ctx, m_renderer, position); + } + void Hud::updateUniformBuffer(const Rc& ctx, const HudUniformData& data) { + auto slice = m_uniformBuffer->allocPhysicalSlice(); + std::memcpy(slice.mapPtr(0), &data, sizeof(data)); + + ctx->invalidateBuffer(m_uniformBuffer, slice); + } + + Rc Hud::createUniformBuffer() { DxvkBufferCreateInfo info; info.size = sizeof(HudUniformData); @@ -64,173 +114,4 @@ namespace dxvk::hud { VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); } - - void Hud::render() { - m_renderer.beginFrame(m_context); - - HudPos position = { 8.0f, 24.0f }; - - if (m_config.elements.test(HudElement::DeviceInfo)) { - position = m_hudDeviceInfo.render( - m_context, m_renderer, position); - } - - position = m_hudFramerate.render(m_context, m_renderer, position); - position = m_hudStats .render(m_context, m_renderer, position); - } - - - void Hud::updateUniformBuffer() { - HudUniformData uniformData; - uniformData.surfaceSize = m_surfaceSize; - - auto slice = m_uniformBuffer->allocPhysicalSlice(); - m_context->invalidateBuffer(m_uniformBuffer, slice); - std::memcpy(slice.mapPtr(0), &uniformData, sizeof(uniformData)); - } - - - void Hud::beginRenderPass(bool initFbo) { - m_context->beginRecording( - m_device->createCommandList()); - - if (initFbo) { - m_context->initImage(m_renderTarget, - VkImageSubresourceRange { - VK_IMAGE_ASPECT_COLOR_BIT, - 0, 1, 0, 1 }); - } - - VkClearRect clearRect; - clearRect.rect.offset = { 0, 0 }; - clearRect.rect.extent = m_surfaceSize; - clearRect.baseArrayLayer = 0; - clearRect.layerCount = 1; - - m_context->bindRenderTargets( - m_renderTargetInfo, false); - - m_context->clearRenderTarget( - m_renderTargetView, clearRect, - VK_IMAGE_ASPECT_COLOR_BIT, - VkClearValue { }); - - VkViewport viewport; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(m_surfaceSize.width); - viewport.height = static_cast(m_surfaceSize.height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor; - scissor.offset = { 0, 0 }; - scissor.extent = m_surfaceSize; - - m_context->setViewports(1, &viewport, &scissor); - m_context->bindResourceBuffer(0, DxvkBufferSlice(m_uniformBuffer)); - } - - - void Hud::endRenderPass() { - m_device->submitCommandList( - m_context->endRecording(), - nullptr, nullptr); - } - - - void Hud::setupFramebuffer(VkExtent2D size) { - DxvkImageCreateInfo imageInfo; - imageInfo.type = VK_IMAGE_TYPE_2D; - imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB; - imageInfo.flags = 0; - imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; - imageInfo.extent = { size.width, size.height, 1 }; - imageInfo.numLayers = 1; - imageInfo.mipLevels = 1; - imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - | VK_IMAGE_USAGE_SAMPLED_BIT; - imageInfo.stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT - | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - imageInfo.access = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT - | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT - | VK_ACCESS_SHADER_READ_BIT; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - m_renderTarget = m_device->createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - DxvkImageViewCreateInfo viewInfo; - viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.format = imageInfo.format; - viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT; - viewInfo.minLevel = 0; - viewInfo.numLevels = 1; - viewInfo.minLayer = 0; - viewInfo.numLayers = 1; - - m_renderTargetView = m_device->createImageView(m_renderTarget, viewInfo); - m_renderTargetInfo.color[0] = { m_renderTargetView, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - } - - - void Hud::setupConstantState() { - DxvkRasterizerState rsState; - rsState.polygonMode = VK_POLYGON_MODE_FILL; - rsState.cullMode = VK_CULL_MODE_BACK_BIT; - rsState.frontFace = VK_FRONT_FACE_CLOCKWISE; - rsState.depthClampEnable = VK_FALSE; - rsState.depthBiasEnable = VK_FALSE; - rsState.depthBiasConstant = 0.0f; - rsState.depthBiasClamp = 0.0f; - rsState.depthBiasSlope = 0.0f; - m_context->setRasterizerState(rsState); - - DxvkMultisampleState msState; - msState.sampleMask = 0xFFFFFFFF; - msState.enableAlphaToCoverage = VK_FALSE; - msState.enableAlphaToOne = VK_FALSE; - m_context->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_NEVER; - 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_NEVER; - dsState.stencilOpFront = stencilOp; - dsState.stencilOpBack = stencilOp; - m_context->setDepthStencilState(dsState); - - DxvkLogicOpState loState; - loState.enableLogicOp = VK_FALSE; - loState.logicOp = VK_LOGIC_OP_NO_OP; - m_context->setLogicOpState(loState); - - DxvkBlendMode blendMode; - blendMode.enableBlending = VK_TRUE; - 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; - - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) - m_context->setBlendMode(i, blendMode); - } - } \ No newline at end of file diff --git a/src/dxvk/hud/dxvk_hud.h b/src/dxvk/hud/dxvk_hud.h index efb09e45..cb260945 100644 --- a/src/dxvk/hud/dxvk_hud.h +++ b/src/dxvk/hud/dxvk_hud.h @@ -36,25 +36,11 @@ namespace dxvk::hud { ~Hud(); - /** - * \brief Renders the HUD - * - * Recreates the render targets for the HUD - * in case the surface size has changed. - * \param [in] size Render target size - */ - void render(VkExtent2D size); - - /** - * \brief Rendered image - * - * Returns the rendered image from - * the previous call to \ref render. - * \returns The image view - */ - Rc texture() const { - return m_renderTargetView; - } + void update(); + + void render( + const Rc& ctx, + VkExtent2D surfaceSize); /** * \brief Creates the HUD @@ -70,33 +56,30 @@ namespace dxvk::hud { private: const HudConfig m_config; - const Rc m_device; - const Rc m_context; - - HudRenderer m_renderer; - VkExtent2D m_surfaceSize = { 0, 0 }; Rc m_uniformBuffer; - Rc m_renderTarget; - Rc m_renderTargetView; - DxvkRenderTargets m_renderTargetInfo; - + + DxvkRasterizerState m_rsState; + DxvkBlendMode m_blendMode; + + HudRenderer m_renderer; HudDeviceInfo m_hudDeviceInfo; HudFps m_hudFramerate; HudStats m_hudStats; - - void render(); + + void setupRendererState( + const Rc& ctx); + + void renderHudElements( + const Rc& ctx); + + void updateUniformBuffer( + const Rc& ctx, + const HudUniformData& data); Rc createUniformBuffer(); - void updateUniformBuffer(); - void beginRenderPass(bool initFbo); - void endRenderPass(); - - void setupFramebuffer(VkExtent2D size); - void setupConstantState(); - }; } \ No newline at end of file diff --git a/src/dxvk/hud/dxvk_hud_renderer.cpp b/src/dxvk/hud/dxvk_hud_renderer.cpp index 18c6da0b..5e68ae54 100644 --- a/src/dxvk/hud/dxvk_hud_renderer.cpp +++ b/src/dxvk/hud/dxvk_hud_renderer.cpp @@ -6,9 +6,7 @@ namespace dxvk::hud { - HudRenderer::HudRenderer( - const Rc& device, - const Rc& context) + HudRenderer::HudRenderer(const Rc& device) : m_mode (Mode::RenderNone), m_vertShader (createVertexShader(device)), m_textShader (createTextShader(device)), @@ -17,7 +15,7 @@ namespace dxvk::hud { m_fontView (createFontView(device)), m_fontSampler (createFontSampler(device)), m_vertexBuffer (createVertexBuffer(device)) { - this->initFontTexture(device, context); + this->initFontTexture(device); this->initCharMap(); } @@ -301,8 +299,9 @@ namespace dxvk::hud { void HudRenderer::initFontTexture( - const Rc& device, - const Rc& context) { + const Rc& device) { + Rc context = device->createContext(); + context->beginRecording( device->createCommandList()); diff --git a/src/dxvk/hud/dxvk_hud_renderer.h b/src/dxvk/hud/dxvk_hud_renderer.h index 0ab04c7e..e9747e64 100644 --- a/src/dxvk/hud/dxvk_hud_renderer.h +++ b/src/dxvk/hud/dxvk_hud_renderer.h @@ -61,8 +61,7 @@ namespace dxvk::hud { public: HudRenderer( - const Rc& device, - const Rc& context); + const Rc& device); ~HudRenderer(); @@ -130,8 +129,7 @@ namespace dxvk::hud { const Rc& device); void initFontTexture( - const Rc& device, - const Rc& context); + const Rc& device); void initCharMap();