rtx: render into fixed 720p framebuffer then upscale
help with perf stability
This commit is contained in:
parent
d6c56d4e1b
commit
3045c6ea1f
|
@ -1,6 +1,9 @@
|
|||
## 2021-03-17..20
|
||||
- [x] rtx: lower resolution framebuffer + upscale
|
||||
- [ ] rtx: importance sample emissive surface
|
||||
|
||||
# Next
|
||||
- [ ] rtx: emissive particles
|
||||
- [ ] rtx: lower resolution framebuffer + upscale
|
||||
- [ ] rtx: textures
|
||||
- [ ] rtx: add fps
|
||||
- [ ] rtx: don't group brush draws by texture
|
||||
|
@ -11,6 +14,7 @@
|
|||
- [ ] rtx: some studio models have glitchy geometry
|
||||
|
||||
# Planned
|
||||
- [ ] rtx: cull light sources (dlights and light textures) using bsp
|
||||
- [ ] dlight for flashlight seems to be broken
|
||||
- [ ] restore render debug labels
|
||||
- [ ] make 2nd commad buffer for resource upload
|
||||
|
|
|
@ -185,6 +185,7 @@ const char *resultName(VkResult result);
|
|||
X(vkCmdPushConstants) \
|
||||
X(vkCreateComputePipelines) \
|
||||
X(vkCmdDispatch) \
|
||||
X(vkCmdBlitImage) \
|
||||
|
||||
#define DEVICE_FUNCS_RTX(X) \
|
||||
X(vkGetAccelerationStructureBuildSizesKHR) \
|
||||
|
|
|
@ -183,7 +183,7 @@ static qboolean createSwapchain( void )
|
|||
create_info->imageExtent.width = vk_frame.surface_caps.currentExtent.width;
|
||||
create_info->imageExtent.height = vk_frame.surface_caps.currentExtent.height;
|
||||
create_info->imageArrayLayers = 1;
|
||||
create_info->imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | (vk_core.rtx ? VK_IMAGE_USAGE_STORAGE_BIT : 0);
|
||||
create_info->imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | (vk_core.rtx ? VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0);
|
||||
create_info->imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
create_info->preTransform = vk_frame.surface_caps.currentTransform;
|
||||
create_info->compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
|
|
|
@ -11,7 +11,7 @@ typedef struct {
|
|||
VkVertexInputAttributeDescription *attribs;
|
||||
uint32_t num_attribs;
|
||||
|
||||
vk_shader_stage_t *stages;
|
||||
const vk_shader_stage_t *stages;
|
||||
uint32_t num_stages;
|
||||
|
||||
uint32_t vertex_stride;
|
||||
|
@ -23,7 +23,7 @@ typedef struct {
|
|||
VkBool32 blendEnable;
|
||||
VkBlendFactor srcColorBlendFactor;
|
||||
VkBlendFactor dstColorBlendFactor;
|
||||
VkBlendOp colorBlendOp;
|
||||
VkBlendOp colorBlendOp;
|
||||
VkBlendFactor srcAlphaBlendFactor;
|
||||
VkBlendFactor dstAlphaBlendFactor;
|
||||
VkBlendOp alphaBlendOp;
|
||||
|
|
|
@ -15,7 +15,12 @@
|
|||
#define MAX_SCRATCH_BUFFER (16*1024*1024)
|
||||
#define MAX_ACCELS_BUFFER (64*1024*1024)
|
||||
|
||||
// TODO settings/realtime modifiable/adaptive
|
||||
#define FRAME_WIDTH 1280
|
||||
#define FRAME_HEIGHT 720
|
||||
|
||||
// TODO sync with shaders
|
||||
// TODO optimal values
|
||||
#define WG_W 16
|
||||
#define WG_H 8
|
||||
|
||||
|
@ -66,6 +71,9 @@ static struct {
|
|||
vk_ray_model_t models[MAX_ACCELS];
|
||||
VkAccelerationStructureKHR tlas;
|
||||
|
||||
int frame_number;
|
||||
vk_image_t frames[2];
|
||||
|
||||
qboolean reload_pipeline;
|
||||
} g_rtx;
|
||||
|
||||
|
@ -303,9 +311,9 @@ void VK_RayScenePushModel( VkCommandBuffer cmdbuf, const vk_ray_model_create_t *
|
|||
continue;
|
||||
ASSERT(tex_id < MAX_TEXTURES);
|
||||
|
||||
g_rtx_emissive_texture_table_t[tex_id].emissive[0] = hack_valve_rad_table->r * scale;
|
||||
g_rtx_emissive_texture_table_t[tex_id].emissive[1] = hack_valve_rad_table->g * scale;
|
||||
g_rtx_emissive_texture_table_t[tex_id].emissive[2] = hack_valve_rad_table->b * scale;
|
||||
g_rtx_emissive_texture_table_t[tex_id].emissive[0] = hack_valve_rad_table[i].r * scale;
|
||||
g_rtx_emissive_texture_table_t[tex_id].emissive[1] = hack_valve_rad_table[i].g * scale;
|
||||
g_rtx_emissive_texture_table_t[tex_id].emissive[2] = hack_valve_rad_table[i].b * scale;
|
||||
g_rtx_emissive_texture_table_t[tex_id].set = true;
|
||||
}
|
||||
}
|
||||
|
@ -384,6 +392,8 @@ void VK_RaySceneEnd(const vk_ray_scene_render_args_t* args)
|
|||
ASSERT(vk_core.rtx);
|
||||
ASSERT(args->ubo.size == sizeof(float) * 16 * 2); // ubo should contain two matrices
|
||||
const VkCommandBuffer cmdbuf = args->cmdbuf;
|
||||
//const vk_image_t* frame_src = g_rtx.frames + 1;
|
||||
const vk_image_t* frame_dst = g_rtx.frames + 0;
|
||||
|
||||
if (g_rtx.reload_pipeline) {
|
||||
gEngine.Con_Printf(S_WARN "Reloading RTX shaders/pipelines\n");
|
||||
|
@ -457,7 +467,7 @@ void VK_RaySceneEnd(const vk_ray_scene_render_args_t* args)
|
|||
{
|
||||
const VkDescriptorImageInfo dii_dst = {
|
||||
.sampler = VK_NULL_HANDLE,
|
||||
.imageView = args->dst.image_view,
|
||||
.imageView = frame_dst->view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
};
|
||||
const VkDescriptorBufferInfo dbi_ubo = {
|
||||
|
@ -572,7 +582,7 @@ void VK_RaySceneEnd(const vk_ray_scene_render_args_t* args)
|
|||
}};
|
||||
VkImageMemoryBarrier image_barrier[] = { {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.image = args->dst.image,
|
||||
.image = frame_dst->image,
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
|
@ -598,7 +608,63 @@ void VK_RaySceneEnd(const vk_ray_scene_render_args_t* args)
|
|||
vkCmdPushConstants(cmdbuf, g_rtx.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push_constants), &push_constants);
|
||||
}
|
||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, g_rtx.pipeline_layout, 0, 1, &g_rtx.desc_set, 0, NULL);
|
||||
vkCmdDispatch(cmdbuf, (args->dst.width+WG_W-1)/WG_W, (args->dst.height+WG_H-1)/WG_H, 1);
|
||||
vkCmdDispatch(cmdbuf, (FRAME_WIDTH+WG_W-1)/WG_W, (FRAME_HEIGHT+WG_H-1)/WG_H, 1);
|
||||
|
||||
// Blit RTX frame onto swapchain image
|
||||
{
|
||||
VkImageMemoryBarrier image_barriers[] = {
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.image = frame_dst->image,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
.subresourceRange =
|
||||
(VkImageSubresourceRange){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.image = args->dst.image,
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
.subresourceRange =
|
||||
(VkImageSubresourceRange){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
}};
|
||||
vkCmdPipelineBarrier(args->cmdbuf,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
0, 0, NULL, 0, NULL, ARRAYSIZE(image_barriers), image_barriers);
|
||||
}
|
||||
|
||||
{
|
||||
VkImageBlit region = {0};
|
||||
region.srcOffsets[1].x = FRAME_WIDTH;
|
||||
region.srcOffsets[1].y = FRAME_HEIGHT;
|
||||
region.srcOffsets[1].z = 1;
|
||||
region.dstOffsets[1].x = args->dst.width;
|
||||
region.dstOffsets[1].y = args->dst.height;
|
||||
region.dstOffsets[1].z = 1;
|
||||
region.srcSubresource.aspectMask = region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.srcSubresource.layerCount = region.dstSubresource.layerCount = 1;
|
||||
vkCmdBlitImage(args->cmdbuf, frame_dst->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
args->dst.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion,
|
||||
VK_FILTER_NEAREST);
|
||||
}
|
||||
}
|
||||
|
||||
static void createLayouts( void ) {
|
||||
|
@ -728,6 +794,11 @@ qboolean VK_RayInit( void )
|
|||
createLayouts();
|
||||
createPipeline();
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(g_rtx.frames); ++i) {
|
||||
g_rtx.frames[i] = VK_ImageCreate(FRAME_WIDTH, FRAME_HEIGHT, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); // | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
}
|
||||
|
||||
if (vk_core.debug)
|
||||
gEngine.Cmd_AddCommand("vk_rtx_reload", reloadPipeline, "Reload RTX shader");
|
||||
|
||||
|
@ -738,13 +809,15 @@ void VK_RayShutdown( void )
|
|||
{
|
||||
ASSERT(vk_core.rtx);
|
||||
|
||||
// TODO dealloc all ASes
|
||||
for (int i = 0; i < ARRAYSIZE(g_rtx.frames); ++i)
|
||||
VK_ImageDestroy(g_rtx.frames + i);
|
||||
|
||||
vkDestroyPipeline(vk_core.device, g_rtx.pipeline, NULL);
|
||||
vkDestroyDescriptorPool(vk_core.device, g_rtx.desc_pool, NULL);
|
||||
vkDestroyPipelineLayout(vk_core.device, g_rtx.pipeline_layout, NULL);
|
||||
vkDestroyDescriptorSetLayout(vk_core.device, g_rtx.desc_layout, NULL);
|
||||
|
||||
// TODO dealloc all ASes
|
||||
cleanupASFIXME();
|
||||
|
||||
destroyBuffer(&g_rtx.scratch_buffer);
|
||||
|
|
|
@ -670,3 +670,45 @@ int VK_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags
|
|||
|
||||
return (tex - vk_textures);
|
||||
}
|
||||
|
||||
vk_image_t VK_ImageCreate(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage) {
|
||||
VkImageCreateInfo ici = {.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
|
||||
ici.imageType = VK_IMAGE_TYPE_2D;
|
||||
ici.extent.width = width;
|
||||
ici.extent.height = height;
|
||||
ici.extent.depth = 1;
|
||||
ici.mipLevels = 1;
|
||||
ici.arrayLayers = 1;
|
||||
ici.format = format;
|
||||
ici.tiling = tiling;
|
||||
ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
ici.usage = usage;
|
||||
ici.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
ici.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
vk_image_t image;
|
||||
XVK_CHECK(vkCreateImage(vk_core.device, &ici, NULL, &image.image));
|
||||
|
||||
VkMemoryRequirements memreq;
|
||||
vkGetImageMemoryRequirements(vk_core.device, image.image, &memreq);
|
||||
image.devmem = allocateDeviceMemory(memreq, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0);
|
||||
XVK_CHECK(vkBindImageMemory(vk_core.device, image.image, image.devmem.device_memory, 0));
|
||||
|
||||
VkImageViewCreateInfo ivci = {.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
ivci.format = ici.format;
|
||||
ivci.image = image.image;
|
||||
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
ivci.subresourceRange.levelCount = 1;
|
||||
ivci.subresourceRange.layerCount = 1;
|
||||
XVK_CHECK(vkCreateImageView(vk_core.device, &ivci, NULL, &image.view));
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void VK_ImageDestroy(vk_image_t *img) {
|
||||
vkDestroyImageView(vk_core.device, img->view, NULL);
|
||||
vkDestroyImage(vk_core.device, img->image, NULL);
|
||||
freeDeviceMemory(&img->devmem);
|
||||
*img = (vk_image_t){0};
|
||||
}
|
||||
|
|
|
@ -65,3 +65,12 @@ int VK_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags
|
|||
|
||||
#define VK_LoadTextureInternal( name, pic, flags ) VK_LoadTextureFromBuffer( name, pic, flags, false )
|
||||
|
||||
typedef struct {
|
||||
// TODO better memory allocation
|
||||
device_memory_t devmem;
|
||||
VkImage image;
|
||||
VkImageView view;
|
||||
} vk_image_t;
|
||||
|
||||
vk_image_t VK_ImageCreate(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage);
|
||||
void VK_ImageDestroy(vk_image_t *img);
|
||||
|
|
Loading…
Reference in New Issue