summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c2.cpp52
-rw-r--r--model.cpp2
-rw-r--r--pipeline.cpp11
-rw-r--r--renderer.cpp6
-rw-r--r--renderer.hpp1
-rw-r--r--video.cpp115
-rw-r--r--video.hpp15
7 files changed, 172 insertions, 30 deletions
diff --git a/c2.cpp b/c2.cpp
index ac9e7d4..94e2e38 100644
--- a/c2.cpp
+++ b/c2.cpp
@@ -24,6 +24,8 @@ extern "C" {
#define scene_arena_size (1024 * 4)
#define per_frame_memory_size (1024 * 1024)
+#define MSAA_SAMPLES 4
+
static float verts[] = {
0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
@@ -653,7 +655,7 @@ struct C2 : public App {
Tonemap tonemap;
Buffer_Id vbo, cbuf;
Sampler_Id clamped_linear;
- Texture_Id hdr_target;
+ Texture_Id hdr_target, hdr_resolved, ms_depth;
Texture_Id ui_texture;
Buffer_Id ui_buffer;
Line_Renderer lr;
@@ -876,7 +878,7 @@ struct C2 : public App {
pb.begin_rp();
pb.rp_target(hdr_target, Clear_Mode::restore);
- pb.rp_depth_target(dev->get_depth_target(), Clear_Mode::restore);
+ pb.rp_depth_target(ms_depth, Clear_Mode::restore);
Render_Pass& sky_pass = pb.build_rp();
pb.begin_rp();
@@ -903,6 +905,7 @@ struct C2 : public App {
dev,
&frame_arena,
hdr_target,
+ ms_depth,
&lighting
);
ctx.debug_pop();
@@ -919,6 +922,8 @@ struct C2 : public App {
);
ctx.debug_pop();
+ ctx.resolve(hdr_resolved, hdr_target);
+
tonemap.update(dev, 0.2f);
ctx.debug_push("TONEMAP");
@@ -927,7 +932,7 @@ struct C2 : public App {
&frame_arena,
quad,
tonemap_pass,
- hdr_target,
+ hdr_resolved,
clamped_linear
);
ctx.debug_pop();
@@ -1014,6 +1019,8 @@ struct C2 : public App {
assets.destroy();
dev->destroy_texture(default_texture);
dev->destroy_texture(hdr_target);
+ dev->destroy_texture(hdr_resolved);
+ dev->destroy_texture(ms_depth);
dev->destroy_texture(ui_texture);
dev->destroy_buffer(ui_buffer);
dev->destroy_sampler(clamped_linear);
@@ -1025,7 +1032,9 @@ struct C2 : public App {
void on_resize() override {
ui->layout(w, h);
dev->on_resize();
+ dev->destroy_texture(ms_depth);
dev->destroy_texture(hdr_target);
+ dev->destroy_texture(hdr_resolved);
dev->destroy_texture(ui_texture);
dev->destroy_buffer(ui_buffer);
make_hdr_target();
@@ -1033,16 +1042,43 @@ struct C2 : public App {
}
void make_hdr_target() {
+ int sw = dev->swap_w();
+ int sh = dev->swap_h();
hdr_target = dev->create_texture(
- "HDR target",
+ "MS HDR target",
texture_format_rgba16f,
- Texture_Flags::sampleable | Texture_Flags::colour_target,
- dev->swap_w(),
- dev->swap_h(),
+ Texture_Flags::copy_src | Texture_Flags::colour_target,
+ sw,
+ sh,
1,
1,
1,
- Buffer_Id(0)
+ Buffer_Id(0),
+ MSAA_SAMPLES
+ );
+ hdr_resolved = dev->create_texture(
+ "Resolved HDR",
+ texture_format_rgba16f,
+ Texture_Flags::sampleable | Texture_Flags::copy_dst,
+ sw,
+ sh,
+ 1,
+ 1,
+ 1,
+ Buffer_Id(0),
+ 1
+ );
+ ms_depth = dev->create_texture(
+ "MS depth",
+ texture_format_d24s8,
+ Texture_Flags::sampleable | Texture_Flags::depth_stencil_target,
+ sw,
+ sh,
+ 1,
+ 1,
+ 1,
+ 0,
+ MSAA_SAMPLES
);
}
diff --git a/model.cpp b/model.cpp
index f24c0eb..cb9c23e 100644
--- a/model.cpp
+++ b/model.cpp
@@ -384,7 +384,7 @@ void Model_Instance::render(
res.vp
);
} else {
- pb.depth(true, false, Depth_Mode::equal);
+ pb.depth(true, true, Depth_Mode::less);
pb.shader(mesh.shader);
pb.sbuffer(mesh.light_binding, lighting->lights.gpuonly);
pb.sbuffer(mesh.casters_binding, lighting->casters.gpuonly);
diff --git a/pipeline.cpp b/pipeline.cpp
index 0636a1c..374dad8 100644
--- a/pipeline.cpp
+++ b/pipeline.cpp
@@ -23,6 +23,7 @@ Pipeline_Builder& Pipeline_Builder::rp_target(Texture_Id id, Colour clear) {
Render_Pass::Target t{
.id = id,
.fmt = texture.fmt,
+ .samples = texture.samples,
.mode = Clear_Mode::clear,
.clear = { .colour = clear }
};
@@ -37,6 +38,7 @@ Pipeline_Builder& Pipeline_Builder::rp_target(Texture_Id id, Clear_Mode clear) {
Render_Pass::Target t{
.id = id,
.fmt = texture.fmt,
+ .samples = texture.samples,
.mode = clear,
.clear = { .depth = 0.0f }
};
@@ -51,6 +53,7 @@ Pipeline_Builder& Pipeline_Builder::rp_depth_target(Texture_Id id, float clear)
Render_Pass::Target t{
.id = id,
.fmt = texture.fmt,
+ .samples = texture.samples,
.mode = Clear_Mode::clear,
.clear = { .depth = clear }
};
@@ -63,6 +66,7 @@ Pipeline_Builder& Pipeline_Builder::rp_depth_target(Texture_Id id, Clear_Mode mo
Render_Pass::Target t{
.id = id,
.fmt = texture.fmt,
+ .samples = texture.samples,
.mode = mode,
.clear = { .depth = 0.0f }
};
@@ -73,7 +77,7 @@ Pipeline_Builder& Pipeline_Builder::rp_depth_target(Texture_Id id, Clear_Mode mo
void Pipeline_Builder::validate_rp() {
int i, c = pass->colour_count;
- int w, h;
+ int w, h, s;
assert(c || pass->depth.id);
if (c) {
Texture& tex = dev->get_texture(pass->colours[0].id);
@@ -81,7 +85,8 @@ void Pipeline_Builder::validate_rp() {
assert(pass->colours[0].fmt == tex.fmt);
w = tex.w;
h = tex.h;
- assert(w && h);
+ s = tex.samples;
+ assert(w && h && s);
}
for (i = 1; i < c; i++) {
Texture& tex = dev->get_texture(pass->colours[i].id);
@@ -89,6 +94,7 @@ void Pipeline_Builder::validate_rp() {
assert(pass->colours[i].fmt == tex.fmt);
assert(tex.w == w);
assert(tex.h == h);
+ assert(tex.samples == s);
}
if (pass->depth.id) {
Texture& d = dev->get_texture(pass->depth.id);
@@ -101,6 +107,7 @@ void Pipeline_Builder::validate_rp() {
if (c) {
assert(d.w == w);
assert(d.h == h);
+ assert(d.samples == s);
}
}
}
diff --git a/renderer.cpp b/renderer.cpp
index d8c4895..c7040ec 100644
--- a/renderer.cpp
+++ b/renderer.cpp
@@ -108,7 +108,9 @@ void Renderer::update_globals(
void Renderer::render(
Device* dev,
- Arena* a, Texture_Id hdr_target,
+ Arena* a,
+ Texture_Id hdr_target,
+ Texture_Id depth_target,
const Lighting* l
) {
int i, j;
@@ -124,7 +126,7 @@ void Renderer::render(
Render_Pass& forward_pass = pb
.begin_rp()
.rp_target(hdr_target, Clear_Mode::restore)
- .rp_depth_target(dev->get_depth_target(), Clear_Mode::restore)
+ .rp_depth_target(depth_target, 1.0f)
.build_rp();
Render_Pass* shadow_passes[Lighting::max_shadows];
for (i = 0; i < Lighting::max_shadows; i++) {
diff --git a/renderer.hpp b/renderer.hpp
index c49c804..6bfe551 100644
--- a/renderer.hpp
+++ b/renderer.hpp
@@ -50,6 +50,7 @@ struct Renderer {
Device* dev,
Arena* a,
Texture_Id hdr_target,
+ Texture_Id depth_target,
const Lighting* l
);
diff --git a/video.cpp b/video.cpp
index 08ee606..9e2699e 100644
--- a/video.cpp
+++ b/video.cpp
@@ -561,7 +561,8 @@ struct Texture_Vk : public Texture, public Late_Terminated {
int array_size,
int start_mip,
int start_array,
- bool alias
+ bool alias,
+ int samples
);
void destroy(Device_Vk*) override;
void set_name(Device_Vk* dev, const char* name);
@@ -732,7 +733,8 @@ struct Pipeline_Vk {
Arena& scope,
Device_Vk* dev,
VkGraphicsPipelineCreateInfo& info,
- const Pipeline& desc
+ const Pipeline& desc,
+ const Render_Pass& rpo
);
void init_depthstencil(
Arena& scope,
@@ -934,6 +936,7 @@ struct Device_Vk : public Device {
VkPhysicalDevice phys_dev;
VkSurfaceKHR surf;
uint32_t backbuffer_index;
+ VkSampleCountFlagBits max_samples;
Texture_Id backbuffer_id;
Swap_Cap swap_cap;
VkPhysicalDeviceMemoryProperties mem_props;
@@ -1021,6 +1024,9 @@ struct Device_Vk : public Device {
void create_terminators();
void create_depth(int w, int h);
+ VkSampleCountFlagBits get_max_samples();
+ VkSampleCountFlagBits get_samples(int);
+
int find_memory_type(
uint32_t filter,
VkMemoryPropertyFlags flags
@@ -1114,6 +1120,37 @@ void Device_Vk::init_validation() {
#endif
+VkSampleCountFlagBits Device_Vk::get_max_samples() {
+ VkPhysicalDeviceProperties p;
+ VkSampleCountFlagBits
+ i = VK_SAMPLE_COUNT_64_BIT,
+ e = VK_SAMPLE_COUNT_1_BIT;
+ VkSampleCountFlags c;
+ vkGetPhysicalDeviceProperties(phys_dev, &p);
+ c =
+ p.limits.framebufferColorSampleCounts &
+ p.limits.framebufferDepthSampleCounts;
+ for (; i >= e; i = (VkSampleCountFlagBits)(i >> 1))
+ if (c & i) return i;
+ return VK_SAMPLE_COUNT_1_BIT;
+}
+
+VkSampleCountFlagBits Device_Vk::get_samples(
+ int c
+) {
+ VkSampleCountFlagBits b = VK_SAMPLE_COUNT_1_BIT;
+ switch (c) {
+ case 1: b = VK_SAMPLE_COUNT_1_BIT; break;
+ case 2: b = VK_SAMPLE_COUNT_2_BIT; break;
+ case 4: b = VK_SAMPLE_COUNT_4_BIT; break;
+ case 8: b = VK_SAMPLE_COUNT_8_BIT; break;
+ case 16: b = VK_SAMPLE_COUNT_16_BIT; break;
+ case 32: b = VK_SAMPLE_COUNT_32_BIT; break;
+ case 64: b = VK_SAMPLE_COUNT_64_BIT; break;
+ default: break;
+ }
+ return std::min(max_samples, b);
+}
bool Device_Vk::has_validation() {
unsigned count, i;
@@ -1352,6 +1389,7 @@ void Device_Vk::init_internal() {
#endif
surf = app_create_vk_surface(app, inst);
create_dev(&swap_cap);
+ max_samples = get_max_samples();
vrama.init(this);
gladLoaderLoadVulkan(inst, phys_dev, dev);
vkGetDeviceQueue(dev, (uint32_t)queue_index, 0, &queue);
@@ -1642,7 +1680,7 @@ void Renderpass_Vk::init(
auto& colour = rp.colours[i];
auto& ad = ads[index];
ad.format = get_vk_format(colour.fmt);
- ad.samples = VK_SAMPLE_COUNT_1_BIT;
+ ad.samples = dev->get_samples(colour.samples);
ad.loadOp = load_op_from_mode(colour.mode);
ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
ad.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -1659,9 +1697,10 @@ void Renderpass_Vk::init(
if (has_depth) {
int i = count++;
auto& ad = ads[i];
- ad.format = get_vk_format(dev->get_texture(rp.depth.id).fmt);
- ad.samples = VK_SAMPLE_COUNT_1_BIT;
- ad.loadOp = load_op_from_mode(rp.depth.mode);
+ auto& depth = rp.depth;
+ ad.format = get_vk_format(dev->get_texture(depth.id).fmt);
+ ad.samples = dev->get_samples(depth.samples);
+ ad.loadOp = load_op_from_mode(depth.mode);
ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
ad.stencilLoadOp = ad.loadOp;
ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
@@ -1887,7 +1926,8 @@ Texture_Id Swapchain::create_image(
1,
0,
0,
- true
+ true,
+ 1
);
return id;
}
@@ -2286,6 +2326,37 @@ void Context::copy(
);
}
+void Context::resolve(Texture_Id dst, Texture_Id src) {
+ Context_Vk* ctx = (Context_Vk*)this;
+ Device_Vk* dev = ctx->dev;
+ Texture_Vk& d = *(Texture_Vk*)&dev->get_texture(dst);
+ Texture_Vk& s = *(Texture_Vk*)&dev->get_texture(src);
+ VkImageResolve r{};
+ r.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ r.srcSubresource.layerCount = 1;
+ r.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ r.dstSubresource.layerCount = 1;
+ r.extent.width = d.w;
+ r.extent.height = d.h;
+ r.extent.depth = 1;
+ assert(d.w == s.w);
+ assert(d.h == s.h);
+ assert(d.d == 1 && s.d == 1);
+ assert(d.samples == 1 && s.samples > 1);
+ ctx->check_end_rp();
+ transition(src, Resource_State::copy_src);
+ transition(dst, Resource_State::copy_dst);
+ vkCmdResolveImage(
+ ctx->cb,
+ s.image,
+ state_to_image_layout(s.state),
+ d.image,
+ state_to_image_layout(d.state),
+ 1,
+ &r
+ );
+}
+
void Context::transition(Texture_Id id, Resource_State state) {
Context_Vk* ctx = (Context_Vk*)this;
Device_Vk* dev = ctx->dev;
@@ -2434,6 +2505,14 @@ void Context::transition(Texture_Id id, Resource_State state) {
b.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
src_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dst_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ } else if (
+ src_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL &&
+ dst_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
+ ) {
+ b.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ b.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dst_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else {
print_err("Bad resource transition.\n");
assert(0);
@@ -2857,7 +2936,8 @@ void Pipeline_Vk::init_msaa(
Arena& scope,
Device_Vk* dev,
VkGraphicsPipelineCreateInfo& info,
- const Pipeline& desc
+ const Pipeline& desc,
+ const Render_Pass& rpo
) {
VkPipelineMultisampleStateCreateInfo& mi =
*(VkPipelineMultisampleStateCreateInfo*)arena_alloc(
@@ -2869,7 +2949,7 @@ void Pipeline_Vk::init_msaa(
zero(&mi, sizeof mi);
mi.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
mi.sampleShadingEnable = VK_FALSE;
- mi.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ mi.rasterizationSamples = dev->get_samples(rpo.get_samples());
info.pMultisampleState = &mi;
}
@@ -3064,7 +3144,7 @@ void Pipeline_Vk::init(Device_Vk* dev, const Pso_Key& key) {
init_input_assembly(scope, dev, info, desc);
init_viewport(scope, info, desc);
init_rasterisation(scope, dev, info, desc);
- init_msaa(scope, dev, info, desc);
+ init_msaa(scope, dev, info, desc, key.rpo.rpo);
init_depthstencil(scope, dev, info, desc);
init_blending(scope, dev, info, key.rpo.rpo, desc);
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
@@ -3594,7 +3674,8 @@ Texture_Id Device::create_texture(
int d,
int mip_count,
int array_size,
- Buffer_Id init
+ Buffer_Id init,
+ int samples
) {
VkImageCreateInfo ii{};
VkResult r;
@@ -3626,7 +3707,7 @@ Texture_Id Device::create_texture(
ii.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
ii.usage = get_texture_usage(flags);
ii.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- ii.samples = VK_SAMPLE_COUNT_1_BIT;
+ ii.samples = dev->get_samples(samples);
ii.flags = image_flags;
r = vkCreateImage(dev->dev, &ii, &dev->ac, &image);
if (r != VK_SUCCESS) {
@@ -3684,7 +3765,8 @@ Texture_Id Device::create_texture(
array_size,
0,
0,
- false
+ false,
+ samples
);
if (init) {
Context& ctx = dev->acquire();
@@ -3747,7 +3829,8 @@ Texture_Id Device::alias_texture(
array_size,
start_mip,
start_array,
- true
+ true,
+ texture.samples
);
nt.set_name(dev, name);
return ntid;
@@ -4049,7 +4132,8 @@ void Texture_Vk::init(
int array_size,
int start_mip,
int start_array,
- bool alias
+ bool alias,
+ int samples
) {
t->id = id;
t->parent = parent;
@@ -4069,6 +4153,7 @@ void Texture_Vk::init(
t->start_mip = start_mip;
t->start_array = start_array;
t->alias = alias;
+ t->samples = samples;
}
void Texture_Vk::destroy(Device_Vk* dev) {
diff --git a/video.hpp b/video.hpp
index 4afb6ba..530b126 100644
--- a/video.hpp
+++ b/video.hpp
@@ -133,6 +133,7 @@ struct Pipeline {
Cull_Mode cull_mode;
Vertex_Format_Id vertex_format;
Shader_Id shader;
+ int samples;
Descriptor descriptors[pipeline_max_descriptors];
int descriptor_count;
@@ -161,7 +162,8 @@ struct Pipeline {
blend_dst_alpha == other.blend_dst_alpha &&
blend_mode == other.blend_mode &&
blend_mode_alpha == other.blend_mode_alpha &&
- cull_mode == other.cull_mode;
+ cull_mode == other.cull_mode &&
+ samples == other.samples;
}
bool desc_layout_eq(const Pipeline& other) const {
@@ -228,6 +230,7 @@ struct Render_Pass {
struct Target {
Texture_Id id;
Texture_Format fmt;
+ int samples;
Clear_Mode mode;
union {
Colour colour;
@@ -266,6 +269,11 @@ struct Render_Pass {
}
return true;
}
+
+ int get_samples() const {
+ if (colour_count) return colours[0].samples;
+ return depth.samples;
+ }
};
struct Vertex_Buffer_Binding {
@@ -359,6 +367,7 @@ struct Texture : public Asset {
int w, h, d;
int mip_count, array_size;
int start_mip, start_array;
+ int samples;
bool alias;
};
@@ -486,7 +495,8 @@ struct Device {
int d,
int mip_count,
int array_size,
- Buffer_Id init
+ Buffer_Id init,
+ int samples = 1
);
Texture_Id alias_texture(
Texture_Id o,
@@ -562,6 +572,7 @@ struct Context {
int w,
int h
);
+ void resolve(Texture_Id dst, Texture_Id src);
void transition(Texture_Id id, Resource_State state);
void debug_push(const char* name);
void debug_pop();