add 2d pipelines with blending; menu is drawn almost ok

also switch to non-srgb framebuffer
and remove a bunch of verbose log messages
This commit is contained in:
Ivan Avdeev 2021-01-18 13:33:22 -08:00
parent ef3a1ad4af
commit e49591652f
9 changed files with 121 additions and 61 deletions

9
ref_vk/buildshaders.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
build() {
NAME="$1"
glslc -o "build-debug-amd64/lib/xash3d/valve/$NAME.spv" "ref_vk/shaders/$NAME"
}
build 2d.frag
build 2d.vert

View File

@ -2,10 +2,11 @@
layout(set=0,binding=0) uniform sampler2D tex;
layout(location = 0) in vec2 vUv;
layout(location=0) in vec2 vUv;
layout(location=1) in vec4 vColor;
layout(location = 0) out vec4 outColor;
void main() {
outColor = texture(tex, vUv);
outColor = texture(tex, vUv) * vColor;
}

View File

@ -2,10 +2,13 @@
layout(location=0) in vec2 aPos;
layout(location=1) in vec2 aUv;
layout(location=2) in vec4 aColor;
layout(location=0) out vec2 vUv;
layout(location=1) out vec4 vColor;
void main() {
gl_Position = vec4(aPos, 0., 1.);
vUv = aUv;
vColor = aColor;
}

View File

