vk: Reuse TriangledFan logic for TriangleStrip

This commit is contained in:
Denis Pauk 2021-04-04 12:11:11 +03:00
parent f8708a0f76
commit 456acfda05
3 changed files with 77 additions and 69 deletions

View File

@ -228,11 +228,8 @@ extern VkDescriptorSetLayout vk_samplerDescSetLayout;
// *** pipelines ***
extern qvkpipeline_t vk_drawTexQuadPipeline[RP_COUNT];
extern qvkpipeline_t vk_drawColorQuadPipeline[RP_COUNT];
extern qvkpipeline_t vk_drawModelPipelineStrip[RP_COUNT];
extern qvkpipeline_t vk_drawModelPipelineFan[RP_COUNT];
extern qvkpipeline_t vk_drawNoDepthModelPipelineStrip;
extern qvkpipeline_t vk_drawNoDepthModelPipelineFan;
extern qvkpipeline_t vk_drawLefthandModelPipelineStrip;
extern qvkpipeline_t vk_drawLefthandModelPipelineFan;
extern qvkpipeline_t vk_drawNullModelPipeline;
extern qvkpipeline_t vk_drawParticlesPipeline;
@ -246,7 +243,6 @@ extern qvkpipeline_t vk_drawBeamPipeline;
extern qvkpipeline_t vk_drawSkyboxPipeline;
extern qvkpipeline_t vk_drawDLightPipeline;
extern qvkpipeline_t vk_showTrisPipeline;
extern qvkpipeline_t vk_shadowsPipelineStrip;
extern qvkpipeline_t vk_shadowsPipelineFan;
extern qvkpipeline_t vk_worldWarpPipeline;
extern qvkpipeline_t vk_postprocessPipeline;
@ -311,6 +307,7 @@ uint8_t* QVk_GetVertexBuffer(VkDeviceSize size, VkBuffer *dstBuffer, VkDeviceSiz
uint8_t* QVk_GetUniformBuffer(VkDeviceSize size, uint32_t *dstOffset, VkDescriptorSet *dstUboDescriptorSet);
uint8_t* QVk_GetStagingBuffer(VkDeviceSize size, int alignment, VkCommandBuffer *cmdBuffer, VkBuffer *buffer, uint32_t *dstOffset);
VkBuffer QVk_GetTriangleFanIbo(VkDeviceSize indexCount);
VkBuffer QVk_GetTriangleStripIbo(VkDeviceSize indexCount);
void QVk_DrawColorRect(float *ubo, VkDeviceSize uboSize, qvkrenderpasstype_t rpType);
void QVk_DrawTexRect(const float *ubo, VkDeviceSize uboSize, qvktexture_t *texture);
void QVk_BindPipeline(qvkpipeline_t *pipeline);

View File

@ -131,13 +131,9 @@ qvkpipeline_t vk_drawTexQuadPipeline[RP_COUNT] = {
QVKPIPELINE_INIT, QVKPIPELINE_INIT, QVKPIPELINE_INIT };
qvkpipeline_t vk_drawColorQuadPipeline[RP_COUNT] = {
QVKPIPELINE_INIT, QVKPIPELINE_INIT, QVKPIPELINE_INIT };
qvkpipeline_t vk_drawModelPipelineStrip[RP_COUNT] = {
QVKPIPELINE_INIT, QVKPIPELINE_INIT, QVKPIPELINE_INIT };
qvkpipeline_t vk_drawModelPipelineFan[RP_COUNT] = {
QVKPIPELINE_INIT, QVKPIPELINE_INIT, QVKPIPELINE_INIT };
qvkpipeline_t vk_drawNoDepthModelPipelineStrip = QVKPIPELINE_INIT;
qvkpipeline_t vk_drawNoDepthModelPipelineFan = QVKPIPELINE_INIT;
qvkpipeline_t vk_drawLefthandModelPipelineStrip = QVKPIPELINE_INIT;
qvkpipeline_t vk_drawLefthandModelPipelineFan = QVKPIPELINE_INIT;
qvkpipeline_t vk_drawNullModelPipeline = QVKPIPELINE_INIT;
qvkpipeline_t vk_drawParticlesPipeline = QVKPIPELINE_INIT;
@ -233,8 +229,9 @@ static qvkstagingbuffer_t vk_stagingBuffers[NUM_DYNBUFFERS];
static int vk_activeDynBufferIdx = 0;
static int vk_activeSwapBufferIdx = 0;
// index buffer for triangle fan emulation - all because Metal/MoltenVK don't support them
// index buffer for triangle fan/strip emulation - all because Metal/MoltenVK don't support them
static VkBuffer *vk_triangleFanIbo = NULL;
static VkBuffer *vk_triangleStripIbo = NULL;
static uint32_t vk_triangleFanIboUsage = 0;
// swap buffers used if primary dynamic buffers get full
@ -1070,14 +1067,15 @@ static int NextPow2(int v)
}
// internal helper
static uint8_t *QVk_GetIndexBuffer(VkDeviceSize size, VkDeviceSize *dstOffset);
static void RebuildTriangleFanIndexBuffer()
static uint8_t *QVk_GetIndexBuffer(VkDeviceSize size, VkDeviceSize *dstOffset, int currentBufferIdx);
static void RebuildTriangleIndexBuffer()
{
int idx = 0;
VkDeviceSize dstOffset = 0;
VkDeviceSize bufferSize = 3 * vk_config.triangle_index_count * sizeof(uint16_t);
uint16_t *iboData = NULL;
uint16_t *fanData = malloc(bufferSize);
uint16_t *stripData = malloc(bufferSize);
// fill the index buffer so that we can emulate triangle fans via triangle lists
for (int i = 0; i < vk_config.triangle_index_count; ++i)
@ -1087,20 +1085,47 @@ static void RebuildTriangleFanIndexBuffer()
fanData[idx++] = i + 2;
}
// fill the index buffer so that we can emulate triangle strips via triangle lists
idx = 0;
for (int i = 2; i < (vk_config.triangle_index_count + 2); ++i)
{
if ((i%2) == 0)
{
stripData[idx++] = i - 2;
stripData[idx++] = i - 1;
stripData[idx++] = i;
}
else
{
stripData[idx++] = i;
stripData[idx++] = i - 1;
stripData[idx++] = i - 2;
}
}
for (int i = 0; i < NUM_DYNBUFFERS; ++i)
{
vk_activeDynBufferIdx = (vk_activeDynBufferIdx + 1) % NUM_DYNBUFFERS;
VK_VERIFY(buffer_invalidate(&vk_dynIndexBuffers[i].resource));
iboData = (uint16_t *)QVk_GetIndexBuffer(bufferSize, &dstOffset);
memcpy(iboData, fanData, bufferSize);
iboData = (uint16_t *)QVk_GetIndexBuffer(bufferSize, &dstOffset, i);
if ((i%2) == 0)
{
memcpy(iboData, fanData, bufferSize);
}
else
{
memcpy(iboData, stripData, bufferSize);
}
VK_VERIFY(buffer_flush(&vk_dynIndexBuffers[i].resource));
}
vk_triangleFanIbo = &vk_dynIndexBuffers[vk_activeDynBufferIdx].resource.buffer;
vk_triangleFanIbo = &vk_dynIndexBuffers[0].resource.buffer;
vk_triangleStripIbo = &vk_dynIndexBuffers[1].resource.buffer;
vk_triangleFanIboUsage = ((bufferSize % 4) == 0) ? bufferSize : (bufferSize + 4 - (bufferSize % 4));
free(fanData);
free(stripData);
}
static void CreateStagingBuffer(VkDeviceSize size, qvkstagingbuffer_t *dstBuffer, int i)
@ -1335,14 +1360,6 @@ static void CreatePipelines()
VK_LOAD_VERTFRAG_SHADERS(shaders, model, model);
for (int i = 0; i < RP_COUNT; ++i)
{
vk_drawModelPipelineStrip[i].topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
vk_drawModelPipelineStrip[i].blendOpts.blendEnable = VK_TRUE;
QVk_CreatePipeline(samplerUboDsLayouts, 2, &vertInfoRGB_RGBA_RG, &vk_drawModelPipelineStrip[i], &vk_renderpasses[i], shaders, 2);
QVk_DebugSetObjectName((uint64_t)vk_drawModelPipelineStrip[i].layout, VK_OBJECT_TYPE_PIPELINE_LAYOUT,
va("Pipeline Layout: draw model: strip (%s)", renderpassObjectNames[i]));
QVk_DebugSetObjectName((uint64_t)vk_drawModelPipelineStrip[i].pl, VK_OBJECT_TYPE_PIPELINE,
va("Pipeline: draw model: strip (%s)", renderpassObjectNames[i]));
vk_drawModelPipelineFan[i].topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
vk_drawModelPipelineFan[i].blendOpts.blendEnable = VK_TRUE;
QVk_CreatePipeline(samplerUboDsLayouts, 2, &vertInfoRGB_RGBA_RG, &vk_drawModelPipelineFan[i], &vk_renderpasses[i], shaders, 2);
@ -1353,13 +1370,6 @@ static void CreatePipelines()
}
// dedicated model pipelines for translucent objects with depth write disabled
vk_drawNoDepthModelPipelineStrip.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
vk_drawNoDepthModelPipelineStrip.depthWriteEnable = VK_FALSE;
vk_drawNoDepthModelPipelineStrip.blendOpts.blendEnable = VK_TRUE;
QVk_CreatePipeline(samplerUboDsLayouts, 2, &vertInfoRGB_RGBA_RG, &vk_drawNoDepthModelPipelineStrip, &vk_renderpasses[RP_WORLD], shaders, 2);
QVk_DebugSetObjectName((uint64_t)vk_drawNoDepthModelPipelineStrip.layout, VK_OBJECT_TYPE_PIPELINE_LAYOUT, "Pipeline Layout: translucent model: strip");
QVk_DebugSetObjectName((uint64_t)vk_drawNoDepthModelPipelineStrip.pl, VK_OBJECT_TYPE_PIPELINE, "Pipeline: translucent model: strip");
vk_drawNoDepthModelPipelineFan.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
vk_drawNoDepthModelPipelineFan.depthWriteEnable = VK_FALSE;
vk_drawNoDepthModelPipelineFan.blendOpts.blendEnable = VK_TRUE;
@ -1368,12 +1378,6 @@ static void CreatePipelines()
QVk_DebugSetObjectName((uint64_t)vk_drawNoDepthModelPipelineFan.pl, VK_OBJECT_TYPE_PIPELINE, "Pipeline: translucent model: fan");
// dedicated model pipelines for when left-handed weapon model is drawn
vk_drawLefthandModelPipelineStrip.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
vk_drawLefthandModelPipelineStrip.cullMode = VK_CULL_MODE_FRONT_BIT;
QVk_CreatePipeline(samplerUboDsLayouts, 2, &vertInfoRGB_RGBA_RG, &vk_drawLefthandModelPipelineStrip, &vk_renderpasses[RP_WORLD], shaders, 2);
QVk_DebugSetObjectName((uint64_t)vk_drawLefthandModelPipelineStrip.layout, VK_OBJECT_TYPE_PIPELINE_LAYOUT, "Pipeline Layout: left-handed model: strip");
QVk_DebugSetObjectName((uint64_t)vk_drawLefthandModelPipelineStrip.pl, VK_OBJECT_TYPE_PIPELINE, "Pipeline: left-handed model: strip");
vk_drawLefthandModelPipelineFan.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
vk_drawLefthandModelPipelineFan.cullMode = VK_CULL_MODE_FRONT_BIT;
QVk_CreatePipeline(samplerUboDsLayouts, 2, &vertInfoRGB_RGBA_RG, &vk_drawLefthandModelPipelineFan, &vk_renderpasses[RP_WORLD], shaders, 2);
@ -1462,12 +1466,6 @@ static void CreatePipelines()
//vk_shadows render pipeline
VK_LOAD_VERTFRAG_SHADERS(shaders, shadows, basic_color_quad);
vk_shadowsPipelineStrip.blendOpts.blendEnable = VK_TRUE;
vk_shadowsPipelineStrip.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
QVk_CreatePipeline(&vk_uboDescSetLayout, 1, &vertInfoRGB, &vk_shadowsPipelineStrip, &vk_renderpasses[RP_WORLD], shaders, 2);
QVk_DebugSetObjectName((uint64_t)vk_shadowsPipelineStrip.layout, VK_OBJECT_TYPE_PIPELINE_LAYOUT, "Pipeline Layout: draw shadows: strip");
QVk_DebugSetObjectName((uint64_t)vk_shadowsPipelineStrip.pl, VK_OBJECT_TYPE_PIPELINE, "Pipeline: draw shadows: strip");
vk_shadowsPipelineFan.blendOpts.blendEnable = VK_TRUE;
vk_shadowsPipelineFan.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
QVk_CreatePipeline(&vk_uboDescSetLayout, 1, &vertInfoRGB, &vk_shadowsPipelineFan, &vk_renderpasses[RP_WORLD], shaders, 2);
@ -1526,14 +1524,11 @@ void QVk_Shutdown( void )
for (int i = 0; i < RP_COUNT; ++i)
{
QVk_DestroyPipeline(&vk_drawColorQuadPipeline[i]);
QVk_DestroyPipeline(&vk_drawModelPipelineStrip[i]);
QVk_DestroyPipeline(&vk_drawModelPipelineFan[i]);
QVk_DestroyPipeline(&vk_drawTexQuadPipeline[i]);
}
QVk_DestroyPipeline(&vk_drawNullModelPipeline);
QVk_DestroyPipeline(&vk_drawNoDepthModelPipelineStrip);
QVk_DestroyPipeline(&vk_drawNoDepthModelPipelineFan);
QVk_DestroyPipeline(&vk_drawLefthandModelPipelineStrip);
QVk_DestroyPipeline(&vk_drawLefthandModelPipelineFan);
QVk_DestroyPipeline(&vk_drawParticlesPipeline);
QVk_DestroyPipeline(&vk_drawPointParticlesPipeline);
@ -1546,7 +1541,6 @@ void QVk_Shutdown( void )
QVk_DestroyPipeline(&vk_drawSkyboxPipeline);
QVk_DestroyPipeline(&vk_drawDLightPipeline);
QVk_DestroyPipeline(&vk_showTrisPipeline);
QVk_DestroyPipeline(&vk_shadowsPipelineStrip);
QVk_DestroyPipeline(&vk_shadowsPipelineFan);
QVk_DestroyPipeline(&vk_worldWarpPipeline);
QVk_DestroyPipeline(&vk_postprocessPipeline);
@ -2021,7 +2015,7 @@ qboolean QVk_Init(void)
// create staging buffers
CreateStagingBuffers();
// assign a dynamic index buffer for triangle fan emulation
RebuildTriangleFanIndexBuffer();
RebuildTriangleIndexBuffer();
CreatePipelines();
CreateSamplers();
@ -2303,12 +2297,12 @@ uint8_t *QVk_GetVertexBuffer(VkDeviceSize size, VkBuffer *dstBuffer, VkDeviceSiz
return (uint8_t *)vk_dynVertexBuffers[vk_activeDynBufferIdx].pMappedData + (*dstOffset);
}
static uint8_t *QVk_GetIndexBuffer(VkDeviceSize size, VkDeviceSize *dstOffset)
static uint8_t *QVk_GetIndexBuffer(VkDeviceSize size, VkDeviceSize *dstOffset, int currentBufferIdx)
{
// align to 4 bytes, so that we can reuse the buffer for both VK_INDEX_TYPE_UINT16 and VK_INDEX_TYPE_UINT32
const uint32_t aligned_size = ROUNDUP(size, 4);
if (vk_dynIndexBuffers[vk_activeDynBufferIdx].currentOffset + aligned_size > vk_config.index_buffer_size)
if (vk_dynIndexBuffers[currentBufferIdx].currentOffset + aligned_size > vk_config.index_buffer_size)
{
vk_config.index_buffer_size = max(vk_config.index_buffer_size * BUFFER_RESIZE_FACTOR, NextPow2(size));
@ -2338,14 +2332,14 @@ static uint8_t *QVk_GetIndexBuffer(VkDeviceSize size, VkDeviceSize *dstOffset)
}
}
*dstOffset = vk_dynIndexBuffers[vk_activeDynBufferIdx].currentOffset;
vk_dynIndexBuffers[vk_activeDynBufferIdx].currentOffset += aligned_size;
*dstOffset = vk_dynIndexBuffers[currentBufferIdx].currentOffset;
vk_dynIndexBuffers[currentBufferIdx].currentOffset += aligned_size;
vk_config.index_buffer_usage = vk_dynIndexBuffers[vk_activeDynBufferIdx].currentOffset;
vk_config.index_buffer_usage = vk_dynIndexBuffers[currentBufferIdx].currentOffset;
if (vk_config.index_buffer_max_usage < vk_config.index_buffer_usage)
vk_config.index_buffer_max_usage = vk_config.index_buffer_usage;
return (uint8_t *)vk_dynIndexBuffers[vk_activeDynBufferIdx].pMappedData + (*dstOffset);
return (uint8_t *)vk_dynIndexBuffers[currentBufferIdx].pMappedData + (*dstOffset);
}
uint8_t *QVk_GetUniformBuffer(VkDeviceSize size, uint32_t *dstOffset, VkDescriptorSet *dstUboDescriptorSet)
@ -2461,7 +2455,8 @@ uint8_t *QVk_GetStagingBuffer(VkDeviceSize size, int alignment, VkCommandBuffer
return data;
}
VkBuffer QVk_GetTriangleFanIbo(VkDeviceSize indexCount)
static void
QVk_CheckTriangleIbo(VkDeviceSize indexCount)
{
if (indexCount > vk_config.triangle_index_usage)
vk_config.triangle_index_usage = indexCount;
@ -2472,13 +2467,25 @@ VkBuffer QVk_GetTriangleFanIbo(VkDeviceSize indexCount)
if (indexCount > vk_config.triangle_index_count)
{
vk_config.triangle_index_count *= BUFFER_RESIZE_FACTOR;
R_Printf(PRINT_ALL, "Resizing triangle fan index buffer to %u indices.\n", vk_config.triangle_index_count);
RebuildTriangleFanIndexBuffer();
R_Printf(PRINT_ALL, "Resizing triangle index buffer to %u indices.\n", vk_config.triangle_index_count);
RebuildTriangleIndexBuffer();
}
}
VkBuffer QVk_GetTriangleFanIbo(VkDeviceSize indexCount)
{
QVk_CheckTriangleIbo(indexCount);
return *vk_triangleFanIbo;
}
VkBuffer QVk_GetTriangleStripIbo(VkDeviceSize indexCount)
{
QVk_CheckTriangleIbo(indexCount);
return *vk_triangleStripIbo;
}
void QVk_SubmitStagingBuffers()
{
for (int i = 0; i < NUM_DYNBUFFERS; ++i)

View File

@ -44,7 +44,7 @@ enum {
} pipelineIdx;
typedef struct {
float vertex[3];
vec3_t vertex;
float color[4];
float texCoord[2];
} modelvert;
@ -78,11 +78,12 @@ extern float r_projection_matrix[16];
extern float r_viewproj_matrix[16];
// correction matrix with "hacked depth" for models with RF_DEPTHHACK flag set
static float r_vulkan_correction_dh[16] = { 1.f, 0.f, 0.f, 0.f,
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, .3f, 0.f,
0.f, 0.f, .3f, 1.f
};
static float r_vulkan_correction_dh[16] = {
1.f, 0.f, 0.f, 0.f,
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, .3f, 0.f,
0.f, 0.f, .3f, 1.f
};
int
Mesh_VertsRealloc(int count)
@ -472,8 +473,9 @@ static void Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *s
// player configuration screen model is using the UI renderpass
int pidx = (r_newrefdef.rdflags & RDF_NOWORLDMODEL) ? RP_UI : RP_WORLD;
// non-depth write alias models don't occur with RF_WEAPONMODEL set, so no need for additional left-handed pipelines
qvkpipeline_t pipelines[2][4] = { { vk_drawModelPipelineStrip[pidx], vk_drawModelPipelineFan[pidx], vk_drawLefthandModelPipelineStrip, vk_drawLefthandModelPipelineFan },
{ vk_drawNoDepthModelPipelineStrip, vk_drawNoDepthModelPipelineFan, vk_drawLefthandModelPipelineStrip, vk_drawLefthandModelPipelineFan } };
qvkpipeline_t pipelines[2][4] = {
{ vk_drawModelPipelineFan[pidx], vk_drawModelPipelineFan[pidx], vk_drawLefthandModelPipelineFan, vk_drawLefthandModelPipelineFan },
{ vk_drawNoDepthModelPipelineFan, vk_drawNoDepthModelPipelineFan, vk_drawLefthandModelPipelineFan, vk_drawLefthandModelPipelineFan } };
for (int p = 0; p < 2; p++)
{
VkDeviceSize vaoSize = sizeof(modelvert) * vertCounts[p];
@ -489,9 +491,11 @@ static void Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *s
if (p == TRIANGLE_STRIP)
{
vkCmdBindIndexBuffer(vk_activeCmdbuffer, QVk_GetTriangleStripIbo(maxTriangleFanIdxCnt), 0, VK_INDEX_TYPE_UINT16);
for (i = 0; i < pipeCounters[p]; i++)
{
vkCmdDraw(vk_activeCmdbuffer, drawInfo[p][i].vertexCount, 1, drawInfo[p][i].firstVertex, 0);
vkCmdDrawIndexed(vk_activeCmdbuffer, (drawInfo[p][i].vertexCount - 2) * 3, 1, 0, drawInfo[p][i].firstVertex, 0);
}
}
else
@ -519,7 +523,6 @@ static void Vk_DrawAliasShadow (dmdl_t *paliashdr, int posenum, float *modelMatr
int *order;
vec3_t point;
float height, lheight;
qvkpipeline_t pipelines[2] = { vk_shadowsPipelineStrip, vk_shadowsPipelineFan };
lheight = currententity->origin[2] - lightspot[2];
@ -589,13 +592,14 @@ static void Vk_DrawAliasShadow (dmdl_t *paliashdr, int posenum, float *modelMatr
uint8_t *vertData = QVk_GetVertexBuffer(vaoSize, &vbo, &vboOffset);
memcpy(vertData, shadowverts, vaoSize);
QVk_BindPipeline(&pipelines[pipelineIdx]);
vkCmdBindDescriptorSets(vk_activeCmdbuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[pipelineIdx].layout, 0, 1, &uboDescriptorSet, 1, &uboOffset);
QVk_BindPipeline(&vk_shadowsPipelineFan);
vkCmdBindDescriptorSets(vk_activeCmdbuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vk_shadowsPipelineFan.layout, 0, 1, &uboDescriptorSet, 1, &uboOffset);
vkCmdBindVertexBuffers(vk_activeCmdbuffer, 0, 1, &vbo, &vboOffset);
if (pipelineIdx == TRIANGLE_STRIP)
{
vkCmdDraw(vk_activeCmdbuffer, i, 1, 0, 0);
vkCmdBindIndexBuffer(vk_activeCmdbuffer, QVk_GetTriangleStripIbo((i - 2) * 3), 0, VK_INDEX_TYPE_UINT16);
vkCmdDrawIndexed(vk_activeCmdbuffer, (i - 2) * 3, 1, 0, 0, 0);
}
else
{