fixed bug causing material buffers to not be written correctly

This commit is contained in:
matthew 2025-07-20 10:36:07 +10:00
parent bf34f3e6e1
commit f02685c6b3
14 changed files with 106 additions and 50 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -114,20 +114,31 @@ struct ShaderUniforms
f32 placeholder; f32 placeholder;
} }
struct Material extern(C) struct Material
{ {
Vec4 ambient;
Vec4 diffuse;
Vec4 specular;
u32 albedo_texture; u32 albedo_texture;
u32 ambient_texture; u32 ambient_texture;
u32 specular_texture; u32 specular_texture;
b32 albedo_has_texture; b32 albedo_has_texture;
b32 ambient_has_texture; b32 ambient_has_texture;
b32 specular_has_texture; b32 specular_has_texture;
Vec4 ambient;
Vec4 diffuse;
Vec4 specular;
f32 shininess = 0.0; f32 shininess = 0.0;
} }
static assert(Material.ambient.offsetof == 0, "ambient offset incorrect");
static assert(Material.diffuse.offsetof == 16, "ambient offset incorrect");
static assert(Material.specular.offsetof == 32, "ambient offset incorrect");
static assert(Material.albedo_texture.offsetof == 48, "ambient offset incorrect");
static assert(Material.ambient_texture.offsetof == 52, "ambient offset incorrect");
static assert(Material.specular_texture.offsetof == 56, "ambient offset incorrect");
static assert(Material.albedo_has_texture.offsetof == 60, "ambient offset incorrect");
static assert(Material.ambient_has_texture.offsetof == 64, "ambient offset incorrect");
static assert(Material.specular_has_texture.offsetof == 68, "ambient offset incorrect");
static assert(Material.shininess.offsetof == 72, "ambient offset incorrect");
struct UIVertex struct UIVertex
{ {
Vec2 p0; Vec2 p0;
@ -399,45 +410,47 @@ LoadModel(Renderer* rd, string name)
u32 w = m3d.texture[i].w; u32 h = m3d.texture[i].h; u32 ch = m3d.texture[i].f; u32 w = m3d.texture[i].w; u32 h = m3d.texture[i].h; u32 ch = m3d.texture[i].f;
u8[] tex_data = m3d.texture[i].d[0 .. w * h * ch]; u8[] tex_data = m3d.texture[i].d[0 .. w * h * ch];
const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)];
CreateImageView(&rd.vk, &model.textures[i], w, h, ch, tex_data); CreateImageView(&rd.vk, &model.textures[i], w, h, ch, tex_data);
tex_lookup[i] = Pop(&rd.vk, DT.SampledImage); tex_lookup[i] = Pop(&rd.vk, DT.SampledImage);
} }
Material[] mats = AllocArray!(Material)(&rd.temp_arena, m3d.nummaterial);
u32[] mat_lookup = AllocArray!(u32)(&rd.temp_arena, m3d.nummaterial); u32[] mat_lookup = AllocArray!(u32)(&rd.temp_arena, m3d.nummaterial);
model.materials = AllocArray!(Buffer)(&rd.arena, m3d.nummaterial); model.materials = AllocArray!(Buffer)(&rd.arena, m3d.nummaterial);
foreach(i; 0 .. m3d.nummaterial) foreach(i; 0 .. m3d.nummaterial)
{ {
Material mat; const(char)[] mat_name = m3d.material[i].name[0 .. strlen(m3d.material[i].name)];
foreach(j; 0 .. m3d.material[i].numprop) foreach(j; 0 .. m3d.material[i].numprop)
{ {
switch (m3d.material[i].prop[j].type) switch (m3d.material[i].prop[j].type)
{ {
case m3dp_Ka: ConvertColor(&mat.ambient, m3d.material[i].prop[j].value.color); break; case m3dp_Ka: ConvertColor(&mats[i].ambient, m3d.material[i].prop[j].value.color); break;
case m3dp_Ks: ConvertColor(&mat.specular, m3d.material[i].prop[j].value.color); break; case m3dp_Ks: ConvertColor(&mats[i].specular, m3d.material[i].prop[j].value.color); break;
case m3dp_Ns: mat.shininess = m3d.material[i].prop[j].value.fnum; break; case m3dp_Ns: mats[i].shininess = m3d.material[i].prop[j].value.fnum; break;
case m3dp_map_Kd: case m3dp_map_Kd:
{ {
mat.albedo_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; mats[i].albedo_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
mat.albedo_has_texture = true; mats[i].albedo_has_texture = true;
} break; } break;
case m3dp_map_Ka: case m3dp_map_Ka:
{ {
mat.ambient_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; mats[i].ambient_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
mat.ambient_has_texture = true; mats[i].ambient_has_texture = true;
} break; } break;
case m3dp_map_Ks: case m3dp_map_Ks:
{ {
mat.specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid]; mats[i].specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
mat.specular_has_texture = true; mats[i].specular_has_texture = true;
} break; } break;
default: break; default: break;
} }
} }
CreateBuffer(&rd.vk, &model.materials[i], BT.Uniform, Material.sizeof, false); CreateBuffer(&rd.vk, &model.materials[i], BT.Uniform, Material.sizeof, false);
assert(Transfer(&rd.vk, &model.materials[i], &mat), "LoadModel failure: Transfer error when transferring material"); assert(Transfer(&rd.vk, &model.materials[i], &mats[i]), "LoadModel failure: Transfer error when transferring material");
mat_lookup[i] = Pop(&rd.vk, DT.Material); mat_lookup[i] = Pop(&rd.vk, DT.Material);
} }
@ -460,7 +473,7 @@ LoadModel(Renderer* rd, string name)
{ {
if (last == u64.max) if (last == u64.max)
{ {
model.parts[index].mat = m3d.face[i].materialid != u32.max ? mat_lookup[m3d.face[i].materialid] : 0; model.parts[index].mat = (m3d.face[i].materialid != u32.max) ? mat_lookup[m3d.face[i].materialid] : 0;
model.parts[index].offset = 0; model.parts[index].offset = 0;
last = m3d.face[i].materialid; last = m3d.face[i].materialid;
} }

View File

@ -13,6 +13,7 @@ import renderer;
import std.math.rounding : Ceil = ceil; import std.math.rounding : Ceil = ceil;
bool g_VLAYER_SUPPORT = false; bool g_VLAYER_SUPPORT = false;
bool g_DEBUG_PRINTF = false;
const FRAME_OVERLAP = 2; const FRAME_OVERLAP = 2;
@ -124,6 +125,7 @@ struct Buffer
{ {
VkBuffer buffer; VkBuffer buffer;
VmaAllocation alloc; VmaAllocation alloc;
u64 size;
} }
struct DescBindings struct DescBindings
@ -403,6 +405,8 @@ CreateBuffer(Vulkan* vk, Buffer* buf, BufferType type, u64 size, bool host_visib
VkResult result = vmaCreateBuffer(vk.vma, &buffer_info, &alloc_info, &buf.buffer, &buf.alloc, &vma_info); VkResult result = vmaCreateBuffer(vk.vma, &buffer_info, &alloc_info, &buf.buffer, &buf.alloc, &vma_info);
// TODO: handle errors here then reallocate buffer // TODO: handle errors here then reallocate buffer
assert(VkCheck("CreateBuffer failure: vmaCreateBuffer error", result), "CreateBuffer failure"); assert(VkCheck("CreateBuffer failure: vmaCreateBuffer error", result), "CreateBuffer failure");
buf.size = size;
} }
void void
@ -703,6 +707,12 @@ ImmSubmit(Vulkan* vk, void delegate() fn)
success = VkCheck("ImmSubmit failure: vkQueueSubmit2 error", result); success = VkCheck("ImmSubmit failure: vkQueueSubmit2 error", result);
} }
if (success)
{
result = vkWaitForFences(vk.device, 1, &vk.imm_fence, true, 999999999);
success = VkCheck("ImmSubmit failure: vkWaitForFences post submission error", result);
}
return success; return success;
} }
@ -1435,7 +1445,7 @@ SetUniform(Vulkan* vk, GlobalUniforms* globals)
VkDescriptorBufferInfo buffer_info = { VkDescriptorBufferInfo buffer_info = {
buffer: vk.global_buf.buffer, buffer: vk.global_buf.buffer,
range: VK_WHOLE_SIZE, range: GlobalUniforms.sizeof,
}; };
VkWriteDescriptorSet write = { VkWriteDescriptorSet write = {
@ -1739,7 +1749,7 @@ WriteConvDescriptor(Vulkan* vk, Buffer* buf)
{ {
VkDescriptorBufferInfo buf_info = { VkDescriptorBufferInfo buf_info = {
buffer: buf.buffer, buffer: buf.buffer,
range: VK_WHOLE_SIZE, range: buf.size,
}; };
VkWriteDescriptorSet write = { VkWriteDescriptorSet write = {
@ -1785,7 +1795,7 @@ WriteDescriptors(Vulkan* vk, DescType type, Buffer[] buffers, u32[] indices)
foreach(i, buf; buffers) foreach(i, buf; buffers)
{ {
buffer_info[i].buffer = buf.buffer; buffer_info[i].buffer = buf.buffer;
buffer_info[i].range = VK_WHOLE_SIZE; buffer_info[i].range = buf.size;
writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[i].dstSet = vk.desc_sets[type]; writes[i].dstSet = vk.desc_sets[type];
@ -2800,6 +2810,22 @@ InitInstance(Vulkan* vk)
ppEnabledExtensionNames: instance_ext.ptr, ppEnabledExtensionNames: instance_ext.ptr,
}; };
VkValidationFeatureEnableEXT validation_enable = VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT;
VkValidationFeaturesEXT validation_features = {
sType: VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
enabledValidationFeatureCount: 1,
pEnabledValidationFeatures: &validation_enable,
};
debug
{
if (g_VLAYER_SUPPORT && g_DEBUG_PRINTF)
{
instance_info.pNext = &validation_features;
}
}
VkResult result = vkCreateInstance(&instance_info, null, &vk.instance); VkResult result = vkCreateInstance(&instance_info, null, &vk.instance);
success = VkCheck("vkCreateInstance failure", result); success = VkCheck("vkCreateInstance failure", result);
@ -2857,6 +2883,11 @@ EnableVLayers(Vulkan* vk)
pfnUserCallback: cast(PFN_vkDebugUtilsMessengerCallbackEXT)&DebugCallback, pfnUserCallback: cast(PFN_vkDebugUtilsMessengerCallbackEXT)&DebugCallback,
}; };
if (g_DEBUG_PRINTF)
{
info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
}
VkResult result = vkCreateDebugUtilsMessengerEXT(vk.instance, &info, null, &vk.dbg_msg); VkResult result = vkCreateDebugUtilsMessengerEXT(vk.instance, &info, null, &vk.dbg_msg);
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
{ {

View File

@ -3,7 +3,7 @@ import std.stdio;
import vulkan : Vulkan; import vulkan : Vulkan;
import std.conv; import std.conv;
import std.string; import std.string;
import core.stdc.string : strlen; import core.stdc.string : strlen, strcmp;
extern(System) VkBool32 extern(System) VkBool32
DebugCallback( DebugCallback(
@ -15,6 +15,9 @@ DebugCallback(
{ {
string ms, mt; string ms, mt;
const(char)[] msg = callback_data.pMessage[0 .. strlen(callback_data.pMessage)];
bool debug_printf = strcmp(callback_data.pMessageIdName, "WARNING-DEBUG-PRINTF") == 0;
switch (message_severity) { switch (message_severity) {
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
ms = "VERBOSE"; ms = "VERBOSE";
@ -60,9 +63,14 @@ DebugCallback(
break; break;
} }
const char[] msg = callback_data.pMessage[0 .. strlen(callback_data.pMessage)]; if (debug_printf)
{
writefln("SHADER PRINT: %s", msg);
}
else
{
writefln("[%s: %s]\n%r\n", ms, mt, msg); writefln("[%s: %s]\n%r\n", ms, mt, msg);
}
return VK_FALSE; return VK_FALSE;
} }

View File

@ -1,6 +1,7 @@
#version 460 #version 460
#extension GL_EXT_shader_8bit_storage : require #extension GL_EXT_shader_8bit_storage : require
#extension GL_EXT_debug_printf : require
layout (constant_id = 0) const int CHANNELS = 3; layout (constant_id = 0) const int CHANNELS = 3;
@ -31,23 +32,28 @@ void main()
if (CHANNELS == 1) if (CHANNELS == 1)
{ {
uint index = x + (y * PC.x); uint index = x + y * PC.x;
vec4 col = vec4(vec3(uint(src[index])), 1.0); vec4 col = vec4(vec3(uint(src[index]) / 255.0), 1.0);
debugPrintfEXT("col = %v4f", col);
imageStore(dst, ivec2(x, y), col); imageStore(dst, ivec2(x, y), col);
} }
else if (CHANNELS == 2) else if (CHANNELS == 2)
{ {
uint index = (x + (y * PC.x)) * 2; uint index = (x + y * PC.x) * 2;
vec4 col = vec4(uint(src[index]), uint(src[index]), uint(src[index]), uint(src[index+1])); float f = uint(src[index]) / 255.0;
float a = uint(src[index+1]) / 255.0;
vec4 col = vec4(f, f, f, a);
debugPrintfEXT("col = %v4f", col);
imageStore(dst, ivec2(x, y), col); imageStore(dst, ivec2(x, y), col);
} }
else if (CHANNELS == 3) else if (CHANNELS == 3)
{ {
uint index = (x + (y * PC.x)) * 3; uint index = (x + y * PC.x) * 3;
vec4 col = vec4(uint(src[index]), uint(src[index+1]), uint(src[index+2]), 1.0); vec4 col = vec4(uint(src[index]) / 255.0, uint(src[index+1]) / 255.0, uint(src[index+2]) / 255.0, 1.0);
debugPrintfEXT("col = %v4f", col);
imageStore(dst, ivec2(x, y), col); imageStore(dst, ivec2(x, y), col);
} }
} }

View File

@ -1,3 +1,7 @@
// ****************************************************************************
// **** STRUCTS MUST BE PACKED IN OPTIMAL PACKING ORDER TO MATCH D STRUCTS ****
// ****************************************************************************
layout (set = 0, binding = 0) uniform GlobalUniforms { layout (set = 0, binding = 0) uniform GlobalUniforms {
vec2 res; vec2 res;
} G; } G;
@ -13,15 +17,15 @@ layout (set = 0, binding = 3) uniform sampler SamplerNearest;
layout (set = 1, binding = 0) uniform texture2D Textures[]; layout (set = 1, binding = 0) uniform texture2D Textures[];
layout (set = 2, binding = 0) uniform Material { layout (set = 2, binding = 0) uniform Material {
vec4 ambient;
vec4 diffuse;
vec4 specular;
uint albedo_texture; uint albedo_texture;
uint ambient_texture; uint ambient_texture;
uint specular_texture; uint specular_texture;
bool albedo_has_texture; bool albedo_has_texture;
bool ambient_has_texture; bool ambient_has_texture;
bool specular_has_texture; bool specular_has_texture;
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess; float shininess;
} Materials[]; } Materials[];

View File

@ -377,23 +377,17 @@ struct Vector(T, int S)
{ {
T r = 0.0; T r = 0.0;
T g = 0.0; T g = 0.0;
static if (S > 2) static if (S > 2) T b = 0.0;
T b = 0.0; static if (S > 3) T a = 0.0;
static if (S > 3)
T a = 0.0;
}; };
struct struct
{ {
T x; T x;
T y; T y;
static if (S > 2) static if (S > 2) T z;
T z; static if (S > 3) T w;
static if (S > 3)
T w;
}; };
static if (S == 4)
T[S] v; T[S] v;
float4 simd;
} }
} }