Skip to content
This repository has been archived by the owner on May 10, 2023. It is now read-only.

Commit

Permalink
Add alpha test support
Browse files Browse the repository at this point in the history
Use specialization constants for different world pipeline modes (alpha_test/fullbright)
  • Loading branch information
Axel Gneiting committed Jul 30, 2016
1 parent 52935ed commit cb1f468
Show file tree
Hide file tree
Showing 14 changed files with 219 additions and 260 deletions.
1 change: 0 additions & 1 deletion Quake/Makefile
Expand Up @@ -234,7 +234,6 @@ SHADER_OBJS = \
../Shaders/Compiled/sky_layer_frag.c \
../Shaders/Compiled/sky_layer_vert.c \
../Shaders/Compiled/world_frag.c \
../Shaders/Compiled/world_fullbright_frag.c \
../Shaders/Compiled/world_vert.c

GLOBJS = \
Expand Down
1 change: 0 additions & 1 deletion Quake/Makefile.w32
Expand Up @@ -224,7 +224,6 @@ SHADER_OBJS = \
../Shaders/Compiled/sky_layer_frag.c \
../Shaders/Compiled/sky_layer_vert.c \
../Shaders/Compiled/world_frag.c \
../Shaders/Compiled/world_fullbright_frag.c \
../Shaders/Compiled/world_vert.c

GLOBJS = \
Expand Down
1 change: 0 additions & 1 deletion Quake/Makefile.w64
Expand Up @@ -222,7 +222,6 @@ SHADER_OBJS = \
../Shaders/Compiled/sky_layer_frag.c \
../Shaders/Compiled/sky_layer_vert.c \
../Shaders/Compiled/world_frag.c \
../Shaders/Compiled/world_fullbright_frag.c \
../Shaders/Compiled/world_vert.c

GLOBJS = \
Expand Down
48 changes: 41 additions & 7 deletions Quake/gl_rmisc.c
Expand Up @@ -972,7 +972,6 @@ void R_CreatePipelines()
VkShaderModule basic_notex_frag_module = R_CreateShaderModule(basic_notex_frag_spv, basic_notex_frag_spv_size);
VkShaderModule world_vert_module = R_CreateShaderModule(world_vert_spv, world_vert_spv_size);
VkShaderModule world_frag_module = R_CreateShaderModule(world_frag_spv, world_frag_spv_size);
VkShaderModule world_fullbright_frag_module = R_CreateShaderModule(world_fullbright_frag_spv, world_fullbright_frag_spv_size);
VkShaderModule alias_vert_module = R_CreateShaderModule(alias_vert_spv, alias_vert_spv_size);
VkShaderModule alias_frag_module = R_CreateShaderModule(alias_frag_spv, alias_frag_spv_size);
VkShaderModule sky_layer_vert_module = R_CreateShaderModule(sky_layer_vert_spv, sky_layer_vert_spv_size);
Expand Down Expand Up @@ -1265,23 +1264,59 @@ void R_CreatePipelines()
vertex_input_state_create_info.vertexBindingDescriptionCount = 1;
vertex_input_state_create_info.pVertexBindingDescriptions = &world_vertex_binding_description;

VkSpecializationMapEntry specialization_entries[2];
specialization_entries[0].constantID = 0;
specialization_entries[0].offset = 0;
specialization_entries[0].size = 4;
specialization_entries[1].constantID = 1;
specialization_entries[1].offset = 4;
specialization_entries[1].size = 4;

uint32_t specialization_data[2];
specialization_data[0] = 0;
specialization_data[1] = 0;

VkSpecializationInfo specialization_info;
specialization_info.mapEntryCount = 2;
specialization_info.pMapEntries = specialization_entries;
specialization_info.dataSize = 8;
specialization_info.pData = specialization_data;

pipeline_create_info.layout = vulkan_globals.world_pipeline_layout;

shader_stages[0].module = world_vert_module;
shader_stages[1].module = world_frag_module;
shader_stages[1].pSpecializationInfo = &specialization_info;

blend_attachment_state.blendEnable = VK_FALSE;

pipeline_create_info.layout = vulkan_globals.world_pipeline_layout;

err = vkCreateGraphicsPipelines(vulkan_globals.device, VK_NULL_HANDLE, 1, &pipeline_create_info, NULL, &vulkan_globals.world_pipeline);
err = vkCreateGraphicsPipelines(vulkan_globals.device, VK_NULL_HANDLE, 1, &pipeline_create_info, NULL, &vulkan_globals.world_pipelines[world_pipeline_base]);
if (err != VK_SUCCESS)
Sys_Error("vkCreateGraphicsPipelines failed");

specialization_data[0] = 1;
specialization_data[1] = 0;

err = vkCreateGraphicsPipelines(vulkan_globals.device, VK_NULL_HANDLE, 1, &pipeline_create_info, NULL, &vulkan_globals.world_pipelines[world_pipeline_fullbright]);
if (err != VK_SUCCESS)
Sys_Error("vkCreateGraphicsPipelines failed");

shader_stages[1].module = world_fullbright_frag_module;
specialization_data[0] = 0;
specialization_data[1] = 1;

err = vkCreateGraphicsPipelines(vulkan_globals.device, VK_NULL_HANDLE, 1, &pipeline_create_info, NULL, &vulkan_globals.world_fullbright_pipeline);
err = vkCreateGraphicsPipelines(vulkan_globals.device, VK_NULL_HANDLE, 1, &pipeline_create_info, NULL, &vulkan_globals.world_pipelines[world_pipeline_alpha_test]);
if (err != VK_SUCCESS)
Sys_Error("vkCreateGraphicsPipelines failed");

specialization_data[0] = 1;
specialization_data[1] = 1;

err = vkCreateGraphicsPipelines(vulkan_globals.device, VK_NULL_HANDLE, 1, &pipeline_create_info, NULL, &vulkan_globals.world_pipelines[world_pipeline_fullbright_alpha_test]);
if (err != VK_SUCCESS)
Sys_Error("vkCreateGraphicsPipelines failed");

shader_stages[1].pSpecializationInfo = NULL;

//================
// Alias pipeline
//================
Expand Down Expand Up @@ -1336,7 +1371,6 @@ void R_CreatePipelines()
vkDestroyShaderModule(vulkan_globals.device, sky_layer_vert_module, NULL);
vkDestroyShaderModule(vulkan_globals.device, alias_frag_module, NULL);
vkDestroyShaderModule(vulkan_globals.device, alias_vert_module, NULL);
vkDestroyShaderModule(vulkan_globals.device, world_fullbright_frag_module, NULL);
vkDestroyShaderModule(vulkan_globals.device, world_frag_module, NULL);
vkDestroyShaderModule(vulkan_globals.device, world_vert_module, NULL);
vkDestroyShaderModule(vulkan_globals.device, basic_notex_frag_module, NULL);
Expand Down
11 changes: 9 additions & 2 deletions Quake/glquake.h
Expand Up @@ -100,6 +100,14 @@ typedef struct particle_s
ptype_t type;
} particle_t;

typedef enum {
world_pipeline_base,
world_pipeline_fullbright,
world_pipeline_alpha_test,
world_pipeline_fullbright_alpha_test,
world_pipeline_count
} world_pipeline_type;

