added better transparency to the pbr shader
This commit is contained in:
parent
0081887f19
commit
e324e47896
BIN
assets/shaders/full_screen_triangle.vert.spv
Normal file
BIN
assets/shaders/full_screen_triangle.vert.spv
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
assets/shaders/oit.frag.spv
Normal file
BIN
assets/shaders/oit.frag.spv
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -3,15 +3,18 @@ import includes;
|
||||
import renderer : Destroy;
|
||||
import renderer;
|
||||
import util;
|
||||
import alloc;
|
||||
import platform;
|
||||
import math;
|
||||
import core.stdc.math : cosf, sinf;
|
||||
import std.algorithm.sorting;
|
||||
|
||||
f32 g_DELTA;
|
||||
|
||||
struct Game
|
||||
{
|
||||
Renderer rd;
|
||||
Arena frame_arena;
|
||||
|
||||
PlatformWindow* window;
|
||||
|
||||
@ -19,6 +22,7 @@ struct Game
|
||||
Pipeline triangle_pipeline;
|
||||
Pipeline compute_pipeline;
|
||||
Pipeline ui_pipeline;
|
||||
Pipeline oit_pipeline;
|
||||
|
||||
GlobalUniforms globals;
|
||||
PushConst pc;
|
||||
@ -36,6 +40,7 @@ InitGame(PlatformWindow* window)
|
||||
{
|
||||
Game g = {
|
||||
rd: InitRenderer(window),
|
||||
frame_arena: CreateArena(MB(16)),
|
||||
window: window,
|
||||
timer: CreateTimer(),
|
||||
globals: {
|
||||
@ -76,13 +81,23 @@ InitGame(PlatformWindow* window)
|
||||
]
|
||||
};
|
||||
|
||||
GfxPipelineInfo oit_info = {
|
||||
vertex_shader: "shaders/full_screen_triangle.vert.spv",
|
||||
frag_shader: "shaders/oit.frag.spv",
|
||||
};
|
||||
|
||||
CompPipelineInfo gradient_info = {
|
||||
shader: "shaders/gradient.comp.spv",
|
||||
};
|
||||
|
||||
Logf("pbr");
|
||||
g.pbr_pipeline = BuildGfxPipeline(&g.rd, &pbr_info);
|
||||
Logf("triangle");
|
||||
g.triangle_pipeline = BuildGfxPipeline(&g.rd, &triangle_info);
|
||||
Logf("ui");
|
||||
g.ui_pipeline = BuildGfxPipeline(&g.rd, &ui_info);
|
||||
Logf("oit");
|
||||
g.oit_pipeline = BuildGfxPipeline(&g.rd, &oit_info);
|
||||
g.compute_pipeline = BuildCompPipeline(&g.rd, &gradient_info);
|
||||
|
||||
PrintShader(&g.rd, &g.pbr_pipeline, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
@ -107,8 +122,12 @@ Cycle(Game* g)
|
||||
{
|
||||
g_DELTA = DeltaTime(&g.timer);
|
||||
|
||||
Reset(&g.frame_arena);
|
||||
|
||||
ProcessInputs(g, &g.camera);
|
||||
|
||||
//Sort(g, g.camera.pos, &g.model);
|
||||
|
||||
//Update(g, &g.camera);
|
||||
|
||||
Update(&g.camera);
|
||||
@ -234,3 +253,28 @@ Update(Camera* cam)
|
||||
Vec4 pos = rotation * Vec4(cam.velocity * 0.5 * g_DELTA, 0.0);
|
||||
cam.pos += pos.xyz;
|
||||
}
|
||||
|
||||
void
|
||||
Sort(Game* g, Vec3 pos, Model* model)
|
||||
{
|
||||
f32[] lengths = AllocArray!(f32)(&g.frame_arena, model.positions.length);
|
||||
|
||||
foreach(i; 0 .. lengths.length)
|
||||
{
|
||||
model.pos_indices[i] = cast(u32)i;
|
||||
lengths.ptr[i] = fabs(Norm(&pos) - Norm(model.positions.ptr + i));
|
||||
}
|
||||
|
||||
makeIndex!("a < b")(lengths, model.pos_indices);
|
||||
|
||||
Logf("%s", model.positions.length);
|
||||
|
||||
foreach(i, v; model.pos_indices)
|
||||
{
|
||||
model.indices[i+0] = cast(u32)((3*v)+0);
|
||||
model.indices[i+1] = cast(u32)((3*v)+1);
|
||||
model.indices[i+2] = cast(u32)((3*v)+2);
|
||||
}
|
||||
|
||||
UpdateIndexBuffer(&g.rd, model);
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import core.stdc.string : memcpy;
|
||||
// 2. Set up VK_AMD_shader_info
|
||||
// 3. Determine how to better handle inputs
|
||||
// 4. Make assets loaded from the disk in debug mode
|
||||
// 5. Set up multisampling
|
||||
|
||||
void main(string[] argv)
|
||||
{
|
||||
|
||||
@ -4,7 +4,7 @@ import assets;
|
||||
import util;
|
||||
import alloc;
|
||||
import vulkan;
|
||||
import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepComputeDrawImage, Dispatch, FinishFrame, BeginFrame, WaitIdle, PushConstants, BindBuffers, SetClearColor;
|
||||
import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepComputeDrawImage, Dispatch, FinishFrame, BeginFrame, WaitIdle, PushConstants, BindBuffers, SetClearColor, ImageBarrier;
|
||||
import assets;
|
||||
import std.math.traits : isNaN;
|
||||
import util : Logf;
|
||||
@ -33,6 +33,8 @@ enum Format : VkFormat
|
||||
RGB_F32 = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
RGBA_UINT = VK_FORMAT_B8G8R8A8_UINT,
|
||||
R_U32 = VK_FORMAT_R32_UINT,
|
||||
RG_U32 = VK_FORMAT_R32G32_UINT,
|
||||
RGBA_UNORM = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
RGBA_SRGB = VK_FORMAT_R8G8B8A8_SRGB,
|
||||
}
|
||||
@ -47,6 +49,7 @@ enum BufferType : int
|
||||
Uniform = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||
Storage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||
Staging = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
BufferView = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
|
||||
}
|
||||
|
||||
alias BT = BufferType;
|
||||
@ -161,6 +164,10 @@ struct Model
|
||||
|
||||
Buffer[] materials;
|
||||
ImageView[] textures;
|
||||
|
||||
Vec3[] positions;
|
||||
u32[] pos_indices;
|
||||
u32[] indices;
|
||||
}
|
||||
|
||||
Renderer
|
||||
@ -260,6 +267,12 @@ Bind(Renderer* rd, Pipeline* pipeline)
|
||||
Bind(&rd.vk, pipeline);
|
||||
}
|
||||
|
||||
void
|
||||
UpdateIndexBuffer(Renderer* rd, Model* model)
|
||||
{
|
||||
assert(Transfer(&rd.vk, &model.index_buffer, model.indices), "UpdateIndexBuffer failure");
|
||||
}
|
||||
|
||||
void
|
||||
DrawRect(Renderer* rd, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col)
|
||||
{
|
||||
@ -345,7 +358,6 @@ LoadModel(Renderer* rd, string name)
|
||||
|
||||
u32[] tex_lookup = AllocArray!(u32)(&rd.temp_arena, m3d.numtexture);
|
||||
model.textures = AllocArray!(ImageView)(&rd.arena, m3d.numtexture);
|
||||
Logf("numtexture %s", m3d.numtexture);
|
||||
foreach(i; 0 .. m3d.numtexture)
|
||||
{
|
||||
u32 w = m3d.texture[i].w; u32 h = m3d.texture[i].h; u32 ch = m3d.texture[i].f;
|
||||
@ -360,7 +372,6 @@ LoadModel(Renderer* rd, string name)
|
||||
Material[] mats = AllocArray!(Material)(&rd.temp_arena, m3d.nummaterial);
|
||||
u32[] mat_lookup = AllocArray!(u32)(&rd.temp_arena, m3d.nummaterial);
|
||||
model.materials = AllocArray!(Buffer)(&rd.arena, m3d.nummaterial);
|
||||
Logf("nummaterial %s", m3d.nummaterial);
|
||||
foreach(i; 0 .. m3d.nummaterial)
|
||||
{
|
||||
const(char)[] mat_name = m3d.material[i].name[0 .. strlen(m3d.material[i].name)];
|
||||
@ -391,7 +402,6 @@ LoadModel(Renderer* rd, string name)
|
||||
} break;
|
||||
case m3dp_map_D:
|
||||
{
|
||||
Logf("alpha %s", i);
|
||||
mats[i].alpha_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
||||
mats[i].alpha_has_texture = true;
|
||||
} break;
|
||||
@ -447,8 +457,10 @@ LoadModel(Renderer* rd, string name)
|
||||
|
||||
m3dv_t* vertex;
|
||||
|
||||
u32[] indices = AllocArray!(u32)(&rd.temp_arena, m3d.numface * 3);
|
||||
u32[] indices = AllocArray!(u32)(&rd.arena, m3d.numface * 3);
|
||||
Vertex[] vertices = AllocArray!(Vertex)(&rd.temp_arena, m3d.numface * 3);
|
||||
Vec3[] positions = AllocArray!(Vec3)(&rd.arena, m3d.numface);
|
||||
u32[] pos_indices = AllocArray!(u32)(&rd.arena, m3d.numface);
|
||||
|
||||
foreach(i; 0 .. m3d.numface)
|
||||
{
|
||||
@ -484,6 +496,11 @@ LoadModel(Renderer* rd, string name)
|
||||
indices[i0] = i0;
|
||||
indices[i1] = i1;
|
||||
indices[i2] = i2;
|
||||
|
||||
Vec3 center = (vertices[i0].pos + vertices[i1].pos + vertices[i2].pos) / 3.0;
|
||||
|
||||
positions[i] = center;
|
||||
pos_indices[i] = i;
|
||||
}
|
||||
|
||||
for(u64 i = 0; i < indices.length; i += 3)
|
||||
@ -529,6 +546,10 @@ LoadModel(Renderer* rd, string name)
|
||||
WriteDescriptors(&rd.vk, DT.Material, model.materials, mat_lookup);
|
||||
WriteDescriptors(&rd.vk, DT.SampledImage, model.textures, tex_lookup);
|
||||
|
||||
model.positions = positions;
|
||||
model.indices = indices;
|
||||
model.pos_indices = pos_indices;
|
||||
|
||||
Reset(&rd.temp_arena);
|
||||
|
||||
return model;
|
||||
@ -618,6 +639,12 @@ ClearColorEnabled(Renderer* rd, bool enabled)
|
||||
rd.vk.enable_clear_color = enabled;
|
||||
}
|
||||
|
||||
void
|
||||
ImageBarrier(Renderer* rd)
|
||||
{
|
||||
ImageBarrier(&rd.vk);
|
||||
}
|
||||
|
||||
void
|
||||
Destroy(Renderer* rd, Model* model)
|
||||
{
|
||||
|
||||
@ -80,6 +80,10 @@ const VkImageUsageFlags VK_DRAW_IMAGE_USAGE_FLAGS = VK_IMAGE_USAGE_TRANSFER_SRC_
|
||||
VK_IMAGE_USAGE_STORAGE_BIT |
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
const VkImageUsageFlags TEXTURE_IMAGE_USAGE = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
const VkImageUsageFlags CONVERT_IMAGE_USAGE = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
const VkImageUsageFlags OIT_IMAGE_USAGE = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
|
||||
enum StepInitialized : u32
|
||||
{
|
||||
Renderer = 1,
|
||||
@ -117,6 +121,14 @@ struct Image
|
||||
VkImageLayout layout;
|
||||
}
|
||||
|
||||
struct BufferView
|
||||
{
|
||||
Buffer base;
|
||||
VkBufferView view;
|
||||
|
||||
alias base this;
|
||||
}
|
||||
|
||||
struct ImageView
|
||||
{
|
||||
Image base;
|
||||
@ -199,6 +211,7 @@ struct Vulkan
|
||||
DescBindings[DT.max] desc_bindings;
|
||||
|
||||
VkSampler nearest_sampler;
|
||||
VkSampler oit_sampler;
|
||||
|
||||
VkPipeline[FRAME_OVERLAP] last_pipeline;
|
||||
VkPipelineLayout pipeline_layout;
|
||||
@ -224,6 +237,9 @@ struct Vulkan
|
||||
bool enable_clear_color;
|
||||
VkClearColorValue clear_color;
|
||||
|
||||
BufferView a_buffer_view;
|
||||
ImageView aux_image;
|
||||
|
||||
alias queues this;
|
||||
}
|
||||
|
||||
@ -755,7 +771,7 @@ TransferAssets(Vulkan* vk)
|
||||
pragma(inline): void
|
||||
CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
|
||||
{
|
||||
CreateImageView(vk, view, w, h);
|
||||
CreateImageView(vk, view, w, h, FMT.RGBA_UNORM, TEXTURE_IMAGE_USAGE);
|
||||
|
||||
if (ch == 4)
|
||||
{
|
||||
@ -768,7 +784,7 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
|
||||
assert(Transfer(vk, &buf, data), "CreateImageView failure: Buffer Transfer error");
|
||||
|
||||
ImageView conv_view;
|
||||
CreateImageView(vk, &conv_view, w, h, FMT.RGBA_F32);
|
||||
CreateImageView(vk, &conv_view, w, h, FMT.RGBA_F32, CONVERT_IMAGE_USAGE);
|
||||
|
||||
WriteConvDescriptor(vk, &buf);
|
||||
WriteConvDescriptor(vk, &conv_view);
|
||||
@ -872,7 +888,25 @@ FinishComputePass(Vulkan* vk)
|
||||
}
|
||||
|
||||
pragma(inline): void
|
||||
CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format = FMT.RGBA_UNORM)
|
||||
CreateBufferView(Vulkan* vk, BufferView* view, u64 size, Format format)
|
||||
{
|
||||
CreateBuffer(vk, &view.base, BT.BufferView, size, false);
|
||||
|
||||
VkBufferViewCreateInfo info = {
|
||||
sType: VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
|
||||
buffer: view.buffer,
|
||||
format: format,
|
||||
range: size,
|
||||
};
|
||||
|
||||
VkResult result = vkCreateBufferView(vk.device, &info, null, &view.view);
|
||||
VkCheckA("CreateBufferView failure: vkCreateBufferView failed", result);
|
||||
|
||||
view.size = size;
|
||||
}
|
||||
|
||||
pragma(inline): void
|
||||
CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format = FMT.RGBA_UNORM, VkImageUsageFlags usage)
|
||||
{
|
||||
VmaAllocationCreateInfo alloc_info = {
|
||||
usage: VMA_MEMORY_USAGE_GPU_ONLY,
|
||||
@ -887,7 +921,7 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format = FMT.R
|
||||
format: format,
|
||||
tiling: VK_IMAGE_TILING_OPTIMAL,
|
||||
initialLayout: VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
usage: format == FMT.RGBA_F32 ? (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT) : (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
|
||||
usage: usage,
|
||||
samples: VK_SAMPLE_COUNT_1_BIT,
|
||||
extent: {
|
||||
width: w,
|
||||
@ -996,6 +1030,27 @@ PushConstants(Vulkan* vk, PushConst* pc)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
ImageBarrier(Vulkan* vk)
|
||||
{
|
||||
VkMemoryBarrier2 barrier = {
|
||||
sType: VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
srcStageMask: VK_PIPELINE_STAGE_2_TRANSFER_BIT,
|
||||
srcAccessMask: VK_ACCESS_2_TRANSFER_WRITE_BIT,
|
||||
dstStageMask: VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
|
||||
dstAccessMask: VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT,
|
||||
};
|
||||
|
||||
VkDependencyInfo dependency = {
|
||||
sType: VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||
dependencyFlags: VK_DEPENDENCY_BY_REGION_BIT,
|
||||
memoryBarrierCount: 1,
|
||||
pMemoryBarriers: &barrier,
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier2(vk.cmds[vk.frame_index], &dependency);
|
||||
}
|
||||
|
||||
bool
|
||||
Transfer(T)(Vulkan* vk, Buffer* buf, T[] data)
|
||||
{
|
||||
@ -1323,7 +1378,7 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info)
|
||||
VkPipelineDepthStencilStateCreateInfo depth_info = {
|
||||
sType: VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||
depthTestEnable: VK_TRUE,
|
||||
depthWriteEnable: VK_TRUE,
|
||||
depthWriteEnable: VK_FALSE,
|
||||
depthCompareOp: VK_COMPARE_OP_GREATER_OR_EQUAL,
|
||||
depthBoundsTestEnable: VK_FALSE,
|
||||
stencilTestEnable: VK_FALSE,
|
||||
@ -1380,36 +1435,36 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info)
|
||||
VkPipelineShaderStageCreateInfo[] shader_info = [
|
||||
{
|
||||
sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
stage: VK_SHADER_STAGE_VERTEX_BIT,
|
||||
pName: "main",
|
||||
stage: VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
pName: "main",
|
||||
},
|
||||
{
|
||||
sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
stage: VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
stage: VK_SHADER_STAGE_VERTEX_BIT,
|
||||
pName: "main",
|
||||
},
|
||||
];
|
||||
|
||||
Arena* arena = &vk.frame_arenas[0];
|
||||
|
||||
u8[] vert_bytes = LoadAssetData(arena, build_info.vertex_shader);
|
||||
u8[] frag_bytes = LoadAssetData(arena, build_info.frag_shader);
|
||||
u8[] vert_bytes = LoadAssetData(arena, build_info.vertex_shader);
|
||||
|
||||
assert(vert_bytes && frag_bytes, "Unable to load shaders");
|
||||
|
||||
Result!(Shader) vert_module = BuildShader(vk, vert_bytes);
|
||||
Result!(Shader) frag_module = BuildShader(vk, frag_bytes);
|
||||
Result!(Shader) vert_module = BuildShader(vk, vert_bytes);
|
||||
|
||||
assert(vert_module.ok && frag_module.ok, "Unable to build vulkan shaders");
|
||||
|
||||
scope(exit)
|
||||
{
|
||||
Destroy(vk, vert_module.value);
|
||||
Destroy(vk, frag_module.value);
|
||||
Destroy(vk, vert_module.value);
|
||||
}
|
||||
|
||||
__traits(getMember, shader_info.ptr + 0, "module") = vert_module.value;
|
||||
__traits(getMember, shader_info.ptr + 1, "module") = frag_module.value;
|
||||
__traits(getMember, shader_info.ptr + 0, "module") = frag_module.value;
|
||||
__traits(getMember, shader_info.ptr + 1, "module") = vert_module.value;
|
||||
|
||||
VkSpecializationInfo vert_spec_info = {
|
||||
dataSize: build_info.vert_spec.size,
|
||||
@ -1652,6 +1707,7 @@ InitDescriptors(Vulkan* vk)
|
||||
{ type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 4096 },
|
||||
{ type: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 4096 },
|
||||
{ type: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 4096 },
|
||||
{ type: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, descriptorCount: 4096 },
|
||||
];
|
||||
|
||||
VkDescriptorPoolCreateInfo pool_info = {
|
||||
@ -1667,7 +1723,17 @@ InitDescriptors(Vulkan* vk)
|
||||
|
||||
if (success)
|
||||
{
|
||||
VkDescriptorBindingFlags[4] shared_binding_flags;
|
||||
VkDescriptorSetLayoutBinding[] shared_bindings = [
|
||||
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
{ binding: 2, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
{ binding: 3, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
{ binding: 4, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
{ binding: 5, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
{ binding: 6, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
];
|
||||
|
||||
VkDescriptorBindingFlags[] shared_binding_flags = AllocArray!(VkDescriptorBindingFlags)(&vk.frame_arenas[0], shared_bindings.length);
|
||||
shared_binding_flags[] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
|
||||
|
||||
VkDescriptorSetLayoutBindingFlagsCreateInfo shared_flag_info = {
|
||||
@ -1676,13 +1742,6 @@ InitDescriptors(Vulkan* vk)
|
||||
pBindingFlags: shared_binding_flags.ptr,
|
||||
};
|
||||
|
||||
VkDescriptorSetLayoutBinding[] shared_bindings = [
|
||||
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
{ binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
{ binding: 2, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
{ binding: 3, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
||||
];
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo shared_set_info = {
|
||||
sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
pNext: &shared_flag_info,
|
||||
@ -1814,20 +1873,89 @@ InitDescriptors(Vulkan* vk)
|
||||
|
||||
if (success)
|
||||
{
|
||||
VkSamplerCreateInfo sampler_info = {
|
||||
sType: VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
magFilter: VK_FILTER_LINEAR,
|
||||
minFilter: VK_FILTER_LINEAR,
|
||||
addressModeU: VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||
addressModeV: VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||
addressModeW: VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||
anisotropyEnable: VK_FALSE,
|
||||
compareEnable: VK_FALSE,
|
||||
borderColor: VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
||||
mipmapMode: VK_SAMPLER_MIPMAP_MODE_NEAREST,
|
||||
unnormalizedCoordinates: VK_FALSE,
|
||||
};
|
||||
|
||||
result = vkCreateSampler(vk.device, &sampler_info, null, &vk.oit_sampler);
|
||||
success = VkCheck("vkCreateSampler failure", result);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
// TODO: move this elsewhere later
|
||||
// Also add samples/supersampling scaling
|
||||
|
||||
CreateBufferView(vk, &vk.a_buffer_view, (u32.sizeof * 2) * vk.swapchain_extent.width * vk.swapchain_extent.height, FMT.RG_U32);
|
||||
CreateImageView(vk, &vk.aux_image, vk.swapchain_extent.width, vk.swapchain_extent.height, FMT.R_U32, OIT_IMAGE_USAGE);
|
||||
|
||||
VkDescriptorBufferInfo a_buffer_info = {
|
||||
buffer: vk.a_buffer_view.buffer,
|
||||
offset: 0,
|
||||
range: VK_WHOLE_SIZE,
|
||||
};
|
||||
|
||||
VkDescriptorImageInfo aux_info = {
|
||||
sampler: vk.oit_sampler,
|
||||
imageView: vk.aux_image.view,
|
||||
imageLayout: VK_IMAGE_LAYOUT_GENERAL,
|
||||
};
|
||||
|
||||
VkDescriptorImageInfo sampler_info = {
|
||||
sampler: vk.nearest_sampler,
|
||||
};
|
||||
|
||||
VkWriteDescriptorSet write = {
|
||||
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
dstSet: vk.desc_sets[DT.Shared],
|
||||
dstBinding: 3,
|
||||
descriptorCount: 1,
|
||||
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
pImageInfo: &sampler_info,
|
||||
VkDescriptorImageInfo oit_sample_info = {
|
||||
sampler: vk.oit_sampler,
|
||||
};
|
||||
|
||||
vkUpdateDescriptorSets(vk.device, 1, &write, 0, null);
|
||||
VkWriteDescriptorSet[] writes = [
|
||||
{
|
||||
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
dstSet: vk.desc_sets[DT.Shared],
|
||||
dstBinding: 3,
|
||||
descriptorCount: 1,
|
||||
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
pImageInfo: &sampler_info,
|
||||
},
|
||||
{
|
||||
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
dstSet: vk.desc_sets[DT.Shared],
|
||||
dstBinding: 4,
|
||||
descriptorCount: 1,
|
||||
descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
|
||||
pBufferInfo: &a_buffer_info,
|
||||
pTexelBufferView: &vk.a_buffer_view.view,
|
||||
},
|
||||
{
|
||||
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
dstSet: vk.desc_sets[DT.Shared],
|
||||
dstBinding: 5,
|
||||
descriptorCount: 1,
|
||||
descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
pImageInfo: &aux_info,
|
||||
},
|
||||
{
|
||||
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
dstSet: vk.desc_sets[DT.Shared],
|
||||
dstBinding: 6,
|
||||
descriptorCount: 1,
|
||||
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
pImageInfo: &oit_sample_info,
|
||||
},
|
||||
];
|
||||
|
||||
vkUpdateDescriptorSets(vk.device, cast(u32)writes.length, writes.ptr, 0, null);
|
||||
|
||||
WriteDrawImageDesc(vk);
|
||||
}
|
||||
@ -2467,6 +2595,7 @@ InitDevice(Vulkan* vk)
|
||||
descriptorBindingSampledImageUpdateAfterBind: VK_TRUE,
|
||||
descriptorBindingStorageImageUpdateAfterBind: VK_TRUE,
|
||||
descriptorBindingStorageBufferUpdateAfterBind: VK_TRUE,
|
||||
descriptorBindingStorageTexelBufferUpdateAfterBind: VK_TRUE,
|
||||
descriptorBindingPartiallyBound: VK_TRUE,
|
||||
shaderSampledImageArrayNonUniformIndexing: VK_TRUE,
|
||||
shaderUniformBufferArrayNonUniformIndexing: VK_TRUE,
|
||||
@ -2488,6 +2617,7 @@ InitDevice(Vulkan* vk)
|
||||
shaderStorageBufferArrayDynamicIndexing: VK_TRUE,
|
||||
shaderStorageImageArrayDynamicIndexing: VK_TRUE,
|
||||
samplerAnisotropy: VK_TRUE,
|
||||
fragmentStoresAndAtomics: VK_TRUE,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2557,6 +2687,7 @@ CheckDeviceFeatures(VkPhysicalDevice device)
|
||||
VkPhysicalDeviceFeatures features = features2.features;
|
||||
bool result = true;
|
||||
|
||||
result &= cast(bool)features.fragmentStoresAndAtomics;
|
||||
result &= cast(bool)features.shaderUniformBufferArrayDynamicIndexing;
|
||||
result &= cast(bool)features.shaderSampledImageArrayDynamicIndexing;
|
||||
result &= cast(bool)features.shaderStorageBufferArrayDynamicIndexing;
|
||||
@ -2566,6 +2697,7 @@ CheckDeviceFeatures(VkPhysicalDevice device)
|
||||
result &= cast(bool)features_12.descriptorIndexing;
|
||||
result &= cast(bool)features_12.bufferDeviceAddress;
|
||||
result &= cast(bool)features_12.descriptorBindingUniformBufferUpdateAfterBind;
|
||||
result &= cast(bool)features_12.descriptorBindingStorageTexelBufferUpdateAfterBind;
|
||||
result &= cast(bool)features_12.descriptorBindingSampledImageUpdateAfterBind;
|
||||
result &= cast(bool)features_12.descriptorBindingStorageImageUpdateAfterBind;
|
||||
result &= cast(bool)features_12.descriptorBindingStorageBufferUpdateAfterBind;
|
||||
|
||||
@ -58,6 +58,7 @@ version(AMD_GPU)
|
||||
PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = null;
|
||||
PFN_vkCreateImage vkCreateImage = null;
|
||||
PFN_vkCreateImageView vkCreateImageView = null;
|
||||
PFN_vkCreateBufferView vkCreateBufferView = null;
|
||||
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = null;
|
||||
PFN_vkGetDeviceQueue vkGetDeviceQueue = null;
|
||||
PFN_vkCreateSemaphore vkCreateSemaphore = null;
|
||||
@ -154,6 +155,7 @@ LoadDeviceFunctions(Vulkan* vk)
|
||||
vkCreateSwapchainKHR = cast(PFN_vkCreateSwapchainKHR)vkGetDeviceProcAddr(vk.device, "vkCreateSwapchainKHR");
|
||||
vkCreateImage = cast(PFN_vkCreateImage)vkGetDeviceProcAddr(vk.device, "vkCreateImage");
|
||||
vkCreateImageView = cast(PFN_vkCreateImageView)vkGetDeviceProcAddr(vk.device, "vkCreateImageView");
|
||||
vkCreateBufferView = cast(PFN_vkCreateBufferView)vkGetDeviceProcAddr(vk.device, "vkCreateBufferView");
|
||||
vkGetSwapchainImagesKHR = cast(PFN_vkGetSwapchainImagesKHR)vkGetDeviceProcAddr(vk.device, "vkGetSwapchainImagesKHR");
|
||||
vkGetDeviceQueue = cast(PFN_vkGetDeviceQueue)vkGetDeviceProcAddr(vk.device, "vkGetDeviceQueue");
|
||||
vkCreateSemaphore = cast(PFN_vkCreateSemaphore)vkGetDeviceProcAddr(vk.device, "vkCreateSemaphore");
|
||||
|
||||
7
src/shaders/full_screen_triangle.vert.glsl
Normal file
7
src/shaders/full_screen_triangle.vert.glsl
Normal file
@ -0,0 +1,7 @@
|
||||
#version 460
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 pos = vec4((float((gl_VertexIndex >> 1U) & 1U)) * 4.0 - 1.0, (float(gl_VertexIndex & 1U)) * 4.0 - 1.0, 0, 1.0);
|
||||
gl_Position = pos;
|
||||
}
|
||||
84
src/shaders/oit.frag.glsl
Normal file
84
src/shaders/oit.frag.glsl
Normal file
@ -0,0 +1,84 @@
|
||||
#version 460
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_nonuniform_qualifier : require
|
||||
|
||||
#define COMPOSITE_PASS
|
||||
|
||||
#include "structures.layout"
|
||||
|
||||
layout (location = 0) out vec4 FragColor;
|
||||
|
||||
void BubbleSort(inout uvec2 array[OIT_LAYERS], int n)
|
||||
{
|
||||
for(int i = (n - 2); i >= 0; --i)
|
||||
{
|
||||
for(int j = 0; j <= i; ++j)
|
||||
{
|
||||
if(uintBitsToFloat(array[j].g) >= uintBitsToFloat(array[j+1].g))
|
||||
{
|
||||
uvec2 temp = array[j+1];
|
||||
array[j+1] = array[j];
|
||||
array[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float UnPreMultSRGBToLinear(float col)
|
||||
{
|
||||
return col < 0.04045f ? col / 12.92f : pow((col + 0.055f) / 1.055f, 2.4f);
|
||||
}
|
||||
|
||||
vec4 UnPreMultSRGBToLinear(vec4 col)
|
||||
{
|
||||
col.r = UnPreMultSRGBToLinear(col.r);
|
||||
col.g = UnPreMultSRGBToLinear(col.g);
|
||||
col.b = UnPreMultSRGBToLinear(col.b);
|
||||
return col;
|
||||
}
|
||||
|
||||
void DoBlend(inout vec4 color, vec4 base_color)
|
||||
{
|
||||
color.rgb += (1 - color.a) * base_color.rgb;
|
||||
color.a += (1 - color.a) * base_color.a;
|
||||
}
|
||||
|
||||
void DoBlendPacked(inout vec4 color, uint fragment)
|
||||
{
|
||||
vec4 unpacked_color = unpackUnorm4x8(fragment);
|
||||
unpacked_color = UnPreMultSRGBToLinear(unpacked_color);
|
||||
unpacked_color.rgb *= unpacked_color.a;
|
||||
DoBlend(color, unpacked_color);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
int store_mask = 0;
|
||||
int view_size = int(G.res.x) * int(G.res.y);
|
||||
int sample_id = 0;
|
||||
int list_pos = view_size * OIT_LAYERS * sample_id + coord.y * int(G.res.x) + coord.x;
|
||||
uvec2 array[OIT_LAYERS];
|
||||
|
||||
vec4 color = vec4(0.0);
|
||||
|
||||
int fragments = int(imageLoad(ImageAux, coord).r);
|
||||
fragments = min(OIT_LAYERS, fragments);
|
||||
|
||||
for (int i = 0; i < fragments; i++)
|
||||
{
|
||||
array[i] = imageLoad(ImageABuffer, list_pos + i * view_size).rg;
|
||||
}
|
||||
|
||||
BubbleSort(array, fragments);
|
||||
|
||||
vec4 color_sum = vec4(0.0);
|
||||
|
||||
for(int i = 0; i < fragments; i++)
|
||||
{
|
||||
DoBlendPacked(color_sum, array[i].x);
|
||||
}
|
||||
|
||||
FragColor = color_sum;
|
||||
}
|
||||
@ -10,7 +10,7 @@ layout (location = 0) in struct FragDataIn {
|
||||
vec2 uv;
|
||||
} FragData;
|
||||
|
||||
layout (location = 0) out vec4 FragColor;
|
||||
layout (location = 0, index = 0) out vec4 FragColor;
|
||||
|
||||
vec4 CalculateDirectionalLight(vec4 diff_col, vec4 diff_samp, vec4 light_col, vec3 dir, vec3 normal)
|
||||
{
|
||||
@ -25,8 +25,27 @@ vec4 CalculateDirectionalLight(vec4 diff_col, vec4 diff_samp, vec4 light_col, ve
|
||||
return (ambient + diffuse);
|
||||
}
|
||||
|
||||
float UnPreMultLinearToSRGB(float col)
|
||||
{
|
||||
return col < 0.0031308f ? col * 12.92f : (pow(col, 1.0f / 2.4f) * 1.055f) - 0.055f;
|
||||
}
|
||||
|
||||
vec4 UnPreMultLinearToSRGB(vec4 col)
|
||||
{
|
||||
col.r = UnPreMultLinearToSRGB(col.x);
|
||||
col.g = UnPreMultLinearToSRGB(col.x);
|
||||
col.b = UnPreMultLinearToSRGB(col.x);
|
||||
return col;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
int store_mask = 0;
|
||||
int view_size = int(G.res.x) * int(G.res.y);
|
||||
int sample_id = 0;
|
||||
int list_pos = view_size * OIT_LAYERS * sample_id + coord.y * int(G.res.x) + coord.x;
|
||||
|
||||
vec4 col = Materials[nonuniformEXT(PC.mat_id)].diffuse;
|
||||
vec4 tex_col = texture(sampler2D(Textures[nonuniformEXT(Materials[nonuniformEXT(PC.mat_id)].albedo_texture)], SamplerNearest), FragData.uv);
|
||||
|
||||
@ -39,5 +58,19 @@ void main()
|
||||
out_col.a = alpha_col.a;
|
||||
}
|
||||
|
||||
FragColor = out_col;
|
||||
vec4 srgb_col = UnPreMultLinearToSRGB(out_col);
|
||||
|
||||
uvec4 store_value = uvec4(packUnorm4x8(srgb_col), floatBitsToUint(gl_FragCoord.z), store_mask, 0);
|
||||
|
||||
uint old_counter = imageAtomicAdd(ImageAux, coord, 1u);
|
||||
if (old_counter < OIT_LAYERS)
|
||||
{
|
||||
imageStore(ImageABuffer, list_pos + int(old_counter) * view_size, store_value);
|
||||
|
||||
FragColor = vec4(0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
FragColor = vec4(out_col.rgb * out_col.a, out_col.a); // Change to vec4(0.0) to disable tail blending
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
// **** STRUCTS MUST BE PACKED IN OPTIMAL PACKING ORDER TO MATCH D STRUCTS ****
|
||||
// ****************************************************************************
|
||||
|
||||
#define OIT_LAYERS 64
|
||||
|
||||
layout (set = 0, binding = 0) uniform GlobalUniforms {
|
||||
mat4 view_matrix;
|
||||
mat4 projection_matrix;
|
||||
@ -20,6 +22,20 @@ layout (rgba16f, set = 0, binding = 2) uniform image2D DrawImage;
|
||||
|
||||
layout (set = 0, binding = 3) uniform sampler SamplerNearest;
|
||||
|
||||
#ifdef COMPOSITE_PASS
|
||||
|
||||
layout (set = 0, binding = 4, rg32ui) uniform restrict readonly uimageBuffer ImageABuffer;
|
||||
|
||||
layout (set = 0, binding = 5, r32ui) uniform restrict readonly uimage2D ImageAux;
|
||||
|
||||
#else
|
||||
|
||||
layout (set = 0, binding = 4, rg32ui) uniform coherent uimageBuffer ImageABuffer;
|
||||
|
||||
layout (set = 0, binding = 5, r32ui) uniform coherent uimage2D ImageAux;
|
||||
|
||||
#endif
|
||||
|
||||
layout (set = 1, binding = 0) uniform texture2D Textures[];
|
||||
|
||||
layout (set = 2, binding = 0) uniform Material {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user