Merge branch 'wip-rua_scene'

This commit is contained in:
Bill Currie 2022-05-06 08:34:31 +09:00
commit 5b103f2570
146 changed files with 4234 additions and 1711 deletions

View file

@ -2133,7 +2133,8 @@ SEARCH_INCLUDES = YES
INCLUDE_PATH = @TOPSRC@/include \
@TOPSRC@/nq/include \
@TOPSRC@/qw/include \
@TOPSRC@/qtv/include
@TOPSRC@/qtv/include \
@TOPSRC@
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
@ -2152,6 +2153,7 @@ INCLUDE_FILE_PATTERNS = *.h
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = "__attribute__(x)=" \
IN_DOXYGEN=1 \
VISIBLE=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this

View file

@ -45,8 +45,8 @@ void gl_R_RotateForEntity (struct entity_s *e);
struct model_s;
struct entqueue_s;
void gl_R_NewMap (struct model_s *worldmodel, struct model_s **models,
int num_models);
struct scene_s;
void gl_R_NewScene (struct scene_s *scene);
void gl_R_RenderView (void);
void gl_R_RenderEntities (struct entqueue_s *queue);
void gl_R_ClearState (void);

View file

@ -29,8 +29,9 @@
#define __QF_GLSL_qf_main_h
struct entqueue_s;
struct scene_s;
void glsl_R_NewMap (model_t *worldmodel, model_t **models, int num_models);
void glsl_R_NewScene (struct scene_s *scene);
void glsl_R_RenderEntities (struct entqueue_s *queue);
void glsl_R_RenderView (void);
void glsl_R_ClearState (void);

View file

@ -149,6 +149,7 @@ include_qf_scene = \
include/QF/scene/camera.h \
include/QF/scene/entity.h \
include/QF/scene/hierarchy.h \
include/QF/scene/light.h \
include/QF/scene/transform.h \
include/QF/scene/scene.h \
include/QF/scene/types.h
@ -178,7 +179,6 @@ include_qf_vulkan = \
include/QF/Vulkan/debug.h \
include/QF/Vulkan/descriptor.h \
include/QF/Vulkan/device.h \
include/QF/Vulkan/draw.h \
include/QF/Vulkan/funclist.h \
include/QF/Vulkan/image.h \
include/QF/Vulkan/instance.h \

View file

@ -1,6 +1,11 @@
#ifndef __QF_Vulkan_barrier_h
#define __QF_Vulkan_barrier_h
#ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES
#endif
#include <vulkan/vulkan.h>
typedef struct {
VkPipelineStageFlags srcStages;
VkPipelineStageFlags dstStages;

View file

@ -1,6 +1,11 @@
#ifndef __QF_Vulkan_buffer_h
#define __QF_Vulkan_buffer_h
#ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES
#endif
#include <vulkan/vulkan.h>
#include "QF/darray.h"
typedef struct qfv_buffertransition_s {

View file

@ -23,7 +23,9 @@ typedef struct qfv_capture_s {
int canBlit;
VkExtent2D extent;
qfv_capture_image_set_t *image_set;
size_t imgsize;
size_t memsize;
byte *data;
VkDeviceMemory memory;
} qfv_capture_t;

View file

@ -1,237 +0,0 @@
/*
draw.h
Video buffer handling definitions and prototypes
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __QF_draw_h
#define __QF_draw_h
/** \defgroup video Video Sub-sytem */
/** \defgroup video_renderer Renderer Sub-system
\ingroup video
*/
/** \defgroup video_renderer_draw Generic draw functions
\ingroup video_renderer
*/
///@{
#include "QF/wad.h"
extern byte *draw_chars;
/** Initialize the draw stuff.
*/
void Draw_Init (void);
/** Draws one 8*8 graphics character with 0 being transparent.
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
\param x horizontal location of the top left corner of the character.
\param y vertical location of the top left corner of the character.
\param ch 8 bit character to draw.
\note The character drawn is from the quake character set, which is
(by default) standard ascii for 0x20-0x7e (white). 0xa0-0xfe is
also standard ascii (brown). 0x01-0x1f and 0x80-0x9f are
various drawing characters, and 0x7f is a backwards arrow.
*/
void Draw_Character (int x, int y, unsigned ch);
/** Draws a character string to the screen.
No line wrapping is performed.
\param x horizontal location of the top left corner of the character.
\param y vertical location of the top left corner of the character.
\param str 8 bit character string to draw.
\note See Draw_Character() for character set description.
String is normal nul terminated C string.
*/
void Draw_String (int x, int y, const char *str);
/** Draws a character sub-string to the screen.
No line wrapping is performed.
\param x horizontal location of the top left corner of the character.
\param y vertical location of the top left corner of the character.
\param str 8 bit character string to draw.
\param count Maximum characters of the string to draw.
\note See Draw_Character() for character set description.
Draws up to \p count characters, or stops at the first nul
character.
*/
void Draw_nString (int x, int y, const char *str, int count);
/** Draws a character string to the screen.
No line wrapping is performed.
\param x horizontal location of the top left corner of the character.
\param y vertical location of the top left corner of the character.
\param str 8 bit character string to draw.
\note See Draw_Character() for character set description.
String is normal nul terminated C string.
Characters of the string are forced to have their high bit set
(ie, they will be in the range 0x80-0xff).
*/
void Draw_AltString (int x, int y, const char *str);
/** Draw the console background with various optional effects.
\param lines Vertical size in pixels of the console.
\param alpha Console transparency level (255 = opaque).
\note \p alpha is effective only in the OpenGL renderer. Effectively
255 (opaque) for the software renderer.
\c gl_conspin causes the background to spin.
\c gl_constretch causes the background to stretch rather than slide.
*/
void Draw_ConsoleBackground (int lines, byte alpha);
/** Draw a crosshair at the center of the screen.
\c crosshair specifies which crosshair (1 = '+', 2 = large 'x' shape,
3 = fancy '+' shape)
\c cl_crossx and \c cl_crossy offset the crosshair from the center of the
screen.
*/
void Draw_Crosshair (void);
/** Draw the specified crosshair on the screen.
\param ch crosshair to draw
\param x horizontal position of the center of the crosshair.
\param y vertical position of the center of the crosshair.
See Draw_Crosshair() for description of crosshair values.
*/
void Draw_CrosshairAt (int ch, int x, int y);
/** Clear a rectangle with a tiled background.
\param x horizontal position of the upper left corner of the rectangle
\param y horizontal position of the upper left corner of the rectangle
\param w width of the rectangle
\param h height of the rectangle
The background used is the "backtile" WAD lump.
*/
void Draw_TileClear (int x, int y, int w, int h);
/** Clear a rectangle with a solid color.
\param x horizontal position of the upper left corner of the rectangle
\param y horizontal position of the upper left corner of the rectangle
\param w width of the rectangle
\param h height of the rectangle
\param c 8 bit color index.
The color comes from the quake palette.
*/
void Draw_Fill (int x, int y, int w, int h, int c);
/** Draw a text box on the screen
\param x horizontal location of the upper left corner of the box
\param y vertical location of the upper left corner of the box
\param width horizontal size in character cells of the region
\param lines vertical size in character cells of the region
\param alpha transparency of the box
*/
void Draw_TextBox (int x, int y, int width, int lines, byte alpha);
/** Darken the screen.
*/
void Draw_FadeScreen (void);
/** Shift the screen colors.
*/
void Draw_BlendScreen (quat_t color);
///@}
/** \defgroup video_renderer_draw_qpic QPic functions
\ingroup video_renderer_draw
*/
///@{
/** Load a qpic from the filesystem.
\param path path of the file within the quake filesystem
\param alpha transparency level of the pic.
\return pointer qpic data.
\note Up to MAX_CACHED_PICS qpics can be loaded at a time this way
*/
qpic_t *Draw_CachePic (const char *path, qboolean alpha);
/** Remove a qpic from the qpic cache.
This affects only those qpics that were loaded via Draw_CachePic.
\param path path of the file within the quake filesystem
*/
void Draw_UncachePic (const char *path);
/** Create a qpic from raw data.
\param width The width of the pic.
\param height The height of the pic.
\param data The raw data bytes. The system palette will be used for
colors.
\return pointer qpic data.
*/
qpic_t *Draw_MakePic (int width, int height, const byte *data);
/** Destroy a qpic created by Draw_MakePic.
\param pic The qpic to destory.
*/
void Draw_DestroyPic (qpic_t *pic);
/** Load a qpic from gfx.wad.
\param name name of the was lump to load
\return pointer qpic data.
*/
qpic_t *Draw_PicFromWad (const char *name);
/** Draw a qpic to the screen
\param x horizontal location of the upper left corner of the qpic
\param y vertical location of the upper left corner of the qpic
\param pic qpic to draw
*/
void Draw_Pic (int x, int y, qpic_t *pic);
/** Draw a qpic to the screen
\param x horizontal location of the upper left corner of the qpic
\param y vertical location of the upper left corner of the qpic
\param pic qpic to draw
*/
void Draw_Picf (float x, float y, qpic_t *pic);
/** Draw a sub-region of a qpic to the screan
\param x horizontal screen location of the upper left corner of the
sub-region
\param y vertical screen location of the upper left corner of the
sub-region
\param pic qpic to draw
\param srcx horizontal qpic location of the upper left corner of the
sub-region
\param srcy vertical qpic location of the upper left corner of the
sub-region
\param width horizontal size of the sub-region to be drawn
\param height vertical size of the sub-region to be drawn
*/
void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height);
///@}
#endif//__QF_draw_h

View file

@ -131,6 +131,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeMemory)
DEVICE_LEVEL_VULKAN_FUNCTION (vkMapMemory)
DEVICE_LEVEL_VULKAN_FUNCTION (vkUnmapMemory)
DEVICE_LEVEL_VULKAN_FUNCTION (vkFlushMappedMemoryRanges)
DEVICE_LEVEL_VULKAN_FUNCTION (vkInvalidateMappedMemoryRanges)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateSampler)
DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateDescriptorSetLayout)

View file

@ -1,7 +1,13 @@
#ifndef __QF_Vulkan_image_h
#define __QF_Vulkan_image_h
#ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES
#endif
#include <vulkan/vulkan.h>
#include "QF/darray.h"
#include "QF/image.h"
typedef struct qfv_imageset_s
DARRAY_TYPE (VkImage) qfv_imageset_t;
@ -95,4 +101,14 @@ void QFV_GenerateMipMaps (struct qfv_device_s *device, VkCommandBuffer cmd,
unsigned width, unsigned height, unsigned layers);
int QFV_MipLevels (int width, int height) __attribute__((const));
/** Convert QFFormat to VkFormat
*
* \param format The format to convert.
* \return The corresponding VkFormat.
*
* \note For tex_palette, VK_FORMAT_R8_UINT is returned. If \a format is
* not a valid QFFormat, then VK_FORMAT_R8_SRGB is returned.
*/
VkFormat QFV_ImageFormat (QFFormat format);
#endif//__QF_Vulkan_image_h

View file

@ -94,10 +94,8 @@ struct qfv_renderframe_s;
struct entity_s;
struct mod_alias_ctx_s;
void *Vulkan_Mod_LoadSkin (struct mod_alias_ctx_s *alias_ctx, byte *skin,
int skinsize, int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc,
struct vulkan_ctx_s *ctx);
void Vulkan_Mod_LoadAllSkins (struct mod_alias_ctx_s *alias_ctx,
struct vulkan_ctx_s *ctx);
void Vulkan_Mod_FinalizeAliasModel (struct mod_alias_ctx_s *alias_ctx,
struct vulkan_ctx_s *ctx);
void Vulkan_Mod_LoadExternalSkins (struct mod_alias_ctx_s *alias_ctx,

113
include/QF/Vulkan/qf_iqm.h Normal file
View file

@ -0,0 +1,113 @@
/*
qf_iqm.h
Vulkan specific iqm model stuff
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2022/5/3
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __QF_Vulkan_qf_iqm_h
#define __QF_Vulkan_qf_iqm_h
#include "QF/darray.h"
#include "QF/model.h"
#include "QF/modelgen.h"
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
// geometry attributes
typedef struct iqmgvert_s {
float vertex[3];
byte bones[4]; // uint
byte weights[4]; // unorm
} iqmgvert_t;
// rendering attributes
typedef struct iqmrvert_s {
float uv[2];
float normal[3];
float tangent[4];
byte color[4]; // unorm
} iqmrvert_t;
typedef struct qfv_iqm_skin_s {
VkImageView view;
byte colora[4];
byte colorb[4];
VkDescriptorSet descriptor;
} qfv_iqm_skin_t;
typedef struct qfv_iqm_s {
VkBuffer geom_buffer;
VkBuffer rend_buffer;
VkBuffer index_buffer;
qfv_iqm_skin_t *skins;
struct qfv_resource_s *mesh;
struct qfv_resource_s *bones;
} qfv_iqm_t;
typedef enum {
QFV_iqmDepth,
QFV_iqmGBuffer,
QFV_iqmTranslucent,
QFV_iqmNumPasses
} QFV_IQMSubpass;
typedef struct iqm_frame_s {
qfv_cmdbufferset_t cmdSet;
} iqm_frame_t;
typedef struct iqm_frameset_s
DARRAY_TYPE (iqm_frame_t) iqm_frameset_t;
typedef struct iqmindset_s
DARRAY_TYPE (unsigned) iqmindset_t;
typedef struct iqmctx_s {
iqm_frameset_t frames;
VkPipeline depth;
VkPipeline gbuf;
VkPipelineLayout layout;
VkSampler sampler;
} iqmctx_t;
struct vulkan_ctx_s;
struct qfv_renderframe_s;
struct entity_s;
struct mod_iqm_ctx_s;
void Vulkan_Mod_IQMFinish (struct model_s *mod, struct vulkan_ctx_s *ctx);
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);
void Vulkan_IQMBegin (struct qfv_renderframe_s *rFrame);
void Vulkan_DrawIQM (struct entity_s *ent, struct qfv_renderframe_s *rFrame);
void Vulkan_IQMEnd (struct qfv_renderframe_s *rFrame);
void Vulkan_IQM_Init (struct vulkan_ctx_s *ctx);
void Vulkan_IQM_Shutdown (struct vulkan_ctx_s *ctx);
#endif//__QF_Vulkan_qf_iqm_h

View file

@ -33,53 +33,26 @@
#include "QF/darray.h"
#include "QF/model.h"
#include "QF/modelgen.h"
#include "QF/scene/light.h"
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
#include "QF/Vulkan/image.h"
#include "QF/simd/types.h"
typedef struct qfv_light_s {
vec3_t color;
int data;
vec3_t position;
float light;
vec3_t direction;
float cone;
} qfv_light_t;
typedef struct qfv_lightset_s DARRAY_TYPE (qfv_light_t) qfv_lightset_t;
typedef struct qfv_lightleafset_s DARRAY_TYPE (int) qfv_lightintset_t;
typedef struct qfv_lightvisset_s DARRAY_TYPE (byte) qfv_lightvisset_t;
typedef struct qfv_lightmatset_s DARRAY_TYPE (mat4f_t) qfv_lightmatset_t;
#define MaxLights 256
#define StyleMask 0x07f
#define ModelMask 0x380
#define ShadowMask 0xc00
#define LM_LINEAR (0 << 7) // light - dist (or radius + dist if -ve)
#define LM_INVERSE (1 << 7) // distFactor1 * light / dist
#define LM_INVERSE2 (2 << 7) // distFactor2 * light / (dist * dist)
#define LM_INFINITE (3 << 7) // light
#define LM_AMBIENT (4 << 7) // light
#define LM_INVERSE3 (5 << 7) // distFactor2 * light / (dist + distFactor2)**2
#define ST_NONE (0 << 10) // no shadows
#define ST_PLANE (1 << 10) // single plane shadow map (small spotlight)
#define ST_CASCADE (2 << 10) // cascaded shadow maps
#define ST_CUBE (3 << 10) // cubemap (omni, large spotlight)
#define NumStyles 64
#define ST_NONE 0 // no shadows
#define ST_PLANE 1 // single plane shadow map (small spotlight)
#define ST_CASCADE 2 // cascaded shadow maps
#define ST_CUBE 3 // cubemap (omni, large spotlight)
typedef struct qfv_light_buffer_s {
float intensity[NumStyles + 4];
float distFactor1;
float distFactor2;
light_t lights[MaxLights] __attribute__((aligned(16)));
int lightCount;
qfv_light_t lights[MaxLights] __attribute__((aligned(16)));
mat4f_t shadowMat[MaxLights];
vec4f_t shadowCascade[MaxLights];
//mat4f_t shadowMat[MaxLights];
//vec4f_t shadowCascade[MaxLights];
} qfv_light_buffer_t;
#define LIGHTING_BUFFER_INFOS 1
@ -101,11 +74,6 @@ typedef struct lightingframe_s {
VkWriteDescriptorSet shadowWrite;
};
};
// A fat PVS of leafs visible from visible leafs so hidden lights can
// illuminate the leafs visible to the player
struct set_s *pvs;
struct mleaf_s *leaf; // the last leaf used to generate the pvs
qfv_lightvisset_t lightvis;
} lightingframe_t;
typedef struct lightingframeset_s
@ -118,13 +86,13 @@ typedef struct lightingctx_s {
VkSampler sampler;
VkDeviceMemory light_memory;
VkDeviceMemory shadow_memory;
qfv_lightset_t lights;
qfv_lightintset_t lightleafs;
qfv_lightmatset_t lightmats;
qfv_imageset_t lightimages;
qfv_lightintset_t lightlayers;
lightintset_t lightlayers;
qfv_imageviewset_t lightviews;
struct set_s *sun_pvs;
struct lightingdata_s *ldata;
struct scene_s *scene;
} lightingctx_t;
struct vulkan_ctx_s;
@ -133,7 +101,6 @@ struct qfv_renderframe_s;
void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx);
void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx);
void Vulkan_Lighting_Draw (struct qfv_renderframe_s *rFrame);
void Vulkan_LoadLights (model_t *model, const char *entity_data,
struct vulkan_ctx_s *ctx);
void Vulkan_LoadLights (struct scene_s *scene, struct vulkan_ctx_s *ctx);
#endif//__QF_Vulkan_qf_lighting_h

View file

@ -31,9 +31,9 @@
struct vulkan_ctx_s;
struct qfv_renderframe_s;
struct entqueue_s;
struct scene_s;
void Vulkan_NewMap (model_t *worldmodel, struct model_s **models,
int num_models, struct vulkan_ctx_s *ctx);
void Vulkan_NewScene (struct scene_s *scene, struct vulkan_ctx_s *ctx);
void Vulkan_RenderView (struct qfv_renderframe_s *rFrame);
void Vulkan_RenderEntities (struct entqueue_s *queue,
struct qfv_renderframe_s *rFrame);

View file

@ -3,7 +3,7 @@
vulkan vid stuff from the renderer.
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2019 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -40,8 +40,8 @@ typedef enum {
QFV_passDepth, // geometry
QFV_passTranslucent, // geometry
QFV_passGBuffer, // geometry
QFV_passLighting, // single quad
QFV_passCompose, // single quad
QFV_passLighting, // single triangle
QFV_passCompose, // single triangle
QFV_NumPasses
} QFV_Subpass;

View file

@ -70,6 +70,8 @@ typedef struct qfv_renderpass_s {
VkDeviceMemory attachmentMemory;
qfv_framebufferset_t *framebuffers;
VkViewport viewport;
VkRect2D scissor;
qfv_renderframeset_t frames;

View file

@ -0,0 +1,68 @@
#ifndef __QF_Vulkan_resource_h
#define __QF_Vulkan_resource_h
#ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES
#endif
#include <vulkan/vulkan.h>
typedef enum {
qfv_res_buffer = 1,
qfv_res_buffer_view,
qfv_res_image,
qfv_res_image_view,
} qfv_res_type;
typedef struct qfv_resobj_s {
const char *name;
qfv_res_type type;
union {
struct {
VkDeviceSize size;
VkBufferUsageFlags usage;
VkBuffer buffer;
} buffer;
struct {
unsigned buffer;
VkFormat format;
VkDeviceSize offset;
VkDeviceSize size;
VkBufferView view;
} buffer_view;
struct {
int cubemap;
VkImageType type;
VkFormat format;
VkExtent3D extent;
uint32_t num_mipmaps;
uint32_t num_layers;
VkSampleCountFlags samples;
VkImageUsageFlags usage;
VkImage image;
} image;
struct {
unsigned image;
VkImageViewType type;
VkFormat format;
VkImageAspectFlags aspect;
VkImageView view;
} image_view;
};
} qfv_resobj_t;
typedef struct qfv_resource_s {
const char *name;
struct va_ctx_s *va_ctx;
VkMemoryPropertyFlags memory_properties;
unsigned num_objects;
qfv_resobj_t *objects;
VkDeviceMemory memory;
} qfv_resource_t;
struct qfv_device_s;
int QFV_CreateResource (struct qfv_device_s *device, qfv_resource_t *resource);
void QFV_DestroyResource (struct qfv_device_s *device,
qfv_resource_t *resource);
#endif//__QF_Vulkan_resource_h

View file

@ -28,6 +28,9 @@
#ifndef __QF_input_h
#define __QF_input_h
/** \defgroup input Input Sub-system */
///@{
typedef struct in_axisinfo_s {
int deviceid;
int axis;
@ -135,4 +138,6 @@ extern int lookstrafe;
#endif
///@}
#endif//__QF_input_h

View file

@ -34,6 +34,11 @@
#include "QF/mathlib.h"
#endif
/** \defgroup input_bindings Input Bindings
\ingroup input
*/
///@{
/*** Recipe for converting an axis to a floating point value.
Absolute axes are converted to the 0..1 range for unbalanced axes, and
@ -366,4 +371,6 @@ void IN_Binding_LoadConfig (struct plitem_s *config);
#endif
///@}
#endif//__QF_input_binding_h

View file

@ -33,6 +33,11 @@
#include "QF/qtypes.h"
/** \defgroup input_events Input Events
\ingroup input
*/
///@{
typedef struct {
int xpos, ypos;
int xlen, ylen;
@ -122,4 +127,6 @@ void IE_Remove_Handler (int handle);
void IE_Set_Focus (int handle);
int IE_Get_Focus (void) __attribute__ ((pure));
///@}
#endif//__QF_in_event_h

View file

@ -29,6 +29,11 @@
#ifndef __QF_input_imt_h
#define __QF_input_imt_h
/** \defgroup input_imt Input Mapping Tables
\ingroup input
*/
///@{
#ifndef __QFCC__
#include "QF/darray.h"
@ -134,4 +139,6 @@ void IMT_LoadConfig (struct plitem_s *config);
#endif
///@}
#endif//__QF_input_imt_h

View file

@ -34,8 +34,6 @@
# include "QF/quakeio.h"
#endif
/** \defgroup input Input Sub-system */
/** \defgroup input_keybinding Key Binding Sub-system
\ingroup input
*/

View file

@ -438,6 +438,7 @@ void Mod_Init_Cvars (void);
void Mod_ClearAll (void);
model_t *Mod_ForName (const char *name, qboolean crash);
void Mod_TouchModel (const char *name);
void Mod_UnloadModel (model_t *model);
// brush specific
mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure));
struct set_s *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model);

View file

@ -67,12 +67,12 @@ struct plfield_s;
dictionary objects.
If null, then the default parser for the object type is used:
* QFString: the point to the actual string. The string continues
to be owned by the string object.
* QFString: pointer to the actual string. The string continues to
be owned by the string object.
* QFBinary: pointer to fixed-size DARRAY_TYPE(byte) (so size isn't
lost)
* QFArray: pointer to fixed-size DARRAY_TYPE(plitem_t *) with the
indivisual objects. The individual objects continue to be owned
individual objects. The individual objects continue to be owned
by the array object.
* QFDictionary: pointer to the hashtab_t hash table used for the
dictionary object. The hash table continues to be owned by the
@ -86,7 +86,9 @@ struct plfield_s;
checking is done: it is up to the top-level caller to
parse out the messages.
\param context Additional context data passed to the parser.
\return 0 for error, 1 for success. See \a PL_ParseDictionary.
\return 0 for error, 1 for success. See \a PL_ParseStruct,
\a PL_ParseArray, \a PL_ParseLabeledArray, and
\a PL_ParseSymtab.
*/
typedef int (*plparser_t) (const struct plfield_s *field,
const struct plitem_s *item,
@ -96,7 +98,15 @@ typedef int (*plparser_t) (const struct plfield_s *field,
/** A field to be parsed from a dictionary item.
something
\a PL_ParseStruct uses an array (terminated by an element with \a name
set to null) of these to describe the fields in the structure being
parsed.
\a PL_ParseArray, \a PL_ParseLabeledArray, and \a PL_ParseSymtab use only
a single \a plfield_t object, and then only the \a data field, which must
point to a \a plelement_t object. This allows all the parse functions to
be used directly as either a \a plfield_t or \a plelement_t object's
\a parser.
*/
typedef struct plfield_s {
const char *name; ///< matched by dictionary key

View file

@ -35,6 +35,7 @@
struct plitem_s;
struct cvar_s;
struct scene_s;
struct skin_s;
struct mod_alias_ctx_s;
@ -58,9 +59,7 @@ typedef struct vid_model_funcs_s {
void (*Mod_LoadSpriteModel) (model_t *mod, void *buffer);
void (*Mod_MakeAliasModelDisplayLists) (struct mod_alias_ctx_s *alias_ctx,
void *_m, int _s, int extra);
void *(*Mod_LoadSkin) (struct mod_alias_ctx_s *alias_ctx, byte *skin,
int skinsize, int snum, int gnum,
qboolean group, maliasskindesc_t *skindesc);
void (*Mod_LoadAllSkins) (struct mod_alias_ctx_s *alias_ctx);
void (*Mod_FinalizeAliasModel) (struct mod_alias_ctx_s *alias_ctx);
void (*Mod_LoadExternalSkins) (struct mod_alias_ctx_s *alias_ctx);
void (*Mod_IQMFinish) (model_t *mod);
@ -107,7 +106,7 @@ typedef struct vid_render_funcs_s {
void (*R_Init) (void);
void (*R_ClearState) (void);
void (*R_LoadSkys) (const char *);
void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models);
void (*R_NewScene) (struct scene_s *scene);
void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height);
void (*begin_frame) (void);

View file

@ -433,7 +433,9 @@ typedef enum {
#define OP_BREAK 0x8000
typedef enum {
#ifndef IN_DOXYGEN
#include "QF/progs/pr_opcode.hinc"
#endif
} pr_opcode_e;
// Used for both branch and comparison, with jump and call being ignored for

View file

@ -167,7 +167,6 @@ typedef struct {
int drawflat;
struct model_s *worldmodel;
struct mleaf_s *viewleaf;
} refdef_t;
// REFRESH ====================================================================

80
include/QF/scene/light.h Normal file
View file

@ -0,0 +1,80 @@
/*
light.h
Entity management
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2021/02/26
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __QF_scene_light_h
#define __QF_scene_light_h
#include "QF/darray.h"
#include "QF/qtypes.h"
#include "QF/simd/types.h"
struct mod_brush_s;
#define NumStyles 64
#define LM_LINEAR 0 // light - dist (or radius + dist if -ve)
#define LM_INVERSE 1 // distFactor1 * light / dist
#define LM_INVERSE2 2 // distFactor2 * light / (dist * dist)
#define LM_INFINITE 3 // light
#define LM_AMBIENT 4 // light
#define LM_INVERSE3 5 // distFactor2 * light / (dist + distFactor2)**2
typedef struct light_s {
vec4f_t color;
vec4f_t position;
vec4f_t direction;
vec4f_t attenuation;
} light_t;
typedef struct lightset_s DARRAY_TYPE (light_t) lightset_t;
typedef struct lightleafset_s DARRAY_TYPE (int) lightintset_t;
typedef struct lightvisset_s DARRAY_TYPE (byte) lightvisset_t;
typedef struct lightingdata_s {
lightset_t lights;
lightintset_t lightstyles;
lightintset_t lightleafs;
lightvisset_t lightvis;
struct set_s *sun_pvs;
// A fat PVS of leafs visible from visible leafs so hidden lights can
// illuminate the leafs visible to the player
struct set_s *pvs;
struct mleaf_s *leaf; // the last leaf used to generate the pvs
struct scene_s *scene;
} lightingdata_t;
lightingdata_t *Light_CreateLightingData (struct scene_s *scene);
void Light_DestroyLightingData (lightingdata_t *ldata);
void Light_ClearLights (lightingdata_t *ldata);
void Light_AddLight (lightingdata_t *ldata, const light_t *light, int style);
void Light_EnableSun (lightingdata_t *ldata);
void Light_FindVisibleLights (lightingdata_t *ldata);
#endif//__QF_scene_light_h

View file

@ -43,6 +43,11 @@
typedef struct scene_s {
struct scene_resources_s *const resources;
struct hierarchy_s *hierarchies;
struct model_s *worldmodel;
int num_models;
struct model_s **models;
struct mleaf_s *viewleaf;
struct lightingdata_s *lights;
} scene_t;
scene_t *Scene_NewScene (void);

View file

@ -29,6 +29,7 @@
#ifndef __QF_screen_h
#define __QF_screen_h
struct scene_s;
struct transform_s;
struct tex_s;
@ -47,6 +48,8 @@ void SCR_SetFOV (float fov);
void SCR_SetFullscreen (qboolean fullscreen);
void SCR_SetBottomMargin (int lines);
void SCR_NewScene (struct scene_s *scene);
extern int hud_fps;
extern int hud_time;
extern int r_timegraph;

View file

@ -175,7 +175,7 @@ mat4fquat (mat4f_t m, vec4f_t q)
vec4f_t b = _mm_xor_ps (shuff103 (yq), (__m128) mpm);
vec4f_t c = _mm_xor_ps (shuff230 (zq), (__m128) pmm);
vec4f_t d = _mm_xor_ps (shuff321 (wq), (__m128) mmp);
// column: ww + xx - yy - zz // 2xy + 2wz // 2zx - 2wy // 0
m[0] = _mm_and_ps (a + b - c - d, (__m128) mask);
}
{
@ -183,6 +183,7 @@ mat4fquat (mat4f_t m, vec4f_t q)
vec4f_t b = yq;
vec4f_t c = _mm_xor_ps (shuff321 (zq), (__m128) mmp);
vec4f_t d = _mm_xor_ps (shuff230 (wq), (__m128) pmm);
// column: 2xy - 2wz // ww - xx + yy - zz // 2yz + 2wx // 0
m[1] = _mm_and_ps (b + c - a - d, (__m128) mask);
}
{
@ -190,6 +191,7 @@ mat4fquat (mat4f_t m, vec4f_t q)
vec4f_t b = _mm_xor_ps (shuff321 (yq), (__m128) mmp);
vec4f_t c = zq;
vec4f_t d = _mm_xor_ps (shuff103 (wq), (__m128) mpm);
// column: 2xz + 2wy // 2yz - 2wx // ww - xx - yy + zz // 0
m[2] = _mm_and_ps (a - b + c - d, (__m128) mask);
}
m[3] = (vec4f_t) { 0, 0, 0, 1 };

View file

@ -133,9 +133,6 @@ void S_StopAllSounds(void);
render some sound.
\param ear Transform for the position and orientation of the stereo
sound pickup.
\param v_forward 3d vector of the client's facing direction
\param v_right 3d vector of the client's rightward direction
\param v_up 3d vector of the client's upward direction
\param ambient_sound_level NUM_AMBIENTS bytes indicating current ambient
sound levels
*/

View file

@ -44,6 +44,7 @@ SYS_DEVELOPER (glt)
SYS_DEVELOPER (glsl)
SYS_DEVELOPER (skin)
SYS_DEVELOPER (model)
SYS_DEVELOPER (lighting)
SYS_DEVELOPER (vulkan)
SYS_DEVELOPER (vulkan_parse)

View file

@ -44,6 +44,17 @@
# endif
#endif
typedef enum {
targa_colormap = 1,
targa_truecolor = 2,
targa_greyscale = 3,
targa_colormap_rle = 9,
targa_truecolor_rle = 10,
targa_greyscale_rle = 11,
targa_max_image_type = 15
} TargaImageType;
typedef struct _TargaHeader {
unsigned char id_length; // __attribute__((packed));
unsigned char colormap_type; // __attribute__((packed));

View file

@ -43,7 +43,6 @@ typedef struct worldscene_s {
struct scene_s *scene;
struct plitem_s *edicts;
struct plitem_s *worldspawn;
struct model_s *worldmodel;
modelset_t models;
} worldscene_t;
@ -51,6 +50,7 @@ extern worldscene_t cl_world;
struct msg_s;
struct entity_state_s;
struct lightingdata_s;
void CL_World_Init (void);
@ -66,5 +66,6 @@ void CL_ParseBaseline (struct msg_s *msg, struct entity_state_s *baseline,
void CL_ParseStatic (struct msg_s *msg, int version);
void CL_MapCfg (const char *mapname);
void CL_World_NewMap (const char *mapname, const char *skyname);
void CL_LoadLights (struct plitem_s *entities, struct scene_s *scene);
#endif//__client_world_h

View file

@ -1,7 +1,7 @@
/*
* Linux Frame Buffer Device Configuration
*
* © Copyright 1995-1998 by Geert Uytterhoeven
* © Copyright 1995-1998 by Geert Uytterhoeven
* (Geert.Uytterhoeven@cs.kuleuven.ac.be)
*
* --------------------------------------------------------------------------

View file

@ -7,9 +7,17 @@
#include "QF/skin.h"
#include "QF/plugin/vid_render.h"
typedef struct mod_alias_skin_s {
int skin_num;
int group_num; // -1 if not in an animated group
byte *texels;
maliasskindesc_t *skindesc;
} mod_alias_skin_t;
typedef struct stvertset_s DARRAY_TYPE (stvert_t) stvertset_t;
typedef struct mtriangleset_s DARRAY_TYPE (mtriangle_t) mtriangleset_t;
typedef struct trivertxset_s DARRAY_TYPE (trivertx_t *) trivertxset_t;
typedef struct askinset_s DARRAY_TYPE (mod_alias_skin_t) askinset_t;
typedef struct mod_alias_ctx_s {
aliashdr_t *header;
@ -17,6 +25,7 @@ typedef struct mod_alias_ctx_s {
stvertset_t stverts;
mtriangleset_t triangles;
trivertxset_t poseverts;
askinset_t skins;
int aliasbboxmins[3];
int aliasbboxmaxs[3];
} mod_alias_ctx_t;
@ -49,27 +58,21 @@ extern vid_model_funcs_t *m_funcs;
void gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m,
int _s, int extra);
void *gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc);
void gl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx);
void gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx);
void gl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx);
void gl_Mod_IQMFinish (model_t *mod);
void glsl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx,
void *_m, int _s, int extra);
void *glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc);
void glsl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx);
void glsl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx);
void glsl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx);
void glsl_Mod_IQMFinish (model_t *mod);
void sw_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m,
int _s, int extra);
void *sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc);
void sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx);
void sw_Mod_IQMFinish (model_t *mod);
void gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp);

View file

@ -45,7 +45,8 @@ struct psystem_s *glsl_ParticleSystem (void);
struct psystem_s *sw_ParticleSystem (void);
void R_RunParticles (float dT);
void R_NewMap (model_t *worldmodel, model_t **models, int num_models);
struct scene_s;
void R_NewScene (struct scene_s *scene);
// LordHavoc: relative bmodel lighting
void R_PushDlights (const vec3_t entorigin);
@ -73,7 +74,7 @@ struct entity_s;
struct animation_s;
void R_DrawAliasModel (struct entity_s *e);
void R_MarkLeaves (void);
void R_MarkLeaves (struct mleaf_s *viewleaf);
void GL_SetPalette (void *data, const byte *palette);
void GLSL_SetPalette (void *data, const byte *palette);

View file

@ -202,8 +202,6 @@ extern void R_RotateBmodel (struct transform_s *transform);
extern int c_faceclip;
extern int r_polycount;
extern model_t *cl_worldmodel;
extern int *pfrustum_indexes[4];
// !!! if this is changed, it must be changed in asm_draw.h too !!!

View file

@ -62,6 +62,9 @@ struct plitem_s *Plist_GetItem (struct progs_s *pr, int handle);
void RUA_Input_Init (struct progs_s *pr, int secure);
void RUA_Mersenne_Init (struct progs_s *pr, int secure);
void RUA_Model_Init (struct progs_s *pr, int secure);
struct model_s *Model_GetModel (progs_t *pr, int handle);
void RUA_Scene_Init (struct progs_s *pr, int secure);
struct scene_s *Scene_GetScene (struct progs_s *pr, pr_ulong_t handle);
#endif//__rua_internal_h

View file

@ -353,10 +353,8 @@ void SND_AmbientOn (snd_t *snd);
/** Update the sound engine with the client's position and orientation and
render some sound.
\param snd sound system state
\param origin 3d coords of the client
\param v_forward 3d vector of the client's facing direction
\param v_right 3d vector of the client's rightward direction
\param v_up 3d vector of the client's upward direction
\param ear Transform for the position and orientation of the stereo
sound pickup.
\param ambient_sound_level Pointer to 4 bytes indicating the levels at
which to play the ambient sounds.
*/

View file

@ -67,15 +67,13 @@ typedef struct vulkan_ctx_s {
struct matrixctx_s *matrix_context;
struct aliasctx_s *alias_context;
struct bspctx_s *bsp_context;
struct iqmctx_s *iqm_context;
struct particlectx_s *particle_context;
struct spritectx_s *sprite_context;
struct drawctx_s *draw_context;
struct lightingctx_s *lighting_context;
struct composectx_s *compose_context;
VkBuffer quad_buffer;
VkDeviceMemory quad_memory;
VkCommandPool cmdpool;
VkCommandBuffer cmdbuffer;
VkFence fence; // for ctx->cmdbuffer only
@ -95,8 +93,9 @@ typedef struct vulkan_ctx_s {
struct qfv_tex_s *default_magenta;
struct qfv_tex_s *default_magenta_array;
VkViewport viewport;
VkRect2D scissor;
// size of window
int window_width;
int window_height;
//FIXME not sure I like it being here (also, type name)
qfv_output_t output;

View file

@ -7,6 +7,7 @@ libs_client_libQFclient_la_SOURCES= \
libs/client/cl_effects.c \
libs/client/cl_entities.c \
libs/client/cl_input.c \
libs/client/cl_light.c \
libs/client/cl_particles.c \
libs/client/cl_temp_entities.c \
libs/client/cl_view.c \

291
libs/client/cl_light.c Normal file
View file

@ -0,0 +1,291 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h>
#include "QF/dstring.h"
#include "QF/mathlib.h"
#include "QF/model.h"
#include "QF/plist.h"
#include "QF/progs.h" //for ED_ConvertToPlist
#include "QF/set.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "QF/simd/vec4f.h"
#include "client/world.h"
static void
dump_light (light_t *light, int leaf)
{
Sys_MaskPrintf (SYS_lighting,
"[%g, %g, %g] %g, "
"[%g, %g, %g, %g], [%g %g %g] %g, [%g, %g, %g, %g] %d\n",
VEC4_EXP (light->color),
VEC4_EXP (light->position),
VEC4_EXP (light->direction),
VEC4_EXP (light->attenuation),
leaf);
}
static float
parse_float (const char *str, float defval)
{
float val = defval;
if (str) {
char *end;
val = strtof (str, &end);
if (end == str) {
val = defval;
}
}
return val;
}
static void
parse_vector (const char *str, vec_t *val)
{
if (str) {
int num = sscanf (str, "%f %f %f", VectorExpandAddr (val));
while (num < 3) {
val[num++] = 0;
}
}
}
static float
ecos (float ang)
{
if (ang == 90 || ang == -90) {
return 0;
}
if (ang == 180 || ang == -180) {
return -1;
}
if (ang == 0 || ang == 360) {
return 1;
}
return cos (ang * M_PI / 180);
}
static float
esin (float ang)
{
if (ang == 90) {
return 1;
}
if (ang == -90) {
return -1;
}
if (ang == 180 || ang == -180) {
return 0;
}
if (ang == 0 || ang == 360) {
return 0;
}
return sin (ang * M_PI / 180);
}
static vec4f_t
sun_vector (const vec_t *ang)
{
// ang is yaw, pitch (maybe roll, but ignored
vec4f_t vec = {
ecos (ang[1]) * ecos (ang[0]),
ecos (ang[1]) * esin (ang[0]),
esin (ang[1]),
0,
};
return vec;
}
static void
parse_sun (lightingdata_t *ldata, plitem_t *entity)
{
light_t light = {};
float sunlight;
//float sunlight2;
vec3_t sunangle = { 0, -90, 0 };
Light_EnableSun (ldata);
sunlight = parse_float (PL_String (PL_ObjectForKey (entity,
"_sunlight")), 0);
//sunlight2 = parse_float (PL_String (PL_ObjectForKey (entity,
// "_sunlight2")), 0);
parse_vector (PL_String (PL_ObjectForKey (entity, "_sun_mangle")),
sunangle);
if (sunlight <= 0) {
return;
}
VectorSet (1, 1, 1, light.color);
light.color[3] = sunlight;
light.position = -sun_vector (sunangle);
light.direction = light.position;
light.direction[3] = 1;
light.attenuation = (vec4f_t) { 0, 0, 1, 0 };
Light_AddLight (ldata, &light, 0);
}
static vec4f_t
parse_position (const char *str)
{
vec3_t vec = {};
sscanf (str, "%f %f %f", VectorExpandAddr (vec));
return (vec4f_t) {vec[0], vec[1], vec[2], 1};
}
static void
parse_light (light_t *light, int *style, const plitem_t *entity,
const plitem_t *targets)
{
const char *str;
int model = 0;
/*Sys_Printf ("{\n");
for (int i = PL_D_NumKeys (entity); i-- > 0; ) {
const char *field = PL_KeyAtIndex (entity, i);
const char *value = PL_String (PL_ObjectForKey (entity, field));
Sys_Printf ("\t%s = %s\n", field, value);
}
Sys_Printf ("}\n");*/
// omnidirectional light (unit length xyz so not treated as ambient)
light->direction = (vec4f_t) { 0, 0, 1, 1 };
// bright white
light->color = (vec4f_t) { 1, 1, 1, 300 };
if ((str = PL_String (PL_ObjectForKey (entity, "origin")))) {
light->position = parse_position (str);
}
if ((str = PL_String (PL_ObjectForKey (entity, "target")))) {
plitem_t *target = PL_ObjectForKey (targets, str);
vec4f_t dir = { 1, 0, 0, 0 };
if (target) {
if ((str = PL_String (PL_ObjectForKey (target, "origin")))) {
dir = parse_position (str);
dir = normalf (dir - light->position);
}
}
float angle = 40;
if ((str = PL_String (PL_ObjectForKey (entity, "angle")))) {
angle = atof (str);
}
dir[3] = -cos (angle * M_PI / 360); // half angle
light->direction = dir;
}
if ((str = PL_String (PL_ObjectForKey (entity, "light_lev")))
|| (str = PL_String (PL_ObjectForKey (entity, "_light")))) {
light->color[3] = atof (str);
}
if ((str = PL_String (PL_ObjectForKey (entity, "style")))) {
*style = atoi (str) & 0x3f;
}
if ((str = PL_String (PL_ObjectForKey (entity, "delay")))) {
model = atoi (str) & 0x7;
if (model == LM_INVERSE2) {
model = LM_INVERSE3; //FIXME for marcher (need a map)
}
}
if ((str = PL_String (PL_ObjectForKey (entity, "color")))
|| (str = PL_String (PL_ObjectForKey (entity, "_color")))) {
sscanf (str, "%f %f %f", VectorExpandAddr (light->color));
VectorScale (light->color, 1/255.0, light->color);
}
vec4f_t attenuation = { 1, 0, 0, 0 }; // inverse square
switch (model) {
case LM_LINEAR:
attenuation = (vec4f_t) { 0, 0, 1, 1 / fabsf (light->color[3]) };
break;
case LM_INVERSE:
attenuation = (vec4f_t) { 0, 1.0 / 128, 0, 0 };
break;
case LM_INVERSE2:
attenuation = (vec4f_t) { 1.0 / 16384, 0, 0, 0 };
break;
case LM_INFINITE:
attenuation = (vec4f_t) { 0, 0, 1, 0 };
break;
case LM_AMBIENT:
attenuation = (vec4f_t) { 0, 0, 1, 0 };
light->direction = (vec4f_t) { 0, 0, 0, 1 };
break;
case LM_INVERSE3:
attenuation = (vec4f_t) { 1.0 / 16384, 2.0 / 128, 1, 0 };
break;
}
light->attenuation = attenuation;
}
void
CL_LoadLights (plitem_t *entities, scene_t *scene)
{
lightingdata_t *ldata = scene->lights;
model_t *model = scene->worldmodel;
Light_ClearLights (ldata);
ldata->sun_pvs = set_new_size (model->brush.visleafs);
if (!entities) {
return;
}
plitem_t *targets = PL_NewDictionary (0);
// find all the targets so spotlights can be aimed
for (int i = 1; i < PL_A_NumObjects (entities); i++) {
plitem_t *entity = PL_ObjectAtIndex (entities, i);
const char *targetname = PL_String (PL_ObjectForKey (entity,
"targetname"));
if (targetname && !PL_ObjectForKey (targets, targetname)) {
PL_D_AddObject (targets, targetname, entity);
}
}
for (int i = 0; i < PL_A_NumObjects (entities); i++) {
plitem_t *entity = PL_ObjectAtIndex (entities, i);
const char *classname = PL_String (PL_ObjectForKey (entity,
"classname"));
if (!classname) {
continue;
}
if (!strcmp (classname, "worldspawn")) {
// parse_sun can add many lights
parse_sun (ldata, entity);
const char *str;
if ((str = PL_String (PL_ObjectForKey (entity, "light_lev")))) {
light_t light = {};
light.color = (vec4f_t) { 1, 1, 1, atof (str) };
light.attenuation = (vec4f_t) { 0, 0, 1, 0 };
light.direction = (vec4f_t) { 0, 0, 0, 1 };
Light_AddLight (ldata, &light, 0);
}
} else if (!strncmp (classname, "light", 5)) {
light_t light = {};
int style = 0;
parse_light (&light, &style, entity, targets);
// some lights have 0 output, so drop them
if (light.color[3]) {
Light_AddLight (ldata, &light, style);
}
}
}
// targets does not own the objects, so need to remove them before
// freeing targets
for (int i = PL_D_NumKeys (targets); i-- > 0; ) {
PL_RemoveObjectForKey (targets, PL_KeyAtIndex (targets, i));
}
PL_Free (targets);
for (size_t i = 0; i < ldata->lights.size; i++) {
dump_light (&ldata->lights.a[i], ldata->lightleafs.a[i]);
}
Sys_MaskPrintf (SYS_lighting, "loaded %zd lights\n", ldata->lights.size);
}

View file

@ -271,7 +271,7 @@ beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx)
} else {
Transform_SetLocalPosition (tent->ent->transform, position);
}
R_AddEfrags (&cl_world.worldmodel->brush, tent->ent);
R_AddEfrags (&cl_world.scene->worldmodel->brush, tent->ent);
}
}
@ -632,7 +632,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx)
ent->animation.frame = f;
if (!ent->visibility.efrag) {
R_AddEfrags (&cl_world.worldmodel->brush, ent);
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
}
}
}
@ -721,7 +721,7 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx)
angles[2] = 0;
CL_TransformEntity (tent->ent, 1, angles, position);
R_AddEfrags (&cl_world.worldmodel->brush, tent->ent);
R_AddEfrags (&cl_world.scene->worldmodel->brush, tent->ent);
}
*tail = cl_projectiles;

View file

@ -47,6 +47,7 @@
#include "QF/msg.h"
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "QF/simd/vec4f.h"
@ -64,6 +65,7 @@ void
CL_World_Init (void)
{
cl_world.scene = Scene_NewScene ();
cl_world.scene->lights = Light_CreateLightingData (cl_world.scene);
}
void
@ -119,7 +121,7 @@ CL_ParseStatic (qmsg_t *msg, int version)
CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin);
R_AddEfrags (&cl_world.worldmodel->brush, ent);
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
}
static void
@ -205,9 +207,11 @@ CL_LoadSky (const char *name)
void
CL_World_NewMap (const char *mapname, const char *skyname)
{
model_t *worldmodel = cl_world.models.a[1];
cl_world.scene->worldmodel = worldmodel;
cl_static_entities.size = 0;
r_funcs->R_NewMap (cl_world.worldmodel,
cl_world.models.a, cl_world.models.size);
if (cl_world.models.a[1] && cl_world.models.a[1]->brush.entities) {
if (cl_world.edicts) {
PL_Free (cl_world.edicts);
@ -219,5 +223,10 @@ CL_World_NewMap (const char *mapname, const char *skyname)
Fog_ParseWorldspawn (cl_world.worldspawn);
}
}
CL_LoadLights (cl_world.edicts, cl_world.scene);
cl_world.scene->models = cl_world.models.a;
cl_world.scene->num_models = cl_world.models.size;
SCR_NewScene (cl_world.scene);
map_cfg (mapname, 1);
}

View file

@ -299,17 +299,22 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks)
plitem_t *value;
char *token;
int anglehack;
const char *msg = "";
while (Script_GetToken (script, 1)) {
token = script->token->str;
if (!strequal (token, "{"))
Sys_Error ("ED_ConvertToPlist: EOF without closing brace");
if (!strequal (token, "{")) {
msg = "EOF without closing brace";
goto parse_error;
}
ent = PL_NewDictionary (hashlinks);
while (1) {
int n;
if (!Script_GetToken (script, 1))
Sys_Error ("ED_ConvertToPlist: EOF without closing brace");
if (!Script_GetToken (script, 1)) {
msg = "EOF without closing brace";
goto parse_error;
}
token = script->token->str;
if (strequal (token, "}"))
break;
@ -327,12 +332,16 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks)
} else {
key = PL_NewString (token);
}
if (!Script_TokenAvailable (script, 0))
Sys_Error ("ED_ConvertToPlist: EOL without value");
if (!Script_TokenAvailable (script, 0)) {
msg = "EOL without value";
goto parse_error;
}
Script_GetToken (script, 0);
token = script->token->str;
if (strequal (token, "}"))
Sys_Error ("ED_ConvertToPlist: closing brace without data");
if (strequal (token, "}")) {
msg = "closing brace without data";
goto parse_error;
}
if (anglehack) {
dsprintf (dstr, "0 %s 0", token);
value = PL_NewString (dstr->str);
@ -346,6 +355,11 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks)
}
dstring_delete (dstr);
return plist;
parse_error:
Sys_Printf ("%s:%d: %s", script->file, script->line, msg);
dstring_delete (dstr);
PL_Free (plist);
return 0;
}

View file

@ -605,19 +605,25 @@ decode_greyscale_rle (TargaHeader *targa, tex_t *tex, byte *dataByte)
typedef void (*decoder_t) (TargaHeader *, tex_t *, byte *);
static decoder_t decoder_functions[] = {
0, // 0 invalid
decode_colormap,
decode_truecolor,
decode_greyscale,
0, 0, 0, 0, // 5-7 invalid
0, // 8 invalid
decode_colormap_rle,
decode_truecolor_rle,
decode_greyscale_rle,
0, 0, 0, 0, // 12-15 invalid
[targa_colormap] = decode_colormap,
[targa_truecolor] = decode_truecolor,
[targa_greyscale] = decode_greyscale,
[targa_colormap_rle] = decode_colormap_rle,
[targa_truecolor_rle] = decode_truecolor_rle,
[targa_greyscale_rle] = decode_greyscale_rle,
[targa_max_image_type] = 0
};
#define NUM_DECODERS (sizeof (decoder_functions) \
/ sizeof (decoder_functions[0]))
static QFFormat targa_formats[] = {
[targa_colormap] = tex_palette,
[targa_truecolor] = tex_rgba,
[targa_greyscale] = tex_l,
[targa_colormap_rle] = tex_palette,
[targa_truecolor_rle] = tex_rgba,
[targa_greyscale_rle] = tex_l,
[targa_max_image_type] = 0
};
struct tex_s *
LoadTGA (QFile *fin, int load)
@ -669,6 +675,11 @@ LoadTGA (QFile *fin, int load)
dataByte += targa->id_length;
decode (targa, tex, dataByte);
} else {
//FIXME
// assume the format is valid so we can return a format type without
// having to check individial image type specific data
tex->format = targa_formats[targa->image_type];
}
Hunk_FreeToLowMark (0, targa_mark);

View file

@ -52,55 +52,67 @@
#include "compat.h"
void *
gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc)
static void
gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *texels,
int snum, int gnum, maliasskindesc_t *skindesc)
{
aliashdr_t *header = alias_ctx->header;
byte *pskin;
char modname[MAX_QPATH + 4];
int fb_texnum = 0, texnum = 0;
dstring_t *name = dstring_new ();
pskin = Hunk_AllocName (0, skinsize, alias_ctx->mod->name);
skindesc->skin = (byte *) pskin - (byte *) header;
memcpy (pskin, skin, skinsize);
Mod_FloodFillSkin (pskin, header->mdl.skinwidth, header->mdl.skinheight);
Mod_FloodFillSkin (texels, header->mdl.skinwidth, header->mdl.skinheight);
// save 8 bit texels for the player model to remap
// FIXME remove model restriction
if (strequal (alias_ctx->mod->path, "progs/player.mdl"))
gl_Skin_SetPlayerSkin (header->mdl.skinwidth, header->mdl.skinheight,
pskin);
texels);
QFS_StripExtension (alias_ctx->mod->path, modname);
if (!alias_ctx->mod->fullbright) {
if (group) {
if (gnum != -1) {
dsprintf (name, "fb_%s_%i_%i", modname, snum, gnum);
} else {
dsprintf (name, "fb_%s_%i", modname, snum);
}
fb_texnum = Mod_Fullbright (pskin, header->mdl.skinwidth,
fb_texnum = Mod_Fullbright (texels, header->mdl.skinwidth,
header->mdl.skinheight, name->str);
Sys_MaskPrintf (SYS_glt, "%s %d\n", name->str, fb_texnum);
}
if (group) {
if (gnum != -1) {
dsprintf (name, "%s_%i_%i", modname, snum, gnum);
} else {
dsprintf (name, "%s_%i", modname, snum);
}
texnum = GL_LoadTexture (name->str, header->mdl.skinwidth,
header->mdl.skinheight, pskin, true, false, 1);
header->mdl.skinheight, texels, true, false, 1);
Sys_MaskPrintf (SYS_glt, "%s %d\n", name->str, texnum);
skindesc->texnum = texnum;
skindesc->fb_texnum = fb_texnum;
alias_ctx->mod->hasfullbrights = fb_texnum;
dstring_delete (name);
// alpha param was true for non group skins
return skin + skinsize;
}
void
gl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
{
aliashdr_t *header = alias_ctx->header;
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
int num_skins = alias_ctx->skins.size;
byte *texel_block = Hunk_AllocName (0, skinsize * num_skins,
alias_ctx->mod->name);
for (int i = 0; i < num_skins; i++) {
__auto_type skin = alias_ctx->skins.a + i;
byte *texels = texel_block + i * skinsize;
skin->skindesc->skin = texels - (byte *) header;
memcpy (texels, skin->texels, skinsize);
gl_Mod_LoadSkin (alias_ctx, texels, skin->skin_num, skin->group_num,
skin->skindesc);
}
}
void

View file

@ -48,6 +48,7 @@
#include "QF/GLSL/qf_textures.h"
#include "mod_internal.h"
#include "qfalloca.h"
#include "r_shared.h"
static vec3_t vertex_normals[NUMVERTEXNORMALS] = {
@ -90,28 +91,34 @@ glsl_alias_clear (model_t *m, void *data)
}
}
void *
glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc)
static void
glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *texels,
int snum, int gnum, maliasskindesc_t *skindesc)
{
aliashdr_t *header = alias_ctx->header;
byte *tskin;
int w = header->mdl.skinwidth;
int h = header->mdl.skinheight;
size_t skinsize = w * h;
byte *tskin = alloca (skinsize);
const char *name;
int w, h;
w = header->mdl.skinwidth;
h = header->mdl.skinheight;
tskin = malloc (skinsize);
memcpy (tskin, skin, skinsize);
memcpy (tskin, texels, skinsize);
Mod_FloodFillSkin (tskin, w, h);
if (group)
if (gnum != -1)
name = va (0, "%s_%i_%i", alias_ctx->mod->path, snum, gnum);
else
name = va (0, "%s_%i", alias_ctx->mod->path, snum);
skindesc->texnum = GLSL_LoadQuakeTexture (name, w, h, tskin);
free (tskin);
return skin + skinsize;
}
void
glsl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
{
for (size_t i = 0; i < alias_ctx->skins.size; i++) {
__auto_type skin = alias_ctx->skins.a + i;
glsl_Mod_LoadSkin (alias_ctx, skin->texels,
skin->skin_num, skin->group_num, skin->skindesc);
}
}
void

View file

@ -75,8 +75,14 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins,
pskindesc[snum].type = pskintype->type;
if (pskintype->type == ALIAS_SKIN_SINGLE) {
skin = (byte *) (pskintype + 1);
skin = m_funcs->Mod_LoadSkin (alias_ctx, skin, skinsize, snum, 0,
false, &pskindesc[snum]);
mod_alias_skin_t askin = {
.skin_num = snum,
.group_num = -1,
.texels = skin,
.skindesc = &pskindesc[snum],
};
skin += skinsize;
DARRAY_APPEND (&alias_ctx->skins, askin);
} else {
pskintype++;
pinskingroup = (daliasskingroup_t *) pskintype;
@ -107,13 +113,20 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins,
for (gnum = 0; gnum < groupskins; gnum++) {
paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE;
skin = mod_funcs->Mod_LoadSkin (alias_ctx, skin, skinsize,
snum, gnum, true,
&paliasskingroup->skindescs[gnum]);
skin = (byte *) (pskintype + 1);
mod_alias_skin_t askin = {
.skin_num = snum,
.group_num = gnum,
.texels = skin,
.skindesc = &paliasskingroup->skindescs[gnum],
};
skin += skinsize;
DARRAY_APPEND (&alias_ctx->skins, askin);
}
}
pskintype = (daliasskintype_t *) skin;
}
mod_funcs->Mod_LoadAllSkins (alias_ctx);
return pskintype;
}
@ -232,6 +245,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
DARRAY_INIT (&alias_ctx.poseverts, 256);
DARRAY_INIT (&alias_ctx.stverts, 256);
DARRAY_INIT (&alias_ctx.triangles, 256);
DARRAY_INIT (&alias_ctx.skins, 256);
if (LittleLong (* (unsigned int *) buffer) == HEADER_MDL16)
extra = 1; // extra precision bytes
@ -392,4 +406,5 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
DARRAY_CLEAR (&alias_ctx.poseverts);
DARRAY_CLEAR (&alias_ctx.stverts);
DARRAY_CLEAR (&alias_ctx.triangles);
DARRAY_CLEAR (&alias_ctx.skins);
}

View file

@ -48,20 +48,22 @@
// a pose is a single set of vertexes. a frame may be
// an animating sequence of poses
void *
sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin,
int skinsize, int snum, int gnum,
qboolean group, maliasskindesc_t *skindesc)
void
sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
{
byte *pskin;
aliashdr_t *header = alias_ctx->header;
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
int num_skins = alias_ctx->skins.size;
byte *texel_block = Hunk_AllocName (0, skinsize * num_skins,
alias_ctx->mod->name);
pskin = Hunk_AllocName (0, skinsize, alias_ctx->mod->name);
skindesc->skin = (byte *) pskin - (byte *) alias_ctx->header;
for (size_t i = 0; i < alias_ctx->skins.size; i++) {
__auto_type skin = alias_ctx->skins.a + i;
byte *texels = texel_block + i * skinsize;
memcpy (pskin, skin, skinsize);
return skin + skinsize;
skin->skindesc->skin = texels - (byte *) header;
memcpy (texels, skin->texels, skinsize);
}
}
static void

View file

@ -111,7 +111,7 @@ vulkan_alias_clear (model_t *m, void *data)
}
}
void *
static void *
Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc, vulkan_ctx_t *ctx)
@ -228,6 +228,20 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
return skinpix + skinsize;
}
void
Vulkan_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx)
{
aliashdr_t *header = alias_ctx->header;
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
for (size_t i = 0; i < alias_ctx->skins.size; i++) {
__auto_type skin = alias_ctx->skins.a + i;
Vulkan_Mod_LoadSkin (alias_ctx, skin->texels, skinsize,
skin->skin_num, skin->group_num,
skin->group_num != -1, skin->skindesc, ctx);
}
}
void
Vulkan_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx)
{
@ -401,6 +415,9 @@ Vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m,
for (i = 0; i < numtris; i++) {
for (j = 0; j < 3; j++) {
int vind = alias_ctx->triangles.a[i].vertindex[j];
// can't use indexmap to do the test because it indicates only
// that the vertex has been duplicated, not whether or not
// the vertex is the original or the duplicate
if (alias_ctx->stverts.a[vind].onseam
&& !alias_ctx->triangles.a[i].facesfront) {
vind = indexmap[vind];

View file

@ -52,8 +52,6 @@
#include "mod_internal.h"
#include "r_internal.h"
static gltex_t gl_notexture = { };
static tex_t *
Mod_LoadAnExternalTexture (const char *tname, const char *mname)
{
@ -122,7 +120,6 @@ gl_Mod_ProcessTexture (model_t *mod, texture_t *tx)
const char *name;
if (!tx) {
r_notexture_mip->render = &gl_notexture;
return;
}
if (gl_textures_external) {

View file

@ -60,8 +60,6 @@
#include "mod_internal.h"
#include "r_internal.h"
static glsltex_t glsl_notexture = { };
static void
glsl_brush_clear (model_t *m, void *data)
{
@ -105,7 +103,6 @@ void
glsl_Mod_ProcessTexture (model_t *mod, texture_t *tx)
{
if (!tx) {
r_notexture_mip->render = &glsl_notexture;
return;
}
glsltex_t *tex = tx->render;

View file

@ -62,8 +62,6 @@
#include "r_internal.h"
#include "vid_vulkan.h"
static vulktex_t vulkan_notexture = { };
static void
vulkan_brush_clear (model_t *mod, void *data)
{
@ -302,8 +300,9 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx)
mod->clear = vulkan_brush_clear;
mod->data = mctx;
r_notexture_mip->render = &vulkan_notexture;
load_textures (mod, ctx);
if (mod->brush.numtextures) {
load_textures (mod, ctx);
}
return;
}

View file

@ -0,0 +1,468 @@
/*
vulkan_model_iqm.c
iqm model processing for Vulkan
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2022/05/03
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include "QF/dstring.h"
#include "QF/image.h"
#include "QF/quakefs.h"
#include "QF/va.h"
#include "QF/Vulkan/barrier.h"
#include "QF/Vulkan/device.h"
#include "QF/Vulkan/image.h"
#include "QF/Vulkan/resource.h"
#include "QF/Vulkan/staging.h"
#include "QF/Vulkan/qf_iqm.h"
#include "QF/Vulkan/qf_texture.h"
#include "mod_internal.h"
#include "r_shared.h"
#include "vid_vulkan.h"
static byte null_texture[] = {
204, 204, 204, 255,
204, 204, 204, 255,
204, 204, 204, 255,
204, 204, 204, 255,
};
#if 0
static byte null_normmap[] = {
127, 127, 255, 255,
127, 127, 255, 255,
127, 127, 255, 255,
127, 127, 255, 255,
};
#endif
static void
vulkan_iqm_clear (model_t *mod, void *data)
{
vulkan_ctx_t *ctx = data;
qfv_device_t *device = ctx->device;
iqm_t *iqm = (iqm_t *) mod->aliashdr;
qfv_iqm_t *mesh = iqm->extra_data;
mod->needload = true;
QFV_DestroyResource (device, mesh->bones);
QFV_DestroyResource (device, mesh->mesh);
free (mesh);
Mod_FreeIQM (iqm);
}
static void
vulkan_iqm_init_image (iqm_t *iqm, int meshnum, qfv_resobj_t *image)
{
const char *material = iqm->text + iqm->meshes[meshnum].material;
dstring_t *str = dstring_new ();
dstring_copystr (str, material);
QFS_StripExtension (str->str, str->str);
tex_t *tex;
if ((tex = LoadImage (va (0, "textures/%s", str->str), 0))) {
*image = (qfv_resobj_t) {
.name = material,
.type = qfv_res_image,
.image = {
.type = VK_IMAGE_TYPE_2D,
.format = QFV_ImageFormat (tex->format),
.extent = {
.width = tex->width,
.height = tex->height,
.depth = 1,
},
.num_mipmaps = QFV_MipLevels (tex->width, tex->height),
.num_layers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT,
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_SAMPLED_BIT,
},
};
} else {
*image = (qfv_resobj_t) {
.name = material,
.type = qfv_res_image,
.image = {
.type = VK_IMAGE_TYPE_2D,
.format = QFV_ImageFormat (tex_rgba),
.extent = {
.width = 2,
.height = 2,
.depth = 1,
},
.num_mipmaps = QFV_MipLevels (2, 2),
.num_layers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT,
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_SAMPLED_BIT,
},
};
}
dstring_delete (str);
}
static void
iqm_transfer_texture (tex_t *tex, VkImage image, qfv_stagebuf_t *stage,
qfv_device_t *device)
{
qfv_devfuncs_t *dfunc = device->funcs;
if (tex->format != tex_rgb && tex->format != tex_rgba) {
Sys_Error ("can't transfer iqm image");
}
// FIXME correct only for rgb and rgba
size_t layer_size = tex->width * tex->height * tex->format;
qfv_packet_t *packet = QFV_PacketAcquire (stage);
byte *dst = QFV_PacketExtend (packet, layer_size);
qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst];
ib.barrier.image = image;
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
0, 0, 0, 0, 0,
1, &ib.barrier);
memcpy (dst, tex->data, layer_size);
int mipLevels = QFV_MipLevels (tex->width, tex->height);
if (mipLevels == 1) {
ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly];
ib.barrier.image = image;
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
0, 0, 0, 0, 0,
1, &ib.barrier);
} else {
QFV_GenerateMipMaps (device, packet->cmd, image, mipLevels,
tex->width, tex->height, 1);
}
QFV_PacketSubmit (packet);
}
static void
vulkan_iqm_load_textures (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh,
vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
dstring_t *str = dstring_new ();
tex_t *tex;
size_t buff_size = 0;
qfv_resobj_t *objects = mesh->mesh->objects;
for (int i = 0; i < iqm->num_meshes; i++) {
int image_ind = 3 + 2 * i;
VkExtent3D extent = objects[image_ind].image.extent;
// probably 3 or 4 bytes per pixel FIXME
buff_size = max (buff_size, extent.width * extent.height * 4);
}
qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device,
va (ctx->va_ctx, "iqm:%s",
mod->name),
4 * buff_size,
ctx->cmdpool);
for (int i = 0; i < iqm->num_meshes; i++) {
int image_ind = 3 + 2 * i;
__auto_type image = &objects[image_ind].image;
__auto_type view = &objects[image_ind + 1].image_view;
qfv_iqm_skin_t *skin = &mesh->skins[i];
*skin = (qfv_iqm_skin_t) {
.view = view->view,
.colora = { 255, 255, 255, 255 },
.colorb = { 255, 255, 255, 255 },
};
dstring_copystr (str, iqm->text + iqm->meshes[i].material);
QFS_StripExtension (str->str, str->str);
if (!(tex = LoadImage (va (0, "textures/%s", str->str), 1))) {
tex_t null_tex = {
.width = 2,
.height = 2,
.format = tex_rgba,
.data = null_texture,
};
tex = &null_tex;
}
iqm_transfer_texture (tex, image->image, stage, device);
}
dstring_delete (str);
QFV_DestroyStagingBuffer (stage);
}
static void
vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh,
vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
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);
size_t buff_size = geom_size + rend_size + elem_size + 1024;
qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device,
va (ctx->va_ctx, "iqm:%s",
mod->name),
buff_size, ctx->cmdpool);
qfv_packet_t *gpacket = QFV_PacketAcquire (stage);
iqmgvert_t *gverts = QFV_PacketExtend (gpacket, geom_size);
qfv_packet_t *rpacket = QFV_PacketAcquire (stage);
iqmrvert_t *rverts = QFV_PacketExtend (rpacket, rend_size);
qfv_packet_t *epacket = QFV_PacketAcquire (stage);
uint16_t *elements = QFV_PacketExtend (epacket, elem_size);
//FIXME this whole thing is silly, but some person went and interleaved
//all the vertex data prematurely
for (int i = 0; i < iqm->num_verts; i++) {
byte *data = iqm->vertices + i * iqm->stride;
iqmgvert_t *gv = gverts + i;
iqmrvert_t *rv = rverts + i;
for (int j = 0; j < iqm->num_arrays; j++) {
__auto_type va = &iqm->vertexarrays[j];
// FIXME assumes standard iqm sizes
size_t size = 0;
switch (va->type) {
case IQM_POSITION:
size = sizeof (gv->vertex);
memcpy (gv->vertex, data, size);
break;
case IQM_TEXCOORD:
size = sizeof (rv->uv);
memcpy (rv->uv, data, size);
break;
case IQM_NORMAL:
size = sizeof (rv->normal);
memcpy (rv->normal, data, size);
break;
case IQM_TANGENT:
size = sizeof (rv->tangent);
memcpy (rv->tangent, data, size);
break;
case IQM_BLENDINDEXES:
size = sizeof (gv->bones);
memcpy (gv->bones, data, size);
break;
case IQM_BLENDWEIGHTS:
size = sizeof (gv->weights);
memcpy (gv->weights, data, size);
break;
case IQM_COLOR:
size = sizeof (rv->color);
memcpy (rv->color, data, size);
break;
case IQM_CUSTOM:
// FIXME model loader doesn't handle these, so nothing to do
break;
}
data += size;
}
}
memcpy (elements, iqm->elements, elem_size);
qfv_bufferbarrier_t bb[] = {
bufferBarriers[qfv_BB_Unknown_to_TransferWrite],
bufferBarriers[qfv_BB_Unknown_to_TransferWrite],
bufferBarriers[qfv_BB_Unknown_to_TransferWrite],
};
bb[0].barrier.buffer = mesh->geom_buffer;
bb[0].barrier.size = geom_size;
bb[1].barrier.buffer = mesh->rend_buffer;
bb[1].barrier.size = rend_size;
bb[2].barrier.buffer = mesh->index_buffer;
bb[2].barrier.size = elem_size;
VkBufferCopy copy_region[] = {
{ gpacket->offset, 0, geom_size },
{ rpacket->offset, 0, rend_size },
{ epacket->offset, 0, elem_size },
};
dfunc->vkCmdPipelineBarrier (gpacket->cmd, bb[0].srcStages, bb[0].dstStages,
0, 0, 0, 1, &bb[0].barrier, 0, 0);
dfunc->vkCmdPipelineBarrier (rpacket->cmd, bb[0].srcStages, bb[0].dstStages,
0, 0, 0, 1, &bb[1].barrier, 0, 0);
dfunc->vkCmdPipelineBarrier (epacket->cmd, bb[0].srcStages, bb[0].dstStages,
0, 0, 0, 1, &bb[2].barrier, 0, 0);
dfunc->vkCmdCopyBuffer (gpacket->cmd, stage->buffer,
mesh->geom_buffer, 1, &copy_region[0]);
dfunc->vkCmdCopyBuffer (rpacket->cmd, stage->buffer,
mesh->rend_buffer, 1, &copy_region[1]);
dfunc->vkCmdCopyBuffer (epacket->cmd, stage->buffer,
mesh->index_buffer, 1, &copy_region[2]);
bb[0] = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead];
bb[1] = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead];
bb[2] = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead];
bb[0].barrier.buffer = mesh->geom_buffer;
bb[0].barrier.size = geom_size;
bb[1].barrier.buffer = mesh->rend_buffer;
bb[1].barrier.size = rend_size;
bb[2].barrier.buffer = mesh->index_buffer;
bb[2].barrier.size = elem_size;
dfunc->vkCmdPipelineBarrier (gpacket->cmd, bb[0].srcStages, bb[0].dstStages,
0, 0, 0, 1, &bb[0].barrier, 0, 0);
dfunc->vkCmdPipelineBarrier (rpacket->cmd, bb[0].srcStages, bb[0].dstStages,
0, 0, 0, 1, &bb[1].barrier, 0, 0);
dfunc->vkCmdPipelineBarrier (epacket->cmd, bb[0].srcStages, bb[0].dstStages,
0, 0, 0, 1, &bb[2].barrier, 0, 0);
QFV_PacketSubmit (gpacket);
QFV_PacketSubmit (rpacket);
QFV_PacketSubmit (epacket);
QFV_DestroyStagingBuffer (stage);
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++) {
vec4f_t *bone = bone_data + i * 3;
bone[0] = (vec4f_t) {1, 0, 0, 0};
bone[1] = (vec4f_t) {0, 1, 0, 0};
bone[2] = (vec4f_t) {0, 0, 1, 0};
}
VkMappedMemoryRange range = {
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
mesh->bones->memory, 0, VK_WHOLE_SIZE,
};
dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range);
dfunc->vkUnmapMemory (device->dev, mesh->bones->memory);
}
void
Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
iqm_t *iqm = (iqm_t *) mod->aliashdr;
mod->clear = vulkan_iqm_clear;
mod->data = ctx;
// FIXME assumes only one texture per mesh (currently the case, but
// when materials are added...)
// 2 is for image + image view
int num_objects = 4 + 2 * iqm->num_meshes;
qfv_iqm_t *mesh = calloc (1, sizeof (qfv_iqm_t)
+ 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->mesh = &mesh->bones[1];
mesh->bones[0] = (qfv_resource_t) {
.name = mod->name,
.va_ctx = ctx->va_ctx,
.memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
.num_objects = 1,
.objects = (qfv_resobj_t *) &mesh->bones[2],
};
mesh->bones->objects[0] = (qfv_resobj_t) {
.name = "bones",
.type = qfv_res_buffer,
.buffer = {
.size = 3 * iqm->num_joints * 3 * sizeof (vec4f_t),
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
},
};
mesh->mesh[0] = (qfv_resource_t) {
.name = "mesh",
.va_ctx = ctx->va_ctx,
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
.num_objects = num_objects - 1,
.objects = mesh->bones->objects + 1,
};
mesh->mesh->objects[0] = (qfv_resobj_t) {
.name = "geom",
.type = qfv_res_buffer,
.buffer = {
.size = iqm->num_verts * sizeof (iqmgvert_t),
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
},
};
mesh->mesh->objects[1] = (qfv_resobj_t) {
.name = "rend",
.type = qfv_res_buffer,
.buffer = {
.size = iqm->num_verts * sizeof (iqmrvert_t),
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
},
};
mesh->mesh->objects[2] = (qfv_resobj_t) {
.name = "index",
.type = qfv_res_buffer,
.buffer = {
.size = iqm->num_elements * sizeof (uint16_t),
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
},
};
for (int i = 0; i < iqm->num_meshes; i++) {
int image_ind = 3 + 2 * i;
__auto_type image = &mesh->mesh->objects[image_ind];
vulkan_iqm_init_image (iqm, i, image);
mesh->mesh->objects[image_ind + 1] = (qfv_resobj_t) {
.name = "view",
.type = qfv_res_image_view,
.image_view = {
.image = image_ind,
.type = VK_IMAGE_VIEW_TYPE_2D,
.format = mesh->mesh->objects[image_ind].image.format,
.aspect = VK_IMAGE_ASPECT_COLOR_BIT,
},
};
}
mesh->skins = (qfv_iqm_skin_t *) &mesh->bones->objects[num_objects];
QFV_CreateResource (device, mesh->mesh);
QFV_CreateResource (device, mesh->bones);
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;
vulkan_iqm_load_textures (mod, iqm, mesh, ctx);
vulkan_iqm_load_arrays (mod, iqm, mesh, ctx);
iqm->extra_data = mesh;
}

View file

@ -138,22 +138,31 @@ Mod_Init_Cvars (void)
Cvar_Register (&gl_textures_external_cvar, 0, 0);
}
static void
mod_unload_model (size_t ind)
{
model_t *mod = mod_known.a[ind];
//FIXME this seems to be correct but need to double check the behavior
//with alias models
if (!mod->needload && mod->clear) {
mod->clear (mod, mod->data);
}
if (mod->type != mod_alias) {
mod->needload = true;
}
if (mod->type == mod_sprite) {
mod->cache.data = 0;
}
}
VISIBLE void
Mod_ClearAll (void)
{
size_t i;
model_t **mod;
for (i = 0, mod = mod_known.a; i < mod_numknown; i++, mod++) {
//FIXME this seems to be correct but need to double check the behavior
//with alias models
if (!(*mod)->needload && (*mod)->clear) {
(*mod)->clear (*mod, (*mod)->data);
}
if ((*mod)->type != mod_alias)
(*mod)->needload = true;
if ((*mod)->type == mod_sprite)
(*mod)->cache.data = 0;
for (i = 0; i < mod_numknown; i++) {
mod_unload_model (i);
}
}
@ -323,6 +332,16 @@ Mod_TouchModel (const char *name)
}
}
VISIBLE void
Mod_UnloadModel (model_t *model)
{
for (size_t i = 0; i < mod_numknown; i++) {
if (mod_known.a[i] == model) {
mod_unload_model (i);
}
}
}
VISIBLE void
Mod_Print (void)
{

View file

@ -34,36 +34,37 @@
net_driver_t net_drivers[MAX_NET_DRIVERS] = {
{
"Loopback",
false,
Loop_Init,
Loop_Listen,
Loop_SearchForHosts,
Loop_Connect,
Loop_CheckNewConnections,
Loop_GetMessage,
Loop_SendMessage,
Loop_SendUnreliableMessage,
Loop_CanSendMessage,
Loop_CanSendUnreliableMessage,
Loop_Close,
Loop_Shutdown}
,
.name = "Loopback",
.initialized = false,
.Init = Loop_Init,
.Listen = Loop_Listen,
.SearchForHosts = Loop_SearchForHosts,
.Connect = Loop_Connect,
.CheckNewConnections = Loop_CheckNewConnections,
.QGetMessage = Loop_GetMessage,
.QSendMessage = Loop_SendMessage,
.SendUnreliableMessage = Loop_SendUnreliableMessage,
.CanSendMessage = Loop_CanSendMessage,
.CanSendUnreliableMessage = Loop_CanSendUnreliableMessage,
.Close = Loop_Close,
.Shutdown = Loop_Shutdown,
},
{
"Datagram",
false,
Datagram_Init,
Datagram_Listen,
Datagram_SearchForHosts,
Datagram_Connect,
Datagram_CheckNewConnections,
Datagram_GetMessage,
Datagram_SendMessage,
Datagram_SendUnreliableMessage,
Datagram_CanSendMessage,
Datagram_CanSendUnreliableMessage,
Datagram_Close,
Datagram_Shutdown}
.name = "Datagram",
.initialized = false,
.Init = Datagram_Init,
.Listen = Datagram_Listen,
.SearchForHosts = Datagram_SearchForHosts,
.Connect = Datagram_Connect,
.CheckNewConnections = Datagram_CheckNewConnections,
.QGetMessage = Datagram_GetMessage,
.QSendMessage = Datagram_SendMessage,
.SendUnreliableMessage = Datagram_SendUnreliableMessage,
.CanSendMessage = Datagram_CanSendMessage,
.CanSendUnreliableMessage = Datagram_CanSendUnreliableMessage,
.Close = Datagram_Close,
.Shutdown = Datagram_Shutdown,
},
};
int net_numdrivers = 2;
@ -72,26 +73,27 @@ int net_numdrivers = 2;
net_landriver_t net_landrivers[MAX_NET_DRIVERS] = {
{
"UDP",
false,
0,
UDP_Init,
UDP_Shutdown,
UDP_Listen,
UDP_OpenSocket,
UDP_CloseSocket,
UDP_Connect,
UDP_CheckNewConnections,
UDP_Read,
UDP_Write,
UDP_Broadcast,
UDP_AddrToString,
UDP_GetSocketAddr,
UDP_GetNameFromAddr,
UDP_GetAddrFromName,
UDP_AddrCompare,
UDP_GetSocketPort,
UDP_SetSocketPort}
.name = "UDP",
.initialized = false,
.controlSock = 0,
.Init = UDP_Init,
.Shutdown = UDP_Shutdown,
.Listen = UDP_Listen,
.OpenSocket = UDP_OpenSocket,
.CloseSocket = UDP_CloseSocket,
.Connect = UDP_Connect,
.CheckNewConnections = UDP_CheckNewConnections,
.Read = UDP_Read,
.Write = UDP_Write,
.Broadcast = UDP_Broadcast,
.AddrToString = UDP_AddrToString,
.GetSocketAddr = UDP_GetSocketAddr,
.GetNameFromAddr = UDP_GetNameFromAddr,
.GetAddrFromName = UDP_GetAddrFromName,
.AddrCompare = UDP_AddrCompare,
.GetSocketPort = UDP_GetSocketPort,
.SetSocketPort = UDP_SetSocketPort,
},
};
int net_numlandrivers = 1;

View file

@ -33,36 +33,37 @@
net_driver_t net_drivers[MAX_NET_DRIVERS] = {
{
"Loopback",
false,
Loop_Init,
Loop_Listen,
Loop_SearchForHosts,
Loop_Connect,
Loop_CheckNewConnections,
Loop_GetMessage,
Loop_SendMessage,
Loop_SendUnreliableMessage,
Loop_CanSendMessage,
Loop_CanSendUnreliableMessage,
Loop_Close,
Loop_Shutdown}
,
.name = "Loopback",
.initialized = false,
.Init = Loop_Init,
.Listen = Loop_Listen,
.SearchForHosts = Loop_SearchForHosts,
.Connect = Loop_Connect,
.CheckNewConnections = Loop_CheckNewConnections,
.QGetMessage = Loop_GetMessage,
.QSendMessage = Loop_SendMessage,
.SendUnreliableMessage = Loop_SendUnreliableMessage,
.CanSendMessage = Loop_CanSendMessage,
.CanSendUnreliableMessage = Loop_CanSendUnreliableMessage,
.Close = Loop_Close,
.Shutdown = Loop_Shutdown,
},
{
"Datagram",
false,
Datagram_Init,
Datagram_Listen,
Datagram_SearchForHosts,
Datagram_Connect,
Datagram_CheckNewConnections,
Datagram_GetMessage,
Datagram_SendMessage,
Datagram_SendUnreliableMessage,
Datagram_CanSendMessage,
Datagram_CanSendUnreliableMessage,
Datagram_Close,
Datagram_Shutdown}
.name = "Datagram",
.initialized = false,
.Init = Datagram_Init,
.Listen = Datagram_Listen,
.SearchForHosts = Datagram_SearchForHosts,
.Connect = Datagram_Connect,
.CheckNewConnections = Datagram_CheckNewConnections,
.QGetMessage = Datagram_GetMessage,
.QSendMessage = Datagram_SendMessage,
.SendUnreliableMessage = Datagram_SendUnreliableMessage,
.CanSendMessage = Datagram_CanSendMessage,
.CanSendUnreliableMessage = Datagram_CanSendUnreliableMessage,
.Close = Datagram_Close,
.Shutdown = Datagram_Shutdown,
},
};
int net_numdrivers = 2;
@ -72,26 +73,27 @@ int net_numdrivers = 2;
net_landriver_t net_landrivers[MAX_NET_DRIVERS] = {
{
"Winsock TCPIP",
false,
0,
WINS_Init,
WINS_Shutdown,
WINS_Listen,
WINS_OpenSocket,
WINS_CloseSocket,
WINS_Connect,
WINS_CheckNewConnections,
WINS_Read,
WINS_Write,
WINS_Broadcast,
WINS_AddrToString,
WINS_GetSocketAddr,
WINS_GetNameFromAddr,
WINS_GetAddrFromName,
WINS_AddrCompare,
WINS_GetSocketPort,
WINS_SetSocketPort},
.name = "Winsock TCPIP",
.initialized = false,
.controlSock = 0,
.Init = WINS_Init,
.Shutdown = WINS_Shutdown,
.Listen = WINS_Listen,
.OpenSocket = WINS_OpenSocket,
.CloseSocket = WINS_CloseSocket,
.Connect = WINS_Connect,
.CheckNewConnections = WINS_CheckNewConnections,
.Read = WINS_Read,
.Write = WINS_Write,
.Broadcast = WINS_Broadcast,
.AddrToString = WINS_AddrToString,
.GetSocketAddr = WINS_GetSocketAddr,
.GetNameFromAddr = WINS_GetNameFromAddr,
.GetAddrFromName = WINS_GetAddrFromName,
.AddrCompare = WINS_AddrCompare,
.GetSocketPort = WINS_GetSocketPort,
.SetSocketPort = WINS_SetSocketPort,
},
};
int net_numlandrivers = 1;

View file

@ -38,4 +38,5 @@ libs_ruamoko_libQFruamoko_client_la_SOURCES= \
libs/ruamoko/rua_game_init.c \
libs/ruamoko/rua_input.c \
libs/ruamoko/rua_mersenne.c \
libs/ruamoko/rua_model.c \
libs/ruamoko/rua_scene.c

View file

@ -36,6 +36,7 @@
static void (*init_funcs[])(progs_t *, int) = {
RUA_Input_Init,
RUA_Mersenne_Init,
RUA_Model_Init,
RUA_Scene_Init,
};

182
libs/ruamoko/rua_model.c Normal file
View file

@ -0,0 +1,182 @@
/*
bi_model.c
Ruamkoko model builtins
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/model.h"
#include "QF/progs.h"
#include "rua_internal.h"
typedef struct rua_model_s {
struct rua_model_s *next;
struct rua_model_s **prev;
model_t *model;
} rua_model_t;
typedef struct {
PR_RESMAP (rua_model_t) model_map;
rua_model_t *handles;
progs_t *pr;
} rua_model_resources_t;
static rua_model_t *
rua_model_handle_new (rua_model_resources_t *res)
{
return PR_RESNEW (res->model_map);
}
static void
rua_model_handle_free (rua_model_resources_t *res, rua_model_t *handle)
{
PR_RESFREE (res->model_map, handle);
}
static void
rua_model_handle_reset (rua_model_resources_t *res)
{
PR_RESRESET (res->model_map);
}
static inline rua_model_t * __attribute__((pure))
rua__model_handle_get (rua_model_resources_t *res, int index, const char *name)
{
rua_model_t *handle = 0;
handle = PR_RESGET(res->model_map, index);
if (!handle) {
PR_RunError (res->pr, "invalid model handle passed to %s", name + 3);
}
return handle;
}
#define rua_model_handle_get(res, index) \
rua__model_handle_get (res, index, __FUNCTION__)
static inline int __attribute__((pure))
rua_model_handle_index (rua_model_resources_t *res, rua_model_t *handle)
{
return PR_RESINDEX(res->model_map, handle);
}
static void
bi_rua_model_clear (progs_t *pr, void *_res)
{
rua_model_resources_t *res = (rua_model_resources_t *) _res;
rua_model_t *handle;
for (handle = res->handles; handle; handle = handle->next)
Mod_UnloadModel (handle->model);
res->handles = 0;
rua_model_handle_reset (res);
}
static int
alloc_handle (rua_model_resources_t *res, model_t *model)
{
rua_model_t *handle = rua_model_handle_new (res);
if (!handle)
return 0;
handle->next = res->handles;
handle->prev = &res->handles;
if (res->handles)
res->handles->prev = &handle->next;
res->handles = handle;
handle->model = model;
return rua_model_handle_index (res, handle);
}
static void
bi_Model_Load (progs_t *pr, void *_res)
{
__auto_type res = (rua_model_resources_t *) _res;
const char *path = P_GSTRING (pr, 0);
model_t *model;
R_INT (pr) = 0;
if (!(model = Mod_ForName (path, 0)))
return;
if (!(R_INT (pr) = alloc_handle (res, model)))
Mod_UnloadModel (model);
}
model_t *
Model_GetModel (progs_t *pr, int handle)
{
if (!handle) {
return 0;
}
rua_model_resources_t *res = PR_Resources_Find (pr, "Model");
rua_model_t *h = rua_model_handle_get (res, handle);
return h->model;
}
static void
bi_Model_Unload (progs_t *pr, void *_res)
{
__auto_type res = (rua_model_resources_t *) _res;
int handle = P_INT (pr, 0);
rua_model_t *h = rua_model_handle_get (res, handle);
if (!h)
PR_RunError (pr, "invalid model handle passed to Qclose");
Mod_UnloadModel (h->model);
*h->prev = h->next;
if (h->next)
h->next->prev = h->prev;
rua_model_handle_free (res, h);
}
#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}}
#define p(type) PR_PARAM(type)
#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), }
static builtin_t builtins[] = {
bi(Model_Load, 1, p(string)),
bi(Model_Unload, 1, p(ptr)),
{0}
};
void
RUA_Model_Init (progs_t *pr, int secure)
{
rua_model_resources_t *res = calloc (sizeof (rua_model_resources_t), 1);
res->pr = pr;
PR_Resources_Register (pr, "Model", res, bi_rua_model_clear);
PR_RegisterBuiltins (pr, builtins, res);
}

View file

@ -38,9 +38,14 @@
#include "QF/cmem.h"
#include "QF/hash.h"
#include "QF/model.h"
#include "QF/progs.h"
#include "QF/render.h"
#include "QF/plugin/vid_render.h"
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "QF/scene/transform.h"
@ -52,10 +57,18 @@ typedef struct rua_scene_s {
scene_t *scene;
} rua_scene_t;
typedef struct rua_lighting_s {
struct rua_lighting_s *next;
struct rua_lighting_s **prev;
lightingdata_t *ldata;
} rua_lighting_t;
typedef struct rua_scene_resources_s {
progs_t *pr;
PR_RESMAP (rua_scene_t) scene_map;
PR_RESMAP (rua_lighting_t) lighting_map;
rua_scene_t *scenes;
rua_lighting_t *ldatas;
} rua_scene_resources_t;
static rua_scene_t *
@ -92,6 +105,12 @@ rua__scene_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name)
}
#define rua_scene_get(res, id) rua__scene_get(res, id, __FUNCTION__)
static int __attribute__((pure))
rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene)
{
return PR_RESINDEX (res->scene_map, scene);
}
static entity_t * __attribute__((pure))
rua__entity_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name)
{
@ -130,10 +149,44 @@ rua__transform_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name)
}
#define rua_transform_get(res, id) rua__transform_get(res, id, __FUNCTION__)
static int __attribute__((pure))
rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene)
static rua_lighting_t *
rua_lighting_new (rua_scene_resources_t *res)
{
return PR_RESINDEX (res->scene_map, scene);
return PR_RESNEW (res->lighting_map);
}
static void
rua_lighting_free (rua_scene_resources_t *res, rua_lighting_t *ldata)
{
if (ldata->next) {
ldata->next->prev = ldata->prev;
}
*ldata->prev = ldata->next;
ldata->prev = 0;
PR_RESFREE (res->lighting_map, ldata);
}
static rua_lighting_t * __attribute__((pure))
rua__lighting_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name)
{
rua_lighting_t *ldata = 0;
if (id <= 0xffffffffu) {
ldata = PR_RESGET (res->lighting_map, (pr_int_t) id);
}
// ldata->prev will be null if the handle is unallocated
if (!ldata || !ldata->prev) {
PR_RunError (res->pr, "invalid lighting passed to %s", name + 3);
}
return ldata;
}
#define rua_lighting_get(res, id) rua__lighting_get(res, id, __FUNCTION__)
static int __attribute__((pure))
rua_lighting_index (rua_scene_resources_t *res, rua_lighting_t *ldata)
{
return PR_RESINDEX (res->lighting_map, ldata);
}
#define MAKE_ID(id, sc_id) ((((pr_ulong_t) (id)) << 32) \
@ -176,6 +229,17 @@ bi_Scene_DeleteScene (progs_t *pr, void *_res)
rua_delete_scene (res, scene);
}
scene_t *
Scene_GetScene (progs_t *pr, pr_ulong_t handle)
{
if (!handle) {
return 0;
}
rua_scene_resources_t *res = PR_Resources_Find (pr, "Scene");
rua_scene_t *scene = rua_scene_get (res, P_ULONG (pr, 0));
return scene->scene;
}
static void
bi_Scene_CreateEntity (progs_t *pr, void *_res)
{
@ -198,6 +262,22 @@ bi_Scene_DestroyEntity (progs_t *pr, void *_res)
Scene_DestroyEntity (scene->scene, ent);
}
static void
bi_Scene_SetLighting (progs_t *pr, void *_res)
{
rua_scene_resources_t *res = _res;
pr_ulong_t scene_id = P_ULONG (pr, 0);
rua_scene_t *scene = rua_scene_get (res, scene_id);
pr_ulong_t ldata_id = P_ULONG (pr, 1);
rua_lighting_t *ldata = 0;
if (ldata_id) {
ldata = rua_lighting_get (res, ldata_id);
}
scene->scene->lights = ldata->ldata;
}
static void
bi_Entity_GetTransform (progs_t *pr, void *_res)
{
@ -209,6 +289,23 @@ bi_Entity_GetTransform (progs_t *pr, void *_res)
R_ULONG (pr) = MAKE_ID (ent->transform->id, ent_id);
}
static void
bi_Entity_SetModel (progs_t *pr, void *_res)
{
rua_scene_resources_t *res = _res;
pr_ulong_t ent_id = P_ULONG (pr, 0);
pr_int_t model_id = P_INT (pr, 1);
entity_t *ent = rua_entity_get (res, ent_id);
model_t *model = Model_GetModel (pr, model_id);
pr_ulong_t scene_id = ent_id & 0xffffffff;
// bad scene caught above
rua_scene_t *scene = rua_scene_get (res, scene_id);
R_RemoveEfrags (ent);
ent->renderer.model = model;
R_AddEfrags (&scene->scene->worldmodel->brush, ent);
}
static void
bi_Transform_ChildCount (progs_t *pr, void *_res)
{
@ -421,6 +518,74 @@ bi_Transform_Up (progs_t *pr, void *_res)
R_PACKED (pr, pr_vec4_t) = Transform_Up (transform);
}
static void
bi_Light_CreateLightingData (progs_t *pr, void *_res)
{
rua_scene_resources_t *res = _res;
pr_ulong_t scene_id = P_ULONG (pr, 0);
rua_scene_t *scene = rua_scene_get (res, scene_id);
rua_lighting_t *ldata = rua_lighting_new (res);
ldata->ldata = Light_CreateLightingData (scene->scene);
ldata->next = res->ldatas;
if (res->ldatas) {
res->ldatas->prev = &ldata->next;
}
ldata->prev = &res->ldatas;
res->ldatas = ldata;
// ldata id in lower 32-bits for all handles
// upper 32-bits reserved
R_ULONG (pr) = MAKE_ID (0, rua_lighting_index (res, ldata));
}
static void
rua_delete_lighting (rua_scene_resources_t *res, rua_lighting_t *ldata)
{
Light_DestroyLightingData (ldata->ldata);
rua_lighting_free (res, ldata);
}
static void
bi_Light_DestroyLightingData (progs_t *pr, void *_res)
{
rua_scene_resources_t *res = _res;
rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0));
rua_delete_lighting (res, ldata);
}
static void
bi_Light_ClearLights (progs_t *pr, void *_res)
{
rua_scene_resources_t *res = _res;
rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0));
Light_ClearLights (ldata->ldata);
}
static void
bi_Light_AddLight (progs_t *pr, void *_res)
{
rua_scene_resources_t *res = _res;
rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0));
light_t *light = &P_PACKED (pr, light_t, 1);
int style = P_INT (pr, 5);
Light_AddLight (ldata->ldata, light, style);
}
static void
bi_Light_EnableSun (progs_t *pr, void *_res)
{
rua_scene_resources_t *res = _res;
rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0));
Light_EnableSun (ldata->ldata);
}
#define p(type) PR_PARAM(type)
#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), }
#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}}
@ -429,8 +594,10 @@ static builtin_t builtins[] = {
bi(Scene_DeleteScene, 1, p(ulong)),
bi(Scene_CreateEntity, 1, p(ulong)),
bi(Scene_DestroyEntity, 1, p(ulong)),
bi(Scene_SetLighting , 2, p(ulong), p(ulong)),
bi(Entity_GetTransform, 1, p(ulong)),
bi(Entity_SetModel, 2, p(ulong), p(int)),
bi(Transform_ChildCount, 1, p(ulong)),
bi(Transform_GetChild, 2, p(ulong), p(int)),
@ -463,6 +630,13 @@ static builtin_t builtins[] = {
bi(Transform_Right, 1, p(ulong)),
bi(Transform_Up, 1, p(ulong)),
bi(Light_CreateLightingData, 1, p(ulong)),
bi(Light_DestroyLightingData, 1, p(ulong)),
bi(Light_ClearLights, 1, p(ulong)),
bi(Light_AddLight, 5, p(ulong),// really, 3
p(vec4), p(vec4), p(vec4), p(vec4), p(int)),
bi(Light_EnableSun, 1, p(ulong)),
{0}
};
@ -471,6 +645,9 @@ bi_scene_clear (progs_t *pr, void *_res)
{
rua_scene_resources_t *res = _res;
while (res->ldatas) {
rua_delete_lighting (res, res->ldatas);
}
while (res->scenes) {
rua_delete_scene (res, res->scenes);
}
@ -483,6 +660,6 @@ RUA_Scene_Init (progs_t *pr, int secure)
res->pr = pr;
PR_Resources_Register (pr, "scene", res, bi_scene_clear);
PR_Resources_Register (pr, "Scene", res, bi_scene_clear);
PR_RegisterBuiltins (pr, builtins, res);
}

View file

@ -11,5 +11,6 @@ libs_scene_libQFscene_la_SOURCES= \
libs/scene/camera.c \
libs/scene/entity.c \
libs/scene/hierarchy.c \
libs/scene/light.c \
libs/scene/scene.c \
libs/scene/transform.c

View file

@ -80,7 +80,7 @@ hierarchy_calcLocalInverse (hierarchy_t *h, uint32_t index)
vec4f_t t = h->localMatrix.a[index][3];
// "one" is to ensure both the scalar and translation have 1 in their
// forth components
// fourth components
vec4f_t one = { 0, 0, 0, 1 };
vec4f_t nx = { x[0], y[0], z[0], 0 };
vec4f_t ny = { x[1], y[1], z[1], 0 };

162
libs/scene/light.c Normal file
View file

@ -0,0 +1,162 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h>
#include "QF/model.h"
#include "QF/set.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "QF/simd/vec4f.h"
static void
expand_pvs (set_t *pvs, model_t *model)
{
set_t base_pvs = SET_STATIC_INIT (model->brush.visleafs, alloca);
set_assign (&base_pvs, pvs);
for (unsigned i = 0; i < model->brush.visleafs; i++) {
if (set_is_member (&base_pvs, i)) {
Mod_LeafPVS_mix (model->brush.leafs + i + 1, model, 0, pvs);
}
}
}
lightingdata_t *
Light_CreateLightingData (scene_t *scene)
{
lightingdata_t *ldata = calloc (1, sizeof (lightingdata_t));
DARRAY_INIT (&ldata->lights, 16);
DARRAY_INIT (&ldata->lightstyles, 16);
DARRAY_INIT (&ldata->lightleafs, 16);
DARRAY_INIT (&ldata->lightvis, 16);
ldata->scene = scene;
return ldata;
}
void
Light_DestroyLightingData (lightingdata_t *ldata)
{
DARRAY_CLEAR (&ldata->lights);
DARRAY_CLEAR (&ldata->lightstyles);
DARRAY_CLEAR (&ldata->lightleafs);
DARRAY_CLEAR (&ldata->lightvis);
free (ldata);
}
void
Light_ClearLights (lightingdata_t *ldata)
{
ldata->lights.size = 0;
ldata->lightstyles.size = 0;
ldata->lightleafs.size = 0;
ldata->lightvis.size = 0;
if (ldata->sun_pvs) {
set_delete (ldata->sun_pvs);
}
ldata->sun_pvs = 0;
if (ldata->pvs) {
set_delete (ldata->pvs);
}
ldata->pvs = 0;
ldata->leaf = 0;
}
void
Light_AddLight (lightingdata_t *ldata, const light_t *light, int style)
{
scene_t *scene = ldata->scene;
model_t *model = scene->worldmodel;
DARRAY_APPEND (&ldata->lights, *light);
DARRAY_APPEND (&ldata->lightstyles, style);
int visleaf = -1; // directional light
if (light->position[3]) {
// positional light
mleaf_t *leaf = Mod_PointInLeaf (&light->position[0], model);
visleaf = leaf - model->brush.leafs - 1;
} else if (!DotProduct (light->direction, light->direction)) {
// ambient light
visleaf = -2;
}
DARRAY_APPEND (&ldata->lightleafs, visleaf);
DARRAY_APPEND (&ldata->lightvis, 0);
}
void
Light_EnableSun (lightingdata_t *ldata)
{
scene_t *scene = ldata->scene;
model_t *model = scene->worldmodel;
if (!ldata->sun_pvs) {
ldata->sun_pvs = set_new_size (model->brush.visleafs);
}
set_expand (ldata->sun_pvs, model->brush.visleafs);
set_empty (ldata->sun_pvs);
// Any leaf with sky surfaces can potentially see the sun, thus put
// the sun "in" every leaf with a sky surface
// however, skip leaf 0 as it is the exterior solid leaf
for (unsigned l = 1; l < model->brush.modleafs; l++) {
if (model->brush.leaf_flags[l] & SURF_DRAWSKY) {
set_add (ldata->sun_pvs, l - 1); //pvs is 1-based
}
}
// any leaf visible from a leaf with a sky surface (and thus the sun)
// can receive shadows from the sun
expand_pvs (ldata->sun_pvs, model);
}
void
Light_FindVisibleLights (lightingdata_t *ldata)
{
scene_t *scene = ldata->scene;
mleaf_t *leaf = scene->viewleaf;
model_t *model = scene->worldmodel;
if (!leaf) {
return;
}
if (!ldata->pvs) {
ldata->pvs = set_new_size (model->brush.visleafs);
}
if (leaf != ldata->leaf) {
//double start = Sys_DoubleTime ();
int flags = 0;
if (leaf == model->brush.leafs) {
set_everything (ldata->pvs);
} else {
Mod_LeafPVS_set (leaf, model, 0, ldata->pvs);
expand_pvs (ldata->pvs, model);
}
for (unsigned i = 0; i < model->brush.visleafs; i++) {
if (set_is_member (ldata->pvs, i)) {
flags |= model->brush.leaf_flags[i + 1];
}
}
ldata->leaf = leaf;
//double end = Sys_DoubleTime ();
//Sys_Printf ("find_visible_lights: %.5gus\n", (end - start) * 1e6);
int visible = 0;
memset (ldata->lightvis.a, 0, ldata->lightvis.size * sizeof (byte));
for (size_t i = 0; i < ldata->lightleafs.size; i++) {
int l = ldata->lightleafs.a[i];
if ((l == -2) || (l == -1 && (flags & SURF_DRAWSKY))
|| set_is_member (ldata->pvs, l)) {
ldata->lightvis.a[i] = 1;
visible++;
}
}
//Sys_Printf ("find_visible_lights: %d / %zd visible\n", visible,
// ldata->lightvis.size);
}
}

View file

@ -35,8 +35,10 @@
# include <strings.h>
#endif
#include "QF/mathlib.h"
#include "QF/progs.h" // for PR_RESMAP
#include "QF/sys.h"
#include "QF/model.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
@ -44,6 +46,44 @@
#include "scn_internal.h"
static byte empty_visdata[] = { 0x01 };
static mleaf_t empty_leafs[] = {
[1] = {
.contents = CONTENTS_EMPTY,
.mins = {-INFINITY, -INFINITY, -INFINITY},
.maxs = { INFINITY, INFINITY, INFINITY},
.compressed_vis = empty_visdata,
},
};
static mnode_t *empty_leaf_parents[] = {
[1] = 0,
};
static int empty_leaf_flags[] = {
[1] = SURF_DRAWSKY,
};
static char empty_entities[] = { 0 };
static model_t empty_world = {
.type = mod_brush,
.radius = INFINITY,
.mins = {-INFINITY, -INFINITY, -INFINITY},
.maxs = { INFINITY, INFINITY, INFINITY},
.brush = {
.modleafs = 2,
.visleafs = 1,
.nodes = (mnode_t *) &empty_leafs[1],
.leafs = empty_leafs,
.entities = empty_entities,
.visdata = empty_visdata,
.leaf_parents = empty_leaf_parents,
.leaf_flags = empty_leaf_flags,
},
};
scene_t *
Scene_NewScene (void)
{
@ -54,6 +94,8 @@ Scene_NewScene (void)
res = calloc (1, sizeof (scene_resources_t));
*(scene_resources_t **)&scene->resources = res;
scene->worldmodel = &empty_world;
return scene;
}
@ -84,6 +126,8 @@ Scene_CreateEntity (scene_t *scene)
hierarchy_t *h = ent->transform->hierarchy;
h->entity.a[ent->transform->index] = ent;
QuatSet (1, 1, 1, 1, ent->renderer.colormod);
return ent;
}

View file

@ -91,7 +91,7 @@ libs_video_renderer_librender_gl_la_SOURCES = \
shader_src= libs/video/renderer/glsl/quakeforge.glsl
shader_gen= libs/video/renderer/glsl/quakeforge.slc
SUFFICES += .frag .vert .spv .spvc .fc .vc .slc .glsl
SUFFIXES += .frag .vert .spv .spvc .fc .vc .slc .glsl
.glsl.slc:
$(V_SED)sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\
$(am__mv) $@.t $@
@ -207,6 +207,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \
libs/video/renderer/vulkan/pipeline.c \
libs/video/renderer/vulkan/projection.c \
libs/video/renderer/vulkan/renderpass.c \
libs/video/renderer/vulkan/resource.c \
libs/video/renderer/vulkan/scrap.c \
libs/video/renderer/vulkan/shader.c \
libs/video/renderer/vulkan/staging.c \
@ -218,6 +219,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \
libs/video/renderer/vulkan/vulkan_bsp.c \
libs/video/renderer/vulkan/vulkan_compose.c \
libs/video/renderer/vulkan/vulkan_draw.c \
libs/video/renderer/vulkan/vulkan_iqm.c \
libs/video/renderer/vulkan/vulkan_lighting.c \
libs/video/renderer/vulkan/vulkan_main.c \
libs/video/renderer/vulkan/vulkan_matrices.c \
@ -299,8 +301,14 @@ alias_gbuf_src = $(vkshaderpath)/alias_gbuf.frag
alias_gbuf_c = $(vkshaderpath)/alias_gbuf.frag.spvc
alias_shadow_src = $(vkshaderpath)/alias_shadow.vert
alias_shadow_c = $(vkshaderpath)/alias_shadow.vert.spvc
iqmv_src = $(vkshaderpath)/iqm.vert
iqmv_c = $(vkshaderpath)/iqm.vert.spvc
iqmf_src = $(vkshaderpath)/iqm.frag
iqmf_c = $(vkshaderpath)/iqm.frag.spvc
passthrough_src = $(vkshaderpath)/passthrough.vert
passthrough_c = $(vkshaderpath)/passthrough.vert.spvc
fstriangle_src = $(vkshaderpath)/fstriangle.vert
fstriangle_c = $(vkshaderpath)/fstriangle.vert.spvc
pushcolor_src = $(vkshaderpath)/pushcolor.frag
pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc
shadow_src = $(vkshaderpath)/shadow.geom
@ -356,8 +364,14 @@ $(alias_gbuf_c): $(alias_gbuf_src)
$(alias_shadow_c): $(alias_shadow_src)
$(iqmv_c): $(iqmv_src)
$(iqmf_c): $(iqmf_src)
$(passthrough_c): $(passthrough_src)
$(fstriangle_c): $(fstriangle_src)
$(pushcolor_c): $(pushcolor_src)
$(shadow_c): $(shadow_src)
@ -390,7 +404,10 @@ vkshader_c = \
$(aliasf_c) \
$(alias_gbuf_c) \
$(alias_shadow_c) \
$(iqmv_c) \
$(iqmf_c) \
$(passthrough_c) \
$(fstriangle_c) \
$(pushcolor_c) \
$(shadow_c)
@ -443,6 +460,7 @@ EXTRA_DIST += \
libs/video/renderer/vulkan/shader/compose.frag \
libs/video/renderer/vulkan/shader/lighting.frag \
libs/video/renderer/vulkan/shader/passthrough.vert \
libs/video/renderer/vulkan/shader/fstriangle.vert \
libs/video/renderer/vulkan/shader/partphysics.comp \
libs/video/renderer/vulkan/shader/partupdate.comp \
libs/video/renderer/vulkan/shader/particle.vert \

View file

@ -278,7 +278,9 @@ gl_R_RenderView (void)
gl_R_DrawWorld ();
S_ExtraUpdate (); // don't let sound get messed up if going slow
gl_R_RenderDlights ();
R_DrawViewModel ();
if (vr_data.view_model) {
R_DrawViewModel ();
}
gl_Fog_DisableGFog ();
}

View file

@ -66,12 +66,15 @@
#include "QF/GL/qf_vid.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "mod_internal.h"
#include "r_internal.h"
#include "varrays.h"
#include "vid_gl.h"
static gltex_t gl_notexture = { };
static void
gl_R_LoadSky_f (void)
{
@ -114,6 +117,8 @@ gl_R_TimeRefresh_f (void)
void
gl_R_Init (void)
{
r_notexture_mip->render = &gl_notexture;
R_Init_Cvars ();
Cmd_AddCommand ("timerefresh", gl_R_TimeRefresh_f,
@ -152,7 +157,7 @@ register_textures (mod_brush_t *brush)
}
void
gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
gl_R_NewScene (scene_t *scene)
{
texture_t *tex;
mod_brush_t *brush;
@ -160,20 +165,19 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
for (int i = 0; i < 256; i++)
d_lightstylevalue[i] = 264; // normal light value
r_refdef.worldmodel = worldmodel;
brush = &worldmodel->brush;
r_refdef.worldmodel = scene->worldmodel;
brush = &scene->worldmodel->brush;
// clear out efrags in case the level hasn't been reloaded
for (unsigned i = 0; i < brush->modleafs; i++)
brush->leafs[i].efrags = NULL;
// Force a vis update
r_refdef.viewleaf = NULL;
R_MarkLeaves ();
R_MarkLeaves (0);
R_ClearParticles ();
GL_BuildLightmaps (models, num_models);
GL_BuildLightmaps (scene->models, scene->num_models);
// identify sky texture
gl_R_ClearTextures ();
@ -189,13 +193,13 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
gl_R_InitSurfaceChains (brush);
gl_R_AddTexture (r_notexture_mip);
register_textures (brush);
for (int i = 0; i < num_models; i++) {
if (!models[i])
for (int i = 0; i < scene->num_models; i++) {
if (!scene->models[i])
continue;
if (*models[i]->path == '*')
if (*scene->models[i]->path == '*')
continue;
if (models[i] != r_refdef.worldmodel
&& models[i]->type == mod_brush)
register_textures (&models[i]->brush);
if (scene->models[i] != r_refdef.worldmodel
&& scene->models[i]->type == mod_brush)
register_textures (&scene->models[i]->brush);
}
}

View file

@ -712,8 +712,6 @@ R_VisitWorldNodes (glbspctx_t *bctx)
}
break;
}
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) node);
}
void

View file

@ -103,6 +103,7 @@ static double sky_time;
static quat_t default_color = { 1, 1, 1, 1 };
static quat_t last_color;
static glsltex_t glsl_notexture = { };
static const char *bsp_vert_effects[] =
{
@ -831,8 +832,6 @@ R_VisitWorldNodes (glslbspctx_t *bctx)
}
break;
}
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) node);
}
static void
@ -1284,6 +1283,8 @@ glsl_R_InitBsp (void)
int vert;
int frag;
r_notexture_mip->render = &glsl_notexture;
vert_shader = GLSL_BuildShader (bsp_vert_effects);
frag_shader = GLSL_BuildShader (bsp_lit_effects);
vert = GLSL_CompileShader ("quakebsp.vert", vert_shader,

View file

@ -46,6 +46,7 @@
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "QF/GLSL/defines.h"
#include "QF/GLSL/funcs.h"
@ -142,7 +143,9 @@ glsl_R_RenderView (void)
R_SetupView ();
glsl_R_DrawWorld ();
glsl_R_DrawSky ();
R_DrawViewModel ();
if (vr_data.view_model) {
R_DrawViewModel ();
}
}
static void
@ -186,23 +189,22 @@ glsl_R_Init (void)
}
void
glsl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
glsl_R_NewScene (scene_t *scene)
{
int i;
for (i = 0; i < 256; i++)
d_lightstylevalue[i] = 264; // normal light value
r_refdef.worldmodel = worldmodel;
r_refdef.worldmodel = scene->worldmodel;
// Force a vis update
r_refdef.viewleaf = NULL;
R_MarkLeaves ();
R_MarkLeaves (0);
R_ClearParticles ();
glsl_R_RegisterTextures (models, num_models);
glsl_R_BuildLightmaps (models, num_models);
glsl_R_BuildDisplayLists (models, num_models);
glsl_R_RegisterTextures (scene->models, scene->num_models);
glsl_R_BuildLightmaps (scene->models, scene->num_models);
glsl_R_BuildDisplayLists (scene->models, scene->num_models);
}
void

View file

@ -47,7 +47,7 @@ static mleaf_t *r_oldviewleaf;
static set_t *solid;
void
R_MarkLeaves (void)
R_MarkLeaves (mleaf_t *viewleaf)
{
set_t *vis;
int c;
@ -56,12 +56,12 @@ R_MarkLeaves (void)
msurface_t **mark;
mod_brush_t *brush = &r_refdef.worldmodel->brush;
if (r_oldviewleaf == r_refdef.viewleaf && !r_novis)
if (r_oldviewleaf == viewleaf && !r_novis)
return;
r_visframecount++;
r_oldviewleaf = r_refdef.viewleaf;
if (!r_refdef.viewleaf)
r_oldviewleaf = viewleaf;
if (!viewleaf)
return;
if (r_novis) {
@ -73,7 +73,7 @@ R_MarkLeaves (void)
}
vis = solid;
} else
vis = Mod_LeafPVS (r_refdef.viewleaf, r_refdef.worldmodel);
vis = Mod_LeafPVS (viewleaf, r_refdef.worldmodel);
for (unsigned i = 0; i < brush->visleafs; i++) {
if (set_is_member (vis, i)) {

View file

@ -126,6 +126,10 @@ R_AnimateLight (void)
{
int i, j, k;
if (!r_data->lightstyle) {
return;
}
// light animations
// 'm' is normal light, 'a' is no light, 'z' is double bright
i = (int) (r_data->realtime * 10);

View file

@ -49,6 +49,7 @@
#include "QF/va.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "QF/scene/transform.h"
#include "QF/ui/view.h"
@ -71,40 +72,41 @@ static framebuffer_t *warp_buffer;
static float fov_x, fov_y;
static float tan_fov_x, tan_fov_y;
static scene_t *scr_scene;//FIXME don't want this here
static mat4f_t box_rotations[] = {
[BOX_FRONT] = {
{ 1, 0, 0, 0}, // front
{ 1, 0, 0, 0},
{ 0, 1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}
},
[BOX_RIGHT] = {
{ 0,-1, 0, 0}, // right
{ 0,-1, 0, 0},
{ 1, 0, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}
},
[BOX_BEHIND] = {
{-1, 0, 0, 0}, // back
{-1, 0, 0, 0},
{ 0,-1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}
},
[BOX_LEFT] = {
{ 0, 1, 0, 0}, // left
{ 0, 1, 0, 0},
{-1, 0, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}
},
[BOX_TOP] = {
{ 0, 0, 1, 0}, // top
{ 0, 0, 1, 0},
{ 0, 1, 0, 0},
{-1, 0, 0, 0},
{ 0, 0, 0, 1}
},
[BOX_BOTTOM] = {
{ 0, 0,-1, 0}, // bottom
{ 0, 0,-1, 0},
{ 0, 1, 0, 0},
{ 1, 0, 0, 0},
{ 0, 0, 0, 1}
@ -268,20 +270,21 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs)
R_RunParticles (r_data->frametime);
R_AnimateLight ();
refdef->viewleaf = 0;
if (refdef->worldmodel) {
if (scr_scene && scr_scene->worldmodel) {
scr_scene->viewleaf = 0;
vec4f_t position = refdef->frame.position;
refdef->viewleaf = Mod_PointInLeaf ((vec_t*)&position, refdef->worldmodel);//FIXME
scr_scene->viewleaf = Mod_PointInLeaf ((vec_t*)&position,
scr_scene->worldmodel);//FIXME
r_dowarpold = r_dowarp;
if (r_waterwarp) {
r_dowarp = refdef->viewleaf->contents <= CONTENTS_WATER;
r_dowarp = scr_scene->viewleaf->contents <= CONTENTS_WATER;
}
if (r_dowarp && !warp_buffer) {
warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width,
r_data->vid->height);
}
R_MarkLeaves (scr_scene->viewleaf);
}
R_MarkLeaves ();
R_PushDlights (vec3_origin);
r_funcs->begin_frame ();
@ -505,3 +508,15 @@ SCR_Init (void)
Cvar_AddListener (var, viewsize_listener, 0);
update_vrect ();
}
void
SCR_NewScene (scene_t *scene)
{
scr_scene = scene;
if (scene) {
r_funcs->set_fov (tan_fov_x, tan_fov_y);
r_funcs->R_NewScene (scene);
} else {
r_funcs->R_ClearState ();
}
}

View file

@ -513,8 +513,6 @@ R_VisitWorldNodes (swbspctx_t *bctx, int clipflags)
}
break;
}
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) node);
}
void

View file

@ -49,6 +49,7 @@
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "compat.h"
#include "mod_internal.h"
@ -151,8 +152,9 @@ sw_R_Init (void)
}
void
R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
R_NewScene (scene_t *scene)
{
model_t *worldmodel = scene->worldmodel;
mod_brush_t *brush = &worldmodel->brush;
r_refdef.worldmodel = worldmodel;
@ -165,8 +167,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
R_InitSky (brush->skytexture);
// Force a vis update
r_refdef.viewleaf = NULL;
R_MarkLeaves ();
R_MarkLeaves (0);
R_ClearParticles ();
@ -589,7 +590,9 @@ R_RenderView_ (void)
R_EdgeDrawing (r_ent_queue);
R_DrawViewModel ();
if (vr_data.view_model) {
R_DrawViewModel ();
}
if (r_aliasstats)
R_PrintAliasStats ();

View file

@ -163,7 +163,7 @@ static vid_model_funcs_t model_funcs = {
Mod_LoadSpriteModel,
gl_Mod_MakeAliasModelDisplayLists,
gl_Mod_LoadSkin,
gl_Mod_LoadAllSkins,
gl_Mod_FinalizeAliasModel,
gl_Mod_LoadExternalSkins,
gl_Mod_IQMFinish,
@ -510,7 +510,7 @@ vid_render_funcs_t gl_vid_render_funcs = {
gl_R_Init,
gl_R_ClearState,
gl_R_LoadSkys,
gl_R_NewMap,
gl_R_NewScene,
gl_R_LineGraph,
gl_begin_frame,
gl_render_view,

View file

@ -74,7 +74,7 @@ static vid_model_funcs_t model_funcs = {
Mod_LoadSpriteModel,
glsl_Mod_MakeAliasModelDisplayLists,
glsl_Mod_LoadSkin,
glsl_Mod_LoadAllSkins,
glsl_Mod_FinalizeAliasModel,
glsl_Mod_LoadExternalSkins,
glsl_Mod_IQMFinish,
@ -454,7 +454,7 @@ vid_render_funcs_t glsl_vid_render_funcs = {
glsl_R_Init,
glsl_R_ClearState,
glsl_R_LoadSkys,
glsl_R_NewMap,
glsl_R_NewScene,
glsl_R_LineGraph,
glsl_begin_frame,
glsl_render_view,

View file

@ -83,7 +83,7 @@ static vid_model_funcs_t model_funcs = {
Mod_LoadSpriteModel,
sw_Mod_MakeAliasModelDisplayLists,
sw_Mod_LoadSkin,
sw_Mod_LoadAllSkins,
0,
0,
sw_Mod_IQMFinish,
@ -474,7 +474,7 @@ vid_render_funcs_t sw_vid_render_funcs = {
sw_R_Init,
R_ClearState,
R_LoadSkys,
R_NewMap,
R_NewScene,
R_LineGraph,
sw_begin_frame,
sw_render_view,

View file

@ -44,6 +44,7 @@
#include "QF/Vulkan/qf_bsp.h"
#include "QF/Vulkan/qf_compose.h"
#include "QF/Vulkan/qf_draw.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"
@ -63,6 +64,7 @@
#include "QF/ui/view.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "mod_internal.h"
#include "r_internal.h"
@ -80,7 +82,6 @@ vulkan_ParticleSystem (void)
static void
vulkan_R_Init (void)
{
r_ent_queue = EntQueue_New (mod_num_types);
Vulkan_CreateStagingBuffers (vulkan_ctx);
Vulkan_CreateSwapchain (vulkan_ctx);
Vulkan_CreateFrames (vulkan_ctx);
@ -118,9 +119,9 @@ vulkan_R_LoadSkys (const char *skyname)
}
static void
vulkan_R_NewMap (model_t *worldmodel, model_t **models, int num_models)
vulkan_R_NewScene (scene_t *scene)
{
Vulkan_NewMap (worldmodel, models, num_models, vulkan_ctx);
Vulkan_NewScene (scene, vulkan_ctx);
}
static void
@ -541,13 +542,10 @@ vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx,
vulkan_ctx);
}
static void *
vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc)
static void
vulkan_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
{
return Vulkan_Mod_LoadSkin (alias_ctx, skin, skinsize, snum, gnum, group,
skindesc, vulkan_ctx);
Vulkan_Mod_LoadAllSkins (alias_ctx, vulkan_ctx);
}
static void
@ -564,6 +562,7 @@ vulkan_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx)
static void
vulkan_Mod_IQMFinish (model_t *mod)
{
Vulkan_Mod_IQMFinish (mod, vulkan_ctx);
}
static void
@ -639,7 +638,7 @@ static vid_model_funcs_t model_funcs = {
Mod_LoadSpriteModel,
vulkan_Mod_MakeAliasModelDisplayLists,
vulkan_Mod_LoadSkin,
vulkan_Mod_LoadAllSkins,
vulkan_Mod_FinalizeAliasModel,
vulkan_Mod_LoadExternalSkins,
vulkan_Mod_IQMFinish,
@ -729,7 +728,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
vulkan_R_Init,
vulkan_R_ClearState,
vulkan_R_LoadSkys,
vulkan_R_NewMap,
vulkan_R_NewScene,
vulkan_R_LineGraph,
vulkan_begin_frame,
vulkan_render_view,
@ -773,8 +772,7 @@ static plugin_t plugin_info = {
QFPLUGIN_VERSION,
"0.1",
"Vulkan Renderer",
"Copyright (C) 1996-1997 Id Software, Inc.\n"
"Copyright (C) 1999-2019 contributors of the QuakeForge project\n"
"Copyright (C) 2019 Bill Currie <bill@taniwha.org>\n"
"Please see the file \"AUTHORS\" for a list of contributors",
&plugin_info_funcs,
&plugin_info_data,

View file

@ -3,7 +3,6 @@
Vulkan buffer functions
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or

View file

@ -3,7 +3,6 @@
Vulkan frame capture support
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
@ -99,22 +98,21 @@ QFV_CreateCapture (qfv_device_t *device, int numframes,
image->layout = VK_IMAGE_LAYOUT_UNDEFINED;
image->cmd = cmdset->a[i];
}
size_t image_size = QFV_GetImageSize (device,
capture->image_set->a[0].image);
capture->memsize = numframes * image_size;
capture->imgsize = QFV_GetImageSize (device,
capture->image_set->a[0].image);
capture->memsize = numframes * capture->imgsize;
capture->memory = QFV_AllocImageMemory (device,
capture->image_set->a[0].image,
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
capture->memsize, 0);
byte *data;
dfunc->vkMapMemory (device->dev, capture->memory, 0, capture->memsize, 0,
(void **) &data);
(void **) &capture->data);
for (int i = 0; i < numframes; i++) {
__auto_type image = &capture->image_set->a[i];
image->data = data + i * image_size;
image->data = capture->data + i * capture->imgsize;
dfunc->vkBindImageMemory (device->dev, image->image, capture->memory,
image->data - data);
image->data - capture->data);
}
return capture;
}
@ -252,6 +250,15 @@ QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, int frame)
const byte *
QFV_CaptureData (qfv_capture_t *capture, int frame)
{
qfv_device_t *device = capture->device;
qfv_devfuncs_t *dfunc = device->funcs;
__auto_type image = &capture->image_set->a[frame];
VkMappedMemoryRange range = {
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
.memory = capture->memory,
.offset = image->data - capture->data,
.size = capture->imgsize,
};
dfunc->vkInvalidateMappedMemoryRanges (device->dev, 1, &range);
return image->data;
}

View file

@ -3,7 +3,6 @@
Common Vulkan video driver functions
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2019 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or

View file

@ -1,223 +1,101 @@
{
flat_color_image_template = {
imageType = `2d;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
};
images = {
depth = {
imageType = `2d;
@inherit = $properties.flat_color_image_template;
format = x8_d24_unorm_pack32;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = depth_stencil_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
};
color = {
imageType = `2d;
@inherit = $properties.flat_color_image_template;
format = r8g8b8a8_unorm;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
};
emission = {
imageType = `2d;
@inherit = $properties.flat_color_image_template;
format = r16g16b16a16_sfloat;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
};
normal = {
imageType = `2d;
@inherit = $properties.flat_color_image_template;
format = r16g16b16a16_sfloat;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
};
position = {
imageType = `2d;
@inherit = $properties.flat_color_image_template;
format = r32g32b32a32_sfloat;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
};
opaque = {
imageType = `2d;
format = r8g8b8a8_unorm;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
@inherit = $properties.flat_color_image_template;
format = r16g16b16a16_sfloat;
};
translucent = {
imageType = `2d;
@inherit = $properties.flat_color_image_template;
format = r8g8b8a8_unorm;
samples = 1;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment|transient_attachment;
initialLayout = undefined;
};
};
flat_color_view_template = {
viewType = VK_IMAGE_VIEW_TYPE_2D;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
imageViews = {
depth = {
@inherit = $properties.flat_color_view_template;
image = depth;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.depth.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = depth;
levelCount = 1;
layerCount = 1;
};
};
color = {
@inherit = $properties.flat_color_view_template;
image = color;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.color.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
emission = {
@inherit = $properties.flat_color_view_template;
image = emission;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.emission.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
normal = {
@inherit = $properties.flat_color_view_template;
image = normal;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.normal.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
position = {
@inherit = $properties.flat_color_view_template;
image = position;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.position.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
opaque = {
@inherit = $properties.flat_color_view_template;
image = opaque;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.opaque.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
translucent = {
@inherit = $properties.flat_color_view_template;
image = translucent;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.translucent.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
};
framebuffer = {
@ -238,86 +116,55 @@
{ color = "[0, 0, 0, 0]"; }, // translucent
{ color = "[0, 0, 0, 1]"; }, // output
);
attachment_template = {
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
};
renderpass = {
attachments = (
{
@inherit = $properties.attachment_template;
format = $properties.images.depth.format;
samples = 1;
loadOp = clear;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = depth_stencil_attachment_optimal;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.color.format;
samples = 1;
loadOp = clear;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.emission.format;
samples = 1;
loadOp = clear;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.normal.format;
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.position.format;
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.opaque.format;
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.translucent.format;
samples = 1;
loadOp = clear;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
@inherit = $properties.attachment_template;
format = $output.format;
samples = 1;
loadOp = clear;
storeOp = store;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = present_src_khr;
},
);

View file

@ -3,7 +3,6 @@
Vulkan descriptor functions
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or

View file

@ -3,7 +3,6 @@
Common Vulkan video driver functions
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2019 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or

View file

@ -0,0 +1,199 @@
{
flat_color_image_template = {
imageType = `2d;
samples = $msaaSamples;
extent = {
width = $output.extent.width;
height = $output.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|transient_attachment;
};
images = {
depth = {
@inherit = @properties.flat_color_image_template;
format = x8_d24_unorm_pack32;
usage = depth_stencil_attachment|transient_attachment;
};
color = {
@inherit = @properties.flat_color_image_template;
format = $output.format;
};
};
flat_color_view_template = {
viewType = `2d;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
imageViews = {
depth = {
@inherit = $properties.flat_color_view_template;
image = depth;
format = $properties.images.depth.format;
subresourceRange = {
aspectMask = depth;
};
};
color = {
@inherit = $properties.flat_color_view_template;
image = color;
format = $properties.images.color.format;
};
};
framebuffer = {
renderPass = $properties.renderpass;
attachment = ($output.view, depth);
width = $output.extent.width;
height = $output.extent.height;
layers = 1;
};
framebuffer_msaa = {
renderPass = $properties.renderpass_msaa;
attachment = ($output.view, depth, color);
width = $output.extent.width;
height = $output.extent.height;
layers = 1;
};
attachment_template = {
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
};
renderpass = {
attachments = (
{
@inherit = $properties.attachment_template;
format = $output.format;
loadOp = clear;
storeOp = store;
finalLayout = present_src_khr;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.depth.format;
loadOp = clear;
finalLayout = depth_stencil_attachment_optimal;
},
);
subpasses = (
{
pipelineBindPoint = graphics;
colorAttachments = (
{
attachment = 0;
layout = color_attachment_optimal;
}
);
depthStencilAttachment = {
attachment = 1;
layout = depth_stencil_attachment_optimal;
};
preserveAttachments = ();
},
);
dependencies = (
{
srcSubpass = ~0u; // external
dstSubpass = 0;
srcStageMask = top_of_pipe;
dstStageMask = color_attachment_output;
srcAccessMask = memory_read;
dstAccessMask = color_attachment_write;
dependencyFlags = by_region;
},
{
srcSubpass = 0;
dstSubpass = ~0u; // external
srcStageMask = color_attachment_output;
dstStageMask = bottom_of_pipe;
srcAccessMask = color_attachment_write;
dstAccessMask = memory_read;
dependencyFlags = by_region;
},
);
};
renderpass_msaa = {
attachments = (
{
@inherit = $properties.attachment_template;
format = $output.format;
storeOp = store;
finalLayout = present_src_khr;
},
{
@inherit = $properties.attachment_template;
format = $properties.images.depth.format;
samples = $msaaSamples;
loadOp = clear;
storeOp = dont_care;
finalLayout = depth_stencil_attachment_optimal;
},
{
@inherit = $properties.attachment_template;
format = $swapchain.format;
samples = $msaaSamples;
loadOp = clear;
storeOp = store;// dont_care?
finalLayout = color_attachment_optimal;
},
);
subpasses = (
{
pipelineBindPoint = graphics;
colorAttachments = (
{
attachment = 2;
layout = color_attachment_optimal;
}
);
resolveAttachments = (
{
attachment = 0;
layout = color_attachment_optimal;
}
);
depthStencilAttachment = {
attachment = 1;
layout = depth_stencil_attachment_optimal;
};
preserveAttachments = ();
},
);
dependencies = (
{
srcSubpass = ~0u; // external
dstSubpass = 0;
srcStageMask = top_of_pipe;
dstStageMask = color_attachment_output;
srcAccessMask = memory_read;
dstAccessMask = color_attachment_write;
dependencyFlags = by_region;
},
{
srcSubpass = 0;
dstSubpass = ~0u; // external
srcStageMask = color_attachment_output;
dstStageMask = bottom_of_pipe;
srcAccessMask = color_attachment_write;
dstAccessMask = memory_read;
dependencyFlags = by_region;
},
);
};
}

View file

@ -3,7 +3,6 @@
Vulkan image functions
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
@ -266,3 +265,24 @@ QFV_MipLevels (int width, int height)
{
return ilog2 (max (width, height)) + 1;
}
VkFormat
QFV_ImageFormat (QFFormat format)
{
switch (format) {
case tex_palette:
return VK_FORMAT_R8_UINT;
case tex_l:
case tex_a:
return VK_FORMAT_R8_UNORM;
case tex_la:
return VK_FORMAT_R8G8_UNORM;
case tex_rgb:
return VK_FORMAT_R8G8B8_UNORM; // SRGB?
case tex_rgba:
return VK_FORMAT_R8G8B8A8_UNORM;// SRGB?
case tex_frgba:
return VK_FORMAT_R32G32B32A32_SFLOAT;
}
return VK_FORMAT_R8_SRGB;
}

View file

@ -0,0 +1,254 @@
{
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;
};
};
}

View file

@ -3,7 +3,6 @@
Vulkan memory functions
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or

View file

@ -3,7 +3,6 @@
Vulkan pipeline functions
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or

View file

@ -206,8 +206,6 @@
},
);
};
quakebsp_set = $properties.setLayouts.texture_set;
alias_set = $properties.setLayouts.texture_set;
sprite_set = {
bindings = (
{
@ -337,7 +335,7 @@
);
};
alias_layout = {
setLayouts = (matrix_set, alias_set);
setLayouts = (matrix_set, texture_set);
pushConstantRanges = (
{
stageFlags = vertex;
@ -559,17 +557,13 @@
};
};
fsquad = {
fstriangle = {
vertexInput = {
bindings = (
{ binding = 0; stride = "4 * 4"; inputRate = vertex; },
);
attributes = (
{ location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; },
);
bindings = ();
attributes = ();
};
inputAssembly = {
topology = triangle_strip;
topology = triangle_list;
primitiveRestartEnable = false;
};
colorBlend = {
@ -1008,7 +1002,7 @@
{
stage = vertex;
name = main;
module = $builtin/passthrough.vert;
module = $builtin/fstriangle.vert;
},
{
stage = fragment;
@ -1022,13 +1016,13 @@
};
},
);
vertexInput = $properties.fsquad.vertexInput;
inputAssembly = $properties.fsquad.inputAssembly;
vertexInput = $properties.fstriangle.vertexInput;
inputAssembly = $properties.fstriangle.inputAssembly;
viewport = $properties.viewport;
rasterization = $properties.rasterization.counter_cw_cull_back;
multisample = $properties.multisample;
depthStencil = $properties.depthStencil.disable;
colorBlend = $properties.fsquad.colorBlend;
colorBlend = $properties.fstriangle.colorBlend;
dynamic = {
dynamicState = ( viewport, scissor );
};
@ -1041,7 +1035,7 @@
{
stage = vertex;
name = main;
module = $builtin/passthrough.vert;
module = $builtin/fstriangle.vert;
},
{
stage = fragment;
@ -1049,13 +1043,13 @@
module = $builtin/compose.frag;
},
);
vertexInput = $properties.fsquad.vertexInput;
inputAssembly = $properties.fsquad.inputAssembly;
vertexInput = $properties.fstriangle.vertexInput;
inputAssembly = $properties.fstriangle.inputAssembly;
viewport = $properties.viewport;
rasterization = $properties.rasterization.counter_cw_cull_back;
multisample = $properties.multisample;
depthStencil = $properties.depthStencil.disable;
colorBlend = $properties.fsquad.colorBlend;
colorBlend = $properties.fstriangle.colorBlend;
dynamic = {
dynamicState = ( viewport, scissor );
};

View file

@ -3,7 +3,6 @@
Vulkan render pass and frame buffer functions
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or

View file

@ -0,0 +1,271 @@
/*
resource.c
Vulkan resource functions
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/va.h"
#include "QF/Vulkan/buffer.h"
#include "QF/Vulkan/debug.h"
#include "QF/Vulkan/device.h"
#include "QF/Vulkan/image.h"
#include "QF/Vulkan/instance.h"
#include "QF/Vulkan/resource.h"
int
QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource)
{
qfv_devfuncs_t *dfunc = device->funcs;
qfv_physdev_t *physdev = device->physDev;
VkPhysicalDeviceMemoryProperties *memprops = &physdev->memory_properties;
VkMemoryRequirements req;
VkDeviceSize size = 0;
for (unsigned i = 0; i < resource->num_objects; i++) {
__auto_type obj = &resource->objects[i];
switch (obj->type) {
case qfv_res_buffer:
{
__auto_type buffer = &obj->buffer;
buffer->buffer = QFV_CreateBuffer (device,
buffer->size,
buffer->usage);
const char *name = va (resource->va_ctx, "buffer:%s:%s",
resource->name, obj->name);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER,
buffer->buffer, name);
dfunc->vkGetBufferMemoryRequirements (device->dev,
buffer->buffer, &req);
}
break;
case qfv_res_buffer_view:
{
__auto_type buffview = &obj->buffer_view;
__auto_type buffobj = &resource->objects[buffview->buffer];
if (buffview->buffer >= resource->num_objects
|| buffobj->type != qfv_res_buffer) {
Sys_Error ("%s:%s invalid buffer for view",
resource->name, obj->name);
}
}
break;
case qfv_res_image:
{
__auto_type image = &obj->image;
image->image = QFV_CreateImage (device,
image->cubemap,
image->type,
image->format,
image->extent,
image->num_mipmaps,
image->num_layers,
image->samples,
image->usage);
const char *name = va (resource->va_ctx, "image:%s:%s",
resource->name, obj->name);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE,
image->image, name);
dfunc->vkGetImageMemoryRequirements (device->dev,
image->image, &req);
}
break;
case qfv_res_image_view:
{
__auto_type imgview = &obj->image_view;
__auto_type imgobj = &resource->objects[imgview->image];
if (imgview->image >= resource->num_objects
|| imgobj->type != qfv_res_image) {
Sys_Error ("%s:%s invalid image for view",
resource->name, obj->name);
}
}
break;
default:
Sys_Error ("%s:%s invalid resource type %d",
resource->name, obj->name, obj->type);
}
size = QFV_NextOffset (size, &req);
size += req.size;
}
VkMemoryPropertyFlags properties = resource->memory_properties;
for (uint32_t type = 0; type < memprops->memoryTypeCount; type++) {
if ((req.memoryTypeBits & (1 << type))
&& ((memprops->memoryTypes[type].propertyFlags & properties)
== properties)) {
VkMemoryAllocateInfo allocate_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = size,
.memoryTypeIndex = type,
};
VkResult res = dfunc->vkAllocateMemory (device->dev, &allocate_info,
0, &resource->memory);
if (res == VK_SUCCESS) {
break;
}
}
}
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
resource->memory, va (resource->va_ctx, "memory:%s",
resource->name));
VkDeviceSize offset = 0;
for (unsigned i = 0; i < resource->num_objects; i++) {
__auto_type obj = &resource->objects[i];
switch (obj->type) {
case qfv_res_buffer:
{
__auto_type buffer = &obj->buffer;
dfunc->vkGetBufferMemoryRequirements (device->dev,
buffer->buffer, &req);
}
break;
case qfv_res_image:
{
__auto_type image = &obj->image;
dfunc->vkGetImageMemoryRequirements (device->dev,
image->image, &req);
}
break;
case qfv_res_buffer_view:
case qfv_res_image_view:
break;
}
offset = QFV_NextOffset (offset, &req);
switch (obj->type) {
case qfv_res_buffer:
{
__auto_type buffer = &obj->buffer;
QFV_BindBufferMemory (device, buffer->buffer,
resource->memory, offset);
}
break;
case qfv_res_image:
{
__auto_type image = &obj->image;
QFV_BindImageMemory (device, image->image,
resource->memory, offset);
}
break;
case qfv_res_buffer_view:
case qfv_res_image_view:
break;
}
offset += req.size;
}
for (unsigned i = 0; i < resource->num_objects; i++) {
__auto_type obj = &resource->objects[i];
switch (obj->type) {
case qfv_res_buffer:
case qfv_res_image:
break;
case qfv_res_buffer_view:
{
__auto_type buffview = &obj->buffer_view;
__auto_type buffobj = &resource->objects[buffview->buffer];
__auto_type buffer = &buffobj->buffer;
buffview->view = QFV_CreateBufferView (device,
buffer->buffer,
buffview->format,
buffview->offset,
buffview->size);
const char *name = va (resource->va_ctx, "bview:%s:%s",
resource->name, obj->name);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER_VIEW,
buffview->view, name);
}
break;
case qfv_res_image_view:
{
__auto_type imgview = &obj->image_view;
__auto_type imgobj = &resource->objects[imgview->image];
__auto_type image = &imgobj->image;
imgview->view = QFV_CreateImageView (device,
image->image,
imgview->type,
imgview->format,
imgview->aspect);
const char *name = va (resource->va_ctx, "iview:%s:%s",
resource->name, obj->name);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW,
imgview->view, name);
}
break;
}
}
return 0;
}
void
QFV_DestroyResource (qfv_device_t *device, qfv_resource_t *resource)
{
qfv_devfuncs_t *dfunc = device->funcs;
for (unsigned i = 0; i < resource->num_objects; i++) {
__auto_type obj = &resource->objects[i];
switch (obj->type) {
case qfv_res_buffer:
case qfv_res_image:
break;
case qfv_res_buffer_view:
{
__auto_type buffview = &obj->buffer_view;
dfunc->vkDestroyBufferView (device->dev, buffview->view, 0);
}
break;
case qfv_res_image_view:
{
__auto_type imgview = &obj->image_view;
dfunc->vkDestroyImageView (device->dev, imgview->view, 0);
}
break;
}
}
for (unsigned i = 0; i < resource->num_objects; i++) {
__auto_type obj = &resource->objects[i];
switch (obj->type) {
case qfv_res_buffer:
{
__auto_type buffer = &obj->buffer;
dfunc->vkDestroyBuffer (device->dev, buffer->buffer, 0);
}
break;
case qfv_res_image:
{
__auto_type image = &obj->image;
dfunc->vkDestroyImage (device->dev, image->image, 0);
}
break;
case qfv_res_buffer_view:
case qfv_res_image_view:
break;
}
}
dfunc->vkFreeMemory (device->dev, resource->memory, 0);
}

View file

@ -93,8 +93,14 @@ static
static
#include "libs/video/renderer/vulkan/shader/alias_shadow.vert.spvc"
static
#include "libs/video/renderer/vulkan/shader/iqm.vert.spvc"
static
#include "libs/video/renderer/vulkan/shader/iqm.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/passthrough.vert.spvc"
static
#include "libs/video/renderer/vulkan/shader/fstriangle.vert.spvc"
static
#include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc"
static
#include "libs/video/renderer/vulkan/shader/shadow.geom.spvc"
@ -133,7 +139,10 @@ static shaderdata_t builtin_shaders[] = {
{ "alias.frag", alias_frag, sizeof (alias_frag) },
{ "alias_gbuf.frag", alias_gbuf_frag, sizeof (alias_gbuf_frag) },
{ "alias_shadow.vert", alias_shadow_vert, sizeof (alias_shadow_vert) },
{ "iqm.vert", iqm_vert, sizeof (iqm_vert) },
{ "iqm.frag", iqm_frag, sizeof (iqm_frag) },
{ "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) },
{ "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) },
{ "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) },
{ "shadow.geom", shadow_geom, sizeof (shadow_geom) },
{}

View file

@ -34,6 +34,6 @@ main (void)
pos = (Model * vertex);
gl_Position = Projection3d * (View * pos);
position = pos;
normal = mat3 (Model) * norm;
normal = normalize (mat3 (Model) * norm);
st = uv;
}

View file

@ -33,6 +33,6 @@ main (void)
frag_color = c;
frag_emission = e;
frag_normal = vec4(normal, 1);
frag_normal = vec4(normalize(normal), 1);
frag_position = position;
}

Some files were not shown because too many files have changed in this diff Show more