mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 06:50:11 +01:00
zink: decouple renderpass from framebuffer state
a framebuffer is based on the surfaces attached to it a renderpass is based on the operations being performed a zink_framebuffer object doesn't necessarily need to be changed if the renderpass changes, as this might just indicate that a clear operation is being used instead of a load, so we can cache the corresponding vk objects into the zink_framebuffer based on the renderpass ops being used to (eventually) reduce fb object thrashing by doing more incremental updates Reviewed-by: Adam Jackson <ajax@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8227>
This commit is contained in:
parent
49bb791991
commit
3d88e65e88
3 changed files with 77 additions and 21 deletions
|
|
@ -709,7 +709,6 @@ create_framebuffer(struct zink_context *ctx)
|
|||
struct pipe_surface *attachments[PIPE_MAX_COLOR_BUFS + 1] = {};
|
||||
|
||||
struct zink_framebuffer_state state = {};
|
||||
state.rp = get_render_pass(ctx);
|
||||
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
|
||||
struct pipe_surface *psurf = ctx->fb_state.cbufs[i];
|
||||
state.attachments[i] = psurf ? zink_surface(psurf)->image_view : VK_NULL_HANDLE;
|
||||
|
|
@ -728,7 +727,9 @@ create_framebuffer(struct zink_context *ctx)
|
|||
state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1);
|
||||
state.samples = ctx->fb_state.samples;
|
||||
|
||||
return zink_create_framebuffer(ctx, screen, &state, attachments);
|
||||
struct zink_framebuffer *fb = zink_create_framebuffer(ctx, &state, attachments);
|
||||
zink_init_framebuffer(screen, fb, get_render_pass(ctx));
|
||||
return fb;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -814,7 +815,7 @@ zink_batch_rp(struct zink_context *ctx)
|
|||
struct zink_batch *batch = zink_curr_batch(ctx);
|
||||
if (!batch->in_rp) {
|
||||
zink_begin_render_pass(ctx, batch);
|
||||
assert(batch->fb && batch->fb->state.rp);
|
||||
assert(batch->fb && batch->fb->rp);
|
||||
}
|
||||
return batch;
|
||||
}
|
||||
|
|
@ -847,7 +848,7 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
|
|||
zink_framebuffer_reference(screen, &fb, NULL);
|
||||
fb = create_framebuffer(ctx);
|
||||
zink_framebuffer_reference(screen, &ctx->framebuffer, fb);
|
||||
ctx->gfx_pipeline_state.render_pass = fb->state.rp;
|
||||
ctx->gfx_pipeline_state.render_pass = fb->rp;
|
||||
|
||||
uint8_t rast_samples = util_framebuffer_get_num_samples(state);
|
||||
/* in vulkan, gl_SampleMask needs to be explicitly ignored for sampleCount == 1 */
|
||||
|
|
|
|||
|
|
@ -63,7 +63,14 @@ void
|
|||
zink_destroy_framebuffer(struct zink_screen *screen,
|
||||
struct zink_framebuffer *fb)
|
||||
{
|
||||
vkDestroyFramebuffer(screen->dev, fb->fb, NULL);
|
||||
hash_table_foreach(&fb->objects, he) {
|
||||
#if defined(_WIN64) || defined(__x86_64__)
|
||||
vkDestroyFramebuffer(screen->dev, he->data, NULL);
|
||||
#else
|
||||
VkFramebuffer *ptr = he->data;
|
||||
vkDestroyFramebuffer(screen->dev, *ptr, NULL);
|
||||
#endif
|
||||
}
|
||||
for (int i = 0; i < ARRAY_SIZE(fb->surfaces); ++i)
|
||||
pipe_surface_reference(fb->surfaces + i, NULL);
|
||||
|
||||
|
|
@ -72,11 +79,60 @@ zink_destroy_framebuffer(struct zink_screen *screen,
|
|||
ralloc_free(fb);
|
||||
}
|
||||
|
||||
void
|
||||
zink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp)
|
||||
{
|
||||
VkFramebuffer ret;
|
||||
|
||||
if (fb->rp == rp)
|
||||
return;
|
||||
|
||||
uint32_t hash = _mesa_hash_pointer(rp);
|
||||
|
||||
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&fb->objects, hash, rp);
|
||||
if (he) {
|
||||
#if defined(_WIN64) || defined(__x86_64__)
|
||||
ret = (VkFramebuffer)he->data;
|
||||
#else
|
||||
VkFramebuffer *ptr = he->data;
|
||||
ret = *ptr;
|
||||
#endif
|
||||
goto out;
|
||||
}
|
||||
|
||||
VkFramebufferCreateInfo fci = {};
|
||||
fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
fci.renderPass = rp->render_pass;
|
||||
fci.attachmentCount = fb->state.num_attachments;
|
||||
fci.pAttachments = fb->state.attachments;
|
||||
fci.width = fb->state.width;
|
||||
fci.height = fb->state.height;
|
||||
fci.layers = fb->state.layers;
|
||||
|
||||
if (vkCreateFramebuffer(screen->dev, &fci, NULL, &ret) != VK_SUCCESS)
|
||||
return;
|
||||
#if defined(_WIN64) || defined(__x86_64__)
|
||||
_mesa_hash_table_insert_pre_hashed(&fb->objects, hash, rp, ret);
|
||||
#else
|
||||
VkFramebuffer *ptr = ralloc(fb, VkFramebuffer);
|
||||
if (!ptr) {
|
||||
vkDestroyFramebuffer(screen->dev, ret, NULL);
|
||||
return;
|
||||
}
|
||||
*ptr = ret;
|
||||
_mesa_hash_table_insert_pre_hashed(&fb->objects, hash, rp, ptr);
|
||||
#endif
|
||||
out:
|
||||
fb->rp = rp;
|
||||
fb->fb = ret;
|
||||
}
|
||||
|
||||
struct zink_framebuffer *
|
||||
zink_create_framebuffer(struct zink_context *ctx, struct zink_screen *screen,
|
||||
zink_create_framebuffer(struct zink_context *ctx,
|
||||
struct zink_framebuffer_state *state,
|
||||
struct pipe_surface **attachments)
|
||||
{
|
||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||
struct zink_framebuffer *fb = rzalloc(NULL, struct zink_framebuffer);
|
||||
if (!fb)
|
||||
return NULL;
|
||||
|
|
@ -93,22 +149,14 @@ zink_create_framebuffer(struct zink_context *ctx, struct zink_screen *screen,
|
|||
}
|
||||
}
|
||||
|
||||
VkFramebufferCreateInfo fci = {};
|
||||
fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
fci.renderPass = state->rp->render_pass;
|
||||
fci.attachmentCount = state->num_attachments;
|
||||
fci.pAttachments = state->attachments;
|
||||
fci.width = state->width;
|
||||
fci.height = state->height;
|
||||
fci.layers = state->layers;
|
||||
|
||||
if (vkCreateFramebuffer(screen->dev, &fci, NULL, &fb->fb) != VK_SUCCESS) {
|
||||
zink_destroy_framebuffer(screen, fb);
|
||||
return NULL;
|
||||
}
|
||||
if (!_mesa_hash_table_init(&fb->objects, fb, _mesa_hash_pointer, _mesa_key_pointer_equal))
|
||||
goto fail;
|
||||
memcpy(&fb->state, state, sizeof(struct zink_framebuffer_state));
|
||||
|
||||
return fb;
|
||||
fail:
|
||||
zink_destroy_framebuffer(screen, fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "pipe/p_state.h"
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "util/hash_table.h"
|
||||
#include "util/u_inlines.h"
|
||||
|
||||
struct zink_context;
|
||||
|
|
@ -34,7 +35,6 @@ struct zink_screen;
|
|||
struct zink_render_pass;
|
||||
|
||||
struct zink_framebuffer_state {
|
||||
struct zink_render_pass *rp;
|
||||
uint32_t width;
|
||||
uint16_t height, layers;
|
||||
uint8_t samples;
|
||||
|
|
@ -44,18 +44,25 @@ struct zink_framebuffer_state {
|
|||
|
||||
struct zink_framebuffer {
|
||||
struct pipe_reference reference;
|
||||
|
||||
/* current objects */
|
||||
VkFramebuffer fb;
|
||||
struct zink_render_pass *rp;
|
||||
|
||||
struct pipe_surface *surfaces[PIPE_MAX_COLOR_BUFS + 1];
|
||||
struct pipe_surface *null_surface; /* for use with unbound attachments */
|
||||
struct zink_framebuffer_state state;
|
||||
struct hash_table objects;
|
||||
};
|
||||
|
||||
struct zink_framebuffer *
|
||||
zink_create_framebuffer(struct zink_context *ctx, struct zink_screen *screen,
|
||||
zink_create_framebuffer(struct zink_context *ctx,
|
||||
struct zink_framebuffer_state *fb,
|
||||
struct pipe_surface **attachments);
|
||||
|
||||
void
|
||||
zink_init_framebuffer(struct zink_screen *screen, struct zink_framebuffer *fb, struct zink_render_pass *rp);
|
||||
|
||||
void
|
||||
zink_destroy_framebuffer(struct zink_screen *screen,
|
||||
struct zink_framebuffer *fbuf);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue