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:
parent
13d2479ecf
commit
c6fb8fa5e8
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user