typedef struct
{
VkDevice device;
Expand All @@ -122,8 +130,7 @@ typedef struct
VkPipeline basic_blend_pipeline;
VkPipeline basic_notex_blend_pipeline;
VkPipelineLayout basic_pipeline_layout;
VkPipeline world_pipeline;
VkPipeline world_fullbright_pipeline;
VkPipeline world_pipelines[world_pipeline_count];
VkPipelineLayout world_pipeline_layout;
VkPipeline water_pipeline;
VkPipeline warp_pipeline;
Expand Down
56 changes: 30 additions & 26 deletions Quake/r_world.c
Expand Up @@ -448,10 +448,18 @@ R_FlushBatch
Draw the current batch if non-empty and clears it, ready for more R_BatchSurface calls.
================
*/
static void R_FlushBatch ()
static void R_FlushBatch (VkPipeline * current_pipeline, qboolean fullbright_enabled, qboolean alpha_test)
{
if (num_vbo_indices > 0)
{
int pipeline_index = (fullbright_enabled ? 1 : 0) + (alpha_test ? 2 : 0);
VkPipeline new_pipeline = vulkan_globals.world_pipelines[pipeline_index];
if (new_pipeline != *current_pipeline)
{
vkCmdBindPipeline(vulkan_globals.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, new_pipeline);
*current_pipeline = new_pipeline;
}

VkBuffer buffer;
VkDeviceSize buffer_offset;
byte * indices = R_IndexAllocate(num_vbo_indices * sizeof(uint32_t), &buffer, &buffer_offset);
Expand All @@ -472,14 +480,14 @@ Add the surface to the current batch, or just draw it immediately if we're not
using VBOs.
================
*/
static void R_BatchSurface (msurface_t *s)
static void R_BatchSurface (msurface_t *s, VkPipeline * current_pipeline, qboolean fullbright_enabled, qboolean alpha_test)
{
int num_surf_indices;

num_surf_indices = R_NumTriangleIndicesForSurf (s);

if (num_vbo_indices + num_surf_indices > MAX_BATCH_SIZE)
R_FlushBatch();
R_FlushBatch(current_pipeline, fullbright_enabled, alpha_test);

R_TriangleIndicesForSurf (s, &vbo_indices[num_vbo_indices]);
num_vbo_indices += num_surf_indices;
Expand Down Expand Up @@ -706,43 +714,41 @@ void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_
msurface_t *s;
texture_t *t;
qboolean bound;
qboolean fullbright_enabled = false;
qboolean alpha_test = false;
int lastlightmap;
gltexture_t *fullbright = NULL;

VkPipeline current_pipeline = VK_NULL_HANDLE;

VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(vulkan_globals.command_buffer, 0, 1, &bmodel_vertex_buffer, &offset);
vkCmdBindPipeline(vulkan_globals.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_globals.world_pipeline);
VkPipeline current_pipeline = vulkan_globals.world_pipeline;

for (i=0 ; i<model->numtextures ; i++)
vkCmdBindDescriptorSets(vulkan_globals.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_globals.world_pipeline_layout, 2, 1, &nulltexture->descriptor_set, 0, NULL);

for (i = 0; i<model->numtextures; ++i)
{
t = model->textures[i];

if (!t || !t->texturechains[chain] || t->texturechains[chain]->flags & (SURF_DRAWTILED | SURF_NOTEXTURE))
continue;

// Enable/disable TMU 2 (fullbrights)

if (gl_fullbrights.value && (fullbright = R_TextureAnimation(t, ent != NULL ? ent->frame : 0)->fullbright))
{
if (current_pipeline != vulkan_globals.world_fullbright_pipeline)
{
vkCmdBindPipeline(vulkan_globals.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_globals.world_fullbright_pipeline);
current_pipeline = vulkan_globals.world_fullbright_pipeline;
}

fullbright_enabled = true;
vkCmdBindDescriptorSets(vulkan_globals.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_globals.world_pipeline_layout, 2, 1, &fullbright->descriptor_set, 0, NULL);
}
else if (current_pipeline != vulkan_globals.world_pipeline)
else
{
vkCmdBindPipeline(vulkan_globals.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_globals.world_pipeline);
current_pipeline = vulkan_globals.world_pipeline;
fullbright_enabled = false;
}

R_ClearBatch ();

bound = false;
lastlightmap = 0; // avoid compiler warning
for (s = t->texturechains[chain]; s; s = s->texturechain)
{
if (!s->culled)
{
if (!bound) //only bind once we are sure we need this texture
Expand All @@ -751,29 +757,27 @@ void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_
gltexture_t * gl_texture = texture->gltexture;
vkCmdBindDescriptorSets(vulkan_globals.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_globals.world_pipeline_layout, 0, 1, &gl_texture->descriptor_set, 0, NULL);

//if (t->texturechains[chain]->flags & SURF_DRAWFENCE)
// glEnable (GL_ALPHA_TEST); // Flip alpha test back on

alpha_test = (t->texturechains[chain]->flags & SURF_DRAWFENCE) != 0;
bound = true;
lastlightmap = s->lightmaptexturenum;
}

if (s->lightmaptexturenum != lastlightmap)
R_FlushBatch ();
{
R_FlushBatch (&current_pipeline, fullbright_enabled, alpha_test);
}

gltexture_t * lightmap_texture = lightmap_textures[s->lightmaptexturenum];
vkCmdBindDescriptorSets(vulkan_globals.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_globals.world_pipeline_layout, 1, 1, &lightmap_texture->descriptor_set, 0, NULL);

lastlightmap = s->lightmaptexturenum;
R_BatchSurface (s);
R_BatchSurface (s, &current_pipeline, fullbright_enabled, alpha_test);

rs_brushpasses++;
}
}

R_FlushBatch ();

//if (bound && t->texturechains[chain]->flags & SURF_DRAWFENCE)
// glDisable (GL_ALPHA_TEST); // Flip alpha test back off
R_FlushBatch (&current_pipeline, fullbright_enabled, alpha_test);
}
}

Expand Down

0 comments on commit cb1f468

Please sign in to comment.