@ -5,6 +5,7 @@
#include "vk_common.h"
#include "vk_textures.h"
#include "vk_framectl.h"
#include "vk_renderstate.h"
#include "com_strings.h"
#include "eiface.h"
@ -29,15 +30,20 @@ void CL_FillRGBABlend( float x, float y, float w, float h, int r, int g, int b,
typedef struct vertex_2d_s {
float x, y;
float u, v;
color_rgba8_t color;
} vertex_2d_t;
// TODO should these be dynamic?
#define MAX_PICS 4096
#define MAX_BATCHES 64
static struct {
typedef struct vk_2d_pipeline_s {
VkPipelineLayout pipeline_layout;
VkPipeline pipeline;
} vk_2d_pipeline_t;
static struct {
vk_2d_pipeline_t pipelines[kRenderTransAdd + 1];
uint32_t max_pics, num_pics;
vk_buffer_t pics_buffer;
@ -45,6 +51,7 @@ static struct {
struct {
uint32_t vertex_offset, vertex_count;
int texture;
int blending_mode;
} batch[MAX_BATCHES];
uint32_t current_batch;
@ -53,16 +60,13 @@ static struct {
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum )
{
/* gEngine.Con_Printf(S_WARN "VK FIXME: %s(%f, %f, %f, %f, %f, %f, %f, %f, %d(%s))\n", __FUNCTION__, */
/* x, y, w, h, s1, t1, s2, t2, texnum, findTexture(texnum)->name); */
if (g2d.batch[g2d.current_batch].texture != texnum)
if (g2d.batch[g2d.current_batch].texture != texnum || g2d.batch[g2d.current_batch].blending_mode != vk_renderstate.blending_mode)
{
if (g2d.batch[g2d.current_batch].vertex_count != 0)
{
if (g2d.current_batch == MAX_BATCHES - 1)
{
gEngine.Con_Printf(S_WARN "VK FIXME RAN OUT OF BATCHES: %s(%f, %f, %f, %f, %f, %f, %f, %f, %d(%s))\n", __FUNCTION__,
gEngine.Con_Printf(S_ERROR "VK FIXME RAN OUT OF BATCHES: %s(%f, %f, %f, %f, %f, %f, %f, %f, %d(%s))\n", __FUNCTION__,
x, y, w, h, s1, t1, s2, t2, texnum, findTexture(texnum)->name);
return;
}
@ -71,13 +75,14 @@ void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, f
}
g2d.batch[g2d.current_batch].texture = texnum;
g2d.batch[g2d.current_batch].blending_mode = vk_renderstate.blending_mode;
g2d.batch[g2d.current_batch].vertex_offset = g2d.num_pics;
g2d.batch[g2d.current_batch].vertex_count = 0;
}
if (g2d.num_pics + 6 > g2d.max_pics)
{
gEngine.Con_Printf(S_WARN "VK FIXME RAN OUT OF BUFFER: %s(%f, %f, %f, %f, %f, %f, %f, %f, %d(%s))\n", __FUNCTION__,
gEngine.Con_Printf(S_ERROR "VK FIXME RAN OUT OF BUFFER: %s(%f, %f, %f, %f, %f, %f, %f, %f, %d(%s))\n", __FUNCTION__,
x, y, w, h, s1, t1, s2, t2, texnum, findTexture(texnum)->name);
return;
}
@ -91,23 +96,25 @@ void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, f
const float y1 = (y / vh)*2.f - 1.f;
const float x2 = ((x + w) / vw)*2.f - 1.f;
const float y2 = ((y + h) / vh)*2.f - 1.f;
const color_rgba8_t color = vk_renderstate.tri_color;
g2d.num_pics += 6;
g2d.batch[g2d.current_batch].vertex_count += 6; // ....
p[0] = (vertex_2d_t){x1, y1, s1, t1};
p[1] = (vertex_2d_t){x1, y2, s1, t2};
p[2] = (vertex_2d_t){x2, y1, s2, t1};
p[3] = (vertex_2d_t){x2, y1, s2, t1};
p[4] = (vertex_2d_t){x1, y2, s1, t2};
p[5] = (vertex_2d_t){x2, y2, s2, t2};
p[0] = (vertex_2d_t){x1, y1, s1, t1, color};
p[1] = (vertex_2d_t){x1, y2, s1, t2, color};
p[2] = (vertex_2d_t){x2, y1, s2, t1, color};
p[3] = (vertex_2d_t){x2, y1, s2, t1, color};
p[4] = (vertex_2d_t){x1, y2, s1, t2, color};
p[5] = (vertex_2d_t){x2, y2, s2, t2, color};
}
}
static VkPipeline createPipeline( void )
static qboolean createPipeline(vk_2d_pipeline_t *pipeline, int blending_mode)
{
VkVertexInputAttributeDescription attribs[] = {
{.binding = 0, .location = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(vertex_2d_t, x)},
{.binding = 0, .location = 1, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(vertex_2d_t, u)},
{.binding = 0, .location = 2, .format = VK_FORMAT_R8G8B8A8_UNORM, .offset = offsetof(vertex_2d_t, color)},
};
VkPipelineShaderStageCreateInfo shader_stages[] = {
@ -240,18 +247,44 @@ static VkPipeline createPipeline( void )
/* .pPushConstantRanges = &push_const, */
};
VkPipeline pipeline;
switch (blending_mode)
{
case kRenderNormal:
blend_attachment.blendEnable = VK_FALSE;
break;
case kRenderTransColor:
case kRenderTransTexture:
blend_attachment.blendEnable = VK_TRUE;
blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
blend_attachment.srcAlphaBlendFactor = blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blend_attachment.dstAlphaBlendFactor = blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
break;
case kRenderTransAlpha:
blend_attachment.blendEnable = VK_FALSE;
// FIXME pglEnable( GL_ALPHA_TEST );
break;
case kRenderGlow:
case kRenderTransAdd:
blend_attachment.blendEnable = VK_TRUE;
blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
blend_attachment.srcAlphaBlendFactor = blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blend_attachment.dstAlphaBlendFactor = blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
break;
}
// FIXME store layout separately
XVK_CHECK(vkCreatePipelineLayout(vk_core.device, &plci, NULL, &g2d.pipeline_layout));
gpci.layout = g2d.pipeline_layout;
XVK_CHECK(vkCreatePipelineLayout(vk_core.device, &plci, NULL, &pipeline->pipeline_layout));
gpci.layout = pipeline->pipeline_layout;
XVK_CHECK(vkCreateGraphicsPipelines(vk_core.device, VK_NULL_HANDLE, 1, &gpci, NULL, &pipeline));
XVK_CHECK(vkCreateGraphicsPipelines(vk_core.device, VK_NULL_HANDLE, 1, &gpci, NULL, &pipeline->pipeline));
for (int i = 0; i < (int)ARRAYSIZE(shader_stages); ++i)
vkDestroyShaderModule(vk_core.device, shader_stages[i].module, NULL);
return pipeline;
return true;
}
void vk2dBegin( void )
@ -275,7 +308,6 @@ void vk2dEnd( void )
if (!g2d.num_pics)
return;
vkCmdBindPipeline(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g2d.pipeline);
vkCmdSetViewport(vk_core.cb, 0, ARRAYSIZE(viewport), viewport);
vkCmdSetScissor(vk_core.cb, 0, ARRAYSIZE(scissor), scissor);
vkCmdBindVertexBuffers(vk_core.cb, 0, 1, &g2d.pics_buffer.buffer, &offset);
@ -283,19 +315,28 @@ void vk2dEnd( void )
for (int i = 0; i <= g2d.current_batch; ++i)
{
vk_texture_t *texture = findTexture(g2d.batch[i].texture);
const vk_2d_pipeline_t *pipeline = g2d.pipelines + g2d.batch[i].blending_mode;
if (texture->vk.descriptor)
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g2d.pipeline_layout, 0, 1, &texture->vk.descriptor, 0, NULL);
// FIXME else what?
vkCmdDraw(vk_core.cb, g2d.batch[i].vertex_count, 1, g2d.batch[i].vertex_offset, 0);
{
vkCmdBindPipeline(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout, 0, 1, &texture->vk.descriptor, 0, NULL);
vkCmdDraw(vk_core.cb, g2d.batch[i].vertex_count, 1, g2d.batch[i].vertex_offset, 0);
} // FIXME else what?
}
}
qboolean initVk2d( void )
{
g2d.pipeline = createPipeline();
for (int i = 0; i < ARRAYSIZE(g2d.pipelines); ++i)
if (!createPipeline(g2d.pipelines + i, i))
{
// TODO complain
return false;
}
if (!createBuffer(&g2d.pics_buffer, sizeof(vertex_2d_t) * (MAX_PICS * 6),
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT ))
// FIXME cleanup
return false;
g2d.max_pics = MAX_PICS * 6;
@ -306,6 +347,8 @@ qboolean initVk2d( void )
void deinitVk2d( void )
{
destroyBuffer(&g2d.pics_buffer);
vkDestroyPipeline(vk_core.device, g2d.pipeline, NULL);
vkDestroyPipelineLayout(vk_core.device, g2d.pipeline_layout, NULL);
for (int i = 0; i < ARRAYSIZE(g2d.pipelines); ++i) {
vkDestroyPipeline(vk_core.device, g2d.pipelines[i].pipeline, NULL);
vkDestroyPipelineLayout(vk_core.device, g2d.pipelines[i].pipeline_layout, NULL);
}
}

View File

@ -15,7 +15,7 @@ static struct
static qboolean createRenderPass( void ) {
VkAttachmentDescription attachments[] = {{
.format = VK_FORMAT_B8G8R8A8_SRGB,// FIXME too early swapchain.create_info.imageFormat;
.format = VK_FORMAT_B8G8R8A8_UNORM, //SRGB,// FIXME too early swapchain.create_info.imageFormat;
.samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
//.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
@ -92,7 +92,7 @@ static qboolean createSwapchain( void )
create_info->sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
create_info->pNext = NULL;
create_info->surface = vk_core.surface.surface;
create_info->imageFormat = VK_FORMAT_B8G8R8A8_SRGB; // TODO get from surface_formats
create_info->imageFormat = VK_FORMAT_B8G8R8A8_UNORM;//SRGB; // TODO get from surface_formats
create_info->imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; // TODO get from surface_formats
create_info->imageExtent.width = vk_frame.surface_caps.currentExtent.width;
create_info->imageExtent.height = vk_frame.surface_caps.currentExtent.height;

View File

@ -9,19 +9,7 @@
#include "com_strings.h"
#include "eiface.h" // ARRAYSIZE
extern ref_api_t gEngine;
extern ref_globals_t *gpGlobals;
typedef struct { uint8_t r, g, b, a; } color_rgba8_t;
typedef struct render_state_s {
color_rgba8_t tri_color;
qboolean fog_allowed;
qboolean mode_2d;
int blending_mode; // kRenderNormal, ...
} render_state_t;
render_state_t render_state = {0};
render_state_t vk_renderstate = {0};
static const char *renderModeName(int mode)
{
@ -39,27 +27,21 @@ static const char *renderModeName(int mode)
void GL_SetRenderMode( int renderMode )
{
//gEngine.Con_Printf(S_WARN "VK FIXME: %s(%s(%d))\n", __FUNCTION__, renderModeName(renderMode), renderMode);
render_state.blending_mode = renderMode;
vk_renderstate.blending_mode = renderMode;
}
void TriColor4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a )
{
//gEngine.Con_Printf(S_WARN "VK FIXME: %s(%d, %d, %d, %d)\n", __FUNCTION__, (int)r, (int)g, (int)b, (int)a);
render_state.tri_color = (color_rgba8_t){r, g, b, a};
vk_renderstate.tri_color = (color_rgba8_t){r, g, b, a};
}
void R_AllowFog( qboolean allow )
{
//gEngine.Con_Printf(S_WARN "VK FIXME: %s(%d)\n", __FUNCTION__, allow);
render_state.fog_allowed = allow;
vk_renderstate.fog_allowed = allow;
}
void R_Set2DMode( qboolean enable )
{
//gEngine.Con_Printf(S_WARN "VK FIXME: %s(%d)\n", __FUNCTION__, enable);
render_state.mode_2d = enable;
vk_renderstate.mode_2d = enable;
}

View File

@ -2,6 +2,17 @@
#include "xash3d_types.h"
typedef struct { uint8_t r, g, b, a; } color_rgba8_t;
typedef struct render_state_s {
color_rgba8_t tri_color;
qboolean fog_allowed;
qboolean mode_2d;
int blending_mode; // kRenderNormal, ...
} render_state_t;
extern render_state_t vk_renderstate;
void GL_SetRenderMode( int renderMode );
void TriColor4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a );
void R_AllowFog( qboolean allow );

View File

@ -77,7 +77,7 @@ void R_ProcessEntData( qboolean allocate )
// debug
void R_ShowTextures( void )
{
gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__);
//gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__);
}
// texture management
@ -402,7 +402,7 @@ void GL_OrthoBounds( const float *mins, const float *maxs )
// grab r_speeds message
qboolean R_SpeedsMessage( char *out, size_t size )
{
gEngine.Con_Printf("VK FIXME: %s\n", __FUNCTION__);
//gEngine.Con_Printf("VK FIXME: %s\n", __FUNCTION__);
return false;
}
// get visdata for current frame from custom renderer

View File

@ -433,6 +433,7 @@ static qboolean VK_UploadTexture(vk_texture_t *tex, rgbdata_t *pic)
ivci.subresourceRange.levelCount = 1; // FIXME params.mipmaps_count;
ivci.subresourceRange.baseArrayLayer = 0;
ivci.subresourceRange.layerCount = 1;
ivci.components = (VkComponentMapping){0, 0, 0, (pic->flags & IMAGE_HAS_ALPHA) ? 0 : VK_COMPONENT_SWIZZLE_ONE};
XVK_CHECK(vkCreateImageView(vk_core.device, &ivci, NULL, &tex->vk.image_view));
}
@ -467,24 +468,34 @@ static qboolean VK_UploadTexture(vk_texture_t *tex, rgbdata_t *pic)
///////////// Render API funcs /////////////
// Texture tools
int VK_FindTexture( const char *name )
int VK_FindTexture( const char *name )
{
gEngine.Con_Printf("VK FIXME: %s\n", __FUNCTION__);
vk_texture_t *tex;
if( !Common_CheckTexName( name ))
return 0;
// see if already loaded
if(( tex = Common_TextureForName( name )))
return (tex - vk_textures);
return 0;
}
const char* VK_TextureName( unsigned int texnum )
{
gEngine.Con_Printf("VK FIXME: %s\n", __FUNCTION__);
return "UNKNOWN";
ASSERT( texnum >= 0 && texnum < MAX_TEXTURES );
return vk_textures[texnum].name;
}
const byte* VK_TextureData( unsigned int texnum )
{
gEngine.Con_Printf("VK FIXME: %s\n", __FUNCTION__);
gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__);
// We don't store original texture data
// TODO do we need to?
return NULL;
}
int VK_LoadTexture( const char *name, const byte *buf, size_t size, int flags )
int VK_LoadTexture( const char *name, const byte *buf, size_t size, int flags )
{
vk_texture_t *tex;
rgbdata_t *pic;