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;
}
struct Material
extern(C) struct Material
{
Vec4 ambient;
Vec4 diffuse;
Vec4 specular;
u32 albedo_texture;
u32 ambient_texture;
u32 specular_texture;
b32 albedo_has_texture;
b32 ambient_has_texture;
b32 specular_has_texture;
Vec4 ambient;
Vec4 diffuse;
Vec4 specular;
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
{
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;
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);
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);
model.materials = AllocArray!(Buffer)(&rd.arena, 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)
{
switch (m3d.material[i].prop[j].type)
{
case m3dp_Ka: ConvertColor(&mat.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_Ns: mat.shininess = m3d.material[i].prop[j].value.fnum; break;
case m3dp_Ka: ConvertColor(&mats[i].ambient, 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: mats[i].shininess = m3d.material[i].prop[j].value.fnum; break;
case m3dp_map_Kd:
{
mat.albedo_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
mat.albedo_has_texture = true;
mats[i].albedo_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
mats[i].albedo_has_texture = true;
} break;
case m3dp_map_Ka:
{
mat.ambient_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
mat.ambient_has_texture = true;
mats[i].ambient_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
mats[i].ambient_has_texture = true;
} break;
case m3dp_map_Ks:
{
mat.specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
mat.specular_has_texture = true;
mats[i].specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
mats[i].specular_has_texture = true;
} break;
default: break;
}
}
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);
}
@ -460,7 +473,7 @@ LoadModel(Renderer* rd, string name)
{
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;
last = m3d.face[i].materialid;
}

View File

@ -13,6 +13,7 @@ import renderer;
import std.math.rounding : Ceil = ceil;
bool g_VLAYER_SUPPORT = false;
bool g_DEBUG_PRINTF = false;
const FRAME_OVERLAP = 2;
@ -124,6 +125,7 @@ struct Buffer
{
VkBuffer buffer;
VmaAllocation alloc;
u64 size;
}
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);
// TODO: handle errors here then reallocate buffer
assert(VkCheck("CreateBuffer failure: vmaCreateBuffer error", result), "CreateBuffer failure");
buf.size = size;
}
void
@ -703,6 +707,12 @@ ImmSubmit(Vulkan* vk, void delegate() fn)
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;
}
@ -1435,7 +1445,7 @@ SetUniform(Vulkan* vk, GlobalUniforms* globals)
VkDescriptorBufferInfo buffer_info = {
buffer: vk.global_buf.buffer,
range: VK_WHOLE_SIZE,
range: GlobalUniforms.sizeof,
};
VkWriteDescriptorSet write = {
@ -1739,7 +1749,7 @@ WriteConvDescriptor(Vulkan* vk, Buffer* buf)
{
VkDescriptorBufferInfo buf_info = {
buffer: buf.buffer,
range: VK_WHOLE_SIZE,
range: buf.size,
};
VkWriteDescriptorSet write = {
@ -1785,7 +1795,7 @@ WriteDescriptors(Vulkan* vk, DescType type, Buffer[] buffers, u32[] indices)
foreach(i, buf; buffers)
{
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].dstSet = vk.desc_sets[type];
@ -2800,6 +2810,22 @@ InitInstance(Vulkan* vk)
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);
success = VkCheck("vkCreateInstance failure", result);
@ -2857,6 +2883,11 @@ EnableVLayers(Vulkan* vk)
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);
if (result != VK_SUCCESS)
{

View File

@ -3,7 +3,7 @@ import std.stdio;
import vulkan : Vulkan;
import std.conv;
import std.string;
import core.stdc.string : strlen;
import core.stdc.string : strlen, strcmp;
extern(System) VkBool32
DebugCallback(
@ -15,6 +15,9 @@ DebugCallback(
{
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) {
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
ms = "VERBOSE";
@ -60,9 +63,14 @@ DebugCallback(
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);
}
return VK_FALSE;
}

View File

@ -1,6 +1,7 @@
#version 460
#extension GL_EXT_shader_8bit_storage : require
#extension GL_EXT_debug_printf : require
layout (constant_id = 0) const int CHANNELS = 3;
@ -31,23 +32,28 @@ void main()
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);
}
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);
}
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);
}
}

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 {
vec2 res;
} G;
@ -13,15 +17,15 @@ layout (set = 0, binding = 3) uniform sampler SamplerNearest;
layout (set = 1, binding = 0) uniform texture2D Textures[];
layout (set = 2, binding = 0) uniform Material {
vec4 ambient;
vec4 diffuse;
vec4 specular;
uint albedo_texture;
uint ambient_texture;
uint specular_texture;
bool albedo_has_texture;
bool ambient_has_texture;
bool specular_has_texture;
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
} Materials[];

View File

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