mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-31 05:00:35 +00:00
[vulkan] Implement sky box loading and rendering
Loading is broken for multi-file image sets due to the way images are loaded (this needs some thought for making it effecient), but the Blender environment map loading works.
This commit is contained in:
parent
c5c44da727
commit
999dd8248b
8 changed files with 342 additions and 136 deletions
|
@ -146,7 +146,8 @@ typedef struct bspctx_s {
|
|||
VkDeviceMemory texture_memory;
|
||||
VkPipeline depth;
|
||||
VkPipeline gbuf;
|
||||
VkPipeline sky;
|
||||
VkPipeline skysheet;
|
||||
VkPipeline skybox;
|
||||
VkPipeline turb;
|
||||
VkPipelineLayout layout;
|
||||
size_t vertex_buffer_size;
|
||||
|
@ -162,6 +163,7 @@ struct vulkan_ctx_s;
|
|||
void Vulkan_ClearElements (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_DrawWorld (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_DrawSky (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_LoadSkys (const char *sky, struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_RegisterTextures (model_t **models, int num_models,
|
||||
struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_BuildDisplayLists (model_t **models, int num_models,
|
||||
|
|
|
@ -15,6 +15,10 @@ void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette,
|
|||
int alpha, int count);
|
||||
qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip,
|
||||
const char *name);
|
||||
qfv_tex_t *Vulkan_LoadEnvMap (struct vulkan_ctx_s *ctx, tex_t *tex,
|
||||
const char *name);
|
||||
qfv_tex_t *Vulkan_LoadEnvSides (struct vulkan_ctx_s *ctx, tex_t **tex,
|
||||
const char *name);
|
||||
VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure));
|
||||
void Vulkan_UnloadTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex);
|
||||
void Vulkan_Texture_Init (struct vulkan_ctx_s *ctx);
|
||||
|
|
|
@ -223,6 +223,7 @@ vulkan_R_ClearState (void)
|
|||
static void
|
||||
vulkan_R_LoadSkys (const char *skyname)
|
||||
{
|
||||
Vulkan_LoadSkys (skyname, vulkan_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -652,6 +652,43 @@
|
|||
layout = quakebsp_layout;
|
||||
//renderPass = renderpass;
|
||||
};
|
||||
bsp_skybox = {
|
||||
subpass = 1;
|
||||
stages = (
|
||||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/quakebsp.vert;
|
||||
},
|
||||
{
|
||||
stage = fragment;
|
||||
name = main;
|
||||
module = $builtin/bsp_sky.frag;
|
||||
specializationInfo = {
|
||||
mapEntries = (
|
||||
{ size = 4; offset = 0; constantID = 1; },
|
||||
{ size = 4; offset = 4; constantID = 0; },
|
||||
);
|
||||
data = <00000000ffffffff>;
|
||||
};
|
||||
},
|
||||
);
|
||||
vertexInput = $properties.vertexInput.brush;
|
||||
inputAssembly = $properties.inputAssembly.brush;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.cw_cull_back;
|
||||
multisample = $properties.multisample;
|
||||
depthStencil = $properties.depthStencil.test_only;
|
||||
colorBlend = {
|
||||
logicOpEnable = false;
|
||||
attachments = ($properties.attachmentBlendOp.disabled);
|
||||
};
|
||||
dynamic = {
|
||||
dynamicState = ( viewport, scissor );
|
||||
};
|
||||
layout = quakebsp_layout;
|
||||
//renderPass = renderpass;
|
||||
};
|
||||
bsp_skysheet = {
|
||||
subpass = 1;
|
||||
stages = (
|
||||
|
|
|
@ -14,7 +14,7 @@ layout (location = 1) in vec3 direction;
|
|||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
|
||||
layout (constant_id = 0) const bool doSkyCube = false;
|
||||
layout (constant_id = 0) const bool doSkyBox = false;
|
||||
layout (constant_id = 1) const bool doSkySheet = false;
|
||||
|
||||
const float SCALE = 8.0;
|
||||
|
@ -55,12 +55,14 @@ sky_sheet (vec3 dir, float time)
|
|||
}
|
||||
|
||||
vec4
|
||||
sky_cube (vec3 dir, float time)
|
||||
sky_box (vec3 dir, float time)
|
||||
{
|
||||
// NOTE: quake's world is right-handed with Z up and X forward, but
|
||||
// Vulkan's cube maps are left-handed with Y up and Z forward. The
|
||||
// rotation to X foward is done by the Sky matrix so all that's left
|
||||
// to do here is swizzle the Y and Z coordinates
|
||||
dir = normalize(dir);
|
||||
//return vec4(dir.xyz, 1) * 0.5 + vec4(0.5);
|
||||
return texture (SkyCube, dir.xzy);
|
||||
}
|
||||
|
||||
|
@ -68,15 +70,14 @@ vec4
|
|||
sky_color (vec3 dir, float time)
|
||||
{
|
||||
if (!doSkySheet) {
|
||||
return vec4 (1, 0, 1, 1);
|
||||
//return sky_cube (dir, time);
|
||||
} if (!doSkyCube) {
|
||||
return sky_box (dir, time);
|
||||
} if (!doSkyBox) {
|
||||
return sky_sheet (dir, time);
|
||||
} else {
|
||||
// can see through the sheet (may look funny when looking down)
|
||||
// maybe have 4 sheet layers instead of 2?
|
||||
vec4 c1 = sky_sheet (dir, time);
|
||||
vec4 c2 = sky_cube (dir, time);
|
||||
vec4 c2 = sky_box (dir, time);
|
||||
return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a));
|
||||
return vec4 (1, 0, 1, 1);
|
||||
}
|
||||
|
@ -87,7 +88,7 @@ main (void)
|
|||
{
|
||||
vec4 c;
|
||||
|
||||
if (doSkyCube || doSkySheet) {
|
||||
if (doSkyBox || doSkySheet) {
|
||||
c = sky_color (direction, time);
|
||||
} else {
|
||||
c = vec4 (0, 0, 0, 1);
|
||||
|
|
|
@ -1054,7 +1054,11 @@ sky_begin (vulkan_ctx_t *ctx)
|
|||
bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex,
|
||||
bctx->default_skybox);
|
||||
|
||||
bsp_begin_subpass (QFV_bspSky, bctx->sky, ctx);
|
||||
if (bctx->skybox_tex) {
|
||||
bsp_begin_subpass (QFV_bspSky, bctx->skybox, ctx);
|
||||
} else {
|
||||
bsp_begin_subpass (QFV_bspSky, bctx->skysheet, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1370,7 +1374,7 @@ create_default_skys (vulkan_ctx_t *ctx)
|
|||
VK_FORMAT_B8G8R8A8_UNORM,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, boxview,
|
||||
"bsp:iview:default_skysheet");
|
||||
"bsp:iview:default_skybox");
|
||||
|
||||
sheetview = QFV_CreateImageView (device, skysheet,
|
||||
VK_IMAGE_VIEW_TYPE_2D_ARRAY,
|
||||
|
@ -1481,7 +1485,8 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
|
|||
|
||||
bctx->depth = Vulkan_CreatePipeline (ctx, "bsp_depth");
|
||||
bctx->gbuf = Vulkan_CreatePipeline (ctx, "bsp_gbuf");
|
||||
bctx->sky = Vulkan_CreatePipeline (ctx, "bsp_skysheet");
|
||||
bctx->skybox = Vulkan_CreatePipeline (ctx, "bsp_skybox");
|
||||
bctx->skysheet = Vulkan_CreatePipeline (ctx, "bsp_skysheet");
|
||||
bctx->turb = Vulkan_CreatePipeline (ctx, "bsp_turb");
|
||||
bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout");
|
||||
bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler");
|
||||
|
@ -1533,7 +1538,8 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx)
|
|||
|
||||
dfunc->vkDestroyPipeline (device->dev, bctx->depth, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, bctx->gbuf, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, bctx->skybox, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, bctx->skysheet, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, bctx->turb, 0);
|
||||
DARRAY_CLEAR (&bctx->texture_chains);
|
||||
DARRAY_CLEAR (&bctx->frames);
|
||||
|
@ -1548,6 +1554,10 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx)
|
|||
dfunc->vkFreeMemory (device->dev, bctx->index_memory, 0);
|
||||
}
|
||||
|
||||
if (bctx->skybox_tex) {
|
||||
Vulkan_UnloadTex (ctx, bctx->skybox_tex);
|
||||
}
|
||||
|
||||
dfunc->vkDestroyImageView (device->dev, bctx->default_skysheet->view, 0);
|
||||
dfunc->vkDestroyImage (device->dev, bctx->default_skysheet->image, 0);
|
||||
|
||||
|
@ -1590,103 +1600,61 @@ copy_sub_tex (tex_t *src, int x, int y, tex_t *dst)
|
|||
dstbytes);
|
||||
}*/
|
||||
|
||||
/*XXX void
|
||||
Vulkan_R_LoadSkys (const char *sky, vulkan_ctx_t *ctx)
|
||||
void
|
||||
Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx)
|
||||
{
|
||||
const char *name;
|
||||
bspctx_t *bctx = ctx->bsp_context;
|
||||
|
||||
const char *name;
|
||||
int i;
|
||||
tex_t *tex;
|
||||
// NOTE: quake's world and GL's world are rotated relative to each other
|
||||
// quake has x right, y in, z up. gl has x right, y up, z out
|
||||
// quake order: +x -x +z -z +y -y
|
||||
// gl order: +x -x +y -y +z -z
|
||||
// fizquake orger: -y +y +z -z +x -x
|
||||
// to get from quake order to fitzquake order, all that's needed is
|
||||
// a -90 degree rotation on the (quake) z-axis. This is taken care of in
|
||||
// the sky_matrix setup code.
|
||||
// However, from the player's perspective, skymaps have lf and rt
|
||||
// swapped, but everythink makes sense if looking at the cube from outside
|
||||
// along the positive y axis, with the front of the cube being the nearest
|
||||
// face. This matches nicely with Blender's default cube in front (num-1)
|
||||
// view.
|
||||
static const char *sky_suffix[] = { "ft", "bk", "up", "dn", "rt", "lf"};
|
||||
static int sky_coords[][2] = {
|
||||
{2, 0}, // front
|
||||
{0, 0}, // back
|
||||
{1, 1}, // up
|
||||
{0, 1}, // down
|
||||
{2, 1}, // left
|
||||
{1, 0}, // right
|
||||
};
|
||||
|
||||
if (!sky || !*sky)
|
||||
if (bctx->skybox_tex) {
|
||||
Vulkan_UnloadTex (ctx, bctx->skybox_tex);
|
||||
}
|
||||
bctx->skybox_tex = 0;
|
||||
|
||||
if (!sky || !*sky) {
|
||||
sky = r_skyname->string;
|
||||
}
|
||||
|
||||
if (!*sky || !strcasecmp (sky, "none")) {
|
||||
skybox_loaded = false;
|
||||
Sys_MaskPrintf (SYS_VULKAN, "Skybox unloaded\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!skybox_tex)
|
||||
qfeglGenTextures (1, &skybox_tex);
|
||||
|
||||
qfeglBindTexture (GL_TEXTURE_CUBE_MAP, skybox_tex);
|
||||
|
||||
//blender envmap
|
||||
// bk rt ft
|
||||
// dn up lt
|
||||
tex = LoadImage (name = va ("env/%s_map", sky));
|
||||
if (tex && tex->format >= 3 && tex->height * 3 == tex->width * 2
|
||||
&& is_pow2 (tex->height)) {
|
||||
tex_t *sub;
|
||||
int size = tex->height / 2;
|
||||
|
||||
skybox_loaded = true;
|
||||
sub = malloc (field_offset (tex_t, data[size * size * tex->format]));
|
||||
sub->width = size;
|
||||
sub->height = size;
|
||||
sub->format = tex->format;
|
||||
sub->palette = tex->palette;
|
||||
for (i = 0; i < 6; i++) {
|
||||
int x, y;
|
||||
x = sky_coords[i][0] * size;
|
||||
y = sky_coords[i][1] * size;
|
||||
copy_sub_tex (tex, x, y, sub);
|
||||
qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,
|
||||
sub->format == 3 ? GL_RGB : GL_RGBA,
|
||||
sub->width, sub->height, 0,
|
||||
sub->format == 3 ? GL_RGB : GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, sub->data);
|
||||
}
|
||||
free (sub);
|
||||
name = va (ctx->va_ctx, "env/%s_map", sky);
|
||||
tex = LoadImage (name, 1);
|
||||
if (tex) {
|
||||
bctx->skybox_tex = Vulkan_LoadEnvMap (ctx, tex, sky);
|
||||
Sys_MaskPrintf (SYS_VULKAN, "Loaded %s\n", name);
|
||||
} else {
|
||||
skybox_loaded = true;
|
||||
int failed = 0;
|
||||
tex_t *sides[6] = { };
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
tex = LoadImage (name = va ("env/%s%s", sky, sky_suffix[i]));
|
||||
if (!tex || tex->format < 3) { // FIXME pcx support
|
||||
Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name);
|
||||
name = va (ctx->va_ctx, "env/%s%s", sky, sky_suffix[i]);
|
||||
tex = LoadImage (name, 1);
|
||||
if (!tex) {
|
||||
Sys_MaskPrintf (SYS_VULKAN, "Couldn't load %s\n", name);
|
||||
// also look in gfx/env, where Darkplaces looks for skies
|
||||
tex = LoadImage (name = va ("gfx/env/%s%s", sky,
|
||||
sky_suffix[i]));
|
||||
if (!tex || tex->format < 3) { // FIXME pcx support
|
||||
Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name);
|
||||
skybox_loaded = false;
|
||||
name = va (ctx->va_ctx, "gfx/env/%s%s", sky, sky_suffix[i]);
|
||||
tex = LoadImage (name, 1);
|
||||
if (!tex) {
|
||||
Sys_MaskPrintf (SYS_VULKAN, "Couldn't load %s\n", name);
|
||||
failed = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Sys_MaskPrintf (SYS_GLSL, "Loaded %s\n", name);
|
||||
qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,
|
||||
tex->format == 3 ? GL_RGB : GL_RGBA,
|
||||
tex->width, tex->height, 0,
|
||||
tex->format == 3 ? GL_RGB : GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, tex->data);
|
||||
sides[i] = tex;
|
||||
Sys_MaskPrintf (SYS_VULKAN, "Loaded %s\n", name);
|
||||
}
|
||||
if (!failed) {
|
||||
bctx->skybox_tex = Vulkan_LoadEnvSides (ctx, sides, sky);
|
||||
}
|
||||
}
|
||||
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
qfeglGenerateMipmap (GL_TEXTURE_CUBE_MAP);
|
||||
}*/
|
||||
if (bctx->skybox_tex) {
|
||||
Sys_MaskPrintf (SYS_VULKAN, "Skybox %s loaded\n", sky);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,45 +96,76 @@ Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette,
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
tex_format (const tex_t *tex, VkFormat *format, int *bpp)
|
||||
{
|
||||
switch (tex->format) {
|
||||
case tex_l:
|
||||
case tex_a:
|
||||
*format = VK_FORMAT_R8_UNORM;
|
||||
*bpp = 1;
|
||||
return 1;
|
||||
case tex_la:
|
||||
*format = VK_FORMAT_R8G8_UNORM;
|
||||
*bpp = 2;
|
||||
return 1;
|
||||
case tex_palette:
|
||||
if (!tex->palette) {
|
||||
return 0;
|
||||
}
|
||||
*format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
*bpp = 4;
|
||||
return 1;
|
||||
case tex_rgb:
|
||||
*format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
*bpp = 4;
|
||||
return 1;
|
||||
case tex_rgba:
|
||||
*format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
*bpp = 4;
|
||||
return 1;
|
||||
case tex_frgba:
|
||||
*format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
*bpp = 16;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
stage_tex_data (qfv_packet_t *packet, tex_t *tex, int bpp)
|
||||
{
|
||||
size_t texels = tex->width * tex->height;
|
||||
byte *tex_data = QFV_PacketExtend (packet, bpp * texels);
|
||||
|
||||
if (tex->format == tex_palette) {
|
||||
Vulkan_ExpandPalette (tex_data, tex->data, tex->palette, 1, texels);
|
||||
} else {
|
||||
if (tex->format == 3) {
|
||||
byte *in = tex->data;
|
||||
byte *out = tex_data;
|
||||
while (texels-- > 0) {
|
||||
*out++ = *in++;
|
||||
*out++ = *in++;
|
||||
*out++ = *in++;
|
||||
*out++ = 255;
|
||||
}
|
||||
} else {
|
||||
memcpy (tex_data, tex->data, bpp * texels);
|
||||
}
|
||||
}
|
||||
return tex_data - (byte *) packet->stage->data;
|
||||
}
|
||||
|
||||
qfv_tex_t *
|
||||
Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
int bpp = 0;
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
int bpp;
|
||||
VkFormat format;
|
||||
|
||||
switch (tex->format) {
|
||||
case tex_l:
|
||||
case tex_a:
|
||||
format = VK_FORMAT_R8_UNORM;
|
||||
bpp = 1;
|
||||
break;
|
||||
case tex_la:
|
||||
format = VK_FORMAT_R8G8_UNORM;
|
||||
bpp = 2;
|
||||
break;
|
||||
case tex_palette:
|
||||
if (!tex->palette) {
|
||||
return 0;
|
||||
}
|
||||
format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
bpp = 4;
|
||||
break;
|
||||
case tex_rgb:
|
||||
format = VK_FORMAT_R8G8B8_UNORM;
|
||||
bpp = 3;
|
||||
break;
|
||||
case tex_rgba:
|
||||
format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
bpp = 4;
|
||||
break;
|
||||
case tex_frgba:
|
||||
format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
bpp = 16;
|
||||
break;
|
||||
}
|
||||
if (format == VK_FORMAT_UNDEFINED) {
|
||||
if (!tex_format (tex, &format, &bpp)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -169,16 +200,8 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name)
|
|||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, qtex->view,
|
||||
va (ctx->va_ctx, "iview:%s", name));
|
||||
|
||||
size_t bytes = bpp * tex->width * tex->height;
|
||||
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
|
||||
byte *tex_data = QFV_PacketExtend (packet, bytes);
|
||||
|
||||
if (tex->format == tex_palette) {
|
||||
Vulkan_ExpandPalette (tex_data, tex->data, tex->palette,
|
||||
1, tex->width * tex->height);
|
||||
} else {
|
||||
memcpy (tex_data, tex->data, bytes);
|
||||
}
|
||||
stage_tex_data (packet, tex, bpp);
|
||||
|
||||
VkImageMemoryBarrier barrier;
|
||||
qfv_pipelinestagepair_t stages;
|
||||
|
@ -214,6 +237,176 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name)
|
|||
return qtex;
|
||||
}
|
||||
|
||||
static qfv_tex_t *
|
||||
create_cubetex (vulkan_ctx_t *ctx, int size, VkFormat format,
|
||||
const char *name)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
|
||||
qfv_tex_t *qtex = malloc (sizeof (qfv_tex_t));
|
||||
|
||||
VkExtent3D extent = { size, size, 1 };
|
||||
qtex->image = QFV_CreateImage (device, 1, VK_IMAGE_TYPE_2D, format, extent,
|
||||
1, 1, VK_SAMPLE_COUNT_1_BIT,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT
|
||||
| VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, qtex->image,
|
||||
va (ctx->va_ctx, "image:envmap:%s", name));
|
||||
qtex->memory = QFV_AllocImageMemory (device, qtex->image,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
0, 0);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, qtex->memory,
|
||||
va (ctx->va_ctx, "memory:%s", name));
|
||||
QFV_BindImageMemory (device, qtex->image, qtex->memory, 0);
|
||||
qtex->view = QFV_CreateImageView (device, qtex->image,
|
||||
VK_IMAGE_VIEW_TYPE_CUBE, format,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, qtex->view,
|
||||
va (ctx->va_ctx, "iview:envmap:%s", name));
|
||||
|
||||
return qtex;
|
||||
}
|
||||
|
||||
qfv_tex_t *
|
||||
Vulkan_LoadEnvMap (vulkan_ctx_t *ctx, tex_t *tex, const char *name)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
int bpp;
|
||||
VkFormat format;
|
||||
|
||||
static int env_coords[][2] = {
|
||||
{2, 0}, // right
|
||||
{0, 0}, // left
|
||||
{1, 1}, // top
|
||||
{0, 1}, // bottom
|
||||
{2, 1}, // front
|
||||
{1, 0}, // back
|
||||
};
|
||||
|
||||
if (!tex_format (tex, &format, &bpp)) {
|
||||
return 0;
|
||||
}
|
||||
if (tex->height * 3 != tex->width * 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int size = tex->height / 2;
|
||||
qfv_tex_t *qtex = create_cubetex (ctx, size, format, name);
|
||||
|
||||
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
|
||||
stage_tex_data (packet, tex, bpp);
|
||||
|
||||
VkImageMemoryBarrier barrier;
|
||||
qfv_pipelinestagepair_t stages;
|
||||
|
||||
stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst];
|
||||
barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst];
|
||||
barrier.image = qtex->image;
|
||||
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst,
|
||||
0, 0, 0, 0, 0,
|
||||
1, &barrier);
|
||||
|
||||
VkBufferImageCopy copy[6] = {
|
||||
{
|
||||
0, tex->width, 0,
|
||||
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
|
||||
{0, 0, 0}, {size, size, 1},
|
||||
},
|
||||
};
|
||||
for (int i = 0; i < 6; i++) {
|
||||
int x = env_coords[i][0] * size;
|
||||
int y = env_coords[i][1] * size;
|
||||
int offset = x + y * tex->width;
|
||||
copy[i] = copy[0];
|
||||
copy[i].bufferOffset = packet->offset + bpp * offset;
|
||||
copy[i].imageSubresource.baseArrayLayer = i;
|
||||
}
|
||||
dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer,
|
||||
qtex->image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
6, copy);
|
||||
stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly];
|
||||
barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly];
|
||||
barrier.image = qtex->image;
|
||||
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst,
|
||||
0, 0, 0, 0, 0,
|
||||
1, &barrier);
|
||||
QFV_PacketSubmit (packet);
|
||||
return qtex;
|
||||
}
|
||||
|
||||
qfv_tex_t *
|
||||
Vulkan_LoadEnvSides (vulkan_ctx_t *ctx, tex_t **tex, const char *name)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
int bpp;
|
||||
VkFormat format;
|
||||
|
||||
if (!tex_format (tex[0], &format, &bpp)) {
|
||||
return 0;
|
||||
}
|
||||
if (tex[0]->height != tex[0]->width) {
|
||||
return 0;
|
||||
}
|
||||
for (int i = 1; i < 6; i++) {
|
||||
if (tex[i]->format != tex[0]->format
|
||||
|| tex[i]->width != tex[0]->width
|
||||
|| tex[i]->height != tex[0]->height) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int size = tex[0]->height;
|
||||
qfv_tex_t *qtex = create_cubetex (ctx, size, format, name);
|
||||
|
||||
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
|
||||
|
||||
VkImageMemoryBarrier barrier;
|
||||
qfv_pipelinestagepair_t stages;
|
||||
|
||||
stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst];
|
||||
barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst];
|
||||
barrier.image = qtex->image;
|
||||
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst,
|
||||
0, 0, 0, 0, 0,
|
||||
1, &barrier);
|
||||
|
||||
VkBufferImageCopy copy[6] = {
|
||||
{
|
||||
0, 0, 0,
|
||||
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
|
||||
{0, 0, 0}, {size, size, 1},
|
||||
},
|
||||
};
|
||||
for (int i = 0; i < 6; i++) {
|
||||
copy[i] = copy[0];
|
||||
copy[i].bufferOffset = stage_tex_data (packet, tex[i], bpp);
|
||||
copy[i].imageSubresource.baseArrayLayer = i;
|
||||
}
|
||||
dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer,
|
||||
qtex->image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
6, copy);
|
||||
stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly];
|
||||
barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly];
|
||||
barrier.image = qtex->image;
|
||||
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst,
|
||||
0, 0, 0, 0, 0,
|
||||
1, &barrier);
|
||||
QFV_PacketSubmit (packet);
|
||||
return qtex;
|
||||
}
|
||||
|
||||
VkImageView
|
||||
Vulkan_TexImageView (qfv_tex_t *tex)
|
||||
{
|
||||
|
|
|
@ -237,7 +237,7 @@ void
|
|||
Vulkan_CreateStagingBuffers (vulkan_ctx_t *ctx)
|
||||
{
|
||||
ctx->staging = QFV_CreateStagingBuffer (ctx->device, "vulkan_ctx",
|
||||
4*1024*1024, ctx->cmdpool);
|
||||
16*1024*1024, ctx->cmdpool);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue