1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-15 07:29:17 +01:00

[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.
This commit is contained in:
Philip Rebohle 2019-12-16 00:01:28 +01:00
parent 13d2479ecf
commit c6fb8fa5e8
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 80 additions and 59 deletions

View File

@ -28,15 +28,14 @@ namespace dxvk::hud {
void HudRenderer::beginFrame(const Rc<DxvkContext>& 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<HudTextVertex*>(
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<float>(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<HudLineVertex*>(
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<VertexBufferData*>(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<DxvkVertexAttribute, 2> ilAttributes = {{
static const std::array<DxvkVertexAttribute, 3> 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<DxvkVertexBinding, 1> ilBindings = {{
{ 0, VK_VERTEX_INPUT_RATE_VERTEX },
static const std::array<DxvkVertexBinding, 2> 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<DxvkVertexBinding, 1> 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<DxvkBuffer> HudRenderer::createVertexBuffer(const Rc<DxvkDevice>& 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;

View File

@ -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<DxvkSampler> m_fontSampler;
Rc<DxvkBuffer> 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();

View File

@ -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);

View File

@ -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);