add cubemap support; add misaligned skybox
This commit is contained in:
parent
714d825956
commit
1ad13817fe
|
@ -5,8 +5,9 @@
|
|||
#include "ray_common.glsl"
|
||||
#include "ray_kusochki.glsl"
|
||||
|
||||
layout (constant_id = 6) const uint MAX_TEXTURES = 4096;
|
||||
layout (set = 0, binding = 6) uniform sampler2D textures[MAX_TEXTURES];
|
||||
//layout (constant_id = 6) const uint MAX_TEXTURES = 4096;
|
||||
//layout (set = 0, binding = 6) uniform sampler2D textures[MAX_TEXTURES];
|
||||
layout (set = 0, binding = 13) uniform samplerCube skybox;
|
||||
layout (set = 0, binding = 7/*, align=4*/) uniform UBOLights { Lights lights; };
|
||||
|
||||
layout(location = PAYLOAD_LOCATION_OPAQUE) rayPayloadInEXT RayPayloadOpaque payload;
|
||||
|
@ -19,9 +20,5 @@ void main() {
|
|||
payload.base_color = vec3(1., 0., 1.);
|
||||
payload.kusok_index = -1;
|
||||
payload.material_index = 0;
|
||||
payload.emissive = vec3(1., 0., 1.);
|
||||
|
||||
const uint tex_skyplane = lights.skybox_up;
|
||||
const vec2 sky_uv = gl_WorldRayDirectionEXT.xy * .5 + .5;
|
||||
payload.emissive = texture(textures[nonuniformEXT(tex_skyplane)], sky_uv).rgb;
|
||||
payload.emissive = texture(skybox, gl_WorldRayDirectionEXT).rgb;
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ struct EmissiveKusok {
|
|||
struct Lights {
|
||||
uint num_kusochki;
|
||||
uint num_point_lights;
|
||||
uint skybox_rt, skybox_bk, skybox_lf, skybox_ft, skybox_up, skybox_dn;
|
||||
PAD(2)
|
||||
STRUCT EmissiveKusok kusochki[MAX_EMISSIVE_KUSOCHKI];
|
||||
STRUCT PointLight point_lights[MAX_POINT_LIGHTS];
|
||||
};
|
||||
|
|
|
@ -12,13 +12,14 @@ xvk_image_t XVK_ImageCreate(const xvk_image_create_t *create) {
|
|||
.extent.height = create->height,
|
||||
.extent.depth = 1,
|
||||
.mipLevels = create->mips,
|
||||
.arrayLayers = 1,
|
||||
.arrayLayers = create->layers,
|
||||
.format = create->format,
|
||||
.tiling = create->tiling,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.usage = create->usage,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.flags = create->is_cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0,
|
||||
};
|
||||
|
||||
XVK_CHECK(vkCreateImage(vk_core.device, &ici, NULL, &image.image));
|
||||
|
@ -30,14 +31,14 @@ xvk_image_t XVK_ImageCreate(const xvk_image_create_t *create) {
|
|||
image.devmem = allocateDeviceMemory(memreq, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0);
|
||||
XVK_CHECK(vkBindImageMemory(vk_core.device, image.image, image.devmem.device_memory, 0));
|
||||
|
||||
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
ivci.viewType = create->is_cubemap ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D;
|
||||
ivci.format = ici.format;
|
||||
ivci.image = image.image;
|
||||
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
ivci.subresourceRange.baseMipLevel = 0;
|
||||
ivci.subresourceRange.levelCount = ici.mipLevels;
|
||||
ivci.subresourceRange.baseArrayLayer = 0;
|
||||
ivci.subresourceRange.layerCount = 1;
|
||||
ivci.subresourceRange.layerCount = ici.arrayLayers;
|
||||
ivci.components = (VkComponentMapping){0, 0, 0, create->has_alpha ? 0 : VK_COMPONENT_SWIZZLE_ONE};
|
||||
XVK_CHECK(vkCreateImageView(vk_core.device, &ivci, NULL, &image.view));
|
||||
|
||||
|
|
|
@ -15,11 +15,12 @@ typedef struct {
|
|||
typedef struct {
|
||||
const char *debug_name;
|
||||
uint32_t width, height;
|
||||
int mips, layers;
|
||||
VkFormat format;
|
||||
VkImageTiling tiling;
|
||||
VkImageUsageFlags usage;
|
||||
int mips;
|
||||
qboolean has_alpha;
|
||||
qboolean is_cubemap;
|
||||
} xvk_image_create_t;
|
||||
|
||||
xvk_image_t XVK_ImageCreate(const xvk_image_create_t *create);
|
||||
|
|
|
@ -76,6 +76,8 @@ enum {
|
|||
RayDescBinding_Dest_ImageAdditive = 11,
|
||||
RayDescBinding_Dest_ImageNormals = 12,
|
||||
|
||||
RayDescBinding_SkyboxCube = 13,
|
||||
|
||||
RayDescBinding_COUNT
|
||||
};
|
||||
|
||||
|
@ -613,6 +615,12 @@ static void updateDescriptors( VkCommandBuffer cmdbuf, const vk_ray_frame_render
|
|||
|
||||
g_rtx.desc_values[RayDescBinding_Textures].image_array = dii_all_textures;
|
||||
|
||||
g_rtx.desc_values[RayDescBinding_SkyboxCube].image = (VkDescriptorImageInfo){
|
||||
.sampler = vk_core.default_sampler,
|
||||
.imageView = tglob.skybox_cube.vk.image.view ? tglob.skybox_cube.vk.image.view : tglob.cubemap_placeholder.vk.image.view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
|
||||
// TODO: move this to vk_texture.c
|
||||
for (int i = 0; i < MAX_TEXTURES; ++i) {
|
||||
const vk_texture_t *texture = findTexture(i);
|
||||
|
@ -793,13 +801,6 @@ static void updateLights( void )
|
|||
|
||||
dst->environment = !!(src->flags & LightFlag_Environment);
|
||||
}
|
||||
|
||||
lights->skybox_rt = tglob.skyboxTextures[0];
|
||||
lights->skybox_bk = tglob.skyboxTextures[1];
|
||||
lights->skybox_lf = tglob.skyboxTextures[2];
|
||||
lights->skybox_ft = tglob.skyboxTextures[3];
|
||||
lights->skybox_up = tglob.skyboxTextures[4];
|
||||
lights->skybox_dn = tglob.skyboxTextures[5];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1148,6 +1149,16 @@ static void createLayouts( void ) {
|
|||
.pImmutableSamplers = NULL, //samplers,
|
||||
};
|
||||
|
||||
g_rtx.desc_bindings[RayDescBinding_SkyboxCube] = (VkDescriptorSetLayoutBinding){
|
||||
.binding = RayDescBinding_SkyboxCube,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR,
|
||||
// FIXME on AMD using immutable samplers leads to nearest filtering ???!
|
||||
.pImmutableSamplers = NULL, //samplers,
|
||||
};
|
||||
|
||||
|
||||
// for (int i = 0; i < ARRAYSIZE(samplers); ++i)
|
||||
// samplers[i] = vk_core.default_sampler;
|
||||
|
||||
|
@ -1256,10 +1267,12 @@ qboolean VK_RayInit( void )
|
|||
.width = FRAME_WIDTH, \
|
||||
.height = FRAME_HEIGHT, \
|
||||
.mips = 1, \
|
||||
.layers = 1, \
|
||||
.format = format_, \
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL, \
|
||||
.usage = VK_IMAGE_USAGE_STORAGE_BIT | add_usage_bits, \
|
||||
.has_alpha = true, \
|
||||
.is_cubemap = false, \
|
||||
}; \
|
||||
Q_snprintf(debug_name, sizeof(debug_name), "rtx frames[%d] " # name, i); \
|
||||
g_rtx.frames[i].name = XVK_ImageCreate(&create); \
|
||||
|
|
|
@ -230,6 +230,8 @@ static void VK_ProcessImage( vk_texture_t *tex, rgbdata_t *pic )
|
|||
}
|
||||
}
|
||||
|
||||
static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap);
|
||||
|
||||
static void VK_CreateInternalTextures( void )
|
||||
{
|
||||
int dx2, dy, d;
|
||||
|
@ -290,6 +292,22 @@ static void VK_CreateInternalTextures( void )
|
|||
// cinematic dummy
|
||||
pic = Common_FakeImage( 640, 100, 1, IMAGE_HAS_COLOR );
|
||||
tglob.cinTexture = VK_LoadTextureInternal( "*cintexture", pic, TF_NOMIPMAP|TF_CLAMP );
|
||||
|
||||
{
|
||||
rgbdata_t *sides[6];
|
||||
pic = Common_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR );
|
||||
for( x = 0; x < 16; x++ )
|
||||
((uint *)pic->buffer)[x] = 0xFFFFFFFF;
|
||||
|
||||
sides[0] = pic;
|
||||
sides[1] = pic;
|
||||
sides[2] = pic;
|
||||
sides[3] = pic;
|
||||
sides[4] = pic;
|
||||
sides[5] = pic;
|
||||
|
||||
uploadTexture( &tglob.cubemap_placeholder, sides, 6, true );
|
||||
}
|
||||
}
|
||||
|
||||
static VkFormat VK_GetFormat(pixformat_t format)
|
||||
|
@ -445,45 +463,67 @@ static void BuildMipMap( byte *in, int srcWidth, int srcHeight, int srcDepth, in
|
|||
}
|
||||
}
|
||||
|
||||
static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *pic) {
|
||||
const VkFormat format = VK_GetFormat(pic->type);
|
||||
const VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
const VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
byte *buf = pic->buffer;
|
||||
|
||||
static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *const *const layers, int num_layers, qboolean cubemap) {
|
||||
const VkFormat format = VK_GetFormat(layers[0]->type);
|
||||
int mipCount = 0;
|
||||
|
||||
// TODO non-rbga textures
|
||||
// TODO cubemaps
|
||||
|
||||
if (!pic->buffer)
|
||||
return false;
|
||||
for (int i = 0; i < num_layers; ++i) {
|
||||
if (!layers[i]->buffer) {
|
||||
gEngine.Con_Printf(S_ERROR "Texture %s layer %d missing buffer\n", tex->name, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
tex->width = pic->width;
|
||||
tex->height = pic->height;
|
||||
mipCount = CalcMipmapCount( tex, ( buf != NULL ));
|
||||
if (i == 0)
|
||||
continue;
|
||||
|
||||
gEngine.Con_Reportf("Uploading texture %s, mips=%d\n", tex->name, mipCount);
|
||||
if (layers[0]->type != layers[i]->type) {
|
||||
gEngine.Con_Printf(S_ERROR "Texture %s layer %d has type %d inconsistent with layer 0 type %d\n", tex->name, i, layers[i]->type, layers[0]->type);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (layers[0]->width != layers[i]->width || layers[0]->height != layers[i]->height) {
|
||||
gEngine.Con_Printf(S_ERROR "Texture %s layer %d has resolution %dx%d inconsistent with layer 0 resolution %dx%d\n",
|
||||
tex->name, i, layers[i]->width, layers[i]->height, layers[0]->width, layers[0]->height);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((layers[0]->flags ^ layers[i]->flags) & IMAGE_HAS_ALPHA) {
|
||||
gEngine.Con_Printf(S_ERROR "Texture %s layer %d has_alpha=%d inconsistent with layer 0 has_alpha=%d\n",
|
||||
tex->name, i,
|
||||
!!(layers[i]->flags & IMAGE_HAS_ALPHA),
|
||||
!!(layers[0]->flags & IMAGE_HAS_ALPHA));
|
||||
}
|
||||
}
|
||||
|
||||
tex->width = layers[0]->width;
|
||||
tex->height = layers[0]->height;
|
||||
mipCount = CalcMipmapCount( tex, true);
|
||||
|
||||
gEngine.Con_Reportf("Uploading texture %s, mips=%d, layers=%d\n", tex->name, mipCount, layers);
|
||||
|
||||
// TODO this vvv
|
||||
// // NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides
|
||||
// if(( tex->depth == 1 ) && (( pic->width != tex->width ) || ( pic->height != tex->height )))
|
||||
// data = GL_ResampleTexture( buf, pic->width, pic->height, tex->width, tex->height, normalMap );
|
||||
// if(( tex->depth == 1 ) && (( layers->width != tex->width ) || ( layers->height != tex->height )))
|
||||
// data = GL_ResampleTexture( buf, layers->width, layers->height, tex->width, tex->height, normalMap );
|
||||
// else data = buf;
|
||||
|
||||
// if( !ImageDXT( pic->type ) && !FBitSet( tex->flags, TF_NOMIPMAP ) && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA ))
|
||||
// if( !ImageDXT( layers->type ) && !FBitSet( tex->flags, TF_NOMIPMAP ) && FBitSet( layers->flags, IMAGE_ONEBIT_ALPHA ))
|
||||
// data = GL_ApplyFilter( data, tex->width, tex->height );
|
||||
|
||||
{
|
||||
const xvk_image_create_t create = {
|
||||
.debug_name = tex->name,
|
||||
.width = pic->width,
|
||||
.height = pic->height,
|
||||
.width = tex->width,
|
||||
.height = tex->height,
|
||||
.mips = mipCount,
|
||||
.layers = num_layers,
|
||||
.format = format,
|
||||
.tiling = tiling,
|
||||
.usage = usage,
|
||||
.has_alpha = pic->flags & IMAGE_HAS_ALPHA,
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||
.has_alpha = layers[0]->flags & IMAGE_HAS_ALPHA,
|
||||
.is_cubemap = cubemap,
|
||||
};
|
||||
tex->vk.image = XVK_ImageCreate(&create);
|
||||
}
|
||||
|
@ -511,7 +551,7 @@ static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *pic) {
|
|||
.baseMipLevel = 0,
|
||||
.levelCount = mipCount,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
.layerCount = num_layers,
|
||||
}};
|
||||
|
||||
XVK_CHECK(vkBeginCommandBuffer(vk_core.cb_tex, &beginfo));
|
||||
|
@ -521,9 +561,10 @@ static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *pic) {
|
|||
0, 0, NULL, 0, NULL, 1, &image_barrier);
|
||||
|
||||
// 5.1.2 copyBufferToImage for all mip levels
|
||||
{
|
||||
for (int mip = 0; mip < mipCount; ++mip)
|
||||
{
|
||||
for (int layer = 0; layer < num_layers; ++layer) {
|
||||
for (int mip = 0; mip < mipCount; ++mip) {
|
||||
const rgbdata_t *const pic = layers[layer];
|
||||
byte *buf = pic->buffer;
|
||||
const int width = Q_max( 1, ( pic->width >> mip ));
|
||||
const int height = Q_max( 1, ( pic->height >> mip ));
|
||||
const size_t mip_size = CalcImageSize( pic->type, width, height, 1 );
|
||||
|
@ -535,7 +576,7 @@ static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *pic) {
|
|||
region.imageSubresource = (VkImageSubresourceLayers){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = mip,
|
||||
.baseArrayLayer = 0,
|
||||
.baseArrayLayer = layer,
|
||||
.layerCount = 1,
|
||||
};
|
||||
region.imageExtent = (VkExtent3D){
|
||||
|
@ -569,7 +610,7 @@ static qboolean uploadTexture(vk_texture_t *tex, rgbdata_t *pic) {
|
|||
.baseMipLevel = 0,
|
||||
.levelCount = mipCount,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
.layerCount = num_layers,
|
||||
};
|
||||
vkCmdPipelineBarrier(vk_core.cb_tex,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
|
@ -676,7 +717,7 @@ int VK_LoadTexture( const char *name, const byte *buf, size_t size, int flags )
|
|||
// upload texture
|
||||
VK_ProcessImage( tex, pic );
|
||||
|
||||
if( !uploadTexture( tex, pic ))
|
||||
if( !uploadTexture( tex, &pic, 1, false ))
|
||||
{
|
||||
memset( tex, 0, sizeof( vk_texture_t ));
|
||||
gEngine.FS_FreeImage( pic ); // release source texture
|
||||
|
@ -788,7 +829,7 @@ int VK_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags
|
|||
|
||||
VK_ProcessImage( tex, pic );
|
||||
|
||||
if( !uploadTexture( tex, pic ))
|
||||
if( !uploadTexture( tex, &pic, 1, false ))
|
||||
{
|
||||
memset( tex, 0, sizeof( vk_texture_t ));
|
||||
return 0;
|
||||
|
@ -814,20 +855,12 @@ int XVK_TextureLookupF( const char *fmt, ...) {
|
|||
return tex_id;
|
||||
}
|
||||
|
||||
static void unloadSkybox( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
// release old skybox
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
if( !tglob.skyboxTextures[i] ) continue;
|
||||
VK_FreeTexture( tglob.skyboxTextures[i] );
|
||||
static void unloadSkybox( void ) {
|
||||
if (tglob.skybox_cube.vk.image.image) {
|
||||
XVK_ImageDestroy(&tglob.skybox_cube.vk.image);
|
||||
memset(&tglob.skybox_cube, 0, sizeof(tglob.skybox_cube));
|
||||
}
|
||||
|
||||
tglob.skyboxbasenum = 5800; // set skybox base (to let some mods load hi-res skyboxes)
|
||||
|
||||
memset( tglob.skyboxTextures, 0, sizeof( tglob.skyboxTextures ));
|
||||
tglob.fCustomSkybox = false;
|
||||
}
|
||||
|
||||
|
@ -880,6 +913,7 @@ void XVK_SetupSky( const char *skyboxname )
|
|||
char loadname[MAX_STRING];
|
||||
char sidename[MAX_STRING];
|
||||
int i, result, len;
|
||||
rgbdata_t *sides[6];
|
||||
|
||||
if( !COM_CheckString( skyboxname ))
|
||||
{
|
||||
|
@ -915,18 +949,30 @@ void XVK_SetupSky( const char *skyboxname )
|
|||
Q_snprintf( sidename, sizeof( sidename ), "%s%s", loadname, r_skyBoxSuffix[i] );
|
||||
else Q_snprintf( sidename, sizeof( sidename ), "%s_%s", loadname, r_skyBoxSuffix[i] );
|
||||
|
||||
tglob.skyboxTextures[i] = VK_LoadTexture( sidename, NULL, 0, TF_CLAMP|TF_SKY );
|
||||
if( !tglob.skyboxTextures[i] ) break;
|
||||
sides[i] = gEngine.FS_LoadImage( sidename, NULL, 0);
|
||||
if (!sides[i])
|
||||
break;
|
||||
|
||||
gEngine.Con_DPrintf( "%s%s%s", skyboxname, r_skyBoxSuffix[i], i != 5 ? ", " : ". " );
|
||||
}
|
||||
|
||||
if( i == 6 )
|
||||
{
|
||||
for (int j = 0; j < i; ++j)
|
||||
gEngine.FS_FreeImage( sides[j] ); // release source texture
|
||||
|
||||
if( i != 6 )
|
||||
goto fail;
|
||||
|
||||
if( !Common_CheckTexName( loadname ))
|
||||
goto fail;
|
||||
|
||||
// needed? VK_ProcessImage( tex, pic );
|
||||
if (uploadTexture(&tglob.skybox_cube, sides, 6, true)) {
|
||||
tglob.fCustomSkybox = true;
|
||||
gEngine.Con_DPrintf( "done\n" );
|
||||
return; // loaded
|
||||
}
|
||||
|
||||
fail:
|
||||
gEngine.Con_DPrintf( "^2failed\n" );
|
||||
unloadSkybox();
|
||||
}
|
||||
|
|
|
@ -36,13 +36,15 @@ typedef struct vk_textures_global_s
|
|||
int alphaskyTexture; // quake1 alpha-sky layer
|
||||
int lightmapTextures[MAX_LIGHTMAPS];
|
||||
int dlightTexture; // custom dlight texture
|
||||
int skyboxTextures[6]; // skybox sides
|
||||
int cinTexture; // cinematic texture
|
||||
|
||||
int skytexturenum; // this not a gl_texturenum!
|
||||
int skyboxbasenum; // start with 5800 FIXME remove this, lewa says this is a GL1 hack
|
||||
|
||||
qboolean fCustomSkybox; // TODO do we need this for anything?
|
||||
|
||||
vk_texture_t skybox_cube;
|
||||
vk_texture_t cubemap_placeholder;
|
||||
} vk_textures_global_t;
|
||||
|
||||
// TODO rename this consistently
|
||||
|
|
Loading…
Reference in New Issue