mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[hud] Greatly simplify text rendering in the HUD
This commit is contained in:
parent
8ce83cabca
commit
0709c5f5c7
@ -15,11 +15,15 @@ namespace dxvk::hud {
|
|||||||
m_device (device),
|
m_device (device),
|
||||||
m_textShaders (createTextShaders()),
|
m_textShaders (createTextShaders()),
|
||||||
m_lineShaders (createLineShaders()),
|
m_lineShaders (createLineShaders()),
|
||||||
|
m_dataBuffer (createDataBuffer()),
|
||||||
|
m_dataView (createDataView()),
|
||||||
|
m_dataOffset (0ull),
|
||||||
|
m_fontBuffer (createFontBuffer()),
|
||||||
m_fontImage (createFontImage()),
|
m_fontImage (createFontImage()),
|
||||||
m_fontView (createFontView()),
|
m_fontView (createFontView()),
|
||||||
m_fontSampler (createFontSampler()),
|
m_fontSampler (createFontSampler()),
|
||||||
m_vertexBuffer (createVertexBuffer()) {
|
m_vertexBuffer (createVertexBuffer()) {
|
||||||
this->initCharMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -32,9 +36,6 @@ namespace dxvk::hud {
|
|||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
this->initFontTexture(context);
|
this->initFontTexture(context);
|
||||||
|
|
||||||
context->bindResourceSampler(0, m_fontSampler);
|
|
||||||
context->bindResourceView (0, m_fontView, nullptr);
|
|
||||||
|
|
||||||
m_mode = Mode::RenderNone;
|
m_mode = Mode::RenderNone;
|
||||||
m_scale = scale;
|
m_scale = scale;
|
||||||
m_surfaceSize = surfaceSize;
|
m_surfaceSize = surfaceSize;
|
||||||
@ -49,66 +50,32 @@ namespace dxvk::hud {
|
|||||||
HudPos pos,
|
HudPos pos,
|
||||||
HudColor color,
|
HudColor color,
|
||||||
const std::string& text) {
|
const std::string& text) {
|
||||||
|
if (text.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
beginTextRendering();
|
beginTextRendering();
|
||||||
|
|
||||||
const float xscale = m_scale / std::max(float(m_surfaceSize.width), 1.0f);
|
// Copy string into string buffer, but extend it to cover a full cache
|
||||||
const float yscale = m_scale / std::max(float(m_surfaceSize.height), 1.0f);
|
// line to avoid potential CPU performance issues with the upload.
|
||||||
|
std::string textCopy = text;
|
||||||
|
textCopy.resize(align(text.size(), CACHE_LINE_SIZE), ' ');
|
||||||
|
|
||||||
uint32_t vertexCount = 6 * text.size();
|
VkDeviceSize offset = allocDataBuffer(textCopy.size());
|
||||||
|
std::memcpy(m_dataBuffer->mapPtr(offset), textCopy.data(), textCopy.size());
|
||||||
|
|
||||||
if (m_currTextVertex + vertexCount > MaxTextVertexCount
|
// Fill in push constants for the next draw
|
||||||
|| m_currTextInstance + 1 > MaxTextInstanceCount)
|
HudTextPushConstants pushData;
|
||||||
allocVertexBufferSlice();
|
pushData.color = color;
|
||||||
|
pushData.pos = pos;
|
||||||
|
pushData.offset = offset;
|
||||||
|
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_currTextVertex, m_currTextInstance);
|
m_context->pushConstants(0, sizeof(pushData), &pushData);
|
||||||
|
|
||||||
const float sizeFactor = size / float(g_hudFont.size);
|
// Draw with orignal vertex count
|
||||||
|
m_context->draw(6 * text.size(), 1, 0, 0);
|
||||||
for (size_t i = 0; i < text.size(); i++) {
|
|
||||||
const HudGlyph& glyph = g_hudFont.glyphs[
|
|
||||||
m_charMap[uint8_t(text[i])]];
|
|
||||||
|
|
||||||
HudPos size = {
|
|
||||||
sizeFactor * float(glyph.w),
|
|
||||||
sizeFactor * float(glyph.h) };
|
|
||||||
|
|
||||||
HudPos origin = {
|
|
||||||
pos.x - sizeFactor * float(glyph.originX),
|
|
||||||
pos.y - sizeFactor * float(glyph.originY) };
|
|
||||||
|
|
||||||
HudPos posTl = { xscale * (origin.x), yscale * (origin.y) };
|
|
||||||
HudPos posBr = { xscale * (origin.x + size.x), yscale * (origin.y + size.y) };
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
m_vertexData->textVertices[idx + 0].position = { posTl.x, posTl.y };
|
|
||||||
m_vertexData->textVertices[idx + 0].texcoord = { texTl.u, texTl.v };
|
|
||||||
|
|
||||||
m_vertexData->textVertices[idx + 1].position = { posBr.x, posTl.y };
|
|
||||||
m_vertexData->textVertices[idx + 1].texcoord = { texBr.u, texTl.v };
|
|
||||||
|
|
||||||
m_vertexData->textVertices[idx + 2].position = { posTl.x, posBr.y };
|
|
||||||
m_vertexData->textVertices[idx + 2].texcoord = { texTl.u, texBr.v };
|
|
||||||
|
|
||||||
m_vertexData->textVertices[idx + 3].position = { posBr.x, posBr.y };
|
|
||||||
m_vertexData->textVertices[idx + 3].texcoord = { texBr.u, texBr.v };
|
|
||||||
|
|
||||||
m_vertexData->textVertices[idx + 4].position = { posTl.x, posBr.y };
|
|
||||||
m_vertexData->textVertices[idx + 4].texcoord = { texTl.u, texBr.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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -142,8 +109,6 @@ namespace dxvk::hud {
|
|||||||
auto vertexSlice = m_vertexBuffer->allocSlice();
|
auto vertexSlice = m_vertexBuffer->allocSlice();
|
||||||
m_context->invalidateBuffer(m_vertexBuffer, vertexSlice);
|
m_context->invalidateBuffer(m_vertexBuffer, vertexSlice);
|
||||||
|
|
||||||
m_currTextVertex = 0;
|
|
||||||
m_currTextInstance = 0;
|
|
||||||
m_currLineVertex = 0;
|
m_currLineVertex = 0;
|
||||||
|
|
||||||
m_vertexData = reinterpret_cast<VertexBufferData*>(vertexSlice.mapPtr);
|
m_vertexData = reinterpret_cast<VertexBufferData*>(vertexSlice.mapPtr);
|
||||||
@ -154,33 +119,20 @@ namespace dxvk::hud {
|
|||||||
if (m_mode != Mode::RenderText) {
|
if (m_mode != Mode::RenderText) {
|
||||||
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_VERTEX_BIT, m_textShaders.vert);
|
||||||
m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_textShaders.frag);
|
m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_textShaders.frag);
|
||||||
|
|
||||||
|
m_context->bindResourceBuffer (0, DxvkBufferSlice(m_fontBuffer));
|
||||||
|
m_context->bindResourceView (1, nullptr, m_dataView);
|
||||||
|
m_context->bindResourceSampler(2, m_fontSampler);
|
||||||
|
m_context->bindResourceView (2, m_fontView, nullptr);
|
||||||
|
|
||||||
static const DxvkInputAssemblyState iaState = {
|
static const DxvkInputAssemblyState iaState = {
|
||||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||||
VK_FALSE, 0 };
|
VK_FALSE, 0 };
|
||||||
|
|
||||||
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, 2> ilBindings = {{
|
|
||||||
{ 0, 0, VK_VERTEX_INPUT_RATE_VERTEX },
|
|
||||||
{ 1, 1, VK_VERTEX_INPUT_RATE_INSTANCE },
|
|
||||||
}};
|
|
||||||
|
|
||||||
m_context->setInputAssemblyState(iaState);
|
m_context->setInputAssemblyState(iaState);
|
||||||
m_context->setInputLayout(
|
m_context->setInputLayout(0, nullptr, 0, nullptr);
|
||||||
ilAttributes.size(),
|
|
||||||
ilAttributes.data(),
|
|
||||||
ilBindings.size(),
|
|
||||||
ilBindings.data());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +167,18 @@ namespace dxvk::hud {
|
|||||||
ilBindings.data());
|
ilBindings.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VkDeviceSize HudRenderer::allocDataBuffer(VkDeviceSize size) {
|
||||||
|
if (m_dataOffset + size > m_dataBuffer->info().size) {
|
||||||
|
m_context->invalidateBuffer(m_dataBuffer, m_dataBuffer->allocSlice());
|
||||||
|
m_dataOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDeviceSize offset = m_dataOffset;
|
||||||
|
m_dataOffset = align(offset + size, 64);
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HudRenderer::ShaderPair HudRenderer::createTextShaders() {
|
HudRenderer::ShaderPair HudRenderer::createTextShaders() {
|
||||||
@ -223,14 +187,21 @@ namespace dxvk::hud {
|
|||||||
const SpirvCodeBuffer vsCode(hud_text_vert);
|
const SpirvCodeBuffer vsCode(hud_text_vert);
|
||||||
const SpirvCodeBuffer fsCode(hud_text_frag);
|
const SpirvCodeBuffer fsCode(hud_text_frag);
|
||||||
|
|
||||||
// Two shader resources: Font texture and sampler
|
const std::array<DxvkResourceSlot, 3> vsResources = {{
|
||||||
|
{ 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM },
|
||||||
|
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM },
|
||||||
|
}};
|
||||||
|
|
||||||
const std::array<DxvkResourceSlot, 1> fsResources = {{
|
const std::array<DxvkResourceSlot, 1> fsResources = {{
|
||||||
{ 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_IMAGE_VIEW_TYPE_2D },
|
{ 2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_IMAGE_VIEW_TYPE_2D },
|
||||||
}};
|
}};
|
||||||
|
|
||||||
result.vert = m_device->createShader(
|
result.vert = m_device->createShader(
|
||||||
VK_SHADER_STAGE_VERTEX_BIT,
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
0, nullptr, { 0x7, 0x3 }, vsCode);
|
vsResources.size(),
|
||||||
|
vsResources.data(),
|
||||||
|
{ 0x0, 0x3, 0, sizeof(HudTextPushConstants) },
|
||||||
|
vsCode);
|
||||||
|
|
||||||
result.frag = m_device->createShader(
|
result.frag = m_device->createShader(
|
||||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
@ -261,6 +232,46 @@ namespace dxvk::hud {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rc<DxvkBuffer> HudRenderer::createDataBuffer() {
|
||||||
|
DxvkBufferCreateInfo info;
|
||||||
|
info.size = DataBufferSize;
|
||||||
|
info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||||
|
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
|
||||||
|
info.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
||||||
|
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
|
info.access = VK_ACCESS_SHADER_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rc<DxvkBufferView> HudRenderer::createDataView() {
|
||||||
|
DxvkBufferViewCreateInfo info;
|
||||||
|
info.format = VK_FORMAT_R8_UINT;
|
||||||
|
info.rangeOffset = 0;
|
||||||
|
info.rangeLength = m_dataBuffer->info().size;
|
||||||
|
|
||||||
|
return m_device->createBufferView(m_dataBuffer, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rc<DxvkBuffer> HudRenderer::createFontBuffer() {
|
||||||
|
DxvkBufferCreateInfo info;
|
||||||
|
info.size = sizeof(HudFontGpuData);
|
||||||
|
info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||||
|
| VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
|
info.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
||||||
|
| VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
info.access = VK_ACCESS_SHADER_READ_BIT
|
||||||
|
| VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
|
||||||
|
return m_device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkImage> HudRenderer::createFontImage() {
|
Rc<DxvkImage> HudRenderer::createFontImage() {
|
||||||
DxvkImageCreateInfo info;
|
DxvkImageCreateInfo info;
|
||||||
info.type = VK_IMAGE_TYPE_2D;
|
info.type = VK_IMAGE_TYPE_2D;
|
||||||
@ -336,31 +347,29 @@ namespace dxvk::hud {
|
|||||||
|
|
||||||
void HudRenderer::initFontTexture(
|
void HudRenderer::initFontTexture(
|
||||||
const Rc<DxvkContext>& context) {
|
const Rc<DxvkContext>& context) {
|
||||||
DxvkBufferCreateInfo bufferInfo;
|
HudFontGpuData gpuData = { };
|
||||||
bufferInfo.size = g_hudFont.width * g_hudFont.height;
|
gpuData.size = float(g_hudFont.size);
|
||||||
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
gpuData.advance = float(g_hudFont.advance);
|
||||||
bufferInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
bufferInfo.access = VK_ACCESS_TRANSFER_READ_BIT;
|
|
||||||
|
|
||||||
auto stagingBuffer = m_device->createBuffer(bufferInfo,
|
for (uint32_t i = 0; i < g_hudFont.charCount; i++) {
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
auto src = &g_hudFont.glyphs[i];
|
||||||
std::memcpy(stagingBuffer->mapPtr(0), g_hudFont.texture, bufferInfo.size);
|
auto dst = &gpuData.glyphs[src->codePoint];
|
||||||
|
|
||||||
context->copyBufferToImage(m_fontImage,
|
dst->x = src->x;
|
||||||
|
dst->y = src->y;
|
||||||
|
dst->w = src->w;
|
||||||
|
dst->h = src->h;
|
||||||
|
dst->originX = src->originX;
|
||||||
|
dst->originY = src->originY;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->uploadBuffer(m_fontBuffer, &gpuData);
|
||||||
|
|
||||||
|
context->uploadImage(m_fontImage,
|
||||||
VkImageSubresourceLayers { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 },
|
VkImageSubresourceLayers { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 },
|
||||||
VkOffset3D { 0, 0, 0 },
|
g_hudFont.texture, g_hudFont.width, g_hudFont.width * g_hudFont.height);
|
||||||
VkExtent3D { g_hudFont.width, g_hudFont.height, 1 },
|
|
||||||
stagingBuffer, 0, 0, 0);
|
|
||||||
|
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HudRenderer::initCharMap() {
|
|
||||||
std::fill(m_charMap.begin(), m_charMap.end(), 0);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < g_hudFont.charCount; i++)
|
|
||||||
m_charMap.at(g_hudFont.glyphs[i].codePoint) = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,17 +17,6 @@ namespace dxvk::hud {
|
|||||||
float y;
|
float y;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Texture coordinates
|
|
||||||
*
|
|
||||||
* Absolute texture coordinates that are used
|
|
||||||
* to pick letters in the font texture.
|
|
||||||
*/
|
|
||||||
struct HudTexCoord {
|
|
||||||
uint32_t u;
|
|
||||||
uint32_t v;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Color
|
* \brief Color
|
||||||
*
|
*
|
||||||
@ -52,14 +41,6 @@ namespace dxvk::hud {
|
|||||||
uint8_t a;
|
uint8_t a;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Text vertex and texture coordinates
|
|
||||||
*/
|
|
||||||
struct HudTextVertex {
|
|
||||||
HudPos position;
|
|
||||||
HudTexCoord texcoord;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Line vertex and color
|
* \brief Line vertex and color
|
||||||
*/
|
*/
|
||||||
@ -67,7 +48,37 @@ namespace dxvk::hud {
|
|||||||
HudPos position;
|
HudPos position;
|
||||||
HudNormColor color;
|
HudNormColor color;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief HUD push constant data
|
||||||
|
*/
|
||||||
|
struct HudTextPushConstants {
|
||||||
|
HudColor color;
|
||||||
|
HudPos pos;
|
||||||
|
uint32_t offset;
|
||||||
|
float size;
|
||||||
|
HudPos scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Glyph data
|
||||||
|
*/
|
||||||
|
struct HudGlyphGpuData {
|
||||||
|
int16_t x;
|
||||||
|
int16_t y;
|
||||||
|
int16_t w;
|
||||||
|
int16_t h;
|
||||||
|
int16_t originX;
|
||||||
|
int16_t originY;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HudFontGpuData {
|
||||||
|
float size;
|
||||||
|
float advance;
|
||||||
|
uint32_t padding[2];
|
||||||
|
HudGlyphGpuData glyphs[256];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Text renderer for the HUD
|
* \brief Text renderer for the HUD
|
||||||
*
|
*
|
||||||
@ -75,14 +86,11 @@ namespace dxvk::hud {
|
|||||||
* display performance and driver information.
|
* display performance and driver information.
|
||||||
*/
|
*/
|
||||||
class HudRenderer {
|
class HudRenderer {
|
||||||
constexpr static uint32_t MaxTextVertexCount = 512 * 6;
|
constexpr static VkDeviceSize DataBufferSize = 16384;
|
||||||
constexpr static uint32_t MaxTextInstanceCount = 64;
|
|
||||||
constexpr static uint32_t MaxLineVertexCount = 1024;
|
constexpr static uint32_t MaxLineVertexCount = 1024;
|
||||||
|
|
||||||
struct VertexBufferData {
|
struct VertexBufferData {
|
||||||
HudColor textColors[MaxTextInstanceCount];
|
HudLineVertex lineVertices[MaxLineVertexCount];
|
||||||
HudTextVertex textVertices[MaxTextVertexCount];
|
|
||||||
HudLineVertex lineVertices[MaxLineVertexCount];
|
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -127,8 +135,6 @@ namespace dxvk::hud {
|
|||||||
Rc<DxvkShader> frag;
|
Rc<DxvkShader> frag;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<uint8_t, 256> m_charMap;
|
|
||||||
|
|
||||||
Mode m_mode;
|
Mode m_mode;
|
||||||
float m_scale;
|
float m_scale;
|
||||||
VkExtent2D m_surfaceSize;
|
VkExtent2D m_surfaceSize;
|
||||||
@ -139,6 +145,11 @@ namespace dxvk::hud {
|
|||||||
ShaderPair m_textShaders;
|
ShaderPair m_textShaders;
|
||||||
ShaderPair m_lineShaders;
|
ShaderPair m_lineShaders;
|
||||||
|
|
||||||
|
Rc<DxvkBuffer> m_dataBuffer;
|
||||||
|
Rc<DxvkBufferView> m_dataView;
|
||||||
|
VkDeviceSize m_dataOffset;
|
||||||
|
|
||||||
|
Rc<DxvkBuffer> m_fontBuffer;
|
||||||
Rc<DxvkImage> m_fontImage;
|
Rc<DxvkImage> m_fontImage;
|
||||||
Rc<DxvkImageView> m_fontView;
|
Rc<DxvkImageView> m_fontView;
|
||||||
Rc<DxvkSampler> m_fontSampler;
|
Rc<DxvkSampler> m_fontSampler;
|
||||||
@ -146,8 +157,6 @@ namespace dxvk::hud {
|
|||||||
Rc<DxvkBuffer> m_vertexBuffer;
|
Rc<DxvkBuffer> m_vertexBuffer;
|
||||||
VertexBufferData* m_vertexData = nullptr;
|
VertexBufferData* m_vertexData = nullptr;
|
||||||
|
|
||||||
uint32_t m_currTextVertex = 0;
|
|
||||||
uint32_t m_currTextInstance = 0;
|
|
||||||
uint32_t m_currLineVertex = 0;
|
uint32_t m_currLineVertex = 0;
|
||||||
|
|
||||||
bool m_initialized = false;
|
bool m_initialized = false;
|
||||||
@ -157,21 +166,25 @@ namespace dxvk::hud {
|
|||||||
void beginTextRendering();
|
void beginTextRendering();
|
||||||
|
|
||||||
void beginLineRendering();
|
void beginLineRendering();
|
||||||
|
|
||||||
|
VkDeviceSize allocDataBuffer(VkDeviceSize size);
|
||||||
|
|
||||||
ShaderPair createTextShaders();
|
ShaderPair createTextShaders();
|
||||||
ShaderPair createLineShaders();
|
ShaderPair createLineShaders();
|
||||||
|
|
||||||
|
Rc<DxvkBuffer> createDataBuffer();
|
||||||
|
Rc<DxvkBufferView> createDataView();
|
||||||
|
|
||||||
|
Rc<DxvkBuffer> createFontBuffer();
|
||||||
Rc<DxvkImage> createFontImage();
|
Rc<DxvkImage> createFontImage();
|
||||||
Rc<DxvkImageView> createFontView();
|
Rc<DxvkImageView> createFontView();
|
||||||
|
|
||||||
Rc<DxvkSampler> createFontSampler();
|
Rc<DxvkSampler> createFontSampler();
|
||||||
|
|
||||||
Rc<DxvkBuffer> createVertexBuffer();
|
Rc<DxvkBuffer> createVertexBuffer();
|
||||||
|
|
||||||
void initFontTexture(
|
void initFontTexture(
|
||||||
const Rc<DxvkContext>& context);
|
const Rc<DxvkContext>& context);
|
||||||
|
|
||||||
void initCharMap();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
layout(constant_id = 1225) const bool srgbSwapchain = false;
|
layout(constant_id = 1225) const bool srgbSwapchain = false;
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform sampler2D s_font;
|
layout(binding = 2) uniform sampler2D s_font;
|
||||||
|
|
||||||
layout(location = 0) in vec2 v_texcoord;
|
layout(location = 0) in vec2 v_texcoord;
|
||||||
layout(location = 1) in vec4 v_color;
|
layout(location = 1) in vec4 v_color;
|
||||||
|
@ -1,16 +1,75 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec2 v_position;
|
struct font_info_t {
|
||||||
layout(location = 1) in uvec2 v_texcoord;
|
float size;
|
||||||
layout(location = 2) in vec4 v_color;
|
float advance;
|
||||||
|
uvec2 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct glyph_info_t {
|
||||||
|
uint packed_xy;
|
||||||
|
uint packed_wh;
|
||||||
|
uint packed_origin;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 0, std430)
|
||||||
|
readonly buffer font_buffer_t {
|
||||||
|
font_info_t font_data;
|
||||||
|
glyph_info_t glyph_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 1) uniform usamplerBuffer text_buffer;
|
||||||
|
|
||||||
|
layout(push_constant)
|
||||||
|
uniform push_data_t {
|
||||||
|
vec4 text_color;
|
||||||
|
vec2 text_pos;
|
||||||
|
uint text_offset;
|
||||||
|
float text_size;
|
||||||
|
vec2 hud_scale;
|
||||||
|
};
|
||||||
|
|
||||||
layout(location = 0) out vec2 o_texcoord;
|
layout(location = 0) out vec2 o_texcoord;
|
||||||
layout(location = 1) out vec4 o_color;
|
layout(location = 1) out vec4 o_color;
|
||||||
|
|
||||||
|
const uvec2 coord_mask = uvec2(0x2a, 0x1c);
|
||||||
|
|
||||||
|
vec2 unpack_u16(uint v) {
|
||||||
|
// Inputs may be signed
|
||||||
|
int hi = int(v);
|
||||||
|
int lo = int(v << 16);
|
||||||
|
return vec2(float(lo >> 16), float(hi >> 16));
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
o_texcoord = vec2(v_texcoord);
|
o_color = text_color;
|
||||||
o_color = v_color;
|
|
||||||
|
// Compute character index and vertex index for the current
|
||||||
vec2 pos = 2.0f * v_position - 1.0f;
|
// character. We'll render two triangles per character.
|
||||||
gl_Position = vec4(pos, 0.0f, 1.0f);
|
uint chr_idx = gl_VertexIndex / 6;
|
||||||
}
|
uint vtx_idx = gl_VertexIndex - 6 * chr_idx;
|
||||||
|
|
||||||
|
// Load glyph info based on vertex index
|
||||||
|
uint glyph_idx = texelFetch(text_buffer, int(text_offset + chr_idx)).x;
|
||||||
|
glyph_info_t glyph_info = glyph_data[glyph_idx];
|
||||||
|
|
||||||
|
// Compute texture coordinate from glyph data
|
||||||
|
vec2 coord = vec2((coord_mask >> vtx_idx) & 0x1);
|
||||||
|
|
||||||
|
vec2 tex_xy = unpack_u16(glyph_info.packed_xy);
|
||||||
|
vec2 tex_wh = unpack_u16(glyph_info.packed_wh);
|
||||||
|
|
||||||
|
o_texcoord = tex_xy + coord * tex_wh;
|
||||||
|
|
||||||
|
// Compute vertex position. We can easily do this here since our
|
||||||
|
// font is a monospace font, otherwise we'd need to preprocess
|
||||||
|
// the strings to render in a compute shader.
|
||||||
|
float size_factor = text_size / font_data.size;
|
||||||
|
|
||||||
|
vec2 local_pos = tex_wh * coord - unpack_u16(glyph_info.packed_origin)
|
||||||
|
+ vec2(font_data.advance * float(chr_idx), 0.0f);
|
||||||
|
vec2 pixel_pos = text_pos + size_factor * local_pos;
|
||||||
|
vec2 scaled_pos = 2.0f * hud_scale * pixel_pos - 1.0f;
|
||||||
|
|
||||||
|
gl_Position = vec4(scaled_pos, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user