From c6fb8fa5e89def689cf70ef04ceb890f82cccb4c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 16 Dec 2019 00:01:28 +0100 Subject: [PATCH] [hud] Clean up HUD rendering - Avoids rebinding the vertex buffer on every single draw. - Avoids push constants. We could use MultiDrawIndirect in the future. - Slightly reduces the vertex buffer size. --- src/dxvk/hud/dxvk_hud_renderer.cpp | 108 +++++++++++++----------- src/dxvk/hud/dxvk_hud_renderer.h | 19 ++++- src/dxvk/hud/shaders/hud_text_frag.frag | 9 +- src/dxvk/hud/shaders/hud_text_vert.vert | 3 + 4 files changed, 80 insertions(+), 59 deletions(-) diff --git a/src/dxvk/hud/dxvk_hud_renderer.cpp b/src/dxvk/hud/dxvk_hud_renderer.cpp index 4f4e6b22..1823de97 100644 --- a/src/dxvk/hud/dxvk_hud_renderer.cpp +++ b/src/dxvk/hud/dxvk_hud_renderer.cpp @@ -28,15 +28,14 @@ namespace dxvk::hud { void HudRenderer::beginFrame(const Rc& context, VkExtent2D surfaceSize) { - auto vertexSlice = m_vertexBuffer->allocSlice(); - context->invalidateBuffer(m_vertexBuffer, vertexSlice); - context->bindResourceSampler(1, m_fontSampler); context->bindResourceView (1, m_fontView, nullptr); m_mode = Mode::RenderNone; m_surfaceSize = surfaceSize; m_context = context; + + allocVertexBufferSlice(); } @@ -52,14 +51,12 @@ namespace dxvk::hud { uint32_t vertexCount = 6 * text.size(); - auto vertexSlice = allocVertexBuffer(vertexCount * sizeof(HudTextVertex)); - m_context->bindVertexBuffer(0, vertexSlice, sizeof(HudTextVertex)); - m_context->pushConstants(0, sizeof(color), &color); - m_context->draw(vertexCount, 1, 0, 0); + if (m_currTextVertex + vertexCount > MaxTextVertexCount + || m_currTextInstance + 1 > MaxTextInstanceCount) + allocVertexBufferSlice(); + + m_context->draw(vertexCount, 1, m_currTextVertex, m_currTextInstance); - auto vertexData = reinterpret_cast( - vertexSlice.getSliceHandle().mapPtr); - const float sizeFactor = size / float(g_hudFont.size); for (size_t i = 0; i < text.size(); i++) { @@ -79,27 +76,34 @@ namespace dxvk::hud { HudTexCoord texTl = { uint32_t(glyph.x), uint32_t(glyph.y) }; HudTexCoord texBr = { uint32_t(glyph.x + glyph.w), uint32_t(glyph.y + glyph.h) }; + + uint32_t idx = 6 * i + m_currTextVertex; - vertexData[6 * i + 0].position = { posTl.x, posTl.y }; - vertexData[6 * i + 0].texcoord = { texTl.u, texTl.v }; + m_vertexData->textVertices[idx + 0].position = { posTl.x, posTl.y }; + m_vertexData->textVertices[idx + 0].texcoord = { texTl.u, texTl.v }; - vertexData[6 * i + 1].position = { posBr.x, posTl.y }; - vertexData[6 * i + 1].texcoord = { texBr.u, texTl.v }; + m_vertexData->textVertices[idx + 1].position = { posBr.x, posTl.y }; + m_vertexData->textVertices[idx + 1].texcoord = { texBr.u, texTl.v }; - vertexData[6 * i + 2].position = { posTl.x, posBr.y }; - vertexData[6 * i + 2].texcoord = { texTl.u, texBr.v }; + m_vertexData->textVertices[idx + 2].position = { posTl.x, posBr.y }; + m_vertexData->textVertices[idx + 2].texcoord = { texTl.u, texBr.v }; - vertexData[6 * i + 3].position = { posBr.x, posBr.y }; - vertexData[6 * i + 3].texcoord = { texBr.u, texBr.v }; + m_vertexData->textVertices[idx + 3].position = { posBr.x, posBr.y }; + m_vertexData->textVertices[idx + 3].texcoord = { texBr.u, texBr.v }; - vertexData[6 * i + 4].position = { posTl.x, posBr.y }; - vertexData[6 * i + 4].texcoord = { texTl.u, texBr.v }; + m_vertexData->textVertices[idx + 4].position = { posTl.x, posBr.y }; + m_vertexData->textVertices[idx + 4].texcoord = { texTl.u, texBr.v }; - vertexData[6 * i + 5].position = { posBr.x, posTl.y }; - vertexData[6 * i + 5].texcoord = { texBr.u, texTl.v }; + m_vertexData->textVertices[idx + 5].position = { posBr.x, posTl.y }; + m_vertexData->textVertices[idx + 5].texcoord = { texBr.u, texTl.v }; pos.x += sizeFactor * static_cast(g_hudFont.advance); } + + m_vertexData->textColors[m_currTextInstance] = color; + + m_currTextVertex += vertexCount; + m_currTextInstance += 1; } @@ -111,41 +115,43 @@ namespace dxvk::hud { const float xscale = 1.0f / std::max(float(m_surfaceSize.width), 1.0f); const float yscale = 1.0f / std::max(float(m_surfaceSize.height), 1.0f); - auto vertexSlice = allocVertexBuffer(vertexCount * sizeof(HudLineVertex)); - m_context->bindVertexBuffer(0, vertexSlice, sizeof(HudLineVertex)); - m_context->draw(vertexCount, 1, 0, 0); - - auto dstVertexData = reinterpret_cast( - vertexSlice.getSliceHandle().mapPtr); + if (m_currLineVertex + vertexCount > MaxLineVertexCount) + allocVertexBufferSlice(); + + m_context->draw(vertexCount, 1, m_currLineVertex, 0); for (size_t i = 0; i < vertexCount; i++) { - dstVertexData[i].position = { + uint32_t idx = m_currLineVertex + i; + + m_vertexData->lineVertices[idx].position = { xscale * vertexData[i].position.x, yscale * vertexData[i].position.y }; - dstVertexData[i].color = vertexData[i].color; + m_vertexData->lineVertices[idx].color = vertexData[i].color; } + + m_currLineVertex += vertexCount; } - DxvkBufferSlice HudRenderer::allocVertexBuffer( - VkDeviceSize dataSize) { - dataSize = align(dataSize, 64); + void HudRenderer::allocVertexBufferSlice() { + auto vertexSlice = m_vertexBuffer->allocSlice(); + m_context->invalidateBuffer(m_vertexBuffer, vertexSlice); + + m_currTextVertex = 0; + m_currTextInstance = 0; + m_currLineVertex = 0; - if (m_vertexOffset + dataSize > m_vertexBuffer->info().size) { - m_context->invalidateBuffer(m_vertexBuffer, m_vertexBuffer->allocSlice()); - m_vertexOffset = 0; - } - - DxvkBufferSlice slice(m_vertexBuffer, m_vertexOffset, dataSize); - m_vertexOffset += dataSize; - return slice; + m_vertexData = reinterpret_cast(vertexSlice.mapPtr); } - + void HudRenderer::beginTextRendering() { if (m_mode != Mode::RenderText) { m_mode = Mode::RenderText; + m_context->bindVertexBuffer(0, DxvkBufferSlice(m_vertexBuffer, offsetof(VertexBufferData, textVertices), sizeof(HudTextVertex) * MaxTextVertexCount), sizeof(HudTextVertex)); + m_context->bindVertexBuffer(1, DxvkBufferSlice(m_vertexBuffer, offsetof(VertexBufferData, textColors), sizeof(HudColor) * MaxTextInstanceCount), sizeof(HudColor)); + m_context->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_textShaders.vert); m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_textShaders.frag); @@ -153,13 +159,15 @@ namespace dxvk::hud { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_FALSE, 0 }; - static const std::array ilAttributes = {{ + static const std::array ilAttributes = {{ { 0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(HudTextVertex, position) }, { 1, 0, VK_FORMAT_R32G32_UINT, offsetof(HudTextVertex, texcoord) }, + { 2, 1, VK_FORMAT_R32G32B32A32_SFLOAT, 0 }, }}; - static const std::array ilBindings = {{ - { 0, VK_VERTEX_INPUT_RATE_VERTEX }, + static const std::array ilBindings = {{ + { 0, 0, VK_VERTEX_INPUT_RATE_VERTEX }, + { 1, 1, VK_VERTEX_INPUT_RATE_INSTANCE }, }}; m_context->setInputAssemblyState(iaState); @@ -176,6 +184,8 @@ namespace dxvk::hud { if (m_mode != Mode::RenderLines) { m_mode = Mode::RenderLines; + 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); @@ -189,7 +199,7 @@ namespace dxvk::hud { }}; static const std::array ilBindings = {{ - { 0, VK_VERTEX_INPUT_RATE_VERTEX }, + { 0, 0, VK_VERTEX_INPUT_RATE_VERTEX }, }}; m_context->setInputAssemblyState(iaState); @@ -215,13 +225,13 @@ namespace dxvk::hud { result.vert = device->createShader( VK_SHADER_STAGE_VERTEX_BIT, - 0, nullptr, { 0x3, 0x1 }, vsCode); + 0, nullptr, { 0x7, 0x3 }, vsCode); result.frag = device->createShader( VK_SHADER_STAGE_FRAGMENT_BIT, fsResources.size(), fsResources.data(), - { 0x1, 0x1, 0, sizeof(HudColor) }, + { 0x3, 0x1 }, fsCode); return result; @@ -307,7 +317,7 @@ namespace dxvk::hud { Rc HudRenderer::createVertexBuffer(const Rc& device) { DxvkBufferCreateInfo info; - info.size = 1 << 16; + 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; diff --git a/src/dxvk/hud/dxvk_hud_renderer.h b/src/dxvk/hud/dxvk_hud_renderer.h index 8b658c49..a0dd0abc 100644 --- a/src/dxvk/hud/dxvk_hud_renderer.h +++ b/src/dxvk/hud/dxvk_hud_renderer.h @@ -75,7 +75,15 @@ namespace dxvk::hud { * display performance and driver information. */ class HudRenderer { + constexpr static uint32_t MaxTextVertexCount = 512 * 6; + constexpr static uint32_t MaxTextInstanceCount = 64; + constexpr static uint32_t MaxLineVertexCount = 1024; + struct VertexBufferData { + HudColor textColors[MaxTextInstanceCount]; + HudTextVertex textVertices[MaxTextVertexCount]; + HudLineVertex lineVertices[MaxLineVertexCount]; + }; public: HudRenderer( @@ -128,11 +136,14 @@ namespace dxvk::hud { Rc m_fontSampler; Rc m_vertexBuffer; - VkDeviceSize m_vertexOffset = 0; - - DxvkBufferSlice allocVertexBuffer( - VkDeviceSize dataSize); + VertexBufferData* m_vertexData = nullptr; + uint32_t m_currTextVertex = 0; + uint32_t m_currTextInstance = 0; + uint32_t m_currLineVertex = 0; + + void allocVertexBufferSlice(); + void beginTextRendering(); void beginLineRendering(); diff --git a/src/dxvk/hud/shaders/hud_text_frag.frag b/src/dxvk/hud/shaders/hud_text_frag.frag index 6d5fd907..bfd5590f 100644 --- a/src/dxvk/hud/shaders/hud_text_frag.frag +++ b/src/dxvk/hud/shaders/hud_text_frag.frag @@ -6,12 +6,9 @@ layout(set = 0, binding = 0) uniform texture2D s_base; layout(set = 0, binding = 1) uniform sampler2D s_font; layout(location = 0) in vec2 v_texcoord; -layout(location = 0) out vec4 o_color; +layout(location = 1) in vec4 v_color; -layout(push_constant) -uniform push_data { - vec4 color; -}; +layout(location = 0) out vec4 o_color; vec3 linearToSrgb(vec3 color) { bvec3 isLo = lessThanEqual(color, vec3(0.0031308f)); @@ -31,7 +28,7 @@ void main() { float r_alpha_center = sampleAlpha(0.0f, 5.0f); float r_alpha_shadow = sampleAlpha(0.3f, 5.0f); - vec4 r_center = vec4(color.rgb, color.a * r_alpha_center); + vec4 r_center = vec4(v_color.rgb, v_color.a * r_alpha_center); vec4 r_shadow = vec4(0.0f, 0.0f, 0.0f, r_alpha_shadow); o_color = mix(r_shadow, r_center, r_alpha_center); diff --git a/src/dxvk/hud/shaders/hud_text_vert.vert b/src/dxvk/hud/shaders/hud_text_vert.vert index 27764283..7b866704 100644 --- a/src/dxvk/hud/shaders/hud_text_vert.vert +++ b/src/dxvk/hud/shaders/hud_text_vert.vert @@ -2,11 +2,14 @@ layout(location = 0) in vec2 v_position; layout(location = 1) in uvec2 v_texcoord; +layout(location = 2) in vec4 v_color; layout(location = 0) out vec2 o_texcoord; +layout(location = 1) out vec4 o_color; void main() { o_texcoord = vec2(v_texcoord); + o_color = v_color; vec2 pos = 2.0f * v_position - 1.0f; gl_Position = vec4(pos, 0.0f, 1.0f);