Fixed r_fastsky and preparation to fix the rest of sky rendering.

This commit is contained in:
Artem Kharytoniuk 2017-04-18 13:40:28 +03:00
parent a5d410fd9f
commit ab32f499f8
9 changed files with 121 additions and 135 deletions

View File

@ -429,23 +429,24 @@ void RB_BeginDrawingView (void) {
} }
#ifdef _DEBUG #ifdef _DEBUG
float color[4] = { 0.8f, 0.7f, 0.4f, 1.0f }; // FIXME: get color of sky float sky_color[4] = { 0.8f, 0.7f, 0.4f, 1.0f }; // FIXME: get color of sky
#else #else
float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; // FIXME: get color of sky float sky_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; // FIXME: get color of sky
#endif #endif
bool clear_color = r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ); bool fast_sky = r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL );
if ( clear_color ) if ( fast_sky )
{ {
clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used
qglClearColor(color[0], color[1], color[2], color[3]); qglClearColor(sky_color[0], sky_color[1], sky_color[2], sky_color[3]);
} }
qglClear( clearBits ); qglClear( clearBits );
// VULKAN // VULKAN
if (glState.vk_dirty_attachments) { if (glState.vk_dirty_attachments || fast_sky) {
VkClearAttachment attachments[2]; VkClearAttachment attachments[2];
uint32_t attachment_count = clear_color ? 2 : 1; uint32_t attachment_count = fast_sky ? 2 : 1;
attachments[0].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; attachments[0].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
attachments[0].clearValue.depthStencil.depth = 1.0f; attachments[0].clearValue.depthStencil.depth = 1.0f;
@ -454,18 +455,33 @@ void RB_BeginDrawingView (void) {
attachments[0].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; attachments[0].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
attachments[0].clearValue.depthStencil.stencil = 0; attachments[0].clearValue.depthStencil.stencil = 0;
} }
if (clear_color) { if (fast_sky) {
attachments[1].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; attachments[1].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
attachments[1].colorAttachment = 0; attachments[1].colorAttachment = 0;
attachments[1].clearValue.color = { color[0], color[1], color[2], color[3] }; attachments[1].clearValue.color = { sky_color[0], sky_color[1], sky_color[2], sky_color[3] };
} }
VkClearRect clear_rect; VkClearRect clear_rect[2];
clear_rect.rect = vk_get_viewport_rect(); clear_rect[0].rect = vk_get_viewport_rect();
clear_rect.baseArrayLayer = 0; clear_rect[0].baseArrayLayer = 0;
clear_rect.layerCount = 1; clear_rect[0].layerCount = 1;
int rect_count = 1;
vkCmdClearAttachments(vk.command_buffer, attachment_count, attachments, 1, &clear_rect); // Split viewport rectangle into two non-overlapping rectangles.
// It's a HACK to prevent Vulkan validation layer's performance warning:
// "vkCmdClearAttachments() issued on command buffer object XXX prior to any Draw Cmds.
// It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw."
//
if (fast_sky) {
uint32_t h = clear_rect[0].rect.extent.height / 2;
clear_rect[0].rect.extent.height = h;
clear_rect[1] = clear_rect[0];
clear_rect[1].rect.offset.y = h;
rect_count = 2;
}
vkCmdClearAttachments(vk.command_buffer, attachment_count, attachments, rect_count, clear_rect);
} }
if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) ) if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) )
@ -922,34 +938,8 @@ const void *RB_DrawBuffer( const void *data ) {
qglDrawBuffer( cmd->buffer ); qglDrawBuffer( cmd->buffer );
// clear screen for debugging
if ( r_clear->integer ) {
qglClearColor( 1, 0, 0.5, 1 );
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}
// VULKAN // VULKAN
VkResult result = vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, vulkan_demo->image_acquired, VK_NULL_HANDLE, &vulkan_demo->swapchain_image_index); vk_begin_frame();
check_vk_result(result, "vkAcquireNextImageKHR");
result = vkWaitForFences(vk.device, 1, &vulkan_demo->rendering_finished_fence, VK_FALSE, 1e9);
check_vk_result(result, "vkWaitForFences");
result = vkResetFences(vk.device, 1, &vulkan_demo->rendering_finished_fence);
check_vk_result(result, "vkResetFences");
VkCommandBufferBeginInfo begin_info;
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.pNext = nullptr;
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
begin_info.pInheritanceInfo = nullptr;
extern FILE* vk_log_file;
if (r_logFile->integer)
fprintf(vk_log_file, "begin\n");
result = vkBeginCommandBuffer(vk.command_buffer, &begin_info);
check_vk_result(result, "vkBeginCommandBuffer");
vulkan_demo->begin_frame();
return (const void *)(cmd + 1); return (const void *)(cmd + 1);
} }

View File

@ -105,7 +105,6 @@ cvar_t *r_picmip;
cvar_t *r_showtris; cvar_t *r_showtris;
cvar_t *r_showsky; cvar_t *r_showsky;
cvar_t *r_shownormals; cvar_t *r_shownormals;
cvar_t *r_clear;
cvar_t *r_swapInterval; cvar_t *r_swapInterval;
cvar_t *r_textureMode; cvar_t *r_textureMode;
cvar_t *r_offsetFactor; cvar_t *r_offsetFactor;
@ -899,7 +898,6 @@ void R_Register( void )
r_showtris = ri.Cvar_Get ("r_showtris", "0", CVAR_CHEAT); r_showtris = ri.Cvar_Get ("r_showtris", "0", CVAR_CHEAT);
r_showsky = ri.Cvar_Get ("r_showsky", "0", CVAR_CHEAT); r_showsky = ri.Cvar_Get ("r_showsky", "0", CVAR_CHEAT);
r_shownormals = ri.Cvar_Get ("r_shownormals", "0", CVAR_CHEAT); r_shownormals = ri.Cvar_Get ("r_shownormals", "0", CVAR_CHEAT);
r_clear = ri.Cvar_Get ("r_clear", "0", CVAR_CHEAT);
r_offsetFactor = ri.Cvar_Get( "r_offsetfactor", "-1", CVAR_CHEAT ); r_offsetFactor = ri.Cvar_Get( "r_offsetfactor", "-1", CVAR_CHEAT );
r_offsetUnits = ri.Cvar_Get( "r_offsetunits", "-2", CVAR_CHEAT ); r_offsetUnits = ri.Cvar_Get( "r_offsetunits", "-2", CVAR_CHEAT );
r_drawBuffer = ri.Cvar_Get( "r_drawBuffer", "GL_BACK", CVAR_CHEAT ); r_drawBuffer = ri.Cvar_Get( "r_drawBuffer", "GL_BACK", CVAR_CHEAT );

View File

@ -1045,7 +1045,6 @@ extern cvar_t *r_logFile; // number of frames to emit GL logs
extern cvar_t *r_showtris; // enables wireframe rendering of the world extern cvar_t *r_showtris; // enables wireframe rendering of the world
extern cvar_t *r_showsky; // forces sky in front of all surfaces extern cvar_t *r_showsky; // forces sky in front of all surfaces
extern cvar_t *r_shownormals; // draws wireframe normals extern cvar_t *r_shownormals; // draws wireframe normals
extern cvar_t *r_clear; // force screen clear every frame
extern cvar_t *r_shadows; // controls shadows: 0 = none, 1 = blur, 2 = stencil, 3 = black planar projection extern cvar_t *r_shadows; // controls shadows: 0 = none, 1 = blur, 2 = stencil, 3 = black planar projection
extern cvar_t *r_flares; // light flares extern cvar_t *r_flares; // light flares

View File

@ -841,7 +841,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
} }
// VULKAN // VULKAN
vk_bind_stage_specific_resources(pStage->vk_pipeline, multitexture); vk_bind_stage_specific_resources(pStage->vk_pipeline, multitexture, input->shader->isSky == qtrue);
vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0); vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0);
glState.vk_dirty_attachments = true; glState.vk_dirty_attachments = true;

View File

@ -504,43 +504,14 @@ static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean ad
} }
} }
static void FillCloudBox( const shader_t *shader, int stage ) static void FillCloudBox( int stage )
{ {
int i; for ( int i = 0; i < 5; i++ )
for ( i =0; i < 6; i++ )
{ {
int sky_mins_subd[2], sky_maxs_subd[2]; int sky_mins_subd[2], sky_maxs_subd[2];
int s, t; int s, t;
float MIN_T;
if ( 1 ) // FIXME? shader->sky.fullClouds ) float MIN_T = -HALF_SKY_SUBDIVISIONS;
{
MIN_T = -HALF_SKY_SUBDIVISIONS;
// still don't want to draw the bottom, even if fullClouds
if ( i == 5 )
continue;
}
else
{
switch( i )
{
case 0:
case 1:
case 2:
case 3:
MIN_T = -1;
break;
case 5:
// don't draw clouds beneath you
continue;
case 4: // top
default:
MIN_T = -HALF_SKY_SUBDIVISIONS;
break;
}
}
sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
@ -625,7 +596,7 @@ void R_BuildCloudData( shaderCommands_t *input )
if ( !tess.xstages[i] ) { if ( !tess.xstages[i] ) {
break; break;
} }
FillCloudBox( input->shader, i ); FillCloudBox( i );
} }
} }
} }

View File

@ -265,29 +265,27 @@ static VkSwapchainKHR create_swapchain(VkPhysicalDevice physical_device, VkDevic
return swapchain; return swapchain;
} }
// TODO: pass device, color format, depth format. Physical device is not needed. static VkRenderPass create_render_pass(VkDevice device, VkFormat color_format, VkFormat depth_format) {
static VkRenderPass create_render_pass(VkPhysicalDevice physical_device, VkDevice device) { VkAttachmentDescription attachments[2];
VkAttachmentDescription color_attachment; attachments[0].flags = 0;
color_attachment.flags = 0; attachments[0].format = color_format;
color_attachment.format = vk.surface_format.format; attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentDescription depth_attachment; attachments[1].flags = 0;
depth_attachment.flags = 0; attachments[1].format = depth_format;
depth_attachment.format = find_depth_format(physical_device); attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depth_attachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference color_attachment_ref; VkAttachmentReference color_attachment_ref;
color_attachment_ref.attachment = 0; color_attachment_ref.attachment = 0;
@ -309,13 +307,12 @@ static VkRenderPass create_render_pass(VkPhysicalDevice physical_device, VkDevic
subpass.preserveAttachmentCount = 0; subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = nullptr; subpass.pPreserveAttachments = nullptr;
std::array<VkAttachmentDescription, 2> attachments{color_attachment, depth_attachment};
VkRenderPassCreateInfo desc; VkRenderPassCreateInfo desc;
desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
desc.pNext = nullptr; desc.pNext = nullptr;
desc.flags = 0; desc.flags = 0;
desc.attachmentCount = static_cast<uint32_t>(attachments.size()); desc.attachmentCount = sizeof(attachments) / sizeof(attachments[0]);
desc.pAttachments = attachments.data(); desc.pAttachments = attachments;
desc.subpassCount = 1; desc.subpassCount = 1;
desc.pSubpasses = &subpass; desc.pSubpasses = &subpass;
desc.dependencyCount = 0; desc.dependencyCount = 0;
@ -408,7 +405,9 @@ bool vk_initialize(HWND hwnd) {
}); });
} }
g.render_pass = create_render_pass(g.physical_device, g.device); VkFormat depth_format = find_depth_format(vk.physical_device);
vk.render_pass = create_render_pass(vk.device, vk.surface_format.format, depth_format);
{ {
std::array<VkImageView, 2> attachments = {VK_NULL_HANDLE, vk.depth_image_view}; std::array<VkImageView, 2> attachments = {VK_NULL_HANDLE, vk.depth_image_view};
@ -1173,7 +1172,7 @@ void vk_bind_resources_shared_between_stages(int num_passes) {
vkCmdPushConstants(vk.command_buffer, vk.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 64, mvp); vkCmdPushConstants(vk.command_buffer, vk.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 64, mvp);
} }
void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture) { void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture, bool sky) {
// //
// Specify color/st for each draw call since they are regenerated for each Q3 shader's stage. // Specify color/st for each draw call since they are regenerated for each Q3 shader's stage.
// xyz are specified only once for all stages. // xyz are specified only once for all stages.
@ -1243,9 +1242,65 @@ void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture) {
viewport.maxDepth = 0.3f; viewport.maxDepth = 0.3f;
} }
if (sky) {
if (r_showsky->integer) {
viewport.minDepth = 0.0f;
viewport.maxDepth = 0.0f;
} else {
viewport.minDepth = 1.0f;
viewport.maxDepth = 1.0f;
}
}
vkCmdSetViewport(vk.command_buffer, 0, 1, &viewport); vkCmdSetViewport(vk.command_buffer, 0, 1, &viewport);
if (tess.shader->polygonOffset) { if (tess.shader->polygonOffset) {
vkCmdSetDepthBias(vk.command_buffer, r_offsetUnits->value, 0.0f, r_offsetFactor->value); vkCmdSetDepthBias(vk.command_buffer, r_offsetUnits->value, 0.0f, r_offsetFactor->value);
} }
} }
void vk_begin_frame() {
extern FILE* vk_log_file;
if (r_logFile->integer)
fprintf(vk_log_file, "vk_begin_frame\n");
VkResult result = vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, vulkan_demo->image_acquired, VK_NULL_HANDLE, &vulkan_demo->swapchain_image_index);
check_vk_result(result, "vkAcquireNextImageKHR");
result = vkWaitForFences(vk.device, 1, &vulkan_demo->rendering_finished_fence, VK_FALSE, 1e9);
check_vk_result(result, "vkWaitForFences");
result = vkResetFences(vk.device, 1, &vulkan_demo->rendering_finished_fence);
check_vk_result(result, "vkResetFences");
VkCommandBufferBeginInfo begin_info;
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.pNext = nullptr;
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
begin_info.pInheritanceInfo = nullptr;
result = vkBeginCommandBuffer(vk.command_buffer, &begin_info);
check_vk_result(result, "vkBeginCommandBuffer");
VkClearValue clear_values[2];
/// ignore clear_values[0] which corresponds to color attachment
clear_values[1].depthStencil.depth = 1.0;
clear_values[1].depthStencil.stencil = 0;
VkRenderPassBeginInfo render_pass_begin_info;
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin_info.pNext = nullptr;
render_pass_begin_info.renderPass = vk.render_pass;
render_pass_begin_info.framebuffer = vk.framebuffers[vulkan_demo->swapchain_image_index];
render_pass_begin_info.renderArea.offset = { 0, 0 };
render_pass_begin_info.renderArea.extent = { (uint32_t)glConfig.vidWidth, (uint32_t)glConfig.vidHeight };
render_pass_begin_info.clearValueCount = 2;
render_pass_begin_info.pClearValues = clear_values;
vkCmdBeginRenderPass(vk.command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
vk.xyz_elements = 0;
vk.color_st_elements = 0;
vk.index_buffer_offset = 0;
glState.vk_dirty_attachments = false;
}

View File

@ -19,7 +19,9 @@ VkRect2D vk_get_viewport_rect();
void vk_get_mvp_transform(float mvp[16]); void vk_get_mvp_transform(float mvp[16]);
void vk_bind_resources_shared_between_stages(int num_passes); void vk_bind_resources_shared_between_stages(int num_passes);
void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture); void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture, bool sky);
void vk_begin_frame();
struct Vk_Staging_Buffer { struct Vk_Staging_Buffer {
VkBuffer handle = VK_NULL_HANDLE; VkBuffer handle = VK_NULL_HANDLE;

View File

@ -107,30 +107,3 @@ void Vulkan_Demo::create_texture_sampler() {
texture_image_sampler = get_resource_manager()->create_sampler(desc); texture_image_sampler = get_resource_manager()->create_sampler(desc);
} }
void Vulkan_Demo::begin_frame() {
if (r_logFile->integer)
fprintf(vk_log_file, "begin_frame\n");
std::array<VkClearValue, 2> clear_values;
clear_values[0].color = {1.0f, 0.3f, 0.3f, 0.0f};
clear_values[1].depthStencil = {1.0, 0};
VkRenderPassBeginInfo render_pass_begin_info;
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin_info.pNext = nullptr;
render_pass_begin_info.renderPass = vk.render_pass;
render_pass_begin_info.framebuffer = vk.framebuffers[swapchain_image_index];
render_pass_begin_info.renderArea.offset = {0, 0};
render_pass_begin_info.renderArea.extent = {(uint32_t)window_width, (uint32_t)window_height};
render_pass_begin_info.clearValueCount = static_cast<uint32_t>(clear_values.size());
render_pass_begin_info.pClearValues = clear_values.data();
vkCmdBeginRenderPass(vk.command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
vk.xyz_elements = 0;
vk.color_st_elements = 0;
vk.index_buffer_offset = 0;
glState.vk_dirty_attachments = false;
}

View File

@ -12,8 +12,6 @@ class Vulkan_Demo {
public: public:
Vulkan_Demo(int window_width, int window_height); Vulkan_Demo(int window_width, int window_height);
void begin_frame();
public: public:
VkImage create_texture(const uint8_t* pixels, int bytes_per_pixel, int width, int height, VkImageView& image_view); VkImage create_texture(const uint8_t* pixels, int bytes_per_pixel, int width, int height, VkImageView& image_view);
void create_texture_sampler(); void create_texture_sampler();