From 49e5357a87c6ef1dc0cb3ff1ed9f3048c4a12928 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 20 Feb 2022 15:40:49 +0100 Subject: [PATCH] [hud] Greatly simplify frame time graph rendering --- src/dxvk/hud/dxvk_hud_item.cpp | 18 ++-- src/dxvk/hud/dxvk_hud_item.h | 2 +- src/dxvk/hud/dxvk_hud_renderer.cpp | 122 ++++++++--------------- src/dxvk/hud/dxvk_hud_renderer.h | 51 +++++----- src/dxvk/hud/shaders/hud_graph_frag.frag | 61 ++++++++++++ src/dxvk/hud/shaders/hud_graph_vert.vert | 23 +++++ src/dxvk/hud/shaders/hud_line_frag.frag | 23 ----- src/dxvk/hud/shaders/hud_line_vert.vert | 13 --- src/dxvk/meson.build | 4 +- 9 files changed, 162 insertions(+), 155 deletions(-) create mode 100644 src/dxvk/hud/shaders/hud_graph_frag.frag create mode 100644 src/dxvk/hud/shaders/hud_graph_vert.vert delete mode 100644 src/dxvk/hud/shaders/hud_line_frag.frag delete mode 100644 src/dxvk/hud/shaders/hud_line_vert.vert diff --git a/src/dxvk/hud/dxvk_hud_item.cpp b/src/dxvk/hud/dxvk_hud_item.cpp index 1b81706f1..d236287a8 100644 --- a/src/dxvk/hud/dxvk_hud_item.cpp +++ b/src/dxvk/hud/dxvk_hud_item.cpp @@ -226,8 +226,7 @@ namespace dxvk::hud { HudPos HudFrameTimeItem::render( HudRenderer& renderer, HudPos position) { - std::array vData; - position.y += 40.0f; + std::array points; // 60 FPS = optimal, 10 FPS = worst const float targetUs = 16'666.6f; @@ -255,21 +254,18 @@ namespace dxvk::hud { uint8_t(255.0f * (g / l)), uint8_t(0), uint8_t(255) }; - float x = position.x + float(i); - float y = position.y; - float hVal = std::log2(std::max((us - minUs) / targetUs + 1.0f, 1.0f)) / std::log2((maxUs - minUs) / targetUs); - float h = std::min(std::max(40.0f * hVal, 2.0f), 40.0f); - vData[2 * i + 0] = HudLineVertex { { x, y }, color }; - vData[2 * i + 1] = HudLineVertex { { x, y - h }, color }; + points[i].value = std::max(hVal, 1.0f / 40.0f); + points[i].color = color; } - renderer.drawLines(vData.size(), vData.data()); + renderer.drawGraph(position, + HudPos { float(NumDataPoints), 40.0f }, + points.size(), points.data()); - // Paint min/max frame times in the entire window - position.y += 18.0f; + position.y += 58.0f; renderer.drawText(12.0f, { position.x, position.y }, diff --git a/src/dxvk/hud/dxvk_hud_item.h b/src/dxvk/hud/dxvk_hud_item.h index 88683f0f0..275461c6d 100644 --- a/src/dxvk/hud/dxvk_hud_item.h +++ b/src/dxvk/hud/dxvk_hud_item.h @@ -213,7 +213,7 @@ namespace dxvk::hud { * \brief HUD item to display the frame rate */ class HudFrameTimeItem : public HudItem { - constexpr static size_t NumDataPoints = 300; + constexpr static size_t NumDataPoints = 304; public: HudFrameTimeItem(); diff --git a/src/dxvk/hud/dxvk_hud_renderer.cpp b/src/dxvk/hud/dxvk_hud_renderer.cpp index a6ee62586..cc5dd6eb5 100644 --- a/src/dxvk/hud/dxvk_hud_renderer.cpp +++ b/src/dxvk/hud/dxvk_hud_renderer.cpp @@ -1,7 +1,7 @@ #include "dxvk_hud_renderer.h" -#include -#include +#include +#include #include #include @@ -14,15 +14,14 @@ namespace dxvk::hud { m_surfaceSize { 0, 0 }, m_device (device), m_textShaders (createTextShaders()), - m_lineShaders (createLineShaders()), + m_graphShaders (createGraphShaders()), m_dataBuffer (createDataBuffer()), m_dataView (createDataView()), m_dataOffset (0ull), m_fontBuffer (createFontBuffer()), m_fontImage (createFontImage()), m_fontView (createFontView()), - m_fontSampler (createFontSampler()), - m_vertexBuffer (createVertexBuffer()) { + m_fontSampler (createFontSampler()) { } @@ -40,8 +39,6 @@ namespace dxvk::hud { m_scale = scale; m_surfaceSize = surfaceSize; m_context = context; - - allocVertexBufferSlice(); } @@ -79,42 +76,30 @@ namespace dxvk::hud { } - void HudRenderer::drawLines( - size_t vertexCount, - const HudLineVertex* vertexData) { - beginLineRendering(); + void HudRenderer::drawGraph( + HudPos pos, + HudPos size, + size_t pointCount, + const HudGraphPoint* pointData) { + beginGraphRendering(); - const float xscale = m_scale / std::max(float(m_surfaceSize.width), 1.0f); - const float yscale = m_scale / std::max(float(m_surfaceSize.height), 1.0f); + VkDeviceSize dataSize = pointCount * sizeof(*pointData); + VkDeviceSize offset = allocDataBuffer(dataSize); + std::memcpy(m_dataBuffer->mapPtr(offset), pointData, dataSize); - if (m_currLineVertex + vertexCount > MaxLineVertexCount) - allocVertexBufferSlice(); + HudGraphPushConstants pushData; + pushData.offset = offset / sizeof(*pointData); + pushData.count = pointCount; + pushData.pos = pos; + pushData.size = size; + pushData.scale.x = m_scale / std::max(float(m_surfaceSize.width), 1.0f); + pushData.scale.y = m_scale / std::max(float(m_surfaceSize.height), 1.0f); - m_context->draw(vertexCount, 1, m_currLineVertex, 0); - - for (size_t i = 0; i < vertexCount; i++) { - uint32_t idx = m_currLineVertex + i; - - m_vertexData->lineVertices[idx].position = { - xscale * vertexData[i].position.x, - yscale * vertexData[i].position.y }; - m_vertexData->lineVertices[idx].color = vertexData[i].color; - } - - m_currLineVertex += vertexCount; + m_context->pushConstants(0, sizeof(pushData), &pushData); + m_context->draw(4, 1, 0, 0); } - void HudRenderer::allocVertexBufferSlice() { - auto vertexSlice = m_vertexBuffer->allocSlice(); - m_context->invalidateBuffer(m_vertexBuffer, vertexSlice); - - m_currLineVertex = 0; - - m_vertexData = reinterpret_cast(vertexSlice.mapPtr); - } - - void HudRenderer::beginTextRendering() { if (m_mode != Mode::RenderText) { m_mode = Mode::RenderText; @@ -137,34 +122,21 @@ namespace dxvk::hud { } - void HudRenderer::beginLineRendering() { - if (m_mode != Mode::RenderLines) { - m_mode = Mode::RenderLines; + void HudRenderer::beginGraphRendering() { + if (m_mode != Mode::RenderGraph) { + m_mode = Mode::RenderGraph; - m_context->bindVertexBuffer(0, DxvkBufferSlice(m_vertexBuffer, offsetof(VertexBufferData, lineVertices), sizeof(HudLineVertex) * MaxLineVertexCount), sizeof(HudLineVertex)); - - m_context->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_lineShaders.vert); - m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_lineShaders.frag); + m_context->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_graphShaders.vert); + m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_graphShaders.frag); + m_context->bindResourceBuffer(0, DxvkBufferSlice(m_dataBuffer)); + static const DxvkInputAssemblyState iaState = { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, VK_FALSE, 0 }; - static const std::array ilAttributes = {{ - { 0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(HudLineVertex, position) }, - { 1, 0, VK_FORMAT_R8G8B8A8_UNORM, offsetof(HudLineVertex, color) }, - }}; - - static const std::array ilBindings = {{ - { 0, 0, VK_VERTEX_INPUT_RATE_VERTEX }, - }}; - m_context->setInputAssemblyState(iaState); - m_context->setInputLayout( - ilAttributes.size(), - ilAttributes.data(), - ilBindings.size(), - ilBindings.data()); + m_context->setInputLayout(0, nullptr, 0, nullptr); } } @@ -214,19 +186,27 @@ namespace dxvk::hud { } - HudRenderer::ShaderPair HudRenderer::createLineShaders() { + HudRenderer::ShaderPair HudRenderer::createGraphShaders() { ShaderPair result; - const SpirvCodeBuffer vsCode(hud_line_vert); - const SpirvCodeBuffer fsCode(hud_line_frag); + const SpirvCodeBuffer vsCode(hud_graph_vert); + const SpirvCodeBuffer fsCode(hud_graph_frag); + const std::array fsResources = {{ + { 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM }, + }}; + result.vert = m_device->createShader( - VK_SHADER_STAGE_VERTEX_BIT, - 0, nullptr, { 0x3, 0x1 }, vsCode); + VK_SHADER_STAGE_VERTEX_BIT, 0, nullptr, + { 0x3, 0x1, 0, sizeof(HudGraphPushConstants) }, + vsCode); result.frag = m_device->createShader( VK_SHADER_STAGE_FRAGMENT_BIT, - 0, nullptr, { 0x1, 0x1 }, fsCode); + fsResources.size(), + fsResources.data(), + { 0x1, 0x1, 0, sizeof(HudGraphPushConstants) }, + fsCode); return result; } @@ -331,20 +311,6 @@ namespace dxvk::hud { } - Rc HudRenderer::createVertexBuffer() { - DxvkBufferCreateInfo info; - info.size = sizeof(VertexBufferData); - info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - info.stages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; - info.access = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - - return m_device->createBuffer(info, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - } - - void HudRenderer::initFontTexture( const Rc& context) { HudFontGpuData gpuData = { }; diff --git a/src/dxvk/hud/dxvk_hud_renderer.h b/src/dxvk/hud/dxvk_hud_renderer.h index e118e0ea6..3986fba81 100644 --- a/src/dxvk/hud/dxvk_hud_renderer.h +++ b/src/dxvk/hud/dxvk_hud_renderer.h @@ -32,20 +32,21 @@ namespace dxvk::hud { /** * \brief Normalized color + * * SRGB color with alpha channel. */ struct HudNormColor { - uint8_t r; - uint8_t g; - uint8_t b; uint8_t a; + uint8_t b; + uint8_t g; + uint8_t r; }; /** - * \brief Line vertex and color + * \brief Graph point with color */ - struct HudLineVertex { - HudPos position; + struct HudGraphPoint { + float value; HudNormColor color; }; @@ -60,6 +61,14 @@ namespace dxvk::hud { HudPos scale; }; + struct HudGraphPushConstants { + uint32_t offset; + uint32_t count; + HudPos pos; + HudPos size; + HudPos scale; + }; + /** * \brief Glyph data */ @@ -87,11 +96,6 @@ namespace dxvk::hud { */ class HudRenderer { constexpr static VkDeviceSize DataBufferSize = 16384; - constexpr static uint32_t MaxLineVertexCount = 1024; - - struct VertexBufferData { - HudLineVertex lineVertices[MaxLineVertexCount]; - }; public: HudRenderer( @@ -110,9 +114,11 @@ namespace dxvk::hud { HudColor color, const std::string& text); - void drawLines( - size_t vertexCount, - const HudLineVertex* vertexData); + void drawGraph( + HudPos pos, + HudPos size, + size_t pointCount, + const HudGraphPoint* pointData); VkExtent2D surfaceSize() const { return m_surfaceSize; @@ -127,7 +133,7 @@ namespace dxvk::hud { enum class Mode { RenderNone, RenderText, - RenderLines, + RenderGraph, }; struct ShaderPair { @@ -143,7 +149,7 @@ namespace dxvk::hud { Rc m_context; ShaderPair m_textShaders; - ShaderPair m_lineShaders; + ShaderPair m_graphShaders; Rc m_dataBuffer; Rc m_dataView; @@ -153,24 +159,17 @@ namespace dxvk::hud { Rc m_fontImage; Rc m_fontView; Rc m_fontSampler; - - Rc m_vertexBuffer; - VertexBufferData* m_vertexData = nullptr; - - uint32_t m_currLineVertex = 0; bool m_initialized = false; - void allocVertexBufferSlice(); - void beginTextRendering(); - void beginLineRendering(); + void beginGraphRendering(); VkDeviceSize allocDataBuffer(VkDeviceSize size); ShaderPair createTextShaders(); - ShaderPair createLineShaders(); + ShaderPair createGraphShaders(); Rc createDataBuffer(); Rc createDataView(); @@ -179,8 +178,6 @@ namespace dxvk::hud { Rc createFontImage(); Rc createFontView(); Rc createFontSampler(); - - Rc createVertexBuffer(); void initFontTexture( const Rc& context); diff --git a/src/dxvk/hud/shaders/hud_graph_frag.frag b/src/dxvk/hud/shaders/hud_graph_frag.frag new file mode 100644 index 000000000..b45aa43ef --- /dev/null +++ b/src/dxvk/hud/shaders/hud_graph_frag.frag @@ -0,0 +1,61 @@ +#version 450 + +layout(constant_id = 1225) const bool srgbSwapchain = false; + +layout(location = 0) in vec2 v_coord; +layout(location = 0) out vec4 o_color; + +struct line_point_t { + float value; + uint color; +}; + +layout(binding = 0, std430) +readonly buffer line_data_t { + line_point_t points[]; +}; + +layout(push_constant) +uniform push_data_t { + uint offset; + uint count; + vec2 pos; + vec2 size; + vec2 scale; +}; + +vec3 linearToSrgb(vec3 color) { + bvec3 isLo = lessThanEqual(color, vec3(0.0031308f)); + + vec3 loPart = color * 12.92f; + vec3 hiPart = pow(color, vec3(5.0f / 12.0f)) * 1.055f - 0.055f; + return mix(hiPart, loPart, isLo); +} + +void main() { + float cx = v_coord.x * float(count); + float fx = fract(cx); + + // We need to roll our own linear interpolation here + uint p0_idx = min(uint(floor(cx)), count - 1) + offset; + uint p1_idx = min(uint(ceil(cx)), count - 1) + offset; + + line_point_t p0 = points[p0_idx]; + line_point_t p1 = points[p1_idx]; + + float value = mix(p0.value, p1.value, fx); + float alpha = value + v_coord.y - 1.0f; + alpha = min(alpha / dFdy(v_coord.y), 1.0f); + + if (alpha <= 0.0f) + discard; + + o_color = mix( + unpackUnorm4x8(p0.color), + unpackUnorm4x8(p1.color), fx); + + if (!srgbSwapchain) + o_color.rgb = linearToSrgb(o_color.rgb); + + o_color *= alpha; +} \ No newline at end of file diff --git a/src/dxvk/hud/shaders/hud_graph_vert.vert b/src/dxvk/hud/shaders/hud_graph_vert.vert new file mode 100644 index 000000000..884dc3187 --- /dev/null +++ b/src/dxvk/hud/shaders/hud_graph_vert.vert @@ -0,0 +1,23 @@ +#version 450 + +layout(location = 0) out vec2 o_coord; + +layout(push_constant) +uniform push_data_t { + uint offset; + uint count; + vec2 pos; + vec2 size; + vec2 scale; +}; + +void main() { + vec2 coord = vec2( + float(gl_VertexIndex & 1), + float(gl_VertexIndex >> 1)); + o_coord = coord; + + vec2 pixel_pos = pos + size * coord; + vec2 scaled_pos = 2.0f * scale * pixel_pos - 1.0f; + gl_Position = vec4(scaled_pos, 0.0f, 1.0f); +} diff --git a/src/dxvk/hud/shaders/hud_line_frag.frag b/src/dxvk/hud/shaders/hud_line_frag.frag deleted file mode 100644 index 73c348657..000000000 --- a/src/dxvk/hud/shaders/hud_line_frag.frag +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout(constant_id = 1225) const bool srgbSwapchain = false; - -layout(location = 0) in vec4 v_color; -layout(location = 0) out vec4 o_color; - -vec3 linearToSrgb(vec3 color) { - bvec3 isLo = lessThanEqual(color, vec3(0.0031308f)); - - vec3 loPart = color * 12.92f; - vec3 hiPart = pow(color, vec3(5.0f / 12.0f)) * 1.055f - 0.055f; - return mix(hiPart, loPart, isLo); -} - -void main() { - o_color = vec4( - v_color.rgb * v_color.a, - v_color.a); - - if (!srgbSwapchain) - o_color.rgb = linearToSrgb(o_color.rgb); -} \ No newline at end of file diff --git a/src/dxvk/hud/shaders/hud_line_vert.vert b/src/dxvk/hud/shaders/hud_line_vert.vert deleted file mode 100644 index 6154baf3e..000000000 --- a/src/dxvk/hud/shaders/hud_line_vert.vert +++ /dev/null @@ -1,13 +0,0 @@ -#version 450 - -layout(location = 0) in vec2 v_position; -layout(location = 1) in vec4 v_color; - -layout(location = 0) out vec4 o_color; - -void main() { - o_color = v_color; - - vec2 pos = 2.0f * v_position - 1.0f; - gl_Position = vec4(pos, 0.0f, 1.0f); -} \ No newline at end of file diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build index a68d0e117..1b61bf20a 100644 --- a/src/dxvk/meson.build +++ b/src/dxvk/meson.build @@ -51,8 +51,8 @@ dxvk_shaders = files([ 'shaders/dxvk_unpack_d24s8.comp', 'shaders/dxvk_unpack_d32s8.comp', - 'hud/shaders/hud_line_frag.frag', - 'hud/shaders/hud_line_vert.vert', + 'hud/shaders/hud_graph_frag.frag', + 'hud/shaders/hud_graph_vert.vert', 'hud/shaders/hud_text_frag.frag', 'hud/shaders/hud_text_vert.vert',