summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c2.cpp4
-rw-r--r--video.cpp273
2 files changed, 217 insertions, 60 deletions
diff --git a/c2.cpp b/c2.cpp
index 5268117..e4834ad 100644
--- a/c2.cpp
+++ b/c2.cpp
@@ -236,6 +236,7 @@ struct Sky {
cb->iview = cam.get_view().inverse();
cb->iprojection = cam.get_proj().inverse();
config.unmap(d);
+ config.update(d->get_ctx());
render_imp(
d,
a,
@@ -284,7 +285,6 @@ struct Sky {
draw.verts = vbb;
draw.vertex_count = 3;
draw.instance_count = 1;
- config.update(ctx);
ctx.submit(draw, pip, pass);
}
};
@@ -407,7 +407,6 @@ struct Env_Probe {
Context& ctx = dev->get_ctx();
update_cbuffer(dev);
for (i = 0; i < 6; i++) {
- ctx.transition(faces[i], Resource_State::render_target);
pb.begin_rp();
pb.rp_target(faces[i], Clear_Mode::discard);
pb.rp_depth_target(cubemap_depth, 1.0f);
@@ -421,7 +420,6 @@ struct Env_Probe {
cubemap_res,
cubemap_res
);
- ctx.transition(faces[i], Resource_State::shader_read);
}
}
};
diff --git a/video.cpp b/video.cpp
index 8bb542a..089735c 100644
--- a/video.cpp
+++ b/video.cpp
@@ -3,6 +3,7 @@
#define device_heap_size (1024 * 1024 * 8)
#define max_textures 1024
+#define max_texture_alias 32
#define max_buffers 1024
#define max_vertex_formats 64
#define max_rpos 64
@@ -379,19 +380,27 @@ static VkImageViewType get_view_type(int a, int d, int flags) {
return t;
}
+template <bool Depth>
VkImageLayout state_to_image_layout(Resource_State s) {
switch (s) {
case undefined: return VK_IMAGE_LAYOUT_UNDEFINED;
case copy_dst: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
case copy_src: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
case shader_read: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- case render_target: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ case render_target:
+ return Depth?
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
case presentable: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
}
assert(0);
return VK_IMAGE_LAYOUT_UNDEFINED;
}
+VkImageLayout state_to_image_layout(Resource_State s) {
+ return state_to_image_layout<false>(s);
+}
+
static void* __stdcall vk_alloc(
void* uptr,
size_t size,
@@ -616,6 +625,8 @@ struct Shader_Vk : public Shader, public Late_Terminated {
struct Renderpass_Vk;
struct Framebuffer_Vk;
+struct Pipeline_Vk;
+struct Rpo_Key;
struct Context_Vk : public Context {
int state;
Device_Vk* dev;
@@ -639,10 +650,19 @@ struct Context_Vk : public Context {
void destroy();
std::pair<Renderpass_Vk&, Framebuffer_Vk&> begin_rp(
- const Render_Pass& rp
+ const Rpo_Key& rp
+ );
+ void end_rp(
+ const Render_Pass& rp,
+ Renderpass_Vk& rpo,
+ Framebuffer_Vk& fbo
);
- void end_rp(Renderpass_Vk& rpo, Framebuffer_Vk& fbo);
void check_end_rp();
+
+ void submit_descriptors(
+ const Pipeline_Vk& pso,
+ const Pipeline& p
+ );
};
struct Texture_Vk : public Texture, public Late_Terminated {
@@ -650,10 +670,14 @@ struct Texture_Vk : public Texture, public Late_Terminated {
VkImageView view;
Vram_Allocator::Allocation memory;
Resource_State state;
+ Texture_Id parent;
+ Texture_Id children[max_texture_alias];
+ int child_count;
static void init(
Texture_Vk* t,
Texture_Id id,
+ Texture_Id parent,
VkImage img,
VkImageView v,
Vram_Allocator::Allocation mem,
@@ -671,6 +695,9 @@ struct Texture_Vk : public Texture, public Late_Terminated {
);
void destroy(Device_Vk*) override;
void set_name(Device_Vk* dev, const char* name);
+ void add_child(Texture_Id id);
+ void rem_child(Texture_Id id);
+ bool child_states_same(Device_Vk* dev);
};
struct Buffer_Vk : public Buffer, public Late_Terminated {
@@ -711,14 +738,30 @@ struct Buffer_Vk : public Buffer, public Late_Terminated {
}
};
+struct Render_Pass_States {
+ Resource_State colours[max_colour_attachments];
+ Resource_State depth;
+ int colour_count;
+
+ bool operator==(const Render_Pass_States& other) const {
+ int i;
+ if (colour_count != other.colour_count) return false;
+ if (depth != other.depth) return false;
+ for (i = 0; i < colour_count; i++)
+ if (colours[i] != other.colours[i])
+ return false;
+ return true;
+ }
+};
+
struct Rpo_Key {
- bool is_first;
Render_Pass rpo;
+ Render_Pass_States states;
bool operator==(const Rpo_Key& other) const {
return
- is_first == other.is_first &&
- rpo.layout_eq(other.rpo);
+ rpo.layout_eq(other.rpo) &&
+ states == other.states;
}
};
@@ -902,8 +945,8 @@ struct Hash_Function<Rpo_Key> {
size_t operator()(const Rpo_Key& k) const {
return (size_t)fnv1a64_2(
k.rpo.layout_hash,
- (uint8_t*)&k.is_first,
- 1
+ (uint8_t*)&k.states,
+ sizeof k.states
);
}
};
@@ -1061,7 +1104,6 @@ struct Device_Vk : public Device {
Terminator* terminators;
uint32_t terminator_index;
- bool first_rp;
Texture_Id depth;
@@ -1116,6 +1158,7 @@ struct Device_Vk : public Device {
uint32_t filter,
VkMemoryPropertyFlags flags
);
+ Render_Pass_States get_rp_states(const Render_Pass& p);
};
#ifdef DEBUG
@@ -1682,6 +1725,25 @@ int Device_Vk::find_memory_type(
return -1;
}
+Render_Pass_States Device_Vk::get_rp_states(
+ const Render_Pass& p
+) {
+ int i;
+ Render_Pass_States s{};
+ s.colour_count = p.colour_count;
+ for (i = 0; i < p.colour_count; i++) {
+ Texture_Vk& t =
+ *(Texture_Vk*)&get_texture(p.colours[i].id);
+ s.colours[i] = t.state;
+ }
+ if (p.depth.id) {
+ Texture_Vk& t =
+ *(Texture_Vk*)&get_texture(p.depth.id);
+ s.depth = t.state;
+ }
+ return s;
+}
+
VkAttachmentLoadOp Renderpass_Vk::load_op_from_mode(
Clear_Mode m
) {
@@ -1704,6 +1766,7 @@ void Renderpass_Vk::init(
VkSubpassDescription sd{};
VkResult r;
auto& rp = rpk.rpo;
+ auto& states = rpk.states;
bool has_depth = rp.depth.id;
int count = 0, i, c = rp.colour_count;
zero(ads, sizeof ads);
@@ -1717,10 +1780,11 @@ void Renderpass_Vk::init(
ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
ad.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- if (rpk.is_first)
- ad.initialLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- else
- ad.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ if (colour.mode == Clear_Mode::restore) {
+ Resource_State state = states.colours[i];
+ ad.initialLayout = state_to_image_layout(state);
+ } else
+ ad.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
ad.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
car.attachment = index;
car.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
@@ -1734,10 +1798,11 @@ void Renderpass_Vk::init(
ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
ad.stencilLoadOp = ad.loadOp;
ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
- if (rp.depth.mode != Clear_Mode::restore)
+ if (rp.depth.mode == Clear_Mode::restore) {
+ Resource_State state = states.depth;
+ ad.initialLayout = state_to_image_layout<true>(state);
+ } else
ad.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- else
- ad.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
ad.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
dar.attachment = i;
dar.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
@@ -1934,6 +1999,7 @@ Texture_Id Swapchain::create_image(
Texture_Vk::init(
&tex,
id,
+ 0,
image,
view,
Vram_Allocator::Allocation::null(),
@@ -1982,9 +2048,6 @@ void Swapchain::get_images(Device_Vk* dev) {
size.width,
size.height
);
- /* needs to be presentable since the first renderpass
- * will expect it to be presentable from "last" frame */
- ctx.transition(textures[i], Resource_State::presentable);
}
dev->submit(ctx);
heap_free(dev->heap, images);
@@ -2047,7 +2110,6 @@ void Device::begin_frame() {
&dev->backbuffer_index
);
dev->backbuffer_id = dev->swapchain.textures[dev->backbuffer_index];
- dev->first_rp = true;
}
void Device::submit(Context& ctx_) {
@@ -2205,13 +2267,9 @@ void Context::submit(
Context_Vk* ctx = (Context_Vk*)this;
Device_Vk* dev = ctx->dev;
Vertex_Buffer_Binding* binding;
- Rpo_Key rpo_key = { dev->first_rp, rp };
+ Rpo_Key rpo_key = { rp, dev->get_rp_states(rp) };
Pso_Key pso_key = { p, rpo_key };
Pipeline_Vk& pso = dev->get_pso(pso_key);
- Descriptor_Set_Vk* dso = 0;
- if (p.descriptor_count)
- dso = &dev->get_dso(pso, *(Dso_Key*)&p);
- auto [rpo, fbo] = ctx->begin_rp(rp);
Texture_Vk& target = *(Texture_Vk*)&dev->get_texture(
dev->get_backbuffer()
);
@@ -2223,19 +2281,8 @@ void Context::submit(
pso.pip
);
ctx->last_pso = pso.pip;
- if (dso && dso->dset != ctx->last_dso) {
- vkCmdBindDescriptorSets(
- ctx->cb,
- VK_PIPELINE_BIND_POINT_GRAPHICS,
- pso.lay,
- 0,
- 1,
- &dso->dset,
- 0,
- 0
- );
- ctx->last_dso = dso->dset;
- }
+ ctx->submit_descriptors(pso, p);
+ auto [rpo, fbo] = ctx->begin_rp(rpo_key);
for (binding = draw.verts; binding->id; binding++) {
VkBuffer buf = ((Buffer_Vk*)&dev->get_buffer(binding->id))->buf;
VkDeviceSize offset = (VkDeviceSize)binding->offset;
@@ -2268,10 +2315,8 @@ void Context::submit(
draw.first_instance
);
}
- ctx->end_rp(rpo, fbo);
+ ctx->end_rp(rp, rpo, fbo);
pso.on_submit();
- if (dso)
- dso->on_submit();
}
void Context::submit(
@@ -2316,6 +2361,7 @@ void Context::copy(Texture_Id dst, Buffer_Id src) {
Texture_Vk& a = *(Texture_Vk*)&dev->get_texture(dst);
Buffer_Vk& b = *(Buffer_Vk*)&dev->get_buffer(src);
VkBufferImageCopy c{};
+ transition(dst, Resource_State::copy_dst);
c.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
c.imageSubresource.layerCount = 1;
c.imageExtent.width = a.w;
@@ -2337,12 +2383,35 @@ void Context::transition(Texture_Id id, Resource_State state) {
Device_Vk* dev = ctx->dev;
Texture_Vk& tex = *(Texture_Vk*)&dev->get_texture(id);
VkImageMemoryBarrier b{};
+ int c = tex.child_count;
VkImageLayout src_layout = state_to_image_layout(tex.state);
VkImageLayout dst_layout = state_to_image_layout(state);
VkPipelineStageFlags src_stage, dst_stage;
+ if (c) {
+ if (tex.child_states_same(dev)) {
+ tex.state =
+ ((Texture_Vk*)&dev->get_texture(tex.children[0]))->state;
+ src_layout = state_to_image_layout(tex.state);
+ } else {
+ ctx->check_end_rp();
+ int i;
+ for (i = 0; i < c; i++) {
+ transition(tex.children[i], state);
+ }
+ tex.state = state;
+ return;
+ }
+ }
if (tex.state == state) return;
ctx->check_end_rp();
- tex.state = state;
+ tex.state = state; {
+ int i;
+ for (i = 0; i < c; i++) {
+ Texture_Vk& child =
+ *(Texture_Vk*)&dev->get_texture(tex.children[i]);
+ child.state = state;
+ }
+ }
b.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
b.oldLayout = src_layout;
b.newLayout = dst_layout;
@@ -2489,9 +2558,10 @@ void Context::debug_pop() {
}
std::pair<Renderpass_Vk&, Framebuffer_Vk&> Context_Vk::begin_rp(
- const Render_Pass& rp
+ const Rpo_Key& rpk
) {
- Renderpass_Vk& rpo = dev->get_rpo({ dev->first_rp, rp});
+ const Render_Pass& rp = rpk.rpo;
+ Renderpass_Vk& rpo = dev->get_rpo(rpk);
Framebuffer_Vk& fbo = dev->get_fbo(rpo, { rp });
VkRenderPassBeginInfo rpbi{};
VkClearValue clears[max_colour_attachments + 1];
@@ -2518,8 +2588,6 @@ std::pair<Renderpass_Vk&, Framebuffer_Vk&> Context_Vk::begin_rp(
dc.depthStencil.depth = rp.depth.clear.depth;
dc.depthStencil.stencil = 0; /* todo */
clears[clear_count++] = dc;
- if (rp.depth.mode == Clear_Mode::restore)
- transition(rp.depth.id, Resource_State::render_target);
}
rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rpbi.renderPass = rpo.rpo;
@@ -2532,13 +2600,28 @@ std::pair<Renderpass_Vk&, Framebuffer_Vk&> Context_Vk::begin_rp(
&rpbi,
VK_SUBPASS_CONTENTS_INLINE
);
- dev->first_rp = false;
last_rpo = rpo.rpo;
last_fbo = fbo.fbo;
return { rpo, fbo };
}
-void Context_Vk::end_rp(Renderpass_Vk& rpo, Framebuffer_Vk& fbo) {
+void Context_Vk::end_rp(
+ const Render_Pass& rp,
+ Renderpass_Vk& rpo,
+ Framebuffer_Vk& fbo
+) {
+ bool has_depth = rp.depth.id;
+ int i, c = rp.colour_count;
+ for (i = 0; i < c; i++){
+ Texture_Vk& tex =
+ *(Texture_Vk*)&dev->get_texture(rp.colours[i].id);
+ tex.state = Resource_State::render_target;
+ }
+ if (has_depth) {
+ Texture_Vk& tex =
+ *(Texture_Vk*)&dev->get_texture(rp.depth.id);
+ tex.state = Resource_State::render_target;
+ }
rpo.on_submit();
fbo.on_submit();
}
@@ -2550,10 +2633,49 @@ void Context_Vk::check_end_rp() {
}
}
+void Context_Vk::submit_descriptors(
+ const Pipeline_Vk& pso,
+ const Pipeline& p
+) {
+ Descriptor_Set_Vk* dso = 0;
+ if (p.descriptor_count) {
+ dso = &dev->get_dso(pso, *(Dso_Key*)&p);
+ if (dso->dset == last_dso) return;
+
+ int i, c = p.descriptor_count;
+ for (i = 0; i < c; i++) {
+ const auto& desc = p.descriptors[i];
+ switch (desc.type) {
+ case Descriptor::Type::texture: {
+ const auto& td = *(const Texture_Descriptor*)desc.payload;
+ transition(td.texture, Resource_State::shader_read);
+ } break;
+ case Descriptor::Type::constant_buffer:
+ break; /* todo */
+ }
+ }
+ vkCmdBindDescriptorSets(
+ cb,
+ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ pso.lay,
+ 0,
+ 1,
+ &dso->dset,
+ 0,
+ 0
+ );
+ last_dso = dso->dset;
+ dso->on_submit();
+ }
+}
+
void Context::submit(const Render_Pass& rp) {
Context_Vk* ctx = (Context_Vk*)this;
- auto [rpo, fbo] = ctx->begin_rp(rp);
- ctx->end_rp(rpo, fbo);
+ auto [rpo, fbo] = ctx->begin_rp({
+ rp,
+ ctx->dev->get_rp_states(rp)
+ });
+ ctx->end_rp(rp, rpo, fbo);
}
void Context_Vk::init_pool() {
@@ -3538,9 +3660,8 @@ Texture_Id Device::create_texture(
VkImageAspectFlags aspect = get_image_aspect(fmt, flags);
VkImageViewCreateInfo vi{};
VkImageCreateFlags image_flags = 0;
- int array_count = array_size;
if (flags & Texture_Flags::cubemap) {
- array_count *= 6;
+ array_size *= 6;
image_flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
}
if (mip_count == 0)
@@ -3551,7 +3672,7 @@ Texture_Id Device::create_texture(
ii.extent.height = h;
ii.extent.depth = d;
ii.mipLevels = mip_count;
- ii.arrayLayers = array_count;
+ ii.arrayLayers = array_size;
ii.format = get_vk_format(fmt);
ii.tiling = VK_IMAGE_TILING_OPTIMAL;
ii.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -3586,13 +3707,13 @@ Texture_Id Device::create_texture(
);
vi.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
vi.image = image;
- vi.viewType = get_view_type(array_count, d, flags);
+ vi.viewType = get_view_type(array_size, d, flags);
vi.format = ii.format;
vi.subresourceRange.aspectMask = aspect;
vi.subresourceRange.baseMipLevel = 0;
vi.subresourceRange.levelCount = mip_count;
vi.subresourceRange.baseArrayLayer = 0;
- vi.subresourceRange.layerCount = array_count;
+ vi.subresourceRange.layerCount = array_size;
r = vkCreateImageView(dev->dev, &vi, &dev->ac, &view);
if (r != VK_SUCCESS) {
print_err("Failed to make image view.\n");
@@ -3601,6 +3722,7 @@ Texture_Id Device::create_texture(
Texture_Vk::init(
&tex,
id,
+ 0,
image,
view,
mem,
@@ -3618,9 +3740,7 @@ Texture_Id Device::create_texture(
);
if (init) {
Context& ctx = dev->acquire();
- ctx.transition(id, Resource_State::copy_dst);
ctx.copy(id, init);
- ctx.transition(id, Resource_State::shader_read);
dev->submit(ctx);
}
tex.set_name(dev, name);
@@ -3665,6 +3785,7 @@ Texture_Id Device::alias_texture(
Texture_Vk::init(
&nt,
ntid,
+ o,
texture.image,
view,
Vram_Allocator::Allocation::null(),
@@ -3680,6 +3801,7 @@ Texture_Id Device::alias_texture(
start_array,
true
);
+ texture.add_child(ntid);
nt.set_name(dev, name);
return ntid;
}
@@ -3703,6 +3825,37 @@ void Texture_Vk::set_name(Device_Vk* dev, const char* name) {
#endif
}
+void Texture_Vk::add_child(Texture_Id id) {
+ assert(child_count < max_texture_alias);
+ children[child_count++] = id;
+}
+
+void Texture_Vk::rem_child(Texture_Id id) {
+ int i;
+ for (i = 0; i < child_count; i++) {
+ if (children[i] == id) {
+ children[i] = children[child_count - 1];
+ return;
+ }
+ }
+}
+
+bool Texture_Vk::child_states_same(Device_Vk* dev) {
+ int i, c = child_count;
+ bool r = true;
+ for (i = 0; i < c; i++) {
+ Texture_Vk& a =
+ *(Texture_Vk*)&dev->get_texture(children[i]);
+ int j;
+ for (j = i + 1; j < c; j++) {
+ Texture_Vk& b =
+ *(Texture_Vk*)&dev->get_texture(children[j]);
+ if (a.state != b.state) r = false;
+ }
+ }
+ return r;
+}
+
Shader& Device::get_shader(Shader_Id id) {
Device_Vk* dev = (Device_Vk*)this;
assert(id.index);
@@ -3943,6 +4096,7 @@ void Texture_Loader::unload(Asset* a) {
void Texture_Vk::init(
Texture_Vk* t,
Texture_Id id,
+ Texture_Id parent,
VkImage img,
VkImageView v,
Vram_Allocator::Allocation mem,
@@ -3959,6 +4113,7 @@ void Texture_Vk::init(
bool alias
) {
t->id = id;
+ t->parent = parent;
t->image = img;
t->view = v;
t->memory = mem;
@@ -3982,6 +4137,10 @@ void Texture_Vk::destroy(Device_Vk* dev) {
vkDestroyImage(dev->dev, image, &dev->ac);
dev->vrama.free(memory);
}
+ if (parent) {
+ Texture_Vk& t = *(Texture_Vk*)&dev->get_texture(parent);
+ t.rem_child(id);
+ }
vkDestroyImageView(dev->dev, view, &dev->ac);
dev->textures.remove(id);
}