if (vkQueueWaitIdle(ctx->queue) != VK_SUCCESS)
debug_printf("vkQueueWaitIdle failed\n");
+ pipe_resource_reference(&ctx->null_buffer, NULL);
+
for (int i = 0; i < ARRAY_SIZE(ctx->batches); ++i)
vkFreeCommandBuffers(screen->dev, ctx->cmdpool, 1, &ctx->batches[i].cmdbuf);
vkDestroyCommandPool(screen->dev, ctx->cmdpool, NULL);
for (int i = 0; i < fb->nr_cbufs; i++) {
struct pipe_surface *surf = fb->cbufs[i];
- state.rts[i].format = zink_get_format(screen, surf->format);
- state.rts[i].samples = surf->nr_samples > 0 ? surf->nr_samples :
- VK_SAMPLE_COUNT_1_BIT;
+ if (surf) {
+ state.rts[i].format = zink_get_format(screen, surf->format);
+ state.rts[i].samples = surf->nr_samples > 0 ? surf->nr_samples :
+ VK_SAMPLE_COUNT_1_BIT;
+ } else {
+ state.rts[i].format = VK_FORMAT_R8_UINT;
+ state.rts[i].samples = VK_SAMPLE_COUNT_1_BIT;
+ }
}
state.num_cbufs = fb->nr_cbufs;
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
struct pipe_surface *psurf = ctx->fb_state.cbufs[i];
state.attachments[i] = zink_surface(psurf);
+ state.has_null_attachments |= !state.attachments[i];
}
state.num_attachments = ctx->fb_state.nr_cbufs;
state.height = ctx->fb_state.height;
state.layers = MAX2(ctx->fb_state.layers, 1);
- return zink_create_framebuffer(screen, &state);
+ return zink_create_framebuffer(ctx, screen, &state);
}
static void
-framebuffer_state_buffer_barriers_setup(const struct pipe_framebuffer_state *state, struct zink_batch *batch)
+framebuffer_state_buffer_barriers_setup(struct zink_context *ctx,
+ const struct pipe_framebuffer_state *state, struct zink_batch *batch)
{
for (int i = 0; i < state->nr_cbufs; i++) {
- struct zink_resource *res = zink_resource(state->cbufs[i]->texture);
+ struct pipe_surface *surf = state->cbufs[i];
+ if (!surf)
+ surf = ctx->framebuffer->null_surface;
+ struct zink_resource *res = zink_resource(surf->texture);
if (res->layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
zink_resource_barrier(batch->cmdbuf, res, res->aspect,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
assert(!batch->rp || batch->rp == ctx->gfx_pipeline_state.render_pass);
assert(!batch->fb || batch->fb == ctx->framebuffer);
- framebuffer_state_buffer_barriers_setup(fb_state, batch);
+ framebuffer_state_buffer_barriers_setup(ctx, fb_state, batch);
zink_render_pass_reference(screen, &batch->rp, ctx->gfx_pipeline_state.render_pass);
zink_framebuffer_reference(screen, &batch->fb, ctx->framebuffer);
struct zink_batch *batch = zink_batch_no_rp(ctx);
- framebuffer_state_buffer_barriers_setup(state, batch);
+ framebuffer_state_buffer_barriers_setup(ctx, state, batch);
}
static void
bool queries_disabled;
struct pipe_resource *dummy_buffer;
+ struct pipe_resource *null_buffer; /* used to create zink_framebuffer->null_surface */
uint32_t num_so_targets;
struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_OUTPUTS];
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+#include "zink_context.h"
#include "zink_framebuffer.h"
#include "zink_render_pass.h"
#include "util/u_memory.h"
#include "util/u_string.h"
+static struct pipe_surface *
+framebuffer_null_surface_init(struct zink_context *ctx, struct zink_framebuffer_state *state)
+{
+ struct pipe_surface surf_templ = {};
+ if (!ctx->null_buffer) {
+ struct pipe_resource *pres;
+ struct pipe_resource templ = {};
+ templ.width0 = state->width;
+ templ.height0 = state->height;
+ templ.depth0 = 1;
+ templ.format = PIPE_FORMAT_R8_UINT;
+ templ.target = PIPE_TEXTURE_2D;
+ templ.bind = PIPE_BIND_RENDER_TARGET;
+
+ pres = ctx->base.screen->resource_create(ctx->base.screen, &templ);
+ if (!pres)
+ return NULL;
+
+ ctx->null_buffer = pres;
+ }
+ surf_templ.format = PIPE_FORMAT_R8_UINT;
+ surf_templ.nr_samples = 1;
+ return ctx->base.create_surface(&ctx->base, ctx->null_buffer, &surf_templ);
+}
+
void
zink_destroy_framebuffer(struct zink_screen *screen,
struct zink_framebuffer *fbuf)
for (int i = 0; i < ARRAY_SIZE(fbuf->surfaces); ++i)
pipe_surface_reference(fbuf->surfaces + i, NULL);
+ pipe_surface_reference(&fbuf->null_surface, NULL);
+
zink_render_pass_reference(screen, &fbuf->rp, NULL);
FREE(fbuf);
}
struct zink_framebuffer *
-zink_create_framebuffer(struct zink_screen *screen,
+zink_create_framebuffer(struct zink_context *ctx, struct zink_screen *screen,
struct zink_framebuffer_state *fb)
{
struct zink_framebuffer *fbuf = CALLOC_STRUCT(zink_framebuffer);
pipe_reference_init(&fbuf->reference, 1);
- VkImageView attachments[ARRAY_SIZE(fb->attachments)];
+ if (fb->has_null_attachments)
+ fbuf->null_surface = framebuffer_null_surface_init(ctx, fb);
+
+ VkImageView attachments[ARRAY_SIZE(fb->attachments)] = {};
for (int i = 0; i < fb->num_attachments; i++) {
struct zink_surface *surf = fb->attachments[i];
+ if (!surf)
+ surf = zink_surface(fbuf->null_surface);
pipe_surface_reference(fbuf->surfaces + i, &surf->base);
attachments[i] = surf->image_view;
}
#include "util/u_inlines.h"
+struct zink_context;
struct zink_screen;
struct zink_render_pass;
uint16_t height, layers;
uint8_t num_attachments;
struct zink_surface *attachments[PIPE_MAX_COLOR_BUFS + 1];
+ bool has_null_attachments;
};
struct zink_framebuffer {
struct pipe_surface *surfaces[PIPE_MAX_COLOR_BUFS + 1];
struct zink_render_pass *rp;
+ struct pipe_surface *null_surface; /* for use with unbound attachments */
};
struct zink_framebuffer *
-zink_create_framebuffer(struct zink_screen *screen,
+zink_create_framebuffer(struct zink_context *ctx, struct zink_screen *screen,
struct zink_framebuffer_state *fb);
void