mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[vulkan] Get IQM rendering working
The bones aren't animated yet (and I realized I made the mistake of thinking the bone buffer was per-model when it's really per-instance (I think this mistake is in the rest of QF, too)), skin rendering is a mess, need to default vertex attributes that aren't in the model... Still, it's quite satisfying seeing Mr Fixit on screen again :) I wound up moving the pipeline spec in with the rest of the pipelines as the system isn't really ready for separating them.
This commit is contained in:
parent
3f7cbae4d0
commit
8795b8eb91
10 changed files with 274 additions and 303 deletions
|
@ -65,6 +65,8 @@ typedef struct qfv_iqm_s {
|
|||
qfv_iqm_skin_t *skins;
|
||||
struct qfv_resource_s *mesh;
|
||||
struct qfv_resource_s *bones;
|
||||
VkBuffer bones_buffer;
|
||||
VkDescriptorSet *bones_descriptors; // one per frame FIXME per instance!!!
|
||||
} qfv_iqm_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -91,15 +93,21 @@ typedef struct iqmctx_s {
|
|||
VkPipeline gbuf;
|
||||
VkPipelineLayout layout;
|
||||
VkSampler sampler;
|
||||
VkDescriptorPool bones_pool;
|
||||
VkDescriptorSetLayout bones_setLayout;
|
||||
} iqmctx_t;
|
||||
|
||||
struct vulkan_ctx_s;
|
||||
struct qfv_renderframe_s;
|
||||
struct entity_s;
|
||||
struct mod_iqm_ctx_s;
|
||||
struct iqm_s;
|
||||
|
||||
void Vulkan_Mod_IQMFinish (struct model_s *mod, struct vulkan_ctx_s *ctx);
|
||||
|
||||
void Vulkan_IQMAddBones (struct vulkan_ctx_s *ctx, struct iqm_s *iqm);
|
||||
void Vulkan_IQMRemoveBones (struct vulkan_ctx_s *ctx, struct iqm_s *iqm);
|
||||
|
||||
void Vulkan_IQMAddSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin);
|
||||
void Vulkan_IQMRemoveSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin);
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ typedef struct {
|
|||
byte weights[4];
|
||||
} iqmblend_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct iqm_s {
|
||||
char *text;
|
||||
int num_meshes;
|
||||
iqmmesh *meshes;
|
||||
|
|
|
@ -81,6 +81,11 @@ vulkan_iqm_clear (model_t *mod, void *data)
|
|||
|
||||
mod->needload = true;
|
||||
|
||||
for (int i = 0; i < iqm->num_meshes; i++) {
|
||||
Vulkan_IQMRemoveSkin (ctx, &mesh->skins[i]);
|
||||
}
|
||||
Vulkan_IQMRemoveBones (ctx, iqm);//FIXME doesn't belong here (per-instance)
|
||||
|
||||
QFV_DestroyResource (device, mesh->bones);
|
||||
QFV_DestroyResource (device, mesh->mesh);
|
||||
free (mesh);
|
||||
|
@ -162,6 +167,14 @@ iqm_transfer_texture (tex_t *tex, VkImage image, qfv_stagebuf_t *stage,
|
|||
0, 0, 0, 0, 0,
|
||||
1, &ib.barrier);
|
||||
memcpy (dst, tex->data, layer_size);
|
||||
VkBufferImageCopy copy = {
|
||||
packet->offset, 0, 0,
|
||||
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
|
||||
{0, 0, 0}, {tex->width, tex->height, 1},
|
||||
};
|
||||
dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer,
|
||||
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ©);
|
||||
|
||||
int mipLevels = QFV_MipLevels (tex->width, tex->height);
|
||||
if (mipLevels == 1) {
|
||||
|
@ -225,6 +238,7 @@ vulkan_iqm_load_textures (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh,
|
|||
tex = &null_tex;
|
||||
}
|
||||
iqm_transfer_texture (tex, image->image, stage, device);
|
||||
Vulkan_IQMAddSkin (ctx, skin);
|
||||
}
|
||||
dstring_delete (str);
|
||||
QFV_DestroyStagingBuffer (stage);
|
||||
|
@ -236,6 +250,8 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh,
|
|||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
iqmctx_t *ictx = ctx->iqm_context;
|
||||
|
||||
size_t geom_size = iqm->num_verts * sizeof (iqmgvert_t);
|
||||
size_t rend_size = iqm->num_verts * sizeof (iqmrvert_t);
|
||||
size_t elem_size = iqm->num_elements * sizeof (uint16_t);
|
||||
|
@ -350,7 +366,7 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh,
|
|||
vec4f_t *bone_data;
|
||||
dfunc->vkMapMemory (device->dev, mesh->bones->memory, 0, VK_WHOLE_SIZE,
|
||||
0, (void **)&bone_data);
|
||||
for (int i = 0; i < 3 * iqm->num_joints; i++) {
|
||||
for (size_t i = 0; i < ictx->frames.size * iqm->num_joints; i++) {
|
||||
vec4f_t *bone = bone_data + i * 3;
|
||||
bone[0] = (vec4f_t) {1, 0, 0, 0};
|
||||
bone[1] = (vec4f_t) {0, 1, 0, 0};
|
||||
|
@ -363,12 +379,15 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh,
|
|||
dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range);
|
||||
|
||||
dfunc->vkUnmapMemory (device->dev, mesh->bones->memory);
|
||||
|
||||
Vulkan_IQMAddBones (ctx, iqm); //FIXME doesn't belong here (per-instance)
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
iqmctx_t *ictx = ctx->iqm_context;
|
||||
iqm_t *iqm = (iqm_t *) mod->aliashdr;
|
||||
mod->clear = vulkan_iqm_clear;
|
||||
mod->data = ctx;
|
||||
|
@ -378,10 +397,12 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx)
|
|||
// 2 is for image + image view
|
||||
int num_objects = 4 + 2 * iqm->num_meshes;
|
||||
qfv_iqm_t *mesh = calloc (1, sizeof (qfv_iqm_t)
|
||||
+ ictx->frames.size * sizeof (VkDescriptorSet)
|
||||
+ 2 * sizeof (qfv_resource_t)
|
||||
+ num_objects * sizeof (qfv_resobj_t)
|
||||
+ iqm->num_meshes * sizeof (qfv_iqm_skin_t));
|
||||
mesh->bones = (qfv_resource_t *) &mesh[1];
|
||||
mesh->bones_descriptors = (VkDescriptorSet *) &mesh[1];
|
||||
mesh->bones = (qfv_resource_t *)&mesh->bones_descriptors[ictx->frames.size];
|
||||
mesh->mesh = &mesh->bones[1];
|
||||
|
||||
mesh->bones[0] = (qfv_resource_t) {
|
||||
|
@ -395,9 +416,9 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx)
|
|||
.name = "bones",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = 3 * iqm->num_joints * 3 * sizeof (vec4f_t),
|
||||
.size = ictx->frames.size * iqm->num_joints * 3 * sizeof (vec4f_t),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -460,9 +481,10 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx)
|
|||
mesh->geom_buffer = mesh->mesh->objects[0].buffer.buffer;
|
||||
mesh->rend_buffer = mesh->mesh->objects[1].buffer.buffer;
|
||||
mesh->index_buffer = mesh->mesh->objects[2].buffer.buffer;
|
||||
mesh->bones_buffer = mesh->bones->objects[0].buffer.buffer;
|
||||
|
||||
iqm->extra_data = mesh;
|
||||
|
||||
vulkan_iqm_load_textures (mod, iqm, mesh, ctx);
|
||||
vulkan_iqm_load_arrays (mod, iqm, mesh, ctx);
|
||||
|
||||
iqm->extra_data = mesh;
|
||||
}
|
||||
|
|
|
@ -92,6 +92,7 @@ vulkan_R_Init (void)
|
|||
Vulkan_Matrix_Init (vulkan_ctx);
|
||||
Vulkan_Alias_Init (vulkan_ctx);
|
||||
Vulkan_Bsp_Init (vulkan_ctx);
|
||||
Vulkan_IQM_Init (vulkan_ctx);
|
||||
Vulkan_Particles_Init (vulkan_ctx);
|
||||
Vulkan_Sprite_Init (vulkan_ctx);
|
||||
Vulkan_Draw_Init (vulkan_ctx);
|
||||
|
@ -686,16 +687,18 @@ vulkan_vid_render_shutdown (void)
|
|||
df->vkDestroyFence (dev, vulkan_ctx->fence, 0);
|
||||
df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0);
|
||||
|
||||
Mod_ClearAll ();
|
||||
|
||||
Vulkan_Compose_Shutdown (vulkan_ctx);
|
||||
Vulkan_Lighting_Shutdown (vulkan_ctx);
|
||||
Vulkan_Draw_Shutdown (vulkan_ctx);
|
||||
Vulkan_Sprite_Shutdown (vulkan_ctx);
|
||||
Vulkan_Particles_Shutdown (vulkan_ctx);
|
||||
Vulkan_IQM_Shutdown (vulkan_ctx);
|
||||
Vulkan_Bsp_Shutdown (vulkan_ctx);
|
||||
Vulkan_Alias_Shutdown (vulkan_ctx);
|
||||
Vulkan_Matrix_Shutdown (vulkan_ctx);
|
||||
|
||||
Mod_ClearAll ();
|
||||
Vulkan_Texture_Shutdown (vulkan_ctx);
|
||||
Vulkan_DestroyRenderPasses (vulkan_ctx);
|
||||
Vulkan_Shutdown_Common (vulkan_ctx);
|
||||
|
|
|
@ -1,254 +0,0 @@
|
|||
{
|
||||
setLayouts = {
|
||||
texture_set = {
|
||||
bindings = (
|
||||
{
|
||||
binding = 0;
|
||||
descriptorType = combined_image_sampler;
|
||||
descriptorCount = 1;
|
||||
stageFlags = fragment;
|
||||
},
|
||||
);
|
||||
};
|
||||
};
|
||||
pipelineLayouts = {
|
||||
iqm_layout = {
|
||||
setLayouts = (matrix_set, texture_set);
|
||||
pushConstantRanges = (
|
||||
{
|
||||
stageFlags = vertex;
|
||||
offset = 0;
|
||||
size = "16 * 4 + 4";
|
||||
},
|
||||
{
|
||||
stageFlags = fragment;
|
||||
offset = 68;
|
||||
size = "3 * 4 + 2 * 4 * 4 + 4";
|
||||
},
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
depthStencil = {
|
||||
test_and_write = {
|
||||
depthTestEnable = true;
|
||||
depthWriteEnable = true;
|
||||
depthCompareOp = less_or_equal;
|
||||
depthBoundsTestEnable = false;
|
||||
stencilTestEnable = false;
|
||||
};
|
||||
test_only = {
|
||||
depthTestEnable = true;
|
||||
depthWriteEnable = false;
|
||||
depthCompareOp = less_or_equal;
|
||||
depthBoundsTestEnable = false;
|
||||
stencilTestEnable = false;
|
||||
};
|
||||
disable = {
|
||||
depthTestEnable = false;
|
||||
depthWriteEnable = false;
|
||||
depthCompareOp = less_or_equal;
|
||||
depthBoundsTestEnable = false;
|
||||
stencilTestEnable = false;
|
||||
};
|
||||
};
|
||||
|
||||
inputAssembly = {
|
||||
iqm = {
|
||||
topology = triangle_list;
|
||||
primitiveRestartEnable = false;
|
||||
};
|
||||
};
|
||||
|
||||
vertexInput = {
|
||||
iqm = {
|
||||
bindings = (
|
||||
{ binding = 0; stride = 20; inputRate = vertex; },
|
||||
{ binding = 1; stride = 40; inputRate = vertex; },
|
||||
);
|
||||
attributes = (
|
||||
{ location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position
|
||||
{ location = 1; binding = 0; format = r8g8b8a8_uint; offset = 0; }, // bonindices
|
||||
{ location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, // boneweights
|
||||
|
||||
{ location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord
|
||||
{ location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal
|
||||
{ location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent
|
||||
{ location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color
|
||||
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
rasterization = {
|
||||
cw_cull_back = {
|
||||
depthClampEnable = false;
|
||||
rasterizerDiscardEnable = false;
|
||||
polygonMode = fill;
|
||||
cullMode = back;
|
||||
frontFace = clockwise;
|
||||
depthBiasEnable = false;
|
||||
lineWidth = 1;
|
||||
};
|
||||
counter_cw_cull_back = {
|
||||
depthClampEnable = false;
|
||||
rasterizerDiscardEnable = false;
|
||||
polygonMode = fill;
|
||||
cullMode = back;
|
||||
frontFace = counter_clockwise;
|
||||
depthBiasEnable = false;
|
||||
lineWidth = 1;
|
||||
};
|
||||
};
|
||||
|
||||
multisample = {
|
||||
rasterizationSamples = $msaaSamples;
|
||||
sampleShadingEnable = false;
|
||||
minSampleShading = 0.5f;
|
||||
alphaToCoverageEnable = false;
|
||||
alphaToOneEnable = false;
|
||||
};
|
||||
|
||||
viewport = {
|
||||
viewports = (
|
||||
{
|
||||
x = 0; y = 0;
|
||||
width = 640; height = 480;
|
||||
minDepth = 0; maxDepth = 1;
|
||||
}
|
||||
);
|
||||
scissors = (
|
||||
{
|
||||
offset = { x = 0; y = 0 };
|
||||
extent = { width = 640; height = 480; };
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
attachmentBlendOp = {
|
||||
disabled = {
|
||||
blendEnable = false;
|
||||
srcColorBlendFactor = src_alpha;
|
||||
dstColorBlendFactor = one_minus_src_alpha;
|
||||
colorBlendOp = add;
|
||||
srcAlphaBlendFactor = src_alpha;
|
||||
dstAlphaBlendFactor = one_minus_src_alpha;
|
||||
alphaBlendOp = add;
|
||||
colorWriteMask = r|g|b|a;
|
||||
};
|
||||
alpha_blend = {
|
||||
blendEnable = true;
|
||||
srcColorBlendFactor = src_alpha;
|
||||
dstColorBlendFactor = one_minus_src_alpha;
|
||||
colorBlendOp = add;
|
||||
srcAlphaBlendFactor = src_alpha;
|
||||
dstAlphaBlendFactor = one_minus_src_alpha;
|
||||
alphaBlendOp = add;
|
||||
colorWriteMask = r|g|b|a;
|
||||
};
|
||||
};
|
||||
|
||||
pipelines = {
|
||||
iqm_shadow = {
|
||||
subpass = 0;
|
||||
stages = (
|
||||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/iqm_shadow.vert;
|
||||
},
|
||||
);
|
||||
vertexInput = {
|
||||
bindings = (
|
||||
"$properties.vertexInput.iqm.bindings[0]",
|
||||
"$properties.vertexInput.iqm.bindings[1]",
|
||||
);
|
||||
attributes = (
|
||||
"$properties.vertexInput.iqm.attributes[0]",
|
||||
"$properties.vertexInput.iqm.attributes[1]",
|
||||
"$properties.vertexInput.iqm.attributes[2]",
|
||||
"$properties.vertexInput.iqm.attributes[3]",
|
||||
);
|
||||
};
|
||||
inputAssembly = $properties.inputAssembly.iqm;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.cw_cull_back;
|
||||
multisample = $properties.multisample;
|
||||
depthStencil = $properties.depthStencil.test_and_write;
|
||||
colorBlend = $properties.pipelines.iqm_gbuf.colorBlend;
|
||||
dynamic = {
|
||||
dynamicState = ( viewport, scissor );
|
||||
};
|
||||
layout = iqm_layout;
|
||||
};
|
||||
iqm_depth = {
|
||||
subpass = 0;
|
||||
stages = (
|
||||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/iqm_depth.vert;
|
||||
},
|
||||
);
|
||||
vertexInput = {
|
||||
// depth pass doesn't use UVs
|
||||
bindings = (
|
||||
"$properties.vertexInput.iqm.bindings[0]",
|
||||
"$properties.vertexInput.iqm.bindings[1]",
|
||||
);
|
||||
attributes = (
|
||||
"$properties.vertexInput.iqm.attributes[0]",
|
||||
"$properties.vertexInput.iqm.attributes[1]",
|
||||
"$properties.vertexInput.iqm.attributes[2]",
|
||||
"$properties.vertexInput.iqm.attributes[3]",
|
||||
);
|
||||
};
|
||||
inputAssembly = $properties.inputAssembly.iqm;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.cw_cull_back;
|
||||
multisample = $properties.multisample;
|
||||
depthStencil = $properties.depthStencil.test_and_write;
|
||||
colorBlend = $properties.pipelines.iqm_gbuf.colorBlend;
|
||||
dynamic = {
|
||||
dynamicState = ( viewport, scissor );
|
||||
};
|
||||
layout = iqm_layout;
|
||||
renderPass = renderpass;
|
||||
};
|
||||
iqm_gbuf = {
|
||||
subpass = 2;
|
||||
stages = (
|
||||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/iqm.vert;
|
||||
},
|
||||
{
|
||||
stage = fragment;
|
||||
name = main;
|
||||
module = $builtin/iqm_gbuf.frag;
|
||||
},
|
||||
);
|
||||
vertexInput = $properties.vertexInput.iqm;
|
||||
inputAssembly = $properties.inputAssembly.iqm;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.cw_cull_back;
|
||||
multisample = $properties.multisample;
|
||||
depthStencil = $properties.depthStencil.test_only;
|
||||
colorBlend = {
|
||||
logicOpEnable = false;
|
||||
attachments = (
|
||||
$properties.attachmentBlendOp.disabled,
|
||||
$properties.attachmentBlendOp.disabled,
|
||||
$properties.attachmentBlendOp.disabled,
|
||||
$properties.attachmentBlendOp.disabled,
|
||||
);
|
||||
};
|
||||
dynamic = {
|
||||
dynamicState = ( viewport, scissor, blend_constants );
|
||||
};
|
||||
layout = iqm_layout;
|
||||
renderPass = renderpass;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -97,6 +97,16 @@
|
|||
},
|
||||
);
|
||||
};
|
||||
bone_pool = {
|
||||
flags = free_descriptor_set;
|
||||
maxSets = 512;
|
||||
bindings = (
|
||||
{
|
||||
type = storage_buffer;
|
||||
descriptorCount = $properties.descriptorPools.bone_pool.maxSets;
|
||||
},
|
||||
);
|
||||
};
|
||||
texture_pool = {
|
||||
flags = free_descriptor_set;
|
||||
maxSets = 512;
|
||||
|
@ -206,6 +216,16 @@
|
|||
},
|
||||
);
|
||||
};
|
||||
bone_set = {
|
||||
bindings = (
|
||||
{
|
||||
binding = 0;
|
||||
descriptorType = storage_buffer;
|
||||
descriptorCount = 1;
|
||||
stageFlags = vertex;
|
||||
},
|
||||
);
|
||||
};
|
||||
sprite_set = {
|
||||
bindings = (
|
||||
{
|
||||
|
@ -349,6 +369,21 @@
|
|||
},
|
||||
);
|
||||
};
|
||||
iqm_layout = {
|
||||
setLayouts = (matrix_set, texture_set, bone_set);
|
||||
pushConstantRanges = (
|
||||
{
|
||||
stageFlags = vertex;
|
||||
offset = 0;
|
||||
size = "16 * 4 + 4";
|
||||
},
|
||||
{
|
||||
stageFlags = fragment;
|
||||
offset = 68;
|
||||
size = "3 * 4 + 2 * 4 * 4 + 4";
|
||||
},
|
||||
);
|
||||
};
|
||||
sprite_layout = {
|
||||
setLayouts = (matrix_set, sprite_set);
|
||||
pushConstantRanges = (
|
||||
|
@ -428,6 +463,10 @@
|
|||
topology = triangle_fan;
|
||||
primitiveRestartEnable = true;
|
||||
};
|
||||
iqm = {
|
||||
topology = triangle_list;
|
||||
primitiveRestartEnable = false;
|
||||
};
|
||||
twod = {
|
||||
topology = triangle_strip;
|
||||
primitiveRestartEnable = true;
|
||||
|
@ -466,6 +505,23 @@
|
|||
{ location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; },
|
||||
);
|
||||
};
|
||||
iqm = {
|
||||
bindings = (
|
||||
{ binding = 0; stride = 20; inputRate = vertex; },
|
||||
{ binding = 1; stride = 40; inputRate = vertex; },
|
||||
);
|
||||
attributes = (
|
||||
{ location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position
|
||||
{ location = 1; binding = 0; format = r8g8b8a8_uint; offset = 12; }, // bonindices
|
||||
{ location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 16; }, // boneweights
|
||||
|
||||
{ location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord
|
||||
{ location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal
|
||||
{ location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent
|
||||
{ location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color
|
||||
|
||||
);
|
||||
};
|
||||
particle = {
|
||||
bindings = (
|
||||
{ binding = 0; stride = "4 * 4 * 4"; inputRate = vertex; },
|
||||
|
@ -833,6 +889,61 @@
|
|||
inputAssembly = $properties.inputAssembly.brush;
|
||||
layout = quakebsp_layout;
|
||||
};
|
||||
iqm_depth = {
|
||||
@inherit = $properties.pipelines.depth_base;
|
||||
stages = (
|
||||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/iqm.vert;
|
||||
specializationInfo = {
|
||||
mapEntries = (
|
||||
// IQMDepthOnly
|
||||
{ size = 4; offset = 0; constantID = 0; },
|
||||
);
|
||||
data = "array(1)";
|
||||
};
|
||||
},
|
||||
);
|
||||
vertexInput = $properties.vertexInput.iqm;
|
||||
/*vertexInput = {
|
||||
bindings = (
|
||||
"$properties.vertexInput.iqm.bindings[0]",
|
||||
);
|
||||
attributes = (
|
||||
"$properties.vertexInput.iqm.attributes[0]",
|
||||
"$properties.vertexInput.iqm.attributes[1]",
|
||||
"$properties.vertexInput.iqm.attributes[2]",
|
||||
);
|
||||
};*/
|
||||
inputAssembly = $properties.inputAssembly.iqm;
|
||||
layout = iqm_layout;
|
||||
};
|
||||
iqm_gbuf = {
|
||||
@inherit = $properties.pipelines.gbuf_base;
|
||||
stages = (
|
||||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/iqm.vert;
|
||||
specializationInfo = {
|
||||
mapEntries = (
|
||||
// !IQMDepthOnly
|
||||
{ size = 4; offset = 0; constantID = 0; },
|
||||
);
|
||||
data = "array(0)";
|
||||
};
|
||||
},
|
||||
{
|
||||
stage = fragment;
|
||||
name = main;
|
||||
module = $builtin/iqm.frag;
|
||||
},
|
||||
);
|
||||
vertexInput = $properties.vertexInput.iqm;
|
||||
inputAssembly = $properties.inputAssembly.iqm;
|
||||
layout = iqm_layout;
|
||||
};
|
||||
partdraw = {
|
||||
@inherit = $properties.pipelines.trans_base;
|
||||
stages = (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#version 450
|
||||
|
||||
layout (set = 1, binding = 0) uniform sampler2DArray Skin;
|
||||
layout (set = 1, binding = 0) uniform sampler2D Skin;
|
||||
|
||||
layout (push_constant) uniform PushConstants {
|
||||
layout (offset = 68)
|
||||
|
@ -15,7 +15,7 @@ layout (location = 1) in vec4 position;
|
|||
layout (location = 2) in vec3 normal;
|
||||
layout (location = 3) in vec3 tangent;
|
||||
layout (location = 4) in vec3 bitangent;
|
||||
layout (location = 5) in vec3 color;
|
||||
layout (location = 5) in vec4 color;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
layout (location = 1) out vec4 frag_emission;
|
||||
|
@ -27,18 +27,19 @@ main (void)
|
|||
{
|
||||
vec4 c;
|
||||
vec4 e;
|
||||
vec3 n;
|
||||
//vec3 n;
|
||||
int i;
|
||||
mat3 tbn = mat3 (tangent, bitangent, normal);
|
||||
//mat3 tbn = mat3 (tangent, bitangent, normal);
|
||||
|
||||
c = texture (Skin, vec3 (texcoord, 0)) * base_color;
|
||||
c += texture (Skin, vec3 (texcoord, 1)) * unpackUnorm4x8(colorA);
|
||||
c += texture (Skin, vec3 (texcoord, 2)) * unpackUnorm4x8(colorB);
|
||||
e = texture (Skin, vec3 (texcoord, 3));
|
||||
n = texture (Skin, vec3 (texcoord, 4)).xyz * 2 - 1;
|
||||
c = texture (Skin, texcoord);// * color;
|
||||
//c = texture (Skin, vec3 (texcoord, 0)) * color;
|
||||
//c += texture (Skin, vec3 (texcoord, 1)) * unpackUnorm4x8(colorA);
|
||||
//c += texture (Skin, vec3 (texcoord, 2)) * unpackUnorm4x8(colorB);
|
||||
//e = texture (Skin, vec3 (texcoord, 3));
|
||||
//n = texture (Skin, vec3 (texcoord, 4)).xyz * 2 - 1;
|
||||
|
||||
frag_color = c;
|
||||
frag_emission = e;
|
||||
frag_normal = vec4(tbn * n, 1);
|
||||
frag_emission = vec4(0,0,0,1);//e;
|
||||
frag_normal = vec4(normal,1);//vec4(tbn * n, 1);
|
||||
frag_position = position;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#version 450
|
||||
|
||||
layout (constant_id = 0) const bool IQMDepthOnly = false;
|
||||
|
||||
layout (set = 0, binding = 0) uniform Matrices {
|
||||
mat4 Projection3d;
|
||||
mat4 View;
|
||||
|
@ -7,7 +9,7 @@ layout (set = 0, binding = 0) uniform Matrices {
|
|||
mat4 Projection2d;
|
||||
};
|
||||
|
||||
layout (set = 3, binding = 0) buffer Bones {
|
||||
layout (set = 2, binding = 0) buffer Bones {
|
||||
// NOTE these are transposed, so v * m
|
||||
mat3x4 bones[];
|
||||
};
|
||||
|
@ -18,7 +20,7 @@ layout (push_constant) uniform PushConstants {
|
|||
};
|
||||
|
||||
layout (location = 0) in vec3 vposition;
|
||||
layout (location = 1) in ivec4 vbones;
|
||||
layout (location = 1) in uvec4 vbones;
|
||||
layout (location = 2) in vec4 vweights;
|
||||
layout (location = 3) in vec2 vtexcoord;
|
||||
layout (location = 4) in vec3 vnormal;
|
||||
|
@ -41,12 +43,16 @@ main (void)
|
|||
m += bones[vbones.w] * vweights.w;
|
||||
vec4 pos = vec4 (Model * vec4(vposition, 1) * m, 1);
|
||||
gl_Position = Projection3d * (View * pos);
|
||||
position = pos;
|
||||
mat3 adjTrans = mat3 (cross(m[1].xyz, m[2].xyz), cross(m[2].xyz, m[0].xyz),
|
||||
cross(m[0].xyz, m[1].xyz));
|
||||
normal = mat3 (Model) * vnormal * adjTrans;
|
||||
tangent = mat3 (Model) * vtangent.xyz * adjTrans;
|
||||
bitangent = cross (normal, tangent) * vtangent.w;
|
||||
texcoord = vtexcoord;
|
||||
color = vcolor;
|
||||
|
||||
if (!IQMDepthOnly) {
|
||||
position = pos;
|
||||
mat3 adjTrans = mat3 (cross(m[1].xyz, m[2].xyz),
|
||||
cross(m[2].xyz, m[0].xyz),
|
||||
cross(m[0].xyz, m[1].xyz));
|
||||
normal = mat3 (Model) * vnormal * adjTrans;
|
||||
tangent = mat3 (Model) * vtangent.xyz * adjTrans;
|
||||
bitangent = cross (normal, tangent) * vtangent.w;
|
||||
texcoord = vtexcoord;
|
||||
color = vcolor;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/iqm.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
|
@ -42,6 +43,7 @@
|
|||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
#include "QF/Vulkan/debug.h"
|
||||
#include "QF/Vulkan/descriptor.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
|
@ -72,7 +74,7 @@ static QFV_Subpass subpass_map[] = {
|
|||
|
||||
static void
|
||||
emit_commands (VkCommandBuffer cmd, int pose1, int pose2,
|
||||
qfv_iqm_skin_t **skins,
|
||||
qfv_iqm_skin_t *skins,
|
||||
uint32_t numPC, qfv_push_constants_t *constants,
|
||||
iqm_t *iqm, qfv_renderframe_t *rFrame)
|
||||
{
|
||||
|
@ -88,20 +90,28 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2,
|
|||
mesh->geom_buffer,
|
||||
mesh->rend_buffer,
|
||||
};
|
||||
int bindingCount = skins ? 2 : 1;
|
||||
int bindingCount = 2;//skins ? 2 : 1;
|
||||
|
||||
dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets);
|
||||
dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0,
|
||||
VK_INDEX_TYPE_UINT32);
|
||||
VK_INDEX_TYPE_UINT16);
|
||||
QFV_PushConstants (device, cmd, ictx->layout, numPC, constants);
|
||||
for (int i = 0; i < iqm->num_meshes; i++) {
|
||||
if (skins) {
|
||||
VkDescriptorSet sets[] = {
|
||||
skins[i]->descriptor,
|
||||
skins[i].descriptor,
|
||||
mesh->bones_descriptors[ctx->curFrame],
|
||||
};
|
||||
dfunc->vkCmdBindDescriptorSets (cmd,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
ictx->layout, 1, 1, sets, 0, 0);
|
||||
ictx->layout, 1, 2, sets, 0, 0);
|
||||
} else {
|
||||
VkDescriptorSet sets[] = {
|
||||
mesh->bones_descriptors[ctx->curFrame],
|
||||
};
|
||||
dfunc->vkCmdBindDescriptorSets (cmd,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
ictx->layout, 2, 1, sets, 0, 0);
|
||||
}
|
||||
dfunc->vkCmdDrawIndexed (cmd, 3 * iqm->meshes[i].num_triangles, 1,
|
||||
3 * iqm->meshes[i].first_triangle, 0, 0);
|
||||
|
@ -117,7 +127,7 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame)
|
|||
model_t *model = ent->renderer.model;
|
||||
iqm_t *iqm = (iqm_t *) model->aliashdr;
|
||||
qfv_iqm_t *mesh = iqm->extra_data;
|
||||
qfv_iqm_skin_t **skins = &mesh->skins;
|
||||
qfv_iqm_skin_t *skins = mesh->skins;
|
||||
iqm_push_constants_t constants = {};
|
||||
|
||||
constants.blend = R_IQMGetLerpedFrames (ent, iqm);
|
||||
|
@ -144,8 +154,8 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame)
|
|||
};
|
||||
|
||||
QuatCopy (ent->renderer.colormod, constants.base_color);
|
||||
QuatCopy (skins[0]->colora, constants.colorA);
|
||||
QuatCopy (skins[0]->colorb, constants.colorB);
|
||||
QuatCopy (skins[0].colora, constants.colorA);
|
||||
QuatCopy (skins[0].colorb, constants.colorB);
|
||||
QuatZero (constants.fog);
|
||||
|
||||
emit_commands (aframe->cmdSet.a[QFV_iqmDepth],
|
||||
|
@ -157,8 +167,8 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame)
|
|||
}
|
||||
|
||||
static void
|
||||
alias_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline,
|
||||
qfv_renderframe_t *rFrame)
|
||||
iqm_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline,
|
||||
qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
|
@ -200,7 +210,7 @@ alias_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline,
|
|||
}
|
||||
|
||||
static void
|
||||
alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx)
|
||||
iqm_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
@ -222,8 +232,8 @@ Vulkan_IQMBegin (qfv_renderframe_t *rFrame)
|
|||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer],
|
||||
aframe->cmdSet.a[QFV_iqmGBuffer]);
|
||||
|
||||
alias_begin_subpass (QFV_iqmDepth, ictx->depth, rFrame);
|
||||
alias_begin_subpass (QFV_iqmGBuffer, ictx->gbuf, rFrame);
|
||||
iqm_begin_subpass (QFV_iqmDepth, ictx->depth, rFrame);
|
||||
iqm_begin_subpass (QFV_iqmGBuffer, ictx->gbuf, rFrame);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -233,8 +243,69 @@ Vulkan_IQMEnd (qfv_renderframe_t *rFrame)
|
|||
iqmctx_t *ictx = ctx->iqm_context;
|
||||
iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame];
|
||||
|
||||
alias_end_subpass (aframe->cmdSet.a[QFV_iqmDepth], ctx);
|
||||
alias_end_subpass (aframe->cmdSet.a[QFV_iqmGBuffer], ctx);
|
||||
iqm_end_subpass (aframe->cmdSet.a[QFV_iqmDepth], ctx);
|
||||
iqm_end_subpass (aframe->cmdSet.a[QFV_iqmGBuffer], ctx);
|
||||
}
|
||||
|
||||
static VkWriteDescriptorSet base_buffer_write = {
|
||||
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0,
|
||||
0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
void
|
||||
Vulkan_IQMAddBones (vulkan_ctx_t *ctx, iqm_t *iqm)
|
||||
{
|
||||
qfvPushDebug (ctx, "Vulkan_IQMAddBones");
|
||||
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
iqmctx_t *ictx = ctx->iqm_context;
|
||||
__auto_type mesh = (qfv_iqm_t *) iqm->extra_data;
|
||||
int num_sets = ictx->frames.size;
|
||||
|
||||
//FIXME kinda dumb
|
||||
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (num_sets, alloca);
|
||||
for (size_t i = 0; i < layouts->size; i++) {
|
||||
layouts->a[i] = ictx->bones_setLayout;
|
||||
}
|
||||
__auto_type sets = QFV_AllocateDescriptorSet (device, ictx->bones_pool,
|
||||
layouts);
|
||||
for (size_t i = 0; i < sets->size; i++) {
|
||||
mesh->bones_descriptors[i] = sets->a[i];
|
||||
}
|
||||
free (sets);
|
||||
|
||||
VkDescriptorBufferInfo bufferInfo[num_sets];
|
||||
size_t bones_size = iqm->num_joints * 3 * sizeof (vec4f_t);
|
||||
for (int i = 0; i < num_sets; i++) {
|
||||
bufferInfo[i].buffer = mesh->bones_buffer;
|
||||
bufferInfo[i].offset = i * bones_size;
|
||||
bufferInfo[i].range = bones_size;
|
||||
};
|
||||
VkWriteDescriptorSet write[num_sets];
|
||||
for (int i = 0; i < num_sets; i++) {
|
||||
write[i] = base_buffer_write;
|
||||
write[i].dstSet = mesh->bones_descriptors[i];
|
||||
write[i].pBufferInfo = &bufferInfo[i];
|
||||
}
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, num_sets, write, 0, 0);
|
||||
|
||||
qfvPopDebug (ctx);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_IQMRemoveBones (vulkan_ctx_t *ctx, iqm_t *iqm)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
iqmctx_t *ictx = ctx->iqm_context;
|
||||
__auto_type mesh = (qfv_iqm_t *) iqm->extra_data;
|
||||
int num_sets = ictx->frames.size;
|
||||
|
||||
dfunc->vkFreeDescriptorSets (device->dev, ictx->bones_pool, num_sets,
|
||||
mesh->bones_descriptors);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -267,11 +338,14 @@ Vulkan_IQM_Init (vulkan_ctx_t *ctx)
|
|||
DARRAY_RESIZE (&ictx->frames, frames);
|
||||
ictx->frames.grow = 0;
|
||||
|
||||
ictx->depth = Vulkan_CreateGraphicsPipeline (ctx, "alias_depth");
|
||||
ictx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "alias_gbuf");
|
||||
ictx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout");
|
||||
ictx->depth = Vulkan_CreateGraphicsPipeline (ctx, "iqm_depth");
|
||||
ictx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "iqm_gbuf");
|
||||
ictx->layout = Vulkan_CreatePipelineLayout (ctx, "iqm_layout");
|
||||
ictx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler");
|
||||
|
||||
ictx->bones_pool = Vulkan_CreateDescriptorPool (ctx, "bone_pool");
|
||||
ictx->bones_setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "bone_set");
|
||||
|
||||
for (size_t i = 0; i < frames; i++) {
|
||||
__auto_type aframe = &ictx->frames.a[i];
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/qf_alias.h"
|
||||
#include "QF/Vulkan/qf_bsp.h"
|
||||
//#include "QF/Vulkan/qf_iqm.h"
|
||||
#include "QF/Vulkan/qf_iqm.h"
|
||||
#include "QF/Vulkan/qf_lighting.h"
|
||||
#include "QF/Vulkan/qf_lightmap.h"
|
||||
#include "QF/Vulkan/qf_main.h"
|
||||
|
@ -95,7 +95,7 @@ Vulkan_RenderEntities (entqueue_t *queue, qfv_renderframe_t *rFrame)
|
|||
} while (0)
|
||||
|
||||
RE_LOOP (alias, Alias);
|
||||
//RE_LOOP (iqm, IQM);
|
||||
RE_LOOP (iqm, IQM);
|
||||
RE_LOOP (sprite, Sprite);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue