mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
Merge branch 'master' into wip-twod
This commit is contained in:
commit
20ee47404f
83 changed files with 1976 additions and 1009 deletions
|
@ -28,7 +28,7 @@ BUILT_SOURCES = $(top_srcdir)/.version
|
|||
#AM_CFLAGS= @PREFER_NON_PIC@
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) $(FREETYPE_CFLAGS) $(HARFBUZZ_CFLAGS)
|
||||
|
||||
common_ldflags= -export-dynamic @PTHREAD_LDFLAGS@
|
||||
common_ldflags= -export-dynamic @STATIC@ @PTHREAD_LDFLAGS@
|
||||
|
||||
SUFFICES =
|
||||
TESTS =
|
||||
|
@ -166,11 +166,11 @@ CLEANFILES += $(shader_DATA)
|
|||
|
||||
$(r_depfiles_remade):
|
||||
$(MKDIR_P) $(@D)
|
||||
echo '$@' | sed -e 's@\$(DEPDIR)/@@' -e 's@\(.*\)\.Qo$$@\1.o: $(top_srcdir)/\1.r qfcc@' >$@-t && $(am__mv) $@-t $@
|
||||
echo '$@' | sed -e 's@\$(DEPDIR)/@@' -e 's@\(.*\)\.Qo$$@\1.o: $(top_srcdir)/\1.r $(QFCC)@' >$@-t && $(am__mv) $@-t $@
|
||||
|
||||
$(pas_depfiles_remade):
|
||||
$(MKDIR_P) $(@D)
|
||||
echo '$@' | sed -e 's@\$(DEPDIR)/@@' -e 's@\(.*\)\.Qo$$@\1.o: $(top_srcdir)/\1.pas qfcc@' >$@-t && $(am__mv) $@-t $@
|
||||
echo '$@' | sed -e 's@\$(DEPDIR)/@@' -e 's@\(.*\)\.Qo$$@\1.o: $(top_srcdir)/\1.pas $(QFCC)@' >$@-t && $(am__mv) $@-t $@
|
||||
|
||||
am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) $(pas_depfiles_remade)
|
||||
echo findme $(ruamoko_gui_libgui_a_dep)
|
||||
|
|
|
@ -246,7 +246,7 @@ if test "x$ENABLE_tools_qfbsp" = xyes; then
|
|||
QF_NEED(libs,[models image util])
|
||||
fi
|
||||
if test "x$ENABLE_tools_qfcc" = xyes; then
|
||||
QFCC_TARGETS="qfcc qfprogs\$(EXEEXT)"
|
||||
QFCC_TARGETS="qfcc\$(EXEEXT) qfprogs\$(EXEEXT)"
|
||||
QF_NEED(tools,[qfcc])
|
||||
QF_NEED(libs,[gamecode util])
|
||||
fi
|
||||
|
|
|
@ -59,10 +59,12 @@ AC_SUBST(SGI_CD_LIBS)
|
|||
|
||||
AC_EGREP_CPP([QF_maGiC_VALUE],
|
||||
[
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#if defined(MCI_SET_DOOR_OPEN)
|
||||
QF_maGiC_VALUE
|
||||
#endif
|
||||
#endif
|
||||
],
|
||||
CDTYPE="$CDTYPE WIN32"
|
||||
|
|
|
@ -238,26 +238,28 @@ QF_maGiC_VALUE
|
|||
fi
|
||||
|
||||
dnl Win32
|
||||
if test "x$ac_cv_header_windows_h" = "xyes"; then
|
||||
SOUND_TYPES="$SOUND_TYPES Win32"
|
||||
QF_NEED(snd_output, [win])
|
||||
QF_NEED(snd_render, [default])
|
||||
WINSND_LIBS="-lwinmm"
|
||||
if test "x$ac_cv_header_dsound_h" = "xyes"; then
|
||||
AC_EGREP_CPP([QF_maGiC_VALUE],
|
||||
[
|
||||
#include <windows.h>
|
||||
#include <dsound.h>
|
||||
#ifdef GMEM_MOVEABLE
|
||||
# ifdef DirectSoundEnumerate
|
||||
QF_maGiC_VALUE
|
||||
# endif
|
||||
#endif
|
||||
],
|
||||
SOUND_TYPES="$SOUND_TYPES DirectX"
|
||||
QF_NEED(snd_output, [dx])
|
||||
if test "x$SYSTYPE" = xWIN32; then
|
||||
if test "x$ac_cv_header_windows_h" = "xyes"; then
|
||||
SOUND_TYPES="$SOUND_TYPES Win32"
|
||||
QF_NEED(snd_output, [win])
|
||||
QF_NEED(snd_render, [default])
|
||||
)
|
||||
WINSND_LIBS="-lwinmm"
|
||||
if test "x$ac_cv_header_dsound_h" = "xyes"; then
|
||||
AC_EGREP_CPP([QF_maGiC_VALUE],
|
||||
[
|
||||
#include <windows.h>
|
||||
#include <dsound.h>
|
||||
#ifdef GMEM_MOVEABLE
|
||||
# ifdef DirectSoundEnumerate
|
||||
QF_maGiC_VALUE
|
||||
# endif
|
||||
#endif
|
||||
],
|
||||
SOUND_TYPES="$SOUND_TYPES DirectX"
|
||||
QF_NEED(snd_output, [dx])
|
||||
QF_NEED(snd_render, [default])
|
||||
)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(WINSND_LIBS)
|
||||
|
|
|
@ -8,7 +8,7 @@ case "$host_os" in
|
|||
if test "x$host" != "x$build"; then
|
||||
case "$build_os" in
|
||||
cygwin*)
|
||||
CFLAGS="$CFLAGS -mno-cygwin -mconsole -D__USE_MINGW_ANSI_STDIO"
|
||||
CFLAGS="$CFLAGS -mconsole -D__USE_MINGW_ANSI_STDIO"
|
||||
CPPFLAGS="$CPPFLAGS $CFLAGS"
|
||||
;;
|
||||
esac
|
||||
|
@ -19,6 +19,7 @@ case "$host_os" in
|
|||
;;
|
||||
cygwin*)
|
||||
cygwin=yes
|
||||
AC_DEFINE(NEED_GNUPRINTF)
|
||||
if test "x$host" != "x$build"; then
|
||||
CC="$host_cpu-$host_os-gcc"
|
||||
AS="$CC"
|
||||
|
|
|
@ -91,8 +91,8 @@ case "${host}" in
|
|||
fi
|
||||
|
||||
;;
|
||||
i?86-*-cygwin*)
|
||||
SYSTYPE=WIN32
|
||||
i?86-*-cygwin*|x86_64-*-cygwin*)
|
||||
#SYSTYPE=WIN32
|
||||
AC_MSG_RESULT([Win32 driver])
|
||||
WIN32_LIBS=' $(NET_LIBS)'
|
||||
;;
|
||||
|
|
|
@ -197,11 +197,11 @@ include_qf_vulkan = \
|
|||
include/QF/Vulkan/qf_matrices.h \
|
||||
include/QF/Vulkan/qf_model.h \
|
||||
include/QF/Vulkan/qf_particles.h \
|
||||
include/QF/Vulkan/qf_renderpass.h \
|
||||
include/QF/Vulkan/qf_scene.h \
|
||||
include/QF/Vulkan/qf_sprite.h \
|
||||
include/QF/Vulkan/qf_texture.h \
|
||||
include/QF/Vulkan/qf_vid.h \
|
||||
include/QF/Vulkan/renderpass.h \
|
||||
include/QF/Vulkan/scrap.h \
|
||||
include/QF/Vulkan/shader.h \
|
||||
include/QF/Vulkan/staging.h \
|
||||
|
|
|
@ -22,7 +22,7 @@ GLOBAL_LEVEL_VULKAN_FUNCTION (vkCreateInstance)
|
|||
#endif
|
||||
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumeratePhysicalDevices)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties2)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFeatures)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceQueueFamilyProperties)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateDevice)
|
||||
|
|
|
@ -42,7 +42,9 @@ typedef struct DARRAY_TYPE(const char *) qfv_debugstack_t;
|
|||
typedef struct qfv_physdev_s {
|
||||
struct qfv_instance_s *instance;
|
||||
VkPhysicalDevice dev;
|
||||
VkPhysicalDeviceProperties properties;
|
||||
VkPhysicalDeviceProperties2 properties2;
|
||||
VkPhysicalDeviceProperties *properties;
|
||||
VkPhysicalDeviceMultiviewProperties multiViewProperties;
|
||||
VkPhysicalDeviceMemoryProperties memory_properties;
|
||||
} qfv_physdev_t;
|
||||
|
||||
|
|
|
@ -39,31 +39,33 @@
|
|||
|
||||
#include "QF/simd/types.h"
|
||||
|
||||
/** \defgroup vulkan_bsp Brush model rendering
|
||||
\ingroup vulkan
|
||||
*/
|
||||
|
||||
/** Represent a single face (polygon) of a brush model.
|
||||
*
|
||||
* There is one of these for each face in the bsp (brush) model, built at run
|
||||
* time when the model is loaded (actually, after all models are loaded but
|
||||
* before rendering begins).
|
||||
*/
|
||||
typedef struct bsp_face_s {
|
||||
uint32_t first_index;
|
||||
uint32_t index_count;
|
||||
uint32_t tex_id;
|
||||
uint32_t flags;
|
||||
uint32_t first_index; ///< index of first index in poly_indices
|
||||
uint32_t index_count; ///< includes primitive restart
|
||||
uint32_t tex_id; ///< texture bound to this face (maybe animated)
|
||||
uint32_t flags; ///< face drawing (alpha, side, sky, turb)
|
||||
} bsp_face_t;
|
||||
|
||||
/** Represent a brush model, both main and sub-model.
|
||||
*
|
||||
* Used for rendering non-world models.
|
||||
*/
|
||||
typedef struct bsp_model_s {
|
||||
uint32_t first_face;
|
||||
uint32_t face_count;
|
||||
} bsp_model_t;
|
||||
|
||||
typedef struct bsp_packet_s {
|
||||
int first_index;
|
||||
int index_count;
|
||||
int transform_id;
|
||||
int color_id;
|
||||
} bsp_packet_t;
|
||||
|
||||
typedef struct bsp_packetset_s
|
||||
DARRAY_TYPE (bsp_packet_t) bsp_packetset_t;
|
||||
|
||||
typedef struct bsp_indexset_s
|
||||
DARRAY_TYPE (uint32_t) bsp_indexset_t;
|
||||
|
||||
#if 0
|
||||
typedef struct texname_s {
|
||||
char name[MIPTEXNAME];
|
||||
} texname_t;
|
||||
|
@ -73,22 +75,58 @@ typedef struct texmip_s {
|
|||
uint32_t height;
|
||||
uint32_t offsets[MIPLEVELS];
|
||||
} texmip_t;
|
||||
|
||||
#endif
|
||||
/** \defgroup vulkan_bsp_texanim Animated Textures
|
||||
* \ingroup vulkan_bsp
|
||||
*
|
||||
* Brush models support texture animations. For general details, see
|
||||
* \ref bsp_texture_animation. These structures allow for quick lookup
|
||||
* of the correct texture to use in an animation cycle, or even whether there
|
||||
* is an animation cycle.
|
||||
*/
|
||||
///@{
|
||||
/** Represent a texture's animation group.
|
||||
*
|
||||
* Every texture is in an animation group, even when not animated. When the
|
||||
* texture is not animated, `count` is 1, otherwise `count` is the number of
|
||||
* frames in the group, thus every texture has at least one frame.
|
||||
*
|
||||
* Each texture in a particular groupp shares the same `base` frame, with
|
||||
* `offset` giving the texture's relative frame number within the group.
|
||||
* The current frame is given by `base + (anim_index + offset) % count` where
|
||||
* `anim_index` is the global time-based texture animation frame.
|
||||
*/
|
||||
typedef struct texanim_s {
|
||||
uint16_t base;
|
||||
byte offset;
|
||||
byte count;
|
||||
uint16_t base; ///< first frame in group
|
||||
byte offset; ///< relative frame in group
|
||||
byte count; ///< number of frames in group
|
||||
} texanim_t;
|
||||
|
||||
/** Holds texture animation data for brush models.
|
||||
*
|
||||
* Brush models support one or two texture animation groups, based on the
|
||||
* entity's frame (0 or non-0). When the entity's frame is 0, group 0 is used,
|
||||
* otherwise group 1 is used. If there is no alternate (group 1) animation
|
||||
* data for the texture, then the texture's group 0 data is copied to group 1
|
||||
* in order to avoid coplications in selecting which texture a face is to use.
|
||||
*
|
||||
* As all of a group's frames are together, `frame_map` is used to get the
|
||||
* actual texture id for the frame.
|
||||
*/
|
||||
typedef struct texdata_s {
|
||||
// texname_t *names;
|
||||
// texmip_t **mips;
|
||||
texanim_t *anim_main;
|
||||
texanim_t *anim_alt;
|
||||
uint16_t *anim_map;
|
||||
texanim_t *anim_main; ///< group 0 animations
|
||||
texanim_t *anim_alt; ///< group 1 animations
|
||||
uint16_t *frame_map; ///< map from texture frame to texture id
|
||||
// int num_tex;
|
||||
} texdata_t;
|
||||
///@}
|
||||
|
||||
/** \defgroup vulkan_bsp_draw Brush model drawing
|
||||
* \ingroup vulkan_bsp
|
||||
*/
|
||||
///@{
|
||||
typedef struct vulktex_s {
|
||||
struct qfv_tex_s *tex;
|
||||
VkDescriptorSet descriptor;
|
||||
|
@ -98,65 +136,186 @@ typedef struct vulktex_s {
|
|||
typedef struct regtexset_s
|
||||
DARRAY_TYPE (vulktex_t *) regtexset_t;
|
||||
|
||||
/** Represent a single draw call.
|
||||
*
|
||||
* For each texture that has faces to be rendered, one or more draw calls is
|
||||
* made. Normally, only one call per texture is made, but if different models
|
||||
* use the same texture, then a separate draw call is made for each model.
|
||||
* When multiple entities use the same model, instanced rendering is used to
|
||||
* draw all the faces sharing a texture for all the entities using that model.
|
||||
* Thus when there are multiple draw calls for a single texture, they are
|
||||
* grouped together so there is only one bind per texture.
|
||||
*
|
||||
* The index buffer is populated every frame with the vertex indices of the
|
||||
* faces to be rendered for the current frame, grouped by texture and instance
|
||||
* id (model render id).
|
||||
*
|
||||
* The model render id is assigned after models are loaded but before rendering
|
||||
* begins and remains constant until the next time models are loaded (level
|
||||
* change).
|
||||
*
|
||||
* The entid buffer is also populated every frame with the render id of the
|
||||
* entities to be drawn that frame, It is used to map gl_InstanceIndex to
|
||||
* entity id so as to look up the entity's transform and color (and any other
|
||||
* data in the future).
|
||||
*
|
||||
* \dot
|
||||
* digraph vulkan_bsp_draw_call {
|
||||
* layout=dot; rankdir=LR; compound=true; nodesep=1.0;
|
||||
* vertices [shape=none,label=< <table border="1" cellborder="1">
|
||||
* <tr><td>vertex</td></tr>
|
||||
* <tr><td>vertex</td></tr>
|
||||
* <tr><td>...</td></tr>
|
||||
* <tr><td port="p">vertex</td></tr>
|
||||
* <tr><td>vertex</td></tr>
|
||||
* </table> >];
|
||||
* indices [shape=none,label=< <table border="1" cellborder="1">
|
||||
* <tr><td>index</td></tr>
|
||||
* <tr><td>index</td></tr>
|
||||
* <tr><td>...</td></tr>
|
||||
* <tr><td port="p">index</td></tr>
|
||||
* <tr><td>index</td></tr>
|
||||
* </table> >];
|
||||
* entids [shape=none,label=< <table border="1" cellborder="1">
|
||||
* <tr><td>entid</td></tr>
|
||||
* <tr><td>...</td></tr>
|
||||
* <tr><td port="p">entid</td></tr>
|
||||
* <tr><td>entid</td></tr>
|
||||
* <tr><td>...</td></tr>
|
||||
* <tr><td>entid</td></tr>
|
||||
* </table> >];
|
||||
* entdata [shape=none,label=< <table border="1" cellborder="1">
|
||||
* <tr><td>transform</td><td>color</td></tr>
|
||||
* <tr><td>transform</td><td>color</td></tr>
|
||||
* <tr><td colspan="2">...</td></tr>
|
||||
* <tr><td port="p">transform</td><td>color</td></tr>
|
||||
* <tr><td colspan="2">...</td></tr>
|
||||
* <tr><td>transform</td><td>color</td></tr>
|
||||
* </table> >];
|
||||
* drawcall [shape=none,label=< <table border="1" cellborder="1">
|
||||
* <tr><td port="tex" >tex_id</td></tr>
|
||||
* <tr><td >inst_id</td></tr>
|
||||
* <tr><td port="ind" >first_index</td></tr>
|
||||
* <tr><td >index_count</td></tr>
|
||||
* <tr><td port="inst">first_instance</td></tr>
|
||||
* <tr><td >instance_count</td></tr>
|
||||
* </table> >];
|
||||
* textures [shape=none,label=< <table border="1" cellborder="1">
|
||||
* <tr><td>texture</td></tr>
|
||||
* <tr><td>texture</td></tr>
|
||||
* <tr><td port="p">texture</td></tr>
|
||||
* <tr><td>...</td></tr>
|
||||
* <tr><td>texture</td></tr>
|
||||
* </table> >];
|
||||
* vertex [label="vertex shader"];
|
||||
* fragment [label="fragment shader"];
|
||||
* drawcall:tex -> textures:p;
|
||||
* drawcall:ind -> indices:p;
|
||||
* drawcall:inst -> entids:p;
|
||||
* entids:p -> entdata:p;
|
||||
* indices:p -> vertices:p;
|
||||
* vertex -> entdata [label="storage buffer"];
|
||||
* vertex -> entids [label="per instance"];
|
||||
* vertex -> indices [label="index buffer"];
|
||||
* vertex -> vertices [label="per vertex"];
|
||||
* fragment -> textures [label="per call"];
|
||||
* }
|
||||
* \enddot
|
||||
*/
|
||||
///@{
|
||||
typedef struct bsp_draw_s {
|
||||
uint32_t tex_id;
|
||||
uint32_t inst_id;
|
||||
uint32_t index_count;
|
||||
uint32_t instance_count;
|
||||
uint32_t first_index;
|
||||
uint32_t first_instance;
|
||||
uint32_t tex_id; ///< texture to bind for this draw call
|
||||
uint32_t inst_id; ///< model render id owning this draw call
|
||||
uint32_t index_count; ///< number of indices for this draw call
|
||||
uint32_t instance_count; ///< number of instances to draw
|
||||
uint32_t first_index; ///< index into index buffer
|
||||
uint32_t first_instance; ///< index into entid buffer
|
||||
} bsp_draw_t;
|
||||
|
||||
typedef struct bsp_drawset_s
|
||||
DARRAY_TYPE (bsp_draw_t) bsp_drawset_t;
|
||||
///@}
|
||||
|
||||
/** Tag models that are to be queued for translucent drawing.
|
||||
*/
|
||||
#define INST_ALPHA (1u<<31)
|
||||
|
||||
/** Representation of a single face queued for drawing.
|
||||
*/
|
||||
///@{
|
||||
typedef struct instface_s {
|
||||
uint32_t inst_id;
|
||||
uint32_t face;
|
||||
uint32_t inst_id; ///< model render id owning this face
|
||||
uint32_t face; ///< index of face in context array
|
||||
} instface_t;
|
||||
|
||||
typedef struct bsp_instfaceset_s
|
||||
DARRAY_TYPE (instface_t) bsp_instfaceset_t;
|
||||
///@}
|
||||
|
||||
/** Track entities using a model.
|
||||
*/
|
||||
///@{
|
||||
typedef struct bsp_modelentset_s
|
||||
DARRAY_TYPE (uint32_t) bsp_modelentset_t;
|
||||
|
||||
/** Represent a single model and the entities using it.
|
||||
*/
|
||||
typedef struct bsp_instance_s {
|
||||
int first_instance;
|
||||
bsp_modelentset_t entities;
|
||||
int first_instance; ///< index into entid buffer
|
||||
bsp_modelentset_t entities; ///< list of entity render ids using this model
|
||||
} bsp_instance_t;
|
||||
///@}
|
||||
|
||||
typedef struct bsp_pass_s {
|
||||
uint32_t *indices; // points into index buffer
|
||||
uint32_t index_count; // number of indices written to buffer
|
||||
uint32_t *entid_data;
|
||||
uint32_t entid_count;
|
||||
int vis_frame;
|
||||
int *face_frames;
|
||||
int *leaf_frames;
|
||||
int *node_frames;
|
||||
bsp_instfaceset_t *face_queue;
|
||||
regtexset_t *textures;
|
||||
int num_queues;
|
||||
bsp_drawset_t *draw_queues;
|
||||
uint32_t inst_id;
|
||||
bsp_instance_t *instances;
|
||||
int ent_frame;
|
||||
vec4f_t position; ///< view position
|
||||
plane_t *frustum; ///< view frustum for culling
|
||||
const struct mod_brush_s *brush;///< data for current model
|
||||
struct bspctx_s *bsp_context; ///< owning bsp context
|
||||
/** \name GPU data
|
||||
*
|
||||
* The indices to be drawn and the entity ids associated with each draw
|
||||
* instance are updated each frame. The pointers are to the per-frame
|
||||
* mapped buffers for the respective data.
|
||||
*/
|
||||
///@{
|
||||
uint32_t *indices; ///< polygon vertex indices
|
||||
uint32_t index_count; ///< number of indices written to buffer
|
||||
uint32_t *entid_data; ///< instance id to entity id map
|
||||
uint32_t entid_count; ///< numer of entids written to buffer
|
||||
///@}
|
||||
/** \name Potentially Visible Sets
|
||||
*
|
||||
* For an object to be in the PVS, its frame id must match the current
|
||||
* visibility frame id, thus clearing all sets is done by incrementing
|
||||
* `vis_frame`, and adding an object to the PVS is done by setting its
|
||||
* current frame id to the current visibility frame id.
|
||||
*/
|
||||
///@{
|
||||
int vis_frame; ///< current visibility frame id
|
||||
int *face_frames; ///< per-face visibility frame ids
|
||||
int *leaf_frames; ///< per-leaf visibility frame ids
|
||||
int *node_frames; ///< per-node visibility frame ids
|
||||
///@}
|
||||
bsp_instfaceset_t *face_queue; ///< per-texture face queues
|
||||
regtexset_t *textures; ///< textures to bind when emitting calls
|
||||
int num_queues; ///< number of pipeline queues
|
||||
bsp_drawset_t *draw_queues; ///< per-pipeline draw queues
|
||||
uint32_t inst_id; ///< render id of current model
|
||||
bsp_instance_t *instances; ///< per-model entid lists
|
||||
// FIXME There are several potential optimizations here:
|
||||
// 1) ent_frame could be forced to be 0 or 1 and then used to index a
|
||||
// two-element array of texanim pointers
|
||||
// 2) ent_frame could be a pointer to the correct texanim array
|
||||
// 3) could update a tex_id map each frame and unconditionally index that
|
||||
//
|
||||
// As the texture id is used for selecting the face queue, 3 could be used
|
||||
// for mapping all textures to 1 or two queues for shadow rendering
|
||||
int ent_frame; ///< animation frame of current entity
|
||||
} bsp_pass_t;
|
||||
///@}
|
||||
|
||||
typedef struct bspvert_s {
|
||||
quat_t vertex;
|
||||
quat_t tlst;
|
||||
} bspvert_t;
|
||||
|
||||
typedef enum {
|
||||
qfv_bsp_texture,
|
||||
qfv_bsp_glowmap,
|
||||
qfv_bsp_lightmap,
|
||||
qfv_bsp_skysheet,
|
||||
qfv_bsp_skycube,
|
||||
} qfv_bsp_tex;
|
||||
|
||||
/// \ingroup vulkan_bsp
|
||||
///@{
|
||||
typedef enum {
|
||||
QFV_bspDepth,
|
||||
QFV_bspGBuffer,
|
||||
|
@ -179,34 +338,33 @@ typedef struct bspframe_s {
|
|||
typedef struct bspframeset_s
|
||||
DARRAY_TYPE (bspframe_t) bspframeset_t;
|
||||
|
||||
/** Main BSP context structure
|
||||
*
|
||||
* This holds all the state and resources needed for rendering brush models.
|
||||
*/
|
||||
typedef struct bspctx_s {
|
||||
regtexset_t registered_textures;
|
||||
|
||||
struct qfv_tex_s *default_skysheet;
|
||||
struct qfv_tex_s *skysheet_tex;
|
||||
|
||||
struct qfv_tex_s *default_skybox;
|
||||
struct qfv_tex_s *skybox_tex;
|
||||
VkDescriptorSet skybox_descriptor;
|
||||
|
||||
vulktex_t notexture;
|
||||
|
||||
quat_t default_color;
|
||||
quat_t last_color;
|
||||
vulktex_t notexture; ///< replacement for invalid textures
|
||||
|
||||
struct scrap_s *light_scrap;
|
||||
struct qfv_stagebuf_s *light_stage;
|
||||
|
||||
bsp_model_t *models;
|
||||
bsp_face_t *faces;
|
||||
uint32_t *poly_indices;
|
||||
int num_models; ///< number of loaded brush models
|
||||
bsp_model_t *models; ///< all loaded brush models
|
||||
bsp_face_t *faces; ///< all faces from all loaded brush models
|
||||
uint32_t *poly_indices; ///< face indices from all loaded brush models
|
||||
|
||||
texdata_t texdata;
|
||||
int anim_index;
|
||||
regtexset_t registered_textures;///< textures for all loaded brush models
|
||||
texdata_t texdata; ///< texture animation data
|
||||
int anim_index; ///< texture animation frame (5fps)
|
||||
struct qfv_tex_s *default_skysheet;
|
||||
struct qfv_tex_s *skysheet_tex; ///< scrolling sky texture for current map
|
||||
|
||||
int model_id;
|
||||
struct qfv_tex_s *default_skybox;
|
||||
struct qfv_tex_s *skybox_tex; ///< sky box texture for current map
|
||||
VkDescriptorSet skybox_descriptor;
|
||||
|
||||
bsp_pass_t main_pass; // camera view depth, gbuffer, etc
|
||||
bsp_pass_t main_pass; ///< camera view depth, gbuffer, etc
|
||||
|
||||
VkSampler sampler;
|
||||
VkPipelineLayout layout;
|
||||
|
@ -230,7 +388,6 @@ typedef struct bspctx_s {
|
|||
|
||||
struct vulkan_ctx_s;
|
||||
struct qfv_renderframe_s;
|
||||
void Vulkan_ClearElements (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_DrawWorld (struct qfv_renderframe_s *rFrame);
|
||||
void Vulkan_DrawSky (struct qfv_renderframe_s *rFrame);
|
||||
void Vulkan_DrawWaterSurfaces (struct qfv_renderframe_s *rFrame);
|
||||
|
@ -242,5 +399,6 @@ void Vulkan_BuildDisplayLists (model_t **models, int num_models,
|
|||
struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Bsp_Init (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx);
|
||||
///@}
|
||||
|
||||
#endif//__QF_Vulkan_qf_bsp_h
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "QF/modelgen.h"
|
||||
#include "QF/scene/light.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/command.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/simd/types.h"
|
||||
|
@ -79,6 +80,20 @@ typedef struct lightingframe_s {
|
|||
typedef struct lightingframeset_s
|
||||
DARRAY_TYPE (lightingframe_t) lightingframeset_t;
|
||||
|
||||
typedef struct light_renderer_s {
|
||||
VkRenderPass renderPass; // shared
|
||||
VkFramebuffer framebuffer;
|
||||
VkImage image; // shared
|
||||
VkImageView view;
|
||||
uint32_t size;
|
||||
uint32_t layer;
|
||||
uint32_t numLayers;
|
||||
int mode;
|
||||
} light_renderer_t;
|
||||
|
||||
typedef struct light_renderer_set_s
|
||||
DARRAY_TYPE (light_renderer_t) light_renderer_set_t;
|
||||
|
||||
typedef struct lightingctx_s {
|
||||
lightingframeset_t frames;
|
||||
VkPipeline pipeline;
|
||||
|
@ -86,10 +101,16 @@ typedef struct lightingctx_s {
|
|||
VkSampler sampler;
|
||||
VkDeviceMemory light_memory;
|
||||
VkDeviceMemory shadow_memory;
|
||||
qfv_lightmatset_t lightmats;
|
||||
qfv_imageset_t lightimages;
|
||||
lightintset_t lightlayers;
|
||||
qfv_imageviewset_t lightviews;
|
||||
qfv_lightmatset_t light_mats;
|
||||
qfv_imageset_t light_images;
|
||||
light_renderer_set_t light_renderers;
|
||||
|
||||
qfv_renderpass_t *qfv_renderpass;
|
||||
VkRenderPass renderpass_6;
|
||||
VkRenderPass renderpass_4;
|
||||
VkRenderPass renderpass_1;
|
||||
|
||||
VkCommandPool cmdpool;
|
||||
|
||||
struct lightingdata_s *ldata;
|
||||
struct scene_s *scene;
|
||||
|
@ -98,6 +119,7 @@ typedef struct lightingctx_s {
|
|||
struct vulkan_ctx_s;
|
||||
struct qfv_renderframe_s;
|
||||
|
||||
void Vulkan_Lighting_CreateRenderPasses (struct vulkan_ctx_s *ctx);
|
||||
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);
|
||||
|
|
|
@ -33,6 +33,7 @@ struct qfv_renderframe_s;
|
|||
struct entqueue_s;
|
||||
struct scene_s;
|
||||
|
||||
void Vulkan_Main_CreateRenderPasses (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,
|
||||
|
|
68
include/QF/Vulkan/qf_renderpass.h
Normal file
68
include/QF/Vulkan/qf_renderpass.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef __QF_Vulkan_renderpass_h
|
||||
#define __QF_Vulkan_renderpass_h
|
||||
|
||||
#include "QF/darray.h"
|
||||
#include "QF/simd/types.h"
|
||||
|
||||
typedef struct qfv_framebufferset_s
|
||||
DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t;
|
||||
|
||||
#define QFV_AllocFrameBuffers(num, allocator) \
|
||||
DARRAY_ALLOCFIXED (qfv_framebufferset_t, num, allocator)
|
||||
|
||||
typedef struct qfv_subpass_s {
|
||||
vec4f_t color;
|
||||
const char *name;
|
||||
} qfv_subpass_t;
|
||||
|
||||
typedef struct qfv_subpassset_s
|
||||
DARRAY_TYPE (qfv_subpass_t) qfv_subpassset_t;
|
||||
|
||||
typedef struct qfv_renderframe_s {
|
||||
struct vulkan_ctx_s *vulkan_ctx;
|
||||
struct qfv_renderpass_s *renderpass;
|
||||
VkSubpassContents subpassContents;
|
||||
int subpassCount;
|
||||
qfv_subpass_t *subpassInfo;
|
||||
struct qfv_cmdbufferset_s *subpassCmdSets;
|
||||
} qfv_renderframe_t;
|
||||
|
||||
typedef struct qfv_renderframeset_s
|
||||
DARRAY_TYPE (qfv_renderframe_t) qfv_renderframeset_t;
|
||||
|
||||
typedef struct clearvalueset_s
|
||||
DARRAY_TYPE (VkClearValue) clearvalueset_t;
|
||||
|
||||
typedef void (*qfv_draw_t) (qfv_renderframe_t *rFrame);
|
||||
|
||||
typedef struct qfv_renderpass_s {
|
||||
vec4f_t color; // for debugging
|
||||
const char *name; // for debugging
|
||||
struct plitem_s *renderpassDef;
|
||||
VkRenderPass renderpass;
|
||||
clearvalueset_t *clearValues;
|
||||
struct qfv_imageset_s *attachment_images;
|
||||
struct qfv_imageviewset_s *attachment_views;
|
||||
VkDeviceMemory attachmentMemory;
|
||||
|
||||
qfv_framebufferset_t *framebuffers;
|
||||
VkViewport viewport;
|
||||
VkRect2D scissor;
|
||||
int order;
|
||||
int primary_commands;
|
||||
size_t subpassCount;
|
||||
qfv_subpassset_t *subpass_info;
|
||||
qfv_renderframeset_t frames;
|
||||
|
||||
qfv_draw_t draw;
|
||||
} qfv_renderpass_t;
|
||||
|
||||
struct qfv_output_s;
|
||||
qfv_renderpass_t *Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx,
|
||||
const char *name,
|
||||
struct qfv_output_s *output,
|
||||
qfv_draw_t draw);
|
||||
void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx,
|
||||
qfv_renderpass_t *renderpass);
|
||||
|
||||
#endif//__QF_Vulkan_renderpass_h
|
|
@ -35,6 +35,14 @@
|
|||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
/** \defgroup vulkan Vulkan Renderer
|
||||
*/
|
||||
|
||||
enum {
|
||||
QFV_rp_shadowmap,
|
||||
QFV_rp_main,
|
||||
};
|
||||
|
||||
//FIXME location
|
||||
typedef enum {
|
||||
QFV_passDepth, // geometry
|
||||
|
@ -61,7 +69,7 @@ struct vulkan_ctx_s;
|
|||
void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateCapture (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateRenderPasses (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_DestroyRenderPasses (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx);
|
||||
|
@ -85,4 +93,6 @@ struct entity_s;
|
|||
void Vulkan_BeginEntityLabel (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd,
|
||||
struct entity_s *ent);
|
||||
|
||||
struct plitem_s *Vulkan_GetConfig (struct vulkan_ctx_s *ctx, const char *name);
|
||||
|
||||
#endif // __QF_Vulkan_vid_h
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
#ifndef __QF_Vulkan_renderpass_h
|
||||
#define __QF_Vulkan_renderpass_h
|
||||
|
||||
#include "QF/darray.h"
|
||||
#include "QF/simd/types.h"
|
||||
|
||||
typedef struct qfv_attachmentdescription_s
|
||||
DARRAY_TYPE (VkAttachmentDescription) qfv_attachmentdescription_t;
|
||||
|
||||
#define QFV_AllocAttachmentDescription(num, allocator) \
|
||||
DARRAY_ALLOCFIXED (qfv_attachmentdescription_t, num, allocator)
|
||||
|
||||
typedef struct qfv_attachmentreference_s
|
||||
DARRAY_TYPE (VkAttachmentReference) qfv_attachmentreference_t;
|
||||
|
||||
#define QFV_AllocAttachmentReference(num, allocator) \
|
||||
DARRAY_ALLOCFIXED (qfv_attachmentreference_t, num, allocator)
|
||||
|
||||
typedef struct qfv_subpassparametersset_s
|
||||
DARRAY_TYPE (VkSubpassDescription) qfv_subpassparametersset_t;
|
||||
|
||||
#define QFV_AllocSubpassParametersSet(num, allocator) \
|
||||
DARRAY_ALLOCFIXED (qfv_subpassparametersset_t, num, allocator)
|
||||
|
||||
typedef struct qfv_subpassdependency_s
|
||||
DARRAY_TYPE (VkSubpassDependency) qfv_subpassdependency_t;
|
||||
|
||||
#define QFV_AllocSubpassDependencies(num, allocator) \
|
||||
DARRAY_ALLOCFIXED (qfv_subpassdependency_t, num, allocator)
|
||||
|
||||
typedef struct qfv_framebufferset_s
|
||||
DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t;
|
||||
|
||||
#define QFV_AllocFrameBuffers(num, allocator) \
|
||||
DARRAY_ALLOCFIXED (qfv_framebufferset_t, num, allocator)
|
||||
|
||||
struct qfv_device_s;
|
||||
struct qfv_imageviewset_s;
|
||||
VkRenderPass
|
||||
QFV_CreateRenderPass (struct qfv_device_s *device,
|
||||
qfv_attachmentdescription_t *attachments,
|
||||
qfv_subpassparametersset_t *subpasses,
|
||||
qfv_subpassdependency_t *dependencies);
|
||||
|
||||
VkFramebuffer
|
||||
QFV_CreateFramebuffer (struct qfv_device_s *device,
|
||||
VkRenderPass renderPass,
|
||||
struct qfv_imageviewset_s *attachments,
|
||||
VkExtent2D, uint32_t layers);
|
||||
|
||||
typedef struct qfv_subpass_s {
|
||||
vec4f_t color;
|
||||
const char *name;
|
||||
} qfv_subpass_t;
|
||||
|
||||
typedef struct qfv_renderframe_s {
|
||||
struct vulkan_ctx_s *vulkan_ctx;
|
||||
struct qfv_renderpass_s *renderpass;
|
||||
VkSubpassContents subpassContents;
|
||||
int subpassCount;
|
||||
qfv_subpass_t *subpassInfo;
|
||||
struct qfv_cmdbufferset_s *subpassCmdSets;
|
||||
} qfv_renderframe_t;
|
||||
|
||||
typedef struct qfv_renderframeset_s
|
||||
DARRAY_TYPE (qfv_renderframe_t) qfv_renderframeset_t;
|
||||
|
||||
typedef struct clearvalueset_s
|
||||
DARRAY_TYPE (VkClearValue) clearvalueset_t;
|
||||
|
||||
typedef struct qfv_renderpass_s {
|
||||
vec4f_t color; // for debugging
|
||||
const char *name; // for debugging
|
||||
struct plitem_s *renderpassDef;
|
||||
VkRenderPass renderpass;
|
||||
clearvalueset_t *clearValues;
|
||||
struct qfv_imageset_s *attachment_images;
|
||||
struct qfv_imageviewset_s *attachment_views;
|
||||
VkDeviceMemory attachmentMemory;
|
||||
|
||||
qfv_framebufferset_t *framebuffers;
|
||||
VkViewport viewport;
|
||||
VkRect2D scissor;
|
||||
|
||||
qfv_renderframeset_t frames;
|
||||
|
||||
void (*draw) (qfv_renderframe_t *rFrame);
|
||||
} qfv_renderpass_t;
|
||||
|
||||
#endif//__QF_Vulkan_renderpass_h
|
|
@ -103,13 +103,13 @@ typedef struct texture_s {
|
|||
} texture_t;
|
||||
|
||||
|
||||
#define SURF_PLANEBACK 0x02
|
||||
#define SURF_DRAWSKY 0x04
|
||||
#define SURF_DRAWTURB 0x08
|
||||
#define SURF_DRAWSKY 0x01
|
||||
#define SURF_DRAWALPHA 0x02
|
||||
#define SURF_DRAWTURB 0x04
|
||||
#define SURF_PLANEBACK 0x08
|
||||
#define SURF_DRAWTILED 0x10
|
||||
#define SURF_DRAWBACKGROUND 0x20
|
||||
#define SURF_DRAWNOALPHA 0x40
|
||||
#define SURF_LIGHTBOTHSIDES 0x80
|
||||
#define SURF_LIGHTBOTHSIDES 0x40
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct {
|
||||
|
|
|
@ -120,7 +120,6 @@ typedef struct vid_render_funcs_s {
|
|||
|
||||
void (*begin_frame) (void);
|
||||
void (*render_view) (void);
|
||||
void (*draw_entities) (struct entqueue_s *queue);
|
||||
void (*draw_particles) (struct psystem_s *psystem);
|
||||
void (*draw_transparent) (void);
|
||||
void (*post_process) (struct framebuffer_s *src);
|
||||
|
|
|
@ -84,6 +84,7 @@ extern gamedir_t *qfs_gamedir;
|
|||
|
||||
/** Function type of callback called on gamedir change.
|
||||
\param phase 0 = before Cache_Flush(), 1 = after Cache_Flush()
|
||||
\param data data pointer passed on to the callback
|
||||
*/
|
||||
typedef void gamedir_callback_t (int phase, void *data);
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
* \param size The number of objects in the ring buffer. Note that the
|
||||
* actual capacity of the buffer is `size - 1` due to the
|
||||
* way ring buffers work.
|
||||
*
|
||||
* \note On its own, this is not thread-safe. Suitable locking is required.
|
||||
*/
|
||||
#define RING_BUFFER(type, size) \
|
||||
struct { \
|
||||
|
@ -45,6 +47,26 @@
|
|||
unsigned tail; \
|
||||
}
|
||||
|
||||
/** Type declaration for a type-safe ring buffer with atomic head and tail.
|
||||
*
|
||||
* \param type The type of data element stored in the ring buffer.
|
||||
* \param size The number of objects in the ring buffer. Note that the
|
||||
* actual capacity of the buffer is `size - 1` due to the
|
||||
* way ring buffers work.
|
||||
*
|
||||
* \note This is suitable only for single-reader/single-writer unless
|
||||
* additional locking is provided for multi-user side. This means `head` must
|
||||
* have an associated lock for multiple writers, and `tail` must have an
|
||||
* associated lock for multiple readers. For multi-reader + multi-writer, it
|
||||
* may be better to use RING_BUFFER with suitable locking.
|
||||
*/
|
||||
#define RING_BUFFER_ATOMIC(type, size) \
|
||||
struct { \
|
||||
type buffer[size]; \
|
||||
_Atomic unsigned head; \
|
||||
_Atomic unsigned tail; \
|
||||
}
|
||||
|
||||
#define RB_buffer_size(ring_buffer) \
|
||||
({ __auto_type rb_s = (ring_buffer); \
|
||||
sizeof (rb_s->buffer) / sizeof (rb_s->buffer[0]); \
|
||||
|
@ -95,7 +117,7 @@
|
|||
const typeof (rb->buffer[0]) *d = (data); \
|
||||
unsigned c = (count); \
|
||||
unsigned h = rb->head; \
|
||||
rb->head = (h + c) % RB_buffer_size (rb); \
|
||||
unsigned new_head = (h + c) % RB_buffer_size (rb); \
|
||||
if (c > RB_buffer_size (rb) - h) { \
|
||||
memcpy (rb->buffer + h, d, \
|
||||
(RB_buffer_size (rb) - h) * sizeof (rb->buffer[0])); \
|
||||
|
@ -104,6 +126,7 @@
|
|||
h = 0; \
|
||||
} \
|
||||
memcpy (rb->buffer + h, d, c * sizeof (rb->buffer[0])); \
|
||||
rb->head = new_head; \
|
||||
})
|
||||
|
||||
/** Acquire \a count objects from the buffer, wrapping if necessary.
|
||||
|
@ -122,8 +145,10 @@
|
|||
({ __auto_type rb = &(ring_buffer); \
|
||||
unsigned c = (count); \
|
||||
unsigned h = rb->head; \
|
||||
rb->head = (h + c) % RB_buffer_size (rb); \
|
||||
&rb->buffer[h]; \
|
||||
unsigned new_head = (h + c) % RB_buffer_size (rb); \
|
||||
__auto_type head_addr = &rb->buffer[h]; \
|
||||
rb->head = new_head; \
|
||||
head_addr; \
|
||||
})
|
||||
|
||||
/** Read \a count objects from the buffer to \a data, wrapping if necessary.
|
||||
|
@ -145,6 +170,7 @@
|
|||
unsigned c = (count); \
|
||||
unsigned oc = c; \
|
||||
unsigned t = rb->tail; \
|
||||
unsigned new_tail = (t + oc) % RB_buffer_size (rb); \
|
||||
if (c > RB_buffer_size (rb) - t) { \
|
||||
memcpy (d, rb->buffer + t, \
|
||||
(RB_buffer_size (rb) - t) * sizeof (rb->buffer[0])); \
|
||||
|
@ -153,7 +179,7 @@
|
|||
t = 0; \
|
||||
} \
|
||||
memcpy (d, rb->buffer + t, c * sizeof (rb->buffer[0])); \
|
||||
rb->tail = (t + oc) % RB_buffer_size (rb); \
|
||||
rb->tail = new_tail; \
|
||||
})
|
||||
|
||||
/** Discard \a count objects from the ring buffer.
|
||||
|
|
|
@ -279,7 +279,7 @@ int SND_Memory_GetRetainCount (void *ptr) __attribute__((pure));
|
|||
\param sfx
|
||||
\param realname
|
||||
\param info
|
||||
\param loader
|
||||
\param load
|
||||
*/
|
||||
void SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info,
|
||||
sfxbuffer_t *(*load) (sfxblock_t *block));
|
||||
|
@ -306,7 +306,7 @@ sfxbuffer_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
|||
void (*close) (sfxbuffer_t *));
|
||||
|
||||
/** Close a stream.
|
||||
\param sfx
|
||||
\param stream
|
||||
*/
|
||||
void SND_SFX_StreamClose (sfxstream_t *stream);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ typedef struct qfv_output_s {
|
|||
VkExtent2D extent;
|
||||
VkImageView view;
|
||||
VkFormat format;
|
||||
VkImageView *view_list; // per frame
|
||||
} qfv_output_t;
|
||||
|
||||
typedef struct vulkan_frame_s {
|
||||
|
@ -76,8 +77,6 @@ typedef struct vulkan_ctx_s {
|
|||
struct composectx_s *compose_context;
|
||||
|
||||
VkCommandPool cmdpool;
|
||||
VkCommandBuffer cmdbuffer;
|
||||
VkFence fence; // for ctx->cmdbuffer only
|
||||
struct qfv_stagebuf_s *staging;
|
||||
size_t curFrame;
|
||||
vulkan_frameset_t frames;
|
||||
|
@ -98,7 +97,7 @@ typedef struct vulkan_ctx_s {
|
|||
int window_width;
|
||||
int window_height;
|
||||
|
||||
//FIXME not sure I like it being here (also, type name)
|
||||
//FIXME this is for the parser
|
||||
qfv_output_t output;
|
||||
|
||||
#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname;
|
||||
|
|
|
@ -287,6 +287,42 @@ static cvar_t cl_yawspeed_cvar = {
|
|||
.flags = CVAR_NONE,
|
||||
.value = { .type = &cexpr_float, .value = &cl_yawspeed },
|
||||
};
|
||||
float cl_maxpitch;
|
||||
static cvar_t cl_maxpitch_cvar = {
|
||||
.name = "cl_maxpitch",
|
||||
.description =
|
||||
"turning speed",
|
||||
.default_value = "90",
|
||||
.flags = CVAR_ARCHIVE,
|
||||
.value = { .type = &cexpr_float, .value = &cl_maxpitch },
|
||||
};
|
||||
float cl_minpitch;
|
||||
static cvar_t cl_minpitch_cvar = {
|
||||
.name = "cl_minpitch",
|
||||
.description =
|
||||
"turning speed",
|
||||
.default_value = "-90",
|
||||
.flags = CVAR_ARCHIVE,
|
||||
.value = { .type = &cexpr_float, .value = &cl_minpitch },
|
||||
};
|
||||
float cl_maxroll;
|
||||
static cvar_t cl_maxroll_cvar = {
|
||||
.name = "cl_maxroll",
|
||||
.description =
|
||||
"turning speed",
|
||||
.default_value = "50",
|
||||
.flags = CVAR_ARCHIVE,
|
||||
.value = { .type = &cexpr_float, .value = &cl_maxroll },
|
||||
};
|
||||
float cl_minroll;
|
||||
static cvar_t cl_minroll_cvar = {
|
||||
.name = "cl_minroll",
|
||||
.description =
|
||||
"turning speed",
|
||||
.default_value = "-50",
|
||||
.flags = CVAR_ARCHIVE,
|
||||
.value = { .type = &cexpr_float, .value = &cl_minroll },
|
||||
};
|
||||
|
||||
int lookspring;
|
||||
static cvar_t lookspring_cvar = {
|
||||
|
@ -376,10 +412,10 @@ CL_AdjustAngles (float frametime, movestate_t *ms, viewstate_t *vs)
|
|||
|
||||
if (delta[PITCH]) {
|
||||
V_StopPitchDrift (vs);
|
||||
ms->angles[PITCH] = bound (-70, ms->angles[PITCH], 80);
|
||||
ms->angles[PITCH] = bound (cl_minpitch, ms->angles[PITCH], cl_maxpitch);
|
||||
}
|
||||
if (delta[ROLL]) {
|
||||
ms->angles[ROLL] = bound (-50, ms->angles[ROLL], 50);
|
||||
ms->angles[ROLL] = bound (cl_minroll, ms->angles[ROLL], cl_maxroll);
|
||||
}
|
||||
if (delta[YAW]) {
|
||||
ms->angles[YAW] = anglemod (ms->angles[YAW]);
|
||||
|
@ -600,6 +636,10 @@ CL_Input_Init_Cvars (void)
|
|||
Cvar_Register (&cl_sidespeed_cvar, 0, 0);
|
||||
Cvar_Register (&cl_upspeed_cvar, 0, 0);
|
||||
Cvar_Register (&cl_yawspeed_cvar, 0, 0);
|
||||
Cvar_Register (&cl_maxpitch_cvar, 0, 0);
|
||||
Cvar_Register (&cl_minpitch_cvar, 0, 0);
|
||||
Cvar_Register (&cl_maxroll_cvar, 0, 0);
|
||||
Cvar_Register (&cl_minroll_cvar, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -204,7 +204,9 @@ parse_light (light_t *light, int *style, const plitem_t *entity,
|
|||
} color = { .v = light->color };
|
||||
sscanf (str, "%f %f %f", VectorExpandAddr (color.a));
|
||||
light->color = color.v;
|
||||
VectorScale (light->color, 1/255.0, light->color);
|
||||
if (light->color[0] > 1 || light->color[1] > 1 || light->color[2] > 1) {
|
||||
VectorScale (light->color, 1/255.0, light->color);
|
||||
}
|
||||
}
|
||||
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "wait")))) {
|
||||
|
|
|
@ -1629,7 +1629,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
|
|||
goto err;
|
||||
}
|
||||
if (mode == 'M' || mode == 'm') {
|
||||
if (!isxdigit (fmt[3])) {
|
||||
if (!isxdigit ((byte) fmt[3])) {
|
||||
goto err;
|
||||
}
|
||||
shift = fmt[3];
|
||||
|
|
|
@ -240,7 +240,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s)
|
|||
*v = ' ';
|
||||
}
|
||||
}
|
||||
if (sscanf (s, "%f %f %f", VectorExpandAddr (vec)) != 3) {
|
||||
if (sscanf (str, "%f %f %f", VectorExpandAddr (vec)) != 3) {
|
||||
Sys_Printf ("Malformed vector %s\n", s);
|
||||
}
|
||||
VectorCopy (vec, PR_PTR (vector, d));
|
||||
|
|
|
@ -206,7 +206,7 @@ LoadPNG (QFile *infile, int load)
|
|||
|
||||
#define WRITEPNG_BIT_DEPTH 8
|
||||
|
||||
int
|
||||
VISIBLE int
|
||||
WritePNG (QFile *outfile, const tex_t *tex)
|
||||
{
|
||||
int i;
|
||||
|
@ -299,9 +299,10 @@ LoadPNG (QFile *infile, int load)
|
|||
return 0;
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
WritePNG (QFile *outfile, const byte *data, int width, int height)
|
||||
VISIBLE int
|
||||
WritePNG (QFile *outfile, const tex_t *tex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -218,6 +218,11 @@ check_device (const char *path)
|
|||
|
||||
dev->event_count = 0;
|
||||
|
||||
dev->data = 0;
|
||||
dev->axis_event = 0;
|
||||
dev->button_event = 0;
|
||||
|
||||
|
||||
//Sys_Printf ("%s:\n", path);
|
||||
//Sys_Printf ("\tname: %s\n", dev->name);
|
||||
//Sys_Printf ("\tbuttons: %d\n", dev->num_buttons);
|
||||
|
|
|
@ -652,19 +652,23 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (out->texinfo->texture->name[0] == '*') { // turbulent
|
||||
out->flags |= (SURF_DRAWTURB
|
||||
| SURF_DRAWTILED
|
||||
| SURF_LIGHTBOTHSIDES);
|
||||
for (i = 0; i < 2; i++) {
|
||||
out->extents[i] = 16384;
|
||||
out->texturemins[i] = -8192;
|
||||
}
|
||||
if (mod_funcs && mod_funcs->Mod_SubdivideSurface) {
|
||||
// cut up polygon for warps
|
||||
mod_funcs->Mod_SubdivideSurface (mod, out);
|
||||
}
|
||||
continue;
|
||||
switch (out->texinfo->texture->name[0]) {
|
||||
case '*': // turbulent
|
||||
out->flags |= (SURF_DRAWTURB
|
||||
| SURF_DRAWTILED
|
||||
| SURF_LIGHTBOTHSIDES);
|
||||
for (i = 0; i < 2; i++) {
|
||||
out->extents[i] = 16384;
|
||||
out->texturemins[i] = -8192;
|
||||
}
|
||||
if (mod_funcs && mod_funcs->Mod_SubdivideSurface) {
|
||||
// cut up polygon for warps
|
||||
mod_funcs->Mod_SubdivideSurface (mod, out);
|
||||
}
|
||||
break;
|
||||
case '{':
|
||||
out->flags |= SURF_DRAWALPHA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,12 +58,6 @@
|
|||
#ifdef HAVE_SYS_IOCTL_H
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
#ifdef HAVE_WINSOCK_H
|
||||
# include <winsock.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
@ -537,7 +531,7 @@ UDP_Read (int socket, byte *buf, int len, netadr_t *from)
|
|||
}
|
||||
SockadrToNetadr (&addr, from);
|
||||
Sys_MaskPrintf (SYS_net, "got %d bytes from %s on iface %d (%s)\n", ret,
|
||||
UDP_AddrToString (from), info ? info->ipi_ifindex - 1 : -1,
|
||||
UDP_AddrToString (from), info ? (int) info->ipi_ifindex - 1 : -1,
|
||||
last_iface ? inet_ntoa (info->ipi_addr) : "?");
|
||||
#else
|
||||
socklen_t addrlen = sizeof (AF_address_t);
|
||||
|
|
|
@ -940,7 +940,11 @@ Sys_ConsoleInput (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static jmp_buf aiee_abort;
|
||||
#else
|
||||
static sigjmp_buf aiee_abort;
|
||||
#endif
|
||||
|
||||
typedef struct sh_stack_s {
|
||||
struct sh_stack_s *next;
|
||||
|
|
|
@ -18,6 +18,7 @@ libs_util_tests = \
|
|||
libs/util/test/test-pqueue \
|
||||
libs/util/test/test-qfs \
|
||||
libs/util/test/test-quat \
|
||||
libs/util/test/test-ringbuffer \
|
||||
libs/util/test/test-seb \
|
||||
libs/util/test/test-sebvf \
|
||||
libs/util/test/test-seg \
|
||||
|
@ -106,6 +107,11 @@ libs_util_test_test_quat_SOURCES=libs/util/test/test-quat.c
|
|||
libs_util_test_test_quat_LDADD=libs/util/libQFutil.la
|
||||
libs_util_test_test_quat_DEPENDENCIES=libs/util/libQFutil.la
|
||||
|
||||
libs_util_test_test_ringbuffer_SOURCES=libs/util/test/test-ringbuffer.c
|
||||
libs_util_test_test_ringbuffer_LDADD=libs/util/libQFutil.la
|
||||
libs_util_test_test_ringbuffer_LDFLAGS=-pthread
|
||||
libs_util_test_test_ringbuffer_DEPENDENCIES=libs/util/libQFutil.la
|
||||
|
||||
libs_util_test_test_seb_SOURCES=libs/util/test/test-seb.c
|
||||
libs_util_test_test_seb_LDADD=libs/util/libQFutil.la
|
||||
libs_util_test_test_seb_DEPENDENCIES=libs/util/libQFutil.la
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
// because libc has its own remove
|
||||
#define remove remove_renamed
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
|
313
libs/util/test/test-ringbuffer.c
Normal file
313
libs/util/test/test-ringbuffer.c
Normal file
|
@ -0,0 +1,313 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <threads.h>
|
||||
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/ringbuffer.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
typedef int (*test_func) (int a, int b);
|
||||
|
||||
typedef RING_BUFFER (int, 8) ringbuffer_t;
|
||||
typedef RING_BUFFER (char, 8) ringbuffer_char_t;
|
||||
typedef RING_BUFFER_ATOMIC (char, 8) ringbuffer_atomic_t;
|
||||
|
||||
static ringbuffer_t int_ringbuffer = { .buffer = { [0 ... 7] = 0xdeadbeef } };
|
||||
static ringbuffer_char_t ringbuffer_char;
|
||||
static ringbuffer_atomic_t ringbuffer_atomic;
|
||||
mtx_t rb_mtx;
|
||||
cnd_t rb_write_cnd;
|
||||
cnd_t rb_read_cnd;
|
||||
|
||||
ringbuffer_atomic_t int_ringbuffer_atomic;
|
||||
|
||||
static int
|
||||
get_size (int a, int b)
|
||||
{
|
||||
return RB_buffer_size (&int_ringbuffer);
|
||||
}
|
||||
|
||||
static int
|
||||
space_available (int a, int b)
|
||||
{
|
||||
return RB_SPACE_AVAILABLE (int_ringbuffer);
|
||||
}
|
||||
|
||||
static int
|
||||
data_available (int a, int b)
|
||||
{
|
||||
return RB_DATA_AVAILABLE (int_ringbuffer);
|
||||
}
|
||||
|
||||
static int
|
||||
write_data (int value, int b)
|
||||
{
|
||||
return RB_WRITE_DATA (int_ringbuffer, &value, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
acquire (int count, int b)
|
||||
{
|
||||
return *RB_ACQUIRE (int_ringbuffer, count);
|
||||
}
|
||||
|
||||
static int
|
||||
read_data (int a, int b)
|
||||
{
|
||||
int ret;
|
||||
RB_READ_DATA (int_ringbuffer, &ret, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
release (int count, int b)
|
||||
{
|
||||
return RB_RELEASE (int_ringbuffer, count);
|
||||
}
|
||||
|
||||
static int
|
||||
peek_data (int offset, int b)
|
||||
{
|
||||
return *RB_PEEK_DATA (int_ringbuffer, offset);
|
||||
}
|
||||
|
||||
static int
|
||||
poke_data (int offset, int value)
|
||||
{
|
||||
return RB_POKE_DATA (int_ringbuffer, offset, value);
|
||||
}
|
||||
|
||||
static int
|
||||
init_threading (int a, int b)
|
||||
{
|
||||
if (mtx_init (&rb_mtx, mtx_plain) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
if (cnd_init (&rb_write_cnd) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
if (cnd_init (&rb_read_cnd) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *text = "Sometimes, it is necessary to write long gibberish "
|
||||
"in order to test things. Hopefully, this may be an exception, though it's "
|
||||
"not exactly the most useful or intersting text around.";
|
||||
|
||||
static dstring_t *out_text;
|
||||
|
||||
static int
|
||||
compare_strings (int a, int b)
|
||||
{
|
||||
int ret = strcmp (out_text->str, text);
|
||||
dstring_delete (out_text);
|
||||
out_text = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
locked_reader (void *data)
|
||||
{
|
||||
if (!out_text) {
|
||||
out_text = dstring_new ();
|
||||
}
|
||||
dstring_clear (out_text);
|
||||
|
||||
do {
|
||||
mtx_lock (&rb_mtx);
|
||||
while (RB_DATA_AVAILABLE (ringbuffer_char) < 1) {
|
||||
cnd_wait (&rb_read_cnd, &rb_mtx);
|
||||
}
|
||||
unsigned len = RB_DATA_AVAILABLE (ringbuffer_char);
|
||||
RB_READ_DATA (ringbuffer_char, dstring_reserve (out_text, len), len);
|
||||
cnd_signal (&rb_write_cnd);
|
||||
mtx_unlock (&rb_mtx);
|
||||
} while (out_text->str[out_text->size - 1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
locked_writer (void *data)
|
||||
{
|
||||
size_t data_len = strlen (text) + 1; // send nul terminator too
|
||||
const char *str = text;
|
||||
|
||||
while (data_len > 0) {
|
||||
mtx_lock (&rb_mtx);
|
||||
while (RB_SPACE_AVAILABLE (ringbuffer_char) < 1) {
|
||||
cnd_wait (&rb_write_cnd, &rb_mtx);
|
||||
}
|
||||
unsigned len = RB_SPACE_AVAILABLE (ringbuffer_char);
|
||||
len = min (len, data_len);
|
||||
RB_WRITE_DATA (ringbuffer_char, str, len);
|
||||
str += len;
|
||||
data_len -= len;
|
||||
cnd_signal (&rb_read_cnd);
|
||||
mtx_unlock (&rb_mtx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
run_locked (int a, int b)
|
||||
{
|
||||
thrd_t writer;
|
||||
thrd_t reader;
|
||||
|
||||
if (thrd_create (&writer, locked_writer, 0) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
if (thrd_create (&reader, locked_reader, 0) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int res;
|
||||
if (thrd_join (writer, &res) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
if (thrd_join (reader, &res) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
free_reader (void *data)
|
||||
{
|
||||
if (!out_text) {
|
||||
out_text = dstring_new ();
|
||||
}
|
||||
dstring_clear (out_text);
|
||||
|
||||
do {
|
||||
while (RB_DATA_AVAILABLE (ringbuffer_atomic) < 1) {
|
||||
}
|
||||
unsigned len = RB_DATA_AVAILABLE (ringbuffer_atomic);
|
||||
RB_READ_DATA (ringbuffer_atomic, dstring_reserve (out_text, len), len);
|
||||
} while (out_text->str[out_text->size - 1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
free_writer (void *data)
|
||||
{
|
||||
size_t data_len = strlen (text) + 1; // send nul terminator too
|
||||
const char *str = text;
|
||||
|
||||
while (data_len > 0) {
|
||||
while (RB_SPACE_AVAILABLE (ringbuffer_atomic) < 1) {
|
||||
}
|
||||
unsigned len = RB_SPACE_AVAILABLE (ringbuffer_atomic);
|
||||
len = min (len, data_len);
|
||||
RB_WRITE_DATA (ringbuffer_atomic, str, len);
|
||||
str += len;
|
||||
data_len -= len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
run_free (int a, int b)
|
||||
{
|
||||
thrd_t writer;
|
||||
thrd_t reader;
|
||||
|
||||
if (thrd_create (&writer, free_writer, 0) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
if (thrd_create (&reader, free_reader, 0) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int res;
|
||||
if (thrd_join (writer, &res) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
if (thrd_join (reader, &res) != thrd_success) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define _ 0 // unused parameter
|
||||
|
||||
struct {
|
||||
test_func test;
|
||||
int param1, param2;
|
||||
int test_expect;
|
||||
} tests[] = {
|
||||
{ get_size, _, _, 8 },
|
||||
{ space_available, _, _, 7 },
|
||||
{ data_available, _, _, 0 },
|
||||
{ write_data, 0x600dc0de, _, 1 },
|
||||
{ space_available, _, _, 6 },
|
||||
{ data_available, _, _, 1 },
|
||||
{ acquire, 0, _, 0xdeadbeef }, // iffy test: 0 count
|
||||
{ space_available, _, _, 6 },
|
||||
{ data_available, _, _, 1 },
|
||||
{ read_data, 1, _, 0x600dc0de },
|
||||
{ space_available, _, _, 7 },
|
||||
{ data_available, _, _, 0 },
|
||||
{ release, 0, _, 1 },
|
||||
{ space_available, _, _, 7 },
|
||||
{ data_available, _, _, 0 },
|
||||
{ poke_data, 0, 1, 1 },
|
||||
{ poke_data, 1, 2, 2 },
|
||||
{ poke_data, 2, 3, 3 },
|
||||
{ poke_data, 3, 4, 4 },
|
||||
{ poke_data, 4, 5, 5 },
|
||||
{ poke_data, 5, 6, 6 },
|
||||
{ acquire, 6, _, 1 },
|
||||
{ space_available, _, _, 1 },
|
||||
{ data_available, _, _, 6 },
|
||||
{ write_data, 7, _, 0 }, // head wrapped to 0
|
||||
{ space_available, _, _, 0 },
|
||||
{ data_available, _, _, 7 },
|
||||
{ peek_data, 0, _, 1 },
|
||||
{ peek_data, 1, _, 2 },
|
||||
{ peek_data, 2, _, 3 },
|
||||
{ peek_data, 3, _, 4 },
|
||||
{ peek_data, 4, _, 5 },
|
||||
{ peek_data, 5, _, 6 },
|
||||
{ peek_data, 6, _, 7 },
|
||||
{ space_available, _, _, 0 },
|
||||
{ data_available, _, _, 7 },
|
||||
{ init_threading, _, _, 0 },
|
||||
{ run_locked, _, _, 0 },
|
||||
{ compare_strings, _, _, 0 },
|
||||
{ run_free, _, _, 0 },
|
||||
{ compare_strings, _, _, 0 },
|
||||
};
|
||||
#define num_tests (sizeof (tests) / sizeof (tests[0]))
|
||||
int test_start_line = __LINE__ - num_tests - 2;
|
||||
|
||||
int
|
||||
main (int argc, const char **argv)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
for (size_t i = 0; i < num_tests; i++) {
|
||||
int test_res;
|
||||
test_res = tests[i].test (tests[i].param1, tests[i].param2);
|
||||
if (test_res != tests[i].test_expect) {
|
||||
res |= 1;
|
||||
printf ("test %zd (line %zd) failed\n", i, i + test_start_line);
|
||||
printf ("expect: %d\n", tests[i].test_expect);
|
||||
printf ("got : %d\n", test_res);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
|
@ -191,6 +191,8 @@ pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist
|
|||
pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc
|
||||
deferred_src = libs/video/renderer/vulkan/deferred.plist
|
||||
deferred_gen = libs/video/renderer/vulkan/deferred.plc
|
||||
shadow_src = libs/video/renderer/vulkan/shadow.plist
|
||||
shadow_gen = libs/video/renderer/vulkan/shadow.plc
|
||||
forward_src = libs/video/renderer/vulkan/forward.plist
|
||||
forward_gen = libs/video/renderer/vulkan/forward.plc
|
||||
|
||||
|
@ -217,7 +219,6 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \
|
|||
libs/video/renderer/vulkan/memory.c \
|
||||
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 \
|
||||
|
@ -235,6 +236,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \
|
|||
libs/video/renderer/vulkan/vulkan_main.c \
|
||||
libs/video/renderer/vulkan/vulkan_matrices.c \
|
||||
libs/video/renderer/vulkan/vulkan_particles.c \
|
||||
libs/video/renderer/vulkan/vulkan_renderpass.c \
|
||||
libs/video/renderer/vulkan/vulkan_scene.c \
|
||||
libs/video/renderer/vulkan/vulkan_sprite.c \
|
||||
libs/video/renderer/vulkan/vulkan_texture.c \
|
||||
|
@ -244,7 +246,13 @@ libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vk
|
|||
|
||||
libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vkshader_c)
|
||||
|
||||
libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) ${deferred_gen} $(forward_gen)
|
||||
libs/video/renderer/vulkan/vulkan_vid_common.lo: \
|
||||
libs/video/renderer/vulkan/vulkan_vid_common.c \
|
||||
$(vkparse_src) \
|
||||
$(pipeline_gen) \
|
||||
${deferred_gen} \
|
||||
${shadow_gen} \
|
||||
$(forward_gen)
|
||||
|
||||
|
||||
qwaq_cmd = $(top_builddir)/ruamoko/qwaq/qwaq-cmd$(EXEEXT)
|
||||
|
@ -325,8 +333,6 @@ 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
|
||||
shadow_c = $(vkshaderpath)/shadow.geom.spvc
|
||||
|
||||
$(partphysicsc_c): $(partphysicsc_src)
|
||||
$(partupdatec_c): $(partupdatec_src)
|
||||
|
@ -390,8 +396,6 @@ $(fstriangle_c): $(fstriangle_src)
|
|||
|
||||
$(pushcolor_c): $(pushcolor_src)
|
||||
|
||||
$(shadow_c): $(shadow_src)
|
||||
|
||||
vkshader_c = \
|
||||
$(partphysicsc_c) \
|
||||
$(partupdatec_c) \
|
||||
|
@ -459,6 +463,7 @@ BUILT_SOURCES += $(shader_gen)
|
|||
|
||||
EXTRA_DIST += \
|
||||
$(deferred_src) \
|
||||
$(shadow_src) \
|
||||
$(forward_src) \
|
||||
$(pipeline_src) \
|
||||
libs/video/renderer/vulkan/vkparse.plist \
|
||||
|
|
|
@ -192,7 +192,6 @@ render_scene (void)
|
|||
r_framecount++;
|
||||
EntQueue_Clear (r_ent_queue);
|
||||
r_funcs->render_view ();
|
||||
r_funcs->draw_entities (r_ent_queue);
|
||||
r_funcs->draw_particles (&r_psystem);
|
||||
r_funcs->draw_transparent ();
|
||||
}
|
||||
|
|
|
@ -264,6 +264,7 @@ gl_render_view (void)
|
|||
// do 3D refresh drawing, and then update the screen
|
||||
qfglClear (GL_DEPTH_BUFFER_BIT);
|
||||
gl_R_RenderView ();
|
||||
gl_R_RenderEntities (r_ent_queue);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -531,7 +532,6 @@ vid_render_funcs_t gl_vid_render_funcs = {
|
|||
gl_R_LineGraph,
|
||||
gl_begin_frame,
|
||||
gl_render_view,
|
||||
gl_R_RenderEntities,
|
||||
gl_R_DrawParticles,
|
||||
gl_draw_transparent,
|
||||
gl_post_process,
|
||||
|
|
|
@ -225,6 +225,7 @@ glsl_render_view (void)
|
|||
{
|
||||
qfeglClear (GL_DEPTH_BUFFER_BIT);
|
||||
glsl_R_RenderView ();
|
||||
glsl_R_RenderEntities (r_ent_queue);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -475,7 +476,6 @@ vid_render_funcs_t glsl_vid_render_funcs = {
|
|||
glsl_R_LineGraph,
|
||||
glsl_begin_frame,
|
||||
glsl_render_view,
|
||||
glsl_R_RenderEntities,
|
||||
glsl_R_DrawParticles,
|
||||
glsl_draw_transparent,
|
||||
glsl_post_process,
|
||||
|
|
|
@ -160,6 +160,7 @@ static void
|
|||
sw_render_view (void)
|
||||
{
|
||||
R_RenderView ();
|
||||
R_DrawEntitiesOnList (r_ent_queue);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -489,7 +490,6 @@ vid_render_funcs_t sw_vid_render_funcs = {
|
|||
R_LineGraph,
|
||||
sw_begin_frame,
|
||||
sw_render_view,
|
||||
R_DrawEntitiesOnList,
|
||||
R_DrawParticles,
|
||||
sw_draw_transparent,
|
||||
sw_post_process,
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/darray.h"
|
||||
|
@ -50,6 +51,7 @@
|
|||
#include "QF/Vulkan/qf_main.h"
|
||||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_particles.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_scene.h"
|
||||
#include "QF/Vulkan/qf_sprite.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
|
@ -62,7 +64,6 @@
|
|||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/projection.h"
|
||||
#include "QF/Vulkan/staging.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
#include "QF/Vulkan/swapchain.h"
|
||||
#include "QF/ui/view.h"
|
||||
|
||||
|
@ -89,7 +90,7 @@ vulkan_R_Init (void)
|
|||
Vulkan_CreateSwapchain (vulkan_ctx);
|
||||
Vulkan_CreateFrames (vulkan_ctx);
|
||||
Vulkan_CreateCapture (vulkan_ctx);
|
||||
Vulkan_CreateRenderPass (vulkan_ctx);
|
||||
Vulkan_CreateRenderPasses (vulkan_ctx);
|
||||
Vulkan_Texture_Init (vulkan_ctx);
|
||||
|
||||
Vulkan_Matrix_Init (vulkan_ctx);
|
||||
|
@ -111,6 +112,7 @@ vulkan_R_Init (void)
|
|||
static void
|
||||
vulkan_R_ClearState (void)
|
||||
{
|
||||
QFV_DeviceWaitIdle (vulkan_ctx->device);
|
||||
r_refdef.worldmodel = 0;
|
||||
R_ClearEfrags ();
|
||||
R_ClearDlights ();
|
||||
|
@ -305,25 +307,13 @@ vulkan_render_view (void)
|
|||
for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) {
|
||||
__auto_type rp = vulkan_ctx->renderPasses.a[i];
|
||||
__auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame];
|
||||
frame->framebuffer = rp->framebuffers->a[imageIndex];
|
||||
if (rp->framebuffers) {
|
||||
frame->framebuffer = rp->framebuffers->a[imageIndex];
|
||||
}
|
||||
rp->draw (rpFrame);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_draw_entities (entqueue_t *queue)
|
||||
{
|
||||
__auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame];
|
||||
uint32_t imageIndex = vulkan_ctx->swapImageIndex;
|
||||
|
||||
for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) {
|
||||
__auto_type rp = vulkan_ctx->renderPasses.a[i];
|
||||
__auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame];
|
||||
frame->framebuffer = rp->framebuffers->a[imageIndex];
|
||||
Vulkan_RenderEntities (queue, rpFrame);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_draw_particles (struct psystem_s *psystem)
|
||||
{
|
||||
|
@ -371,13 +361,27 @@ vulkan_end_frame (void)
|
|||
.renderArea = { {0, 0}, vulkan_ctx->swapchain->extent },
|
||||
};
|
||||
|
||||
__auto_type cmdBufs = (qfv_cmdbufferset_t) DARRAY_STATIC_INIT (4);
|
||||
DARRAY_APPEND (&cmdBufs, frame->cmdBuffer);
|
||||
|
||||
dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo);
|
||||
for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) {
|
||||
__auto_type rp = vulkan_ctx->renderPasses.a[i];
|
||||
__auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame];
|
||||
|
||||
if (rp->primary_commands) {
|
||||
for (int j = 0; j < rpFrame->subpassCount; j++) {
|
||||
__auto_type cmdSet = &rpFrame->subpassCmdSets[j];
|
||||
size_t base = cmdBufs.size;
|
||||
DARRAY_RESIZE (&cmdBufs, base + cmdSet->size);
|
||||
memcpy (&cmdBufs.a[base], cmdSet->a,
|
||||
cmdSet->size * sizeof (VkCommandBuffer));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color);
|
||||
if (rpFrame->renderpass) {
|
||||
if (rpFrame->renderpass && rp->renderpass) {
|
||||
renderPassInfo.framebuffer = frame->framebuffer,
|
||||
renderPassInfo.renderPass = rp->renderpass;
|
||||
renderPassInfo.clearValueCount = rp->clearValues->size;
|
||||
|
@ -435,12 +439,14 @@ vulkan_end_frame (void)
|
|||
VkSubmitInfo submitInfo = {
|
||||
VK_STRUCTURE_TYPE_SUBMIT_INFO, 0,
|
||||
1, &frame->imageAvailableSemaphore, &waitStage,
|
||||
1, &frame->cmdBuffer,
|
||||
cmdBufs.size, cmdBufs.a,
|
||||
1, &frame->renderDoneSemaphore,
|
||||
};
|
||||
dfunc->vkResetFences (dev, 1, &frame->fence);
|
||||
dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence);
|
||||
|
||||
DARRAY_CLEAR (&cmdBufs);
|
||||
|
||||
if (vulkan_ctx->capture_callback) {
|
||||
//FIXME look into "threading" this rather than waiting here
|
||||
dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE,
|
||||
|
@ -648,11 +654,6 @@ vulkan_vid_render_choose_visual (void *data)
|
|||
vulkan_ctx->cmdpool = QFV_CreateCommandPool (vulkan_ctx->device,
|
||||
vulkan_ctx->device->queue.queueFamily,
|
||||
0, 1);
|
||||
__auto_type cmdset = QFV_AllocCommandBufferSet (1, alloca);
|
||||
QFV_AllocateCommandBuffers (vulkan_ctx->device, vulkan_ctx->cmdpool, 0,
|
||||
cmdset);
|
||||
vulkan_ctx->cmdbuffer = cmdset->a[0];
|
||||
vulkan_ctx->fence = QFV_CreateFence (vulkan_ctx->device, 1);
|
||||
Sys_MaskPrintf (SYS_vulkan, "vk choose visual %p %p %d %#zx\n",
|
||||
vulkan_ctx->device->dev, vulkan_ctx->device->queue.queue,
|
||||
vulkan_ctx->device->queue.queueFamily,
|
||||
|
@ -664,7 +665,7 @@ vulkan_vid_render_create_context (void *data)
|
|||
{
|
||||
vulkan_ctx->create_window (vulkan_ctx);
|
||||
vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx);
|
||||
Sys_MaskPrintf (SYS_vulkan, "vk create context %#zx\n",
|
||||
Sys_MaskPrintf (SYS_vulkan, "vk create context: surface:%#zx\n",
|
||||
(size_t) vulkan_ctx->surface);
|
||||
}
|
||||
|
||||
|
@ -743,7 +744,6 @@ vulkan_vid_render_shutdown (void)
|
|||
Vulkan_DestroyRenderPasses (vulkan_ctx);
|
||||
|
||||
QFV_DestroyStagingBuffer (vulkan_ctx->staging);
|
||||
df->vkDestroyFence (dev, vulkan_ctx->fence, 0);
|
||||
df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0);
|
||||
|
||||
Vulkan_Shutdown_Common (vulkan_ctx);
|
||||
|
@ -784,7 +784,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
|
|||
vulkan_R_LineGraph,
|
||||
vulkan_begin_frame,
|
||||
vulkan_render_view,
|
||||
vulkan_draw_entities,
|
||||
vulkan_draw_particles,
|
||||
vulkan_draw_transparent,
|
||||
vulkan_post_process,
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
};
|
||||
};
|
||||
framebuffer = {
|
||||
renderPass = $properties.renderpass;
|
||||
renderPass = deferred;
|
||||
attachments = (depth, color, emission, normal, position, opaque,
|
||||
translucent, $output.view);
|
||||
width = $output.extent.width;
|
||||
|
@ -125,6 +125,16 @@
|
|||
initialLayout = undefined;
|
||||
finalLayout = color_attachment_optimal;
|
||||
};
|
||||
info = {
|
||||
color = "[0, 1, 0, 1]";
|
||||
subpass_info = (
|
||||
{ name = depth; color = "[ 0.5, 0.5, 0.5, 1]" },
|
||||
{ name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" },
|
||||
{ name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" },
|
||||
{ name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" },
|
||||
{ name = compose; color = "[ 0.7, 0.3, 0.3, 1]" },
|
||||
);
|
||||
};
|
||||
renderpass = {
|
||||
attachments = (
|
||||
{
|
||||
|
|
|
@ -149,11 +149,16 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions)
|
|||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0,
|
||||
family, 1, &priority
|
||||
};
|
||||
VkPhysicalDeviceMultiviewFeatures multiview_features = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
|
||||
.multiview = 1,
|
||||
};
|
||||
VkPhysicalDeviceFeatures features = {
|
||||
.geometryShader = 1,
|
||||
.multiViewport = 1,
|
||||
};
|
||||
VkDeviceCreateInfo dCreateInfo = {
|
||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0,
|
||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, &multiview_features, 0,
|
||||
1, &qCreateInfo,
|
||||
nlay, lay,
|
||||
next, ext,
|
||||
|
|
|
@ -279,7 +279,15 @@ QFV_CreateInstance (vulkan_ctx_t *ctx,
|
|||
qfv_physdev_t *dev = &inst->devices[i];
|
||||
dev->instance = inst;
|
||||
dev->dev = physDev;
|
||||
ifunc->vkGetPhysicalDeviceProperties (physDev, &dev->properties);
|
||||
dev->properties2 = (VkPhysicalDeviceProperties2) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
|
||||
.pNext = &dev->multiViewProperties,
|
||||
};
|
||||
dev->multiViewProperties = (VkPhysicalDeviceMultiviewProperties) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES,
|
||||
};
|
||||
ifunc->vkGetPhysicalDeviceProperties2 (physDev, &dev->properties2);
|
||||
dev->properties = &dev->properties2.properties;
|
||||
ifunc->vkGetPhysicalDeviceMemoryProperties (physDev,
|
||||
&dev->memory_properties);
|
||||
}
|
||||
|
@ -306,8 +314,8 @@ QFV_GetMaxSampleCount (qfv_physdev_t *physdev)
|
|||
{
|
||||
VkSampleCountFlagBits maxSamples = VK_SAMPLE_COUNT_64_BIT;
|
||||
VkSampleCountFlagBits counts;
|
||||
counts = min (physdev->properties.limits.framebufferColorSampleCounts,
|
||||
physdev->properties.limits.framebufferDepthSampleCounts);
|
||||
counts = min (physdev->properties->limits.framebufferColorSampleCounts,
|
||||
physdev->properties->limits.framebufferDepthSampleCounts);
|
||||
while (maxSamples && maxSamples > counts) {
|
||||
maxSamples >>= 1;
|
||||
}
|
||||
|
|
|
@ -365,7 +365,7 @@
|
|||
{
|
||||
stageFlags = fragment;
|
||||
offset = 0;
|
||||
size = "4 * 4 + 4 + 4";
|
||||
size = "4 * 4 + 4 + 4 + 4";
|
||||
},
|
||||
);
|
||||
};
|
||||
|
@ -672,7 +672,7 @@
|
|||
dynamic = {
|
||||
dynamicState = ( viewport, scissor );
|
||||
};
|
||||
renderPass = renderpass;
|
||||
renderPass = deferred;
|
||||
};
|
||||
depth_base = {
|
||||
@inherit = $properties.pipelines.base;
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
renderpass.c
|
||||
|
||||
Vulkan render pass and frame buffer functions
|
||||
|
||||
Copyright (C) 2020 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/cvar.h"
|
||||
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
|
||||
VkRenderPass
|
||||
QFV_CreateRenderPass (qfv_device_t *device,
|
||||
qfv_attachmentdescription_t *attachments,
|
||||
qfv_subpassparametersset_t *subpassparams,
|
||||
qfv_subpassdependency_t *dependencies)
|
||||
{
|
||||
VkDevice dev = device->dev;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
if (developer & SYS_vulkan) {
|
||||
Sys_Printf ("attachments: %zd\n", attachments->size);
|
||||
for (size_t i = 0; i < attachments->size; i++) {
|
||||
Sys_Printf (" attachment: %zd\n", i);
|
||||
Sys_Printf (" flags: %x\n", attachments->a[i].flags);
|
||||
Sys_Printf (" format: %d\n", attachments->a[i].format);
|
||||
Sys_Printf (" samples: %x\n", attachments->a[i].samples);
|
||||
Sys_Printf (" loadOp: %d\n", attachments->a[i].loadOp);
|
||||
Sys_Printf (" storeOp: %d\n", attachments->a[i].storeOp);
|
||||
Sys_Printf (" stencilLoadOp: %d\n",
|
||||
attachments->a[i].stencilLoadOp);
|
||||
Sys_Printf (" stencilStoreOp: %d\n",
|
||||
attachments->a[i].stencilStoreOp);
|
||||
Sys_Printf (" initialLayout: %d\n",
|
||||
attachments->a[i].initialLayout);
|
||||
Sys_Printf (" finalLayout: %d\n",
|
||||
attachments->a[i].finalLayout);
|
||||
}
|
||||
Sys_Printf ("subpassparams: %zd\n", subpassparams->size);
|
||||
for (size_t i = 0; i < subpassparams->size; i++) {
|
||||
VkSubpassDescription *sp = &subpassparams->a[i];
|
||||
Sys_Printf (" flags: %x\n", sp->flags);
|
||||
Sys_Printf (" piplineBindPoint: %d\n", sp->pipelineBindPoint);
|
||||
Sys_Printf (" inputAttachmentCount: %d\n",
|
||||
sp->inputAttachmentCount);
|
||||
for (size_t j = 0; j < sp->inputAttachmentCount; j++) {
|
||||
const VkAttachmentReference *ref = &sp->pInputAttachments[j];
|
||||
Sys_Printf (" c %d %d\n", ref->attachment, ref->layout);
|
||||
}
|
||||
Sys_Printf (" colorAttachmentCount: %d\n",
|
||||
sp->colorAttachmentCount);
|
||||
for (size_t j = 0; j < sp->colorAttachmentCount; j++) {
|
||||
const VkAttachmentReference *ref = &sp->pColorAttachments[j];
|
||||
Sys_Printf (" c %d %d\n", ref->attachment, ref->layout);
|
||||
}
|
||||
if (sp->pResolveAttachments) {
|
||||
for (size_t j = 0; j < sp->colorAttachmentCount; j++) {
|
||||
const VkAttachmentReference *ref
|
||||
= &sp->pResolveAttachments[j];
|
||||
Sys_Printf (" r %d %d\n", ref->attachment,
|
||||
ref->layout);
|
||||
}
|
||||
}
|
||||
Sys_Printf (" pDepthStencilAttachment: %p\n",
|
||||
sp->pDepthStencilAttachment);
|
||||
if (sp->pDepthStencilAttachment) {
|
||||
const VkAttachmentReference *ref = sp->pDepthStencilAttachment;
|
||||
Sys_Printf (" %d %d\n", ref->attachment, ref->layout);
|
||||
}
|
||||
Sys_Printf (" preserveAttachmentCount: %d\n",
|
||||
sp->preserveAttachmentCount);
|
||||
for (size_t j = 0; j < sp->preserveAttachmentCount; j++) {
|
||||
Sys_Printf (" %d\n", sp->pPreserveAttachments[j]);
|
||||
}
|
||||
}
|
||||
Sys_Printf ("dependencies: %zd\n", dependencies->size);
|
||||
for (size_t i = 0; i < dependencies->size; i++) {
|
||||
Sys_Printf (" srcSubpass: %d\n", dependencies->a[i].srcSubpass);
|
||||
Sys_Printf (" dstSubpass: %d\n", dependencies->a[i].dstSubpass);
|
||||
Sys_Printf (" srcStageMask: %x\n", dependencies->a[i].srcStageMask);
|
||||
Sys_Printf (" dstStageMask: %x\n", dependencies->a[i].dstStageMask);
|
||||
Sys_Printf (" srcAccessMask: %x\n", dependencies->a[i].srcAccessMask);
|
||||
Sys_Printf (" dstAccessMask: %x\n", dependencies->a[i].dstAccessMask);
|
||||
Sys_Printf (" dependencyFlags: %x\n", dependencies->a[i].dependencyFlags);
|
||||
}
|
||||
}
|
||||
VkRenderPassCreateInfo createInfo = {
|
||||
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 0, 0,
|
||||
attachments->size, attachments->a,
|
||||
subpassparams->size, subpassparams->a,
|
||||
dependencies->size, dependencies->a,
|
||||
};
|
||||
|
||||
VkRenderPass renderpass;
|
||||
dfunc->vkCreateRenderPass (dev, &createInfo, 0, &renderpass);
|
||||
return renderpass;
|
||||
}
|
||||
|
||||
VkFramebuffer
|
||||
QFV_CreateFramebuffer (qfv_device_t *device, VkRenderPass renderPass,
|
||||
qfv_imageviewset_t *attachments,
|
||||
VkExtent2D extent, uint32_t layers)
|
||||
{
|
||||
VkDevice dev = device->dev;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
VkFramebufferCreateInfo createInfo = {
|
||||
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 0, 0,
|
||||
renderPass, attachments->size, attachments->a,
|
||||
extent.width, extent.height, layers,
|
||||
};
|
||||
|
||||
VkFramebuffer framebuffer;
|
||||
dfunc->vkCreateFramebuffer (dev, &createInfo, 0, &framebuffer);
|
||||
return framebuffer;
|
||||
}
|
|
@ -104,8 +104,6 @@ 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"
|
||||
|
||||
typedef struct shaderdata_s {
|
||||
const char *name;
|
||||
|
@ -147,7 +145,6 @@ static shaderdata_t builtin_shaders[] = {
|
|||
{ "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) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ layout (location = 0) in vec4 tl_st;
|
|||
layout (location = 1) in vec3 direction;
|
||||
layout (location = 2) in vec3 normal;
|
||||
layout (location = 3) in vec4 position;
|
||||
layout (location = 4) in vec4 color;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
layout (location = 1) out vec4 frag_emission;
|
||||
|
@ -37,7 +38,7 @@ main (void)
|
|||
vec3 e_st = vec3 (tl_st.xy, 1);
|
||||
vec2 l_st = vec2 (tl_st.zw);
|
||||
|
||||
c = texture (Texture, t_st);
|
||||
c = texture (Texture, t_st) * color;
|
||||
e = texture (Texture, e_st);
|
||||
frag_color = c;//fogBlend (c);
|
||||
frag_emission = e;
|
||||
|
|
|
@ -11,11 +11,13 @@ layout (triangles) in;
|
|||
layout (triangle_strip, max_vertices = 3) out;
|
||||
layout (location = 0) in vec4 v_tl_st[];
|
||||
layout (location = 1) in vec3 v_direction[];
|
||||
layout (location = 2) in vec4 v_color[];
|
||||
|
||||
layout (location = 0) out vec4 tl_st;
|
||||
layout (location = 1) out vec3 direction;
|
||||
layout (location = 2) out vec3 normal;
|
||||
layout (location = 3) out vec4 position;
|
||||
layout (location = 4) out vec4 color;
|
||||
|
||||
void
|
||||
main()
|
||||
|
@ -31,6 +33,7 @@ main()
|
|||
gl_Position = Projection3d * (View * (p));
|
||||
tl_st = v_tl_st[vert];
|
||||
direction = v_direction[vert];
|
||||
color = v_color[vert];
|
||||
normal = n;
|
||||
position = p;
|
||||
EmitVertex ();
|
||||
|
|
|
@ -20,6 +20,7 @@ layout (location = 2) in uint entid;
|
|||
|
||||
layout (location = 0) out vec4 tl_st;
|
||||
layout (location = 1) out vec3 direction;
|
||||
layout (location = 2) out vec4 color;
|
||||
|
||||
void
|
||||
main (void)
|
||||
|
@ -29,4 +30,5 @@ main (void)
|
|||
gl_Position = vec4 (vert, 1);
|
||||
direction = (Sky * vertex).xyz;
|
||||
tl_st = tl_uv;
|
||||
color = entities[entid].color;
|
||||
}
|
||||
|
|
|
@ -10,10 +10,12 @@ layout (push_constant) uniform PushConstants {
|
|||
vec4 fog;
|
||||
float time;
|
||||
float alpha;
|
||||
float turb_scale;
|
||||
};
|
||||
|
||||
layout (location = 0) in vec4 tl_st;
|
||||
layout (location = 1) in vec3 direction;
|
||||
layout (location = 2) in vec4 color;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
|
||||
|
|
|
@ -6,10 +6,12 @@ layout (push_constant) uniform PushConstants {
|
|||
vec4 fog;
|
||||
float time;
|
||||
float alpha;
|
||||
float turb_scale;
|
||||
};
|
||||
|
||||
layout (location = 0) in vec4 tl_st;
|
||||
layout (location = 1) in vec3 direction;
|
||||
layout (location = 2) in vec4 color;
|
||||
|
||||
layout (location = 0) out vec4 frag_color;
|
||||
|
||||
|
@ -25,7 +27,7 @@ warp_st (vec2 st, float time)
|
|||
{
|
||||
vec2 angle = st.ts * CYCLE / 2.0;
|
||||
vec2 phase = vec2 (time, time) * SPEED;
|
||||
return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE;
|
||||
return st + turb_scale * (sin ((angle + phase) * FACTOR) + BIAS) / SCALE;
|
||||
}
|
||||
|
||||
vec4
|
||||
|
@ -48,7 +50,8 @@ main (void)
|
|||
|
||||
c = texture (Texture, t_st);
|
||||
e = texture (Texture, e_st);
|
||||
float a = c.a * e.a * alpha;
|
||||
c += e;
|
||||
c.a = alpha;
|
||||
frag_color = c;//fogBlend (c);
|
||||
c.a = a;
|
||||
frag_color = c * color;//fogBlend (c);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ layout (location = 2) in uint entid;
|
|||
|
||||
layout (location = 0) out vec4 tl_st;
|
||||
layout (location = 1) out vec3 direction;
|
||||
layout (location = 2) out vec4 color;
|
||||
|
||||
void
|
||||
main (void)
|
||||
|
@ -28,4 +29,5 @@ main (void)
|
|||
gl_Position = Projection3d * (View * vec4 (vert, 1));
|
||||
direction = (Sky * vertex).xyz;
|
||||
tl_st = tl_uv;
|
||||
color = entities[entid].color;
|
||||
}
|
||||
|
|
|
@ -1,54 +1,17 @@
|
|||
{
|
||||
images = {
|
||||
shadow = {
|
||||
flags = cube_compatible;
|
||||
imageType = `2d;
|
||||
format = x8_d24_unorm_pack32;
|
||||
samples = 1;
|
||||
extent = {
|
||||
width = 256; // FIXME config
|
||||
height = 256; // FIXME config
|
||||
depth = 1;
|
||||
};
|
||||
mipLevels = 1;
|
||||
arrayLayers = 2048; // FIXME config
|
||||
tiling = optimal;
|
||||
usage = depth_stencil_attachment|sampled;
|
||||
initialLayout = undefined;
|
||||
};
|
||||
};
|
||||
imageViews = {
|
||||
shadow = {
|
||||
image = depth;
|
||||
viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
format = $properties.images.shadow.format;
|
||||
components = {
|
||||
r = identity;
|
||||
g = identity;
|
||||
b = identity;
|
||||
a = identity;
|
||||
};
|
||||
subresourceRange = {
|
||||
aspectMask = depth;
|
||||
levelCount = 1;
|
||||
layerCount = $properties.images.shadow.arrayLayers;
|
||||
};
|
||||
};
|
||||
};
|
||||
framebuffer = {
|
||||
renderPass = $properties.renderpass;
|
||||
attachments = (shadown);
|
||||
width = $properties.images.shadow.extent.width;
|
||||
height = $properties.images.shadow.extent.height;
|
||||
layers = $properties.images.shadow.arrayLayers;
|
||||
};
|
||||
clearValues = (
|
||||
{ depthStencil = { depth = 1; stencil = 0; }; },
|
||||
);
|
||||
renderpass = {
|
||||
info = {
|
||||
color = "[0.2, 0.2, 0.2, 1]";
|
||||
subpass_info = (
|
||||
{ name = depth; color = "[ 0.5, 0.5, 0.5, 1]" },
|
||||
);
|
||||
};
|
||||
renderpass_base = {
|
||||
attachments = (
|
||||
{
|
||||
format = $properties.images.depth.format;
|
||||
format = $output.format;
|
||||
samples = 1;
|
||||
loadOp = dont_care;
|
||||
storeOp = store;
|
||||
|
@ -68,4 +31,22 @@
|
|||
}
|
||||
);
|
||||
};
|
||||
renderpass_6 = {
|
||||
@inherit = $properties.renderpass_base;
|
||||
@next = (VkRenderPassMultiviewCreateInfo, {
|
||||
viewMasks = (0x0000003fu);
|
||||
});
|
||||
};
|
||||
renderpass_4 = {
|
||||
@inherit = $properties.renderpass_base;
|
||||
@next = (VkRenderPassMultiviewCreateInfo, {
|
||||
viewMasks = (0x0000000fu);
|
||||
});
|
||||
};
|
||||
renderpass_1 = {
|
||||
@inherit = $properties.renderpass_base;
|
||||
@next = (VkRenderPassMultiviewCreateInfo, {
|
||||
viewMasks = (0x00000001u);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ qfv_stagebuf_t *
|
|||
QFV_CreateStagingBuffer (qfv_device_t *device, const char *name, size_t size,
|
||||
VkCommandPool cmdPool)
|
||||
{
|
||||
size_t atom = device->physDev->properties.limits.nonCoherentAtomSize;
|
||||
size_t atom = device->physDev->properties->limits.nonCoherentAtomSize;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
dstring_t *str = dstring_new ();
|
||||
|
||||
|
|
|
@ -155,11 +155,14 @@ qfv_devfuncs_t dfuncs = {
|
|||
.vkQueueSubmit = vkQueueSubmit,
|
||||
};
|
||||
qfv_physdev_t physDev = {
|
||||
.properties = {
|
||||
.limits = {
|
||||
.nonCoherentAtomSize = 256,
|
||||
.properties2 = {
|
||||
.properties = {
|
||||
.limits = {
|
||||
.nonCoherentAtomSize = 256,
|
||||
},
|
||||
},
|
||||
},
|
||||
.properties = &physDev.properties2.properties,
|
||||
};
|
||||
qfv_device_t device = {
|
||||
.physDev = &physDev,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
@interface Struct: Type
|
||||
{
|
||||
string outname;
|
||||
int write_symtab;
|
||||
}
|
||||
-(void) queueFieldTypes;
|
||||
-(qfot_var_t *)findField:(string) fieldName;
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
PLItem *new_name = [field_dict getObjectForKey:".name"];
|
||||
Array *field_defs = [Array array];
|
||||
int have_sType = 0;
|
||||
int have_pNext = 0;
|
||||
|
||||
if ([parse string] == "skip") {
|
||||
return;
|
||||
|
@ -97,6 +98,10 @@
|
|||
if (field.name == "sType") {
|
||||
have_sType = 1;
|
||||
}
|
||||
if (field.name == "pNext") {
|
||||
have_pNext = 1;
|
||||
write_symtab = 1;
|
||||
}
|
||||
}
|
||||
if (field_dict) {
|
||||
PLItem *field_keys = [field_dict allKeys];
|
||||
|
@ -133,6 +138,11 @@
|
|||
fprintf (output_file,
|
||||
"\t{\"@inherit\", 0, QFString, parse_inherit, &%s_fields},\n",
|
||||
[self outname]);
|
||||
if (have_pNext) {
|
||||
fprintf (output_file,
|
||||
"\t{\"@next\", field_offset (%s, pNext), "
|
||||
"QFArray, parse_next, 0},", [self outname]);
|
||||
}
|
||||
for (int i = [field_defs count]; i-- > 0; ) {
|
||||
FieldDef *field_def = [field_defs objectAtIndex:i];
|
||||
[field_def writeField];
|
||||
|
@ -140,14 +150,14 @@
|
|||
fprintf (output_file, "\t{ }\n");
|
||||
fprintf (output_file, "};\n");
|
||||
|
||||
fprintf (header_file, "int parse_%s (const plfield_t *field,"
|
||||
fprintf (header_file, "int %s (const plfield_t *field,"
|
||||
" const plitem_t *item, void *data, plitem_t *messages,"
|
||||
" void *context);\n",
|
||||
[self outname]);
|
||||
fprintf (output_file, "int parse_%s (const plfield_t *field,"
|
||||
[self parseFunc]);
|
||||
fprintf (output_file, "int %s (const plfield_t *field,"
|
||||
" const plitem_t *item, void *data, plitem_t *messages,"
|
||||
" void *context)\n",
|
||||
[self outname]);
|
||||
[self parseFunc]);
|
||||
fprintf (output_file, "{\n");
|
||||
if (have_sType) {
|
||||
fprintf (output_file, "\t((%s *) data)->sType", [self outname]);
|
||||
|
@ -162,6 +172,12 @@
|
|||
" context);\n",
|
||||
[self outname], [self outname]);
|
||||
fprintf (output_file, "}\n");
|
||||
if (have_pNext) {
|
||||
fprintf (output_file, "static parserref_t %s_parser = ",
|
||||
[self outname]);
|
||||
fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n",
|
||||
[self outname], [self parseFunc], [self outname]);
|
||||
}
|
||||
|
||||
fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self outname]);
|
||||
if (field_defs) {
|
||||
|
@ -216,6 +232,12 @@
|
|||
|
||||
-(void) writeSymtabEntry
|
||||
{
|
||||
if (!write_symtab || [parse string] == "skip") {
|
||||
return;
|
||||
}
|
||||
fprintf (output_file,
|
||||
"\tHash_Add (parser_table, &%s_parser);\n",
|
||||
[self outname]);
|
||||
}
|
||||
|
||||
-(string) outname
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
#define __x86_64__
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "QF/Vulkan/swapchain.h"
|
||||
|
||||
//FIXME copy of qfv_subpass_t in qf_renderpass.h
|
||||
//except it doesn't really matter because a custom spec is used
|
||||
typedef struct qfv_subpass_s {
|
||||
vec4 color;
|
||||
string name;
|
||||
} qfv_subpass_t;
|
||||
|
|
|
@ -41,14 +41,14 @@
|
|||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/pipeline.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
#include "QF/Vulkan/shader.h"
|
||||
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
#define vkparse_internal
|
||||
#include "vkparse.h"
|
||||
#undef vkparse_internal
|
||||
#include "libs/video/renderer/vulkan/vkparse.hinc"
|
||||
|
||||
typedef struct parseres_s {
|
||||
const char *name;
|
||||
|
@ -56,6 +56,12 @@ typedef struct parseres_s {
|
|||
size_t offset;
|
||||
} parseres_t;
|
||||
|
||||
typedef struct parseref_s {
|
||||
const char *name;
|
||||
plparser_t parse;
|
||||
size_t size;
|
||||
} parserref_t;
|
||||
|
||||
typedef struct handleref_s {
|
||||
char *name;
|
||||
uint64_t handle;
|
||||
|
@ -150,6 +156,7 @@ parse_basic (const plfield_t *field, const plitem_t *item,
|
|||
exprctx_t ectx = *((parsectx_t *) context)->ectx;
|
||||
exprval_t result = { etype, data };
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
const char *valstr = PL_String (item);
|
||||
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_basic: %s %zd %d %p %p: %s\n",
|
||||
// field->name, field->offset, field->type, field->parser,
|
||||
|
@ -169,6 +176,34 @@ parse_basic (const plfield_t *field, const plitem_t *item,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_int32_t (const plfield_t *field, const plitem_t *item,
|
||||
void *data, plitem_t *messages, void *context)
|
||||
{
|
||||
int ret = 1;
|
||||
// use size_t (and cexpr_size_t) for val so references to array sizes
|
||||
// can be used
|
||||
size_t val = 0;
|
||||
exprval_t result = { &cexpr_size_t, &val };
|
||||
exprctx_t ectx = *((parsectx_t *) context)->ectx;
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
const char *valstr = PL_String (item);
|
||||
//Sys_MaskPrintf (SYS_vulkan_parse,
|
||||
// "parse_int32_t: %s %zd %d %p %p %s\n",
|
||||
// field->name, field->offset, field->type, field->parser,
|
||||
// field->data, valstr);
|
||||
ret = !cexpr_eval_string (valstr, &ectx);
|
||||
if (!ret) {
|
||||
PL_Message (messages, item, "error parsing %s: %s",
|
||||
field->name, valstr);
|
||||
}
|
||||
*(int32_t *) data = val;
|
||||
//Sys_MaskPrintf (SYS_vulkan_parse, " %d\n", *(int32_t *)data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_uint32_t (const plfield_t *field, const plitem_t *item,
|
||||
void *data, plitem_t *messages, void *context)
|
||||
|
@ -180,6 +215,7 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item,
|
|||
exprval_t result = { &cexpr_size_t, &val };
|
||||
exprctx_t ectx = *((parsectx_t *) context)->ectx;
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
const char *valstr = PL_String (item);
|
||||
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_uint32_t: %s %zd %d %p %p: %s\n",
|
||||
// field->name, field->offset, field->type, field->parser,
|
||||
|
@ -235,6 +271,7 @@ parse_reference (const plitem_t *item, const char *type, plitem_t *messages,
|
|||
plitem_t *refItem = 0;
|
||||
exprval_t result = { &cexpr_plitem, &refItem };
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
const char *name = PL_String (item);
|
||||
if (cexpr_eval_string (name, &ectx)) {
|
||||
PL_Message (messages, item, "not a %s reference", type);
|
||||
|
@ -383,6 +420,7 @@ parse_inherit (const plfield_t *field, const plitem_t *item,
|
|||
plitem_t *inheritItem = 0;
|
||||
exprval_t result = { &cexpr_plitem, &inheritItem };
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
const char *inheritstr = PL_String (item);
|
||||
Sys_MaskPrintf (SYS_vulkan_parse, "parse_inherit: %s\n", inheritstr);
|
||||
int ret = !cexpr_eval_string (inheritstr, &ectx);
|
||||
|
@ -393,6 +431,33 @@ parse_inherit (const plfield_t *field, const plitem_t *item,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static hashtab_t *parser_table;
|
||||
|
||||
static int
|
||||
parse_next (const plfield_t *field, const plitem_t *item, void *data,
|
||||
plitem_t *messages, void *context)
|
||||
{
|
||||
const char *type_name = PL_String (PL_ObjectAtIndex (item, 0));
|
||||
plitem_t *next_def = PL_ObjectAtIndex (item, 1);
|
||||
|
||||
if (!type_name || PL_Type (next_def) != QFDictionary) {
|
||||
PL_Message (messages, item, "invalid @next");
|
||||
return 0;
|
||||
}
|
||||
parserref_t *parser = Hash_Find (parser_table, type_name);
|
||||
if (!parser) {
|
||||
PL_Message (messages, item, "Invalid type for @next: %s", type_name);
|
||||
return 0;
|
||||
}
|
||||
void *data_ptr = vkparse_alloc (context, parser->size);
|
||||
memset (data_ptr, 0, parser->size);
|
||||
if (!parser->parse (field, next_def, data_ptr, messages, context)) {
|
||||
return 0;
|
||||
}
|
||||
*(void **) data = data_ptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_RGBA (const plitem_t *item, void **data,
|
||||
plitem_t *messages, parsectx_t *context)
|
||||
|
@ -401,6 +466,7 @@ parse_RGBA (const plitem_t *item, void **data,
|
|||
exprctx_t ectx = *context->ectx;
|
||||
exprval_t result = { &cexpr_vector, data[0] };
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
const char *valstr = PL_String (item);
|
||||
Sys_MaskPrintf (SYS_vulkan_parse, "parse_RGBA: %s\n", valstr);
|
||||
ret = !cexpr_eval_string (valstr, &ectx);
|
||||
|
@ -463,6 +529,7 @@ parse_VkRenderPass (const plitem_t *item, void **data,
|
|||
plitem_t *setItem = 0;
|
||||
exprval_t result = { &cexpr_plitem, &setItem };
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
ret = !cexpr_eval_string (path, &ectx);
|
||||
if (ret) {
|
||||
VkRenderPass setLayout;
|
||||
|
@ -471,7 +538,7 @@ parse_VkRenderPass (const plitem_t *item, void **data,
|
|||
|
||||
// path not guaranteed to survive cexpr_eval_string due to va
|
||||
path = resource_path (ctx, 0, name);
|
||||
QFV_AddHandle (ctx->setLayouts, path, (uint64_t) setLayout);
|
||||
QFV_AddHandle (ctx->renderpasses, path, (uint64_t) setLayout);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -523,6 +590,7 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item,
|
|||
plitem_t *setItem = 0;
|
||||
exprval_t result = { &cexpr_plitem, &setItem };
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
ret = !cexpr_eval_string (path, &ectx);
|
||||
if (ret) {
|
||||
VkDescriptorSetLayout setLayout;
|
||||
|
@ -558,6 +626,7 @@ parse_VkPipelineLayout (const plitem_t *item, void **data,
|
|||
plitem_t *setItem = 0;
|
||||
exprval_t result = { &cexpr_plitem, &setItem };
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
ret = !cexpr_eval_string (path, &ectx);
|
||||
if (ret) {
|
||||
VkPipelineLayout layout;
|
||||
|
@ -592,6 +661,7 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages,
|
|||
plitem_t *imageItem = 0;
|
||||
exprval_t result = { &cexpr_plitem, &imageItem };
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
ret = !cexpr_eval_string (path, &ectx);
|
||||
if (ret) {
|
||||
VkImage image;
|
||||
|
@ -635,6 +705,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data,
|
|||
exprval_t *value = 0;
|
||||
exprval_t result = { &cexpr_exprval, &value };
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
ret = !cexpr_eval_string (path, &ectx);
|
||||
|
||||
plitem_t *imageViewItem = 0;
|
||||
|
@ -864,6 +935,7 @@ parse_specialization_data (const plitem_t *item, void **data,
|
|||
ectx.parent = ((parsectx_t *)context)->ectx;
|
||||
ectx.symtab = &data_array_symtab;
|
||||
ectx.result = &result;
|
||||
ectx.item = item;
|
||||
const char *valstr = PL_String (item);
|
||||
//Sys_MaskPrintf (SYS_vulkan_parse,
|
||||
// "parse_specialization_data: %s %zd %d %p %p %s\n",
|
||||
|
@ -918,46 +990,6 @@ exprtype_t vulkan_frameset_t_type = {
|
|||
.data = &vulkan_frameset_t_symtab,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
qfv_attachmentdescription_t *attachments;
|
||||
qfv_subpassparametersset_t *subpasses;
|
||||
qfv_subpassdependency_t *dependencies;
|
||||
} vkparse_renderpass_t;
|
||||
|
||||
static plelement_t parse_qfv_renderpass_attachments_data = {
|
||||
QFDictionary,
|
||||
sizeof (VkAttachmentDescription),
|
||||
vkparse_alloc,
|
||||
parse_VkAttachmentDescription,
|
||||
0,
|
||||
};
|
||||
|
||||
static plelement_t parse_qfv_renderpass_subpasses_data = {
|
||||
QFDictionary,
|
||||
sizeof (VkSubpassDescription),
|
||||
vkparse_alloc,
|
||||
parse_VkSubpassDescription,
|
||||
0,
|
||||
};
|
||||
|
||||
static plelement_t parse_qfv_renderpass_dependencies_data = {
|
||||
QFDictionary,
|
||||
sizeof (VkSubpassDependency),
|
||||
vkparse_alloc,
|
||||
parse_VkSubpassDependency,
|
||||
0,
|
||||
};
|
||||
|
||||
static plfield_t renderpass_fields[] = {
|
||||
{ "attachments", field_offset(vkparse_renderpass_t,attachments), QFArray,
|
||||
PL_ParseArray, &parse_qfv_renderpass_attachments_data },
|
||||
{ "subpasses", field_offset(vkparse_renderpass_t,subpasses), QFArray,
|
||||
PL_ParseArray, &parse_qfv_renderpass_subpasses_data },
|
||||
{ "dependencies", field_offset(vkparse_renderpass_t,dependencies), QFArray,
|
||||
PL_ParseArray, &parse_qfv_renderpass_dependencies_data },
|
||||
{}
|
||||
};
|
||||
|
||||
static hashtab_t *
|
||||
handlref_symtab (void (*free_func)(void*,void*), vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
@ -971,6 +1003,13 @@ enum_symtab_getkey (const void *e, void *unused)
|
|||
return enm->type->name;
|
||||
}
|
||||
|
||||
static const char *
|
||||
parser_getkey (const void *e, void *unused)
|
||||
{
|
||||
__auto_type parser = (const parserref_t *) e;
|
||||
return parser->name;
|
||||
}
|
||||
|
||||
static exprtab_t root_symtab = {
|
||||
.symbols = cexpr_lib_symbols,
|
||||
};
|
||||
|
@ -988,6 +1027,7 @@ QFV_InitParse (vulkan_ctx_t *ctx)
|
|||
{
|
||||
exprctx_t context = {};
|
||||
enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, &ctx->hashctx);
|
||||
parser_table = Hash_NewTable (61, parser_getkey, 0, 0, &ctx->hashctx);
|
||||
context.hashctx = &ctx->hashctx;
|
||||
vkgen_init_symtabs (&context);
|
||||
cexpr_init_symtab (&qfv_output_t_symtab, &context);
|
||||
|
@ -1024,7 +1064,7 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist,
|
|||
{"frames", &vulkan_frameset_t_type, &ctx->frames},
|
||||
{"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples},
|
||||
{"physDevLimits", &VkPhysicalDeviceLimits_type,
|
||||
&ctx->device->physDev->properties.limits },
|
||||
&ctx->device->physDev->properties->limits },
|
||||
{QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties},
|
||||
{}
|
||||
};
|
||||
|
@ -1050,33 +1090,25 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_qfv_renderpass (const plfield_t *field, const plitem_t *item, void *data,
|
||||
plitem_t *messages, void *context)
|
||||
{
|
||||
return PL_ParseStruct (renderpass_fields, item, data, messages, context);
|
||||
}
|
||||
|
||||
VkRenderPass
|
||||
QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
|
||||
{
|
||||
memsuper_t *memsuper = new_memsuper ();
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
vkparse_renderpass_t renderpass_data = {};
|
||||
VkRenderPassCreateInfo cInfo = {};
|
||||
|
||||
if (!parse_object (ctx, memsuper, plist, parse_qfv_renderpass,
|
||||
&renderpass_data, properties)) {
|
||||
if (!parse_object (ctx, memsuper, plist, parse_VkRenderPassCreateInfo,
|
||||
&cInfo, properties)) {
|
||||
delete_memsuper (memsuper);
|
||||
return 0;
|
||||
}
|
||||
|
||||
VkRenderPass renderpass;
|
||||
qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseRenderPass: %d", PL_Line (plist)));
|
||||
renderpass = QFV_CreateRenderPass (device,
|
||||
renderpass_data.attachments,
|
||||
renderpass_data.subpasses,
|
||||
renderpass_data.dependencies);
|
||||
qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseRenderPass: %d",
|
||||
PL_Line (plist)));
|
||||
dfunc->vkCreateRenderPass (device->dev, &cInfo, 0, &renderpass);
|
||||
qfvPopDebug (ctx);
|
||||
|
||||
delete_memsuper (memsuper);
|
||||
|
@ -1496,3 +1528,65 @@ QFV_ParseClearValues (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
|
|||
delete_memsuper (memsuper);
|
||||
return cv;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_subpassset (const plfield_t *field, const plitem_t *item, void *data,
|
||||
plitem_t *messages, void *context)
|
||||
{
|
||||
plelement_t element = {
|
||||
QFDictionary,
|
||||
sizeof (qfv_subpass_t),
|
||||
vkparse_alloc,
|
||||
parse_qfv_subpass_t,
|
||||
0,
|
||||
};
|
||||
plfield_t f = { 0, 0, 0, 0, &element };
|
||||
|
||||
if (!PL_ParseArray (&f, item, data, messages, context)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
qfv_subpassset_t *
|
||||
QFV_ParseSubpasses (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
|
||||
{
|
||||
qfv_subpassset_t *sp = 0;
|
||||
memsuper_t *memsuper = new_memsuper ();
|
||||
qfv_subpassset_t *subpasses = 0;
|
||||
|
||||
if (parse_object (ctx, memsuper, plist, parse_subpassset, &subpasses,
|
||||
properties)) {
|
||||
sp = DARRAY_ALLOCFIXED (qfv_subpassset_t, subpasses->size, malloc);
|
||||
memcpy (sp->a, subpasses->a, sp->size * sizeof (sp->a[0]));
|
||||
// the name is in memsuper which is about to be freed
|
||||
for (size_t i = 0; i < sp->size; i++) {
|
||||
sp->a[i].name = strdup (sp->a[i].name);
|
||||
}
|
||||
}
|
||||
delete_memsuper (memsuper);
|
||||
return sp;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_rgba (const plfield_t *field, const plitem_t *item, void *data,
|
||||
plitem_t *messages, void *context)
|
||||
{
|
||||
return parse_RGBA (item, &data, messages, context);
|
||||
}
|
||||
|
||||
int
|
||||
QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist,
|
||||
plitem_t *properties)
|
||||
{
|
||||
memsuper_t *memsuper = new_memsuper ();
|
||||
int ret = 0;
|
||||
vec4f_t color;
|
||||
|
||||
if (parse_object (ctx, memsuper, plist, parse_rgba, &color, properties)) {
|
||||
memcpy (rgba, &color, sizeof (color));
|
||||
ret = 1;
|
||||
}
|
||||
delete_memsuper (memsuper);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -10,9 +10,6 @@ typedef struct parsectx_s {
|
|||
|
||||
#include "QF/cexpr.h"
|
||||
#include "QF/plist.h"
|
||||
#ifdef vkparse_internal
|
||||
#include "libs/video/renderer/vulkan/vkparse.hinc"
|
||||
#endif
|
||||
|
||||
#define QFV_PROPERTIES "properties"
|
||||
|
||||
|
@ -52,5 +49,9 @@ struct clearvalueset_s *QFV_ParseClearValues (vulkan_ctx_t *ctx,
|
|||
plitem_t *plist,
|
||||
plitem_t *properties);
|
||||
|
||||
|
||||
struct qfv_subpassset_s *QFV_ParseSubpasses (vulkan_ctx_t *ctx,
|
||||
plitem_t *plist,
|
||||
plitem_t *properties);
|
||||
int QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist,
|
||||
plitem_t *properties);
|
||||
#endif//__vkparse_h
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
VkFramebufferCreateInfo,
|
||||
VkClearValue,
|
||||
VkPhysicalDeviceLimits,
|
||||
VkRenderPassCreateInfo,
|
||||
VkRenderPassMultiviewCreateInfo,
|
||||
|
||||
qfv_subpass_t,
|
||||
);
|
||||
parse = {
|
||||
VkSubpassDescription = {
|
||||
|
@ -359,5 +363,34 @@
|
|||
};
|
||||
depthStencil = auto;
|
||||
};
|
||||
}
|
||||
VkRenderPassMultiviewCreateInfo = {
|
||||
viewMasks = {
|
||||
type = (array, uint32_t);
|
||||
size = subpassCount;
|
||||
values = pViewMasks;
|
||||
};
|
||||
viewOffsets = {
|
||||
type = (array, int32_t);
|
||||
size = dependencyCount;
|
||||
values = pViewOffsets;
|
||||
};
|
||||
correlationMasks = {
|
||||
type = (array, uint32_t);
|
||||
size = correlationMaskCount;
|
||||
values = pCorrelationMasks;
|
||||
};
|
||||
};
|
||||
|
||||
qfv_subpass_s = {
|
||||
.name = qfv_subpass_t;
|
||||
color = {
|
||||
type = (custom, QFString, parse_RGBA);
|
||||
fields = (color);
|
||||
};
|
||||
name = {
|
||||
type = string;
|
||||
string = name;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -42,11 +42,11 @@
|
|||
|
||||
#include "QF/Vulkan/qf_alias.h"
|
||||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
#include "QF/Vulkan/debug.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
|
|
@ -51,11 +51,13 @@
|
|||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "QF/math/bitop.h"
|
||||
#include "QF/scene/entity.h"
|
||||
|
||||
#include "QF/Vulkan/qf_bsp.h"
|
||||
#include "QF/Vulkan/qf_lightmap.h"
|
||||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_scene.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
#include "QF/Vulkan/buffer.h"
|
||||
|
@ -66,7 +68,6 @@
|
|||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
#include "QF/Vulkan/scrap.h"
|
||||
#include "QF/Vulkan/staging.h"
|
||||
|
||||
|
@ -79,6 +80,7 @@ typedef struct bsp_push_constants_s {
|
|||
quat_t fog;
|
||||
float time;
|
||||
float alpha;
|
||||
float turb_scale;
|
||||
} bsp_push_constants_t;
|
||||
|
||||
static const char * __attribute__((used)) bsp_pass_names[] = {
|
||||
|
@ -89,14 +91,12 @@ static const char * __attribute__((used)) bsp_pass_names[] = {
|
|||
};
|
||||
|
||||
static QFV_Subpass subpass_map[] = {
|
||||
QFV_passDepth, // QFV_bspDepth
|
||||
QFV_passGBuffer, // QFV_bspGBuffer
|
||||
QFV_passTranslucent, // QFV_bspSky
|
||||
QFV_passTranslucent, // QFV_bspTurb
|
||||
[QFV_bspDepth] = QFV_passDepth,
|
||||
[QFV_bspGBuffer] = QFV_passGBuffer,
|
||||
[QFV_bspSky] = QFV_passTranslucent,
|
||||
[QFV_bspTurb] = QFV_passTranslucent,
|
||||
};
|
||||
|
||||
#define ALLOC_CHUNK 64
|
||||
|
||||
static void
|
||||
add_texture (texture_t *tx, vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
@ -111,22 +111,16 @@ add_texture (texture_t *tx, vulkan_ctx_t *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_ClearElements (vulkan_ctx_t *ctx)
|
||||
{
|
||||
// bspctx_t *bctx = ctx->bsp_context;
|
||||
}
|
||||
|
||||
static inline void
|
||||
chain_surface (const bsp_face_t *face, bsp_pass_t *pass, bspctx_t *bctx)
|
||||
chain_surface (const bsp_face_t *face, bsp_pass_t *pass, const bspctx_t *bctx)
|
||||
{
|
||||
int ent_frame = pass->ent_frame;
|
||||
// if the texture has no alt animations, anim_alt holds the sama data
|
||||
// as anim_main
|
||||
texanim_t *anim = ent_frame ? &bctx->texdata.anim_alt[face->tex_id]
|
||||
: &bctx->texdata.anim_main[face->tex_id];
|
||||
const texanim_t *anim = ent_frame ? &bctx->texdata.anim_alt[face->tex_id]
|
||||
: &bctx->texdata.anim_main[face->tex_id];
|
||||
int anim_ind = (bctx->anim_index + anim->offset) % anim->count;
|
||||
int tex_id = bctx->texdata.anim_map[anim->base + anim_ind];
|
||||
int tex_id = bctx->texdata.frame_map[anim->base + anim_ind];
|
||||
DARRAY_APPEND (&pass->face_queue[tex_id],
|
||||
((instface_t) { pass->inst_id, face - bctx->faces }));
|
||||
}
|
||||
|
@ -163,11 +157,14 @@ clear_textures (vulkan_ctx_t *ctx)
|
|||
void
|
||||
Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
||||
{
|
||||
mod_brush_t *brush = &r_refdef.worldmodel->brush;
|
||||
|
||||
clear_textures (ctx);
|
||||
add_texture (r_notexture_mip, ctx);
|
||||
register_textures (brush, ctx);
|
||||
{
|
||||
// FIXME make worldmodel non-special. needs smarter handling of
|
||||
// textures on sub-models but not on main model.
|
||||
mod_brush_t *brush = &r_refdef.worldmodel->brush;
|
||||
register_textures (brush, ctx);
|
||||
}
|
||||
for (int i = 0; i < num_models; i++) {
|
||||
model_t *m = models[i];
|
||||
if (!m)
|
||||
|
@ -176,9 +173,10 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
if (*m->path == '*')
|
||||
continue;
|
||||
// world has already been done, not interested in non-brush models
|
||||
// FIXME see above
|
||||
if (m == r_refdef.worldmodel || m->type != mod_brush)
|
||||
continue;
|
||||
brush = &m->brush;
|
||||
mod_brush_t *brush = &m->brush;
|
||||
brush->numsubmodels = 1; // no support for submodels in non-world model
|
||||
register_textures (brush, ctx);
|
||||
}
|
||||
|
@ -194,7 +192,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
if (!m || *m->path == '*') {
|
||||
continue;
|
||||
}
|
||||
brush = &m->brush;
|
||||
mod_brush_t *brush = &m->brush;
|
||||
for (unsigned j = 0; j < brush->numtextures; j++) {
|
||||
if (brush->textures[j]) {
|
||||
textures[t++] = brush->textures[j];
|
||||
|
@ -202,11 +200,13 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
// 2.5 for two texanim_t structs (32-bits each) and 1 uint16_t for each
|
||||
// element
|
||||
size_t texdata_size = 2.5 * num_tex * sizeof (texanim_t);
|
||||
texanim_t *texdata = Hunk_AllocName (0, texdata_size, "texdata");
|
||||
bctx->texdata.anim_main = texdata;
|
||||
bctx->texdata.anim_alt = texdata + num_tex;
|
||||
bctx->texdata.anim_map = (uint16_t *) (texdata + 2 * num_tex);
|
||||
bctx->texdata.frame_map = (uint16_t *) (texdata + 2 * num_tex);
|
||||
int16_t map_index = 0;
|
||||
for (int i = 0; i < num_tex; i++) {
|
||||
texanim_t *anim = bctx->texdata.anim_main + i;
|
||||
|
@ -215,7 +215,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
continue;
|
||||
}
|
||||
*anim = (texanim_t) { .base = map_index, .offset = 0, .count = 1 };
|
||||
bctx->texdata.anim_map[anim->base] = i;
|
||||
bctx->texdata.frame_map[anim->base] = i;
|
||||
|
||||
if (textures[i]->anim_total > 1) {
|
||||
// bsp loader multiplies anim_total by ANIM_CYCLE to slow the
|
||||
|
@ -233,7 +233,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
}
|
||||
*a = *anim;
|
||||
a->offset = j;
|
||||
bctx->texdata.anim_map[a->base + a->offset] = vtex->tex_id;
|
||||
bctx->texdata.frame_map[a->base + a->offset] = vtex->tex_id;
|
||||
tx = tx->anim_next;
|
||||
}
|
||||
if (tx != textures[i]) {
|
||||
|
@ -253,6 +253,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
// create face queue arrays
|
||||
bctx->main_pass.face_queue = malloc (num_tex * sizeof (bsp_instfaceset_t));
|
||||
for (int i = 0; i < num_tex; i++) {
|
||||
bctx->main_pass.face_queue[i]
|
||||
|
@ -269,13 +270,18 @@ typedef struct {
|
|||
typedef struct DARRAY_TYPE (faceref_t) facerefset_t;
|
||||
|
||||
static void
|
||||
count_verts_inds (faceref_t *faceref, uint32_t *verts, uint32_t *inds)
|
||||
count_verts_inds (const faceref_t *faceref, uint32_t *verts, uint32_t *inds)
|
||||
{
|
||||
msurface_t *surf = faceref->face;
|
||||
*verts = surf->numedges;
|
||||
*inds = surf->numedges + 1;
|
||||
}
|
||||
|
||||
typedef struct bspvert_s {
|
||||
quat_t vertex;
|
||||
quat_t tlst;
|
||||
} bspvert_t;
|
||||
|
||||
typedef struct {
|
||||
bsp_face_t *faces;
|
||||
uint32_t *indices;
|
||||
|
@ -367,11 +373,11 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
face_sets[i] = (facerefset_t) DARRAY_STATIC_INIT (1024);
|
||||
}
|
||||
|
||||
for (int i = 0; i < bctx->model_id; i++) {
|
||||
for (int i = 0; i < bctx->num_models; i++) {
|
||||
DARRAY_CLEAR (&bctx->main_pass.instances[i].entities);
|
||||
}
|
||||
free (bctx->main_pass.instances);
|
||||
bctx->model_id = 0;
|
||||
bctx->num_models = 0;
|
||||
|
||||
// run through all surfaces, chaining them to their textures, thus
|
||||
// effectively sorting the surfaces by texture (without worrying about
|
||||
|
@ -384,7 +390,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
if (!m || m->type != mod_brush) {
|
||||
continue;
|
||||
}
|
||||
m->render_id = bctx->model_id++;
|
||||
m->render_id = bctx->num_models++;
|
||||
if (*m->path == '*') {
|
||||
continue;
|
||||
}
|
||||
|
@ -410,9 +416,9 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
}
|
||||
face_base += brush->numsurfaces;
|
||||
}
|
||||
bctx->main_pass.instances = malloc (bctx->model_id
|
||||
bctx->main_pass.instances = malloc (bctx->num_models
|
||||
* sizeof (bsp_instance_t));
|
||||
for (int i = 0; i < bctx->model_id; i++) {
|
||||
for (int i = 0; i < bctx->num_models; i++) {
|
||||
DARRAY_INIT (&bctx->main_pass.instances[i].entities, 16);
|
||||
}
|
||||
// All vertices from all brush models go into one giant vbo.
|
||||
|
@ -434,7 +440,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
size_t atom = device->physDev->properties.limits.nonCoherentAtomSize;
|
||||
size_t atom = device->physDev->properties->limits.nonCoherentAtomSize;
|
||||
size_t atom_mask = atom - 1;
|
||||
size_t frames = bctx->frames.size;
|
||||
size_t index_buffer_size = index_count * frames * sizeof (uint32_t);
|
||||
|
@ -457,7 +463,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx)
|
|||
free (bctx->faces);
|
||||
free (bctx->poly_indices);
|
||||
free (bctx->models);
|
||||
bctx->models = malloc (bctx->model_id * sizeof (bsp_model_t));
|
||||
bctx->models = malloc (bctx->num_models * sizeof (bsp_model_t));
|
||||
bctx->faces = malloc (face_base * sizeof (bsp_face_t));
|
||||
bctx->poly_indices = malloc (index_count * sizeof (uint32_t));
|
||||
|
||||
|
@ -589,13 +595,13 @@ R_DrawBrushModel (entity_t *e, bsp_pass_t *pass, vulkan_ctx_t *ctx)
|
|||
Transform_GetWorldMatrix (e->transform, mat);
|
||||
if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) {
|
||||
radius = model->radius;
|
||||
if (R_CullSphere (r_refdef.frustum, (vec_t*)&mat[3], radius)) { //FIXME
|
||||
if (R_CullSphere (pass->frustum, (vec_t*)&mat[3], radius)) { //FIXME
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
VectorAdd (mat[3], model->mins, mins);
|
||||
VectorAdd (mat[3], model->maxs, maxs);
|
||||
if (R_CullBox (r_refdef.frustum, mins, maxs))
|
||||
if (R_CullBox (pass->frustum, mins, maxs))
|
||||
return 1;
|
||||
}
|
||||
if (Vulkan_Scene_AddEntity (ctx, e) < 0) {
|
||||
|
@ -604,6 +610,7 @@ R_DrawBrushModel (entity_t *e, bsp_pass_t *pass, vulkan_ctx_t *ctx)
|
|||
|
||||
pass->ent_frame = e->animation.frame & 1;
|
||||
pass->inst_id = model->render_id;
|
||||
pass->inst_id |= e->renderer.colormod[3] < 1 ? INST_ALPHA : 0;
|
||||
if (!pass->instances[model->render_id].entities.size) {
|
||||
bsp_model_t *m = &bctx->models[model->render_id];
|
||||
bsp_face_t *face = &bctx->faces[m->first_face];
|
||||
|
@ -628,19 +635,18 @@ visit_leaf (mleaf_t *leaf)
|
|||
|
||||
// 1 = back side, 0 = front side
|
||||
static inline int
|
||||
get_side (mnode_t *node)
|
||||
get_side (const bsp_pass_t *pass, const mnode_t *node)
|
||||
{
|
||||
// find the node side on which we are
|
||||
vec4f_t org = r_refdef.frame.position;
|
||||
vec4f_t org = pass->position;
|
||||
|
||||
return dotf (org, node->plane)[0] < 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx)
|
||||
visit_node (bsp_pass_t *pass, const mnode_t *node, int side)
|
||||
{
|
||||
bspctx_t *bctx = ctx->bsp_context;
|
||||
bsp_pass_t *pass = &ctx->bsp_context->main_pass;
|
||||
bspctx_t *bctx = pass->bsp_context;
|
||||
int c;
|
||||
|
||||
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
|
||||
|
@ -651,8 +657,9 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx)
|
|||
if ((c = node->numsurfaces)) {
|
||||
const bsp_face_t *face = bctx->faces + node->firstsurface;
|
||||
const int *frame = pass->face_frames + node->firstsurface;
|
||||
int vis_frame = pass->vis_frame;
|
||||
for (; c; c--, face++, frame++) {
|
||||
if (*frame != r_visframecount)
|
||||
if (*frame != vis_frame)
|
||||
continue;
|
||||
|
||||
// side is either 0 or SURF_PLANEBACK
|
||||
|
@ -667,21 +674,22 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx)
|
|||
}
|
||||
|
||||
static inline int
|
||||
test_node (mod_brush_t *brush, int node_id)
|
||||
test_node (const bsp_pass_t *pass, int node_id)
|
||||
{
|
||||
if (node_id < 0)
|
||||
return 0;
|
||||
if (r_node_visframes[node_id] != r_visframecount)
|
||||
if (pass->node_frames[node_id] != pass->vis_frame)
|
||||
return 0;
|
||||
mnode_t *node = brush->nodes + node_id;
|
||||
if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3))
|
||||
mnode_t *node = pass->brush->nodes + node_id;
|
||||
if (R_CullBox (pass->frustum, node->minmaxs, node->minmaxs + 3))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx)
|
||||
R_VisitWorldNodes (bsp_pass_t *pass, vulkan_ctx_t *ctx)
|
||||
{
|
||||
const mod_brush_t *brush = pass->brush;
|
||||
typedef struct {
|
||||
int node_id;
|
||||
int side;
|
||||
|
@ -698,11 +706,11 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx)
|
|||
node_ptr = node_stack;
|
||||
|
||||
while (1) {
|
||||
while (test_node (brush, node_id)) {
|
||||
while (test_node (pass, node_id)) {
|
||||
mnode_t *node = brush->nodes + node_id;
|
||||
side = get_side (node);
|
||||
side = get_side (pass, node);
|
||||
front = node->children[side];
|
||||
if (test_node (brush, front)) {
|
||||
if (test_node (pass, front)) {
|
||||
node_ptr->node_id = node_id;
|
||||
node_ptr->side = side;
|
||||
node_ptr++;
|
||||
|
@ -719,7 +727,7 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx)
|
|||
visit_leaf (leaf);
|
||||
}
|
||||
}
|
||||
visit_node (brush, node, side, ctx);
|
||||
visit_node (pass, node, side);
|
||||
node_id = node->children[side ^ 1];
|
||||
}
|
||||
if (node_id < 0) {
|
||||
|
@ -733,7 +741,7 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx)
|
|||
node_id = node_ptr->node_id;
|
||||
side = node_ptr->side;
|
||||
mnode_t *node = brush->nodes + node_id;
|
||||
visit_node (brush, node, side, ctx);
|
||||
visit_node (pass, node, side);
|
||||
node_id = node->children[side ^ 1];
|
||||
continue;
|
||||
}
|
||||
|
@ -767,8 +775,11 @@ push_fragconst (bsp_push_constants_t *constants, VkPipelineLayout layout,
|
|||
{ VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
field_offset (bsp_push_constants_t, alpha),
|
||||
sizeof (constants->alpha), &constants->alpha },
|
||||
{ VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
field_offset (bsp_push_constants_t, turb_scale),
|
||||
sizeof (constants->turb_scale), &constants->turb_scale },
|
||||
};
|
||||
QFV_PushConstants (device, cmd, layout, 3, push_constants);
|
||||
QFV_PushConstants (device, cmd, layout, 4, push_constants);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -840,9 +851,6 @@ bsp_begin (qfv_renderframe_t *rFrame)
|
|||
bspctx_t *bctx = ctx->bsp_context;
|
||||
//XXX quat_t fog;
|
||||
|
||||
bctx->default_color[3] = 1;
|
||||
QuatCopy (bctx->default_color, bctx->last_color);
|
||||
|
||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth],
|
||||
|
@ -872,10 +880,6 @@ turb_begin (qfv_renderframe_t *rFrame)
|
|||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
bspctx_t *bctx = ctx->bsp_context;
|
||||
|
||||
bctx->default_color[3] = bound (0, r_wateralpha, 1);
|
||||
|
||||
QuatCopy (bctx->default_color, bctx->last_color);
|
||||
|
||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent],
|
||||
|
@ -901,9 +905,6 @@ sky_begin (qfv_renderframe_t *rFrame)
|
|||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
bspctx_t *bctx = ctx->bsp_context;
|
||||
|
||||
bctx->default_color[3] = 1;
|
||||
QuatCopy (bctx->default_color, bctx->last_color);
|
||||
|
||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent],
|
||||
|
@ -936,7 +937,7 @@ clear_queues (bspctx_t *bctx, bsp_pass_t *pass)
|
|||
for (int i = 0; i < pass->num_queues; i++) {
|
||||
DARRAY_RESIZE (&pass->draw_queues[i], 0);
|
||||
}
|
||||
for (int i = 0; i < bctx->model_id; i++) {
|
||||
for (int i = 0; i < bctx->num_models; i++) {
|
||||
pass->instances[i].first_instance = -1;
|
||||
DARRAY_RESIZE (&pass->instances[i].entities, 0);
|
||||
}
|
||||
|
@ -944,7 +945,7 @@ clear_queues (bspctx_t *bctx, bsp_pass_t *pass)
|
|||
}
|
||||
|
||||
static void
|
||||
queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe)
|
||||
queue_faces (bsp_pass_t *pass, const bspctx_t *bctx, bspframe_t *bframe)
|
||||
{
|
||||
pass->indices = bframe->index_data + bframe->index_count;
|
||||
for (size_t i = 0; i < bctx->registered_textures.size; i++) {
|
||||
|
@ -956,6 +957,10 @@ queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe)
|
|||
__auto_type is = queue->a[j];
|
||||
__auto_type f = bctx->faces[is.face];
|
||||
|
||||
f.flags |= ((is.inst_id & INST_ALPHA)
|
||||
>> (BITOP_LOG2(INST_ALPHA)
|
||||
- BITOP_LOG2(SURF_DRAWALPHA))) & SURF_DRAWALPHA;
|
||||
is.inst_id &= ~INST_ALPHA;
|
||||
if (pass->instances[is.inst_id].first_instance == -1) {
|
||||
uint32_t count = pass->instances[is.inst_id].entities.size;
|
||||
pass->instances[is.inst_id].first_instance = pass->entid_count;
|
||||
|
@ -966,12 +971,15 @@ queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe)
|
|||
}
|
||||
|
||||
int dq = 0;
|
||||
if (bctx->faces[queue->a[0].face].flags & SURF_DRAWSKY) {
|
||||
if (f.flags & SURF_DRAWSKY) {
|
||||
dq = 1;
|
||||
}
|
||||
if (bctx->faces[queue->a[0].face].flags & SURF_DRAWTURB) {
|
||||
if (f.flags & SURF_DRAWALPHA) {
|
||||
dq = 2;
|
||||
}
|
||||
if (f.flags & SURF_DRAWTURB) {
|
||||
dq = 3;
|
||||
}
|
||||
|
||||
size_t dq_size = pass->draw_queues[dq].size;
|
||||
bsp_draw_t *draw = &pass->draw_queues[dq].a[dq_size - 1];
|
||||
|
@ -1033,8 +1041,11 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame)
|
|||
//qfv_devfuncs_t *dfunc = device->funcs;
|
||||
bspctx_t *bctx = ctx->bsp_context;
|
||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||
mod_brush_t *brush;
|
||||
|
||||
bctx->main_pass.bsp_context = bctx;
|
||||
bctx->main_pass.position = r_refdef.frame.position;
|
||||
bctx->main_pass.frustum = r_refdef.frustum;
|
||||
bctx->main_pass.vis_frame = r_visframecount;
|
||||
bctx->main_pass.face_frames = r_face_visframes;
|
||||
bctx->main_pass.leaf_frames = r_leaf_visframes;
|
||||
bctx->main_pass.node_frames = r_node_visframes;
|
||||
|
@ -1052,18 +1063,18 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame)
|
|||
.colormod = { 1, 1, 1, 1 },
|
||||
},
|
||||
};
|
||||
brush = &r_refdef.worldmodel->brush;
|
||||
|
||||
Vulkan_Scene_AddEntity (ctx, &worldent);
|
||||
|
||||
int world_id = worldent.renderer.model->render_id;
|
||||
bctx->main_pass.ent_frame = 0; // world is always frame 0
|
||||
bctx->main_pass.inst_id = world_id;
|
||||
bctx->main_pass.brush = &worldent.renderer.model->brush;
|
||||
if (bctx->main_pass.instances) {
|
||||
DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities,
|
||||
worldent.renderer.render_id);
|
||||
}
|
||||
R_VisitWorldNodes (brush, ctx);
|
||||
R_VisitWorldNodes (&bctx->main_pass, ctx);
|
||||
if (!bctx->vertex_buffer) {
|
||||
return;
|
||||
}
|
||||
|
@ -1105,7 +1116,7 @@ Vulkan_Bsp_Flush (vulkan_ctx_t *ctx)
|
|||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
bspctx_t *bctx = ctx->bsp_context;
|
||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||
size_t atom = device->physDev->properties.limits.nonCoherentAtomSize;
|
||||
size_t atom = device->physDev->properties->limits.nonCoherentAtomSize;
|
||||
size_t atom_mask = atom - 1;
|
||||
size_t index_offset = bframe->index_offset;
|
||||
size_t index_size = bframe->index_count * sizeof (uint32_t);
|
||||
|
@ -1140,22 +1151,30 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame)
|
|||
bspctx_t *bctx = ctx->bsp_context;
|
||||
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
|
||||
|
||||
if (!bctx->main_pass.draw_queues[2].size)
|
||||
if (!bctx->main_pass.draw_queues[3].size)
|
||||
return;
|
||||
|
||||
turb_begin (rFrame);
|
||||
bsp_push_constants_t frag_constants = {
|
||||
.time = vr_data.realtime,
|
||||
.alpha = r_wateralpha
|
||||
};
|
||||
push_fragconst (&frag_constants, bctx->layout, device,
|
||||
bframe->cmdSet.a[QFV_bspTurb]);
|
||||
|
||||
VkPipelineLayout layout = bctx->layout;
|
||||
bsp_push_constants_t frag_constants = {
|
||||
.time = vr_data.realtime,
|
||||
.alpha = 1,
|
||||
.turb_scale = 0,
|
||||
};
|
||||
push_fragconst (&frag_constants, layout, device,
|
||||
bframe->cmdSet.a[QFV_bspTurb]);
|
||||
|
||||
__auto_type pass = &bctx->main_pass;
|
||||
pass->textures = &bctx->registered_textures;
|
||||
draw_queue (pass, 2, layout, device, bframe->cmdSet.a[QFV_bspTurb]);
|
||||
|
||||
frag_constants.alpha = r_wateralpha;
|
||||
frag_constants.turb_scale = 1;
|
||||
push_fragconst (&frag_constants, bctx->layout, device,
|
||||
bframe->cmdSet.a[QFV_bspTurb]);
|
||||
draw_queue (pass, 3, layout, device, bframe->cmdSet.a[QFV_bspTurb]);
|
||||
|
||||
turb_end (ctx);
|
||||
}
|
||||
|
||||
|
@ -1381,7 +1400,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
|
|||
|
||||
DARRAY_INIT (&bctx->registered_textures, 64);
|
||||
|
||||
bctx->main_pass.num_queues = 3;//solid, sky, water
|
||||
bctx->main_pass.num_queues = 4;//solid, sky, water, transparent
|
||||
bctx->main_pass.draw_queues = malloc (bctx->main_pass.num_queues
|
||||
* sizeof (bsp_drawset_t));
|
||||
for (int i = 0; i < bctx->main_pass.num_queues; i++) {
|
||||
|
@ -1403,7 +1422,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
|
|||
|
||||
size_t entid_count = Vulkan_Scene_MaxEntities (ctx);
|
||||
size_t entid_size = entid_count * sizeof (uint32_t);
|
||||
size_t atom = device->physDev->properties.limits.nonCoherentAtomSize;
|
||||
size_t atom = device->physDev->properties->limits.nonCoherentAtomSize;
|
||||
size_t atom_mask = atom - 1;
|
||||
entid_size = (entid_size + atom_mask) & ~atom_mask;
|
||||
bctx->entid_buffer
|
||||
|
@ -1482,7 +1501,7 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx)
|
|||
free (bctx->models);
|
||||
|
||||
free (bctx->main_pass.draw_queues);
|
||||
for (int i = 0; i < bctx->model_id; i++) {
|
||||
for (int i = 0; i < bctx->num_models; i++) {
|
||||
DARRAY_CLEAR (&bctx->main_pass.instances[i].entities);
|
||||
}
|
||||
free (bctx->main_pass.instances);
|
||||
|
|
|
@ -45,12 +45,12 @@
|
|||
#include "QF/sys.h"
|
||||
|
||||
#include "QF/Vulkan/qf_compose.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/debug.h"
|
||||
#include "QF/Vulkan/descriptor.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "compat.h"
|
||||
#include "QF/Vulkan/qf_draw.h"
|
||||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/barrier.h"
|
||||
|
@ -62,7 +63,6 @@
|
|||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
#include "QF/Vulkan/scrap.h"
|
||||
#include "QF/Vulkan/staging.h"
|
||||
#include "QF/ui/view.h"
|
||||
|
|
|
@ -41,12 +41,12 @@
|
|||
|
||||
#include "QF/Vulkan/qf_iqm.h"
|
||||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
#include "QF/Vulkan/debug.h"
|
||||
#include "QF/Vulkan/descriptor.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
#include "QF/Vulkan/resource.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
|
|
|
@ -52,8 +52,11 @@
|
|||
#include "QF/va.h"
|
||||
|
||||
#include "QF/scene/scene.h"
|
||||
#include "QF/ui/view.h"
|
||||
|
||||
#include "QF/Vulkan/qf_draw.h"
|
||||
#include "QF/Vulkan/qf_lighting.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
#include "QF/Vulkan/barrier.h"
|
||||
#include "QF/Vulkan/buffer.h"
|
||||
|
@ -63,13 +66,13 @@
|
|||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/projection.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
#include "QF/Vulkan/staging.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
#include "vkparse.h"
|
||||
|
||||
static void
|
||||
update_lights (vulkan_ctx_t *ctx)
|
||||
|
@ -118,6 +121,11 @@ update_lights (vulkan_ctx_t *ctx)
|
|||
light->color[3] *= style_intensities[ldata->lightstyles.a[i]];
|
||||
}
|
||||
}
|
||||
if (developer & SYS_lighting) {
|
||||
Vulkan_Draw_String (vid.conview->xlen - 32, 8,
|
||||
va (ctx->va_ctx, "%3d", light_data->lightCount),
|
||||
ctx);
|
||||
}
|
||||
|
||||
qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite];
|
||||
bb.barrier.buffer = lframe->light_buffer;
|
||||
|
@ -210,6 +218,75 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame)
|
|||
dfunc->vkEndCommandBuffer (cmd);
|
||||
}
|
||||
|
||||
static void
|
||||
lighting_draw_maps (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
lightingctx_t *lctx = ctx->lighting_context;
|
||||
|
||||
if (rFrame->subpassCmdSets[0].size) {
|
||||
__auto_type sets = &rFrame->subpassCmdSets[0];
|
||||
dfunc->vkFreeCommandBuffers (device->dev, lctx->cmdpool,
|
||||
sets->size, sets->a);
|
||||
sets->size = 0;
|
||||
}
|
||||
|
||||
if (!lctx->ldata) {
|
||||
return;
|
||||
}
|
||||
|
||||
__auto_type bufferset = QFV_AllocCommandBufferSet (1, alloca);
|
||||
QFV_AllocateCommandBuffers (device, lctx->cmdpool, 0, bufferset);
|
||||
VkCommandBuffer cmd = bufferset->a[0];
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
|
||||
cmd, va (ctx->va_ctx, "lighting:%zd", ctx->curFrame));
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
};
|
||||
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
|
||||
|
||||
__auto_type rp = rFrame->renderpass;
|
||||
QFV_CmdBeginLabel (device, cmd, rp->name, rp->color);
|
||||
|
||||
__auto_type lr = &lctx->light_renderers.a[0];
|
||||
VkRenderPassBeginInfo renderPassInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.renderArea = { {0, 0}, {lr->size, lr->size} },
|
||||
.framebuffer = lr->framebuffer,
|
||||
.renderPass = lr->renderPass,
|
||||
.pClearValues = lctx->qfv_renderpass->clearValues->a,
|
||||
};
|
||||
__auto_type subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
|
||||
dfunc->vkCmdBeginRenderPass (cmd, &renderPassInfo, subpassContents);
|
||||
//...
|
||||
dfunc->vkCmdEndRenderPass (cmd);
|
||||
QFV_CmdEndLabel (device, cmd);
|
||||
dfunc->vkEndCommandBuffer (cmd);
|
||||
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[0], cmd);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Lighting_CreateRenderPasses (vulkan_ctx_t *ctx)
|
||||
{
|
||||
lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t));
|
||||
ctx->lighting_context = lctx;
|
||||
|
||||
// extents are dynamic and filled in for each light
|
||||
// frame buffers are highly dynamic
|
||||
qfv_output_t output = {};
|
||||
__auto_type rp = Vulkan_CreateRenderPass (ctx, "shadow",
|
||||
&output, lighting_draw_maps);
|
||||
rp->primary_commands = 1;
|
||||
rp->order = QFV_rp_shadowmap;
|
||||
DARRAY_APPEND (&ctx->renderPasses, rp);
|
||||
|
||||
lctx->qfv_renderpass = rp;
|
||||
}
|
||||
|
||||
static VkDescriptorBufferInfo base_buffer_info = {
|
||||
0, 0, VK_WHOLE_SIZE
|
||||
};
|
||||
|
@ -243,13 +320,24 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx)
|
|||
|
||||
qfvPushDebug (ctx, "lighting init");
|
||||
|
||||
lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t));
|
||||
ctx->lighting_context = lctx;
|
||||
// lighting_context initialized in Vulkan_Lighting_CreateRenderPasses
|
||||
|
||||
DARRAY_INIT (&lctx->lightmats, 16);
|
||||
DARRAY_INIT (&lctx->lightlayers, 16);
|
||||
DARRAY_INIT (&lctx->lightimages, 16);
|
||||
DARRAY_INIT (&lctx->lightviews, 16);
|
||||
ctx->output = (qfv_output_t) {.format = VK_FORMAT_X8_D24_UNORM_PACK32 };
|
||||
lightingctx_t *lctx = ctx->lighting_context;
|
||||
plitem_t *rp_def = lctx->qfv_renderpass->renderpassDef;
|
||||
plitem_t *rp_cfg = PL_ObjectForKey (rp_def, "renderpass_6");
|
||||
lctx->renderpass_6 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def);
|
||||
rp_cfg = PL_ObjectForKey (rp_def, "renderpass_4");
|
||||
lctx->renderpass_4 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def);
|
||||
rp_cfg = PL_ObjectForKey (rp_def, "renderpass_1");
|
||||
lctx->renderpass_1 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def);
|
||||
|
||||
lctx->cmdpool = QFV_CreateCommandPool (device, device->queue.queueFamily,
|
||||
1, 1);
|
||||
|
||||
DARRAY_INIT (&lctx->light_mats, 16);
|
||||
DARRAY_INIT (&lctx->light_images, 16);
|
||||
DARRAY_INIT (&lctx->light_renderers, 16);
|
||||
|
||||
size_t frames = ctx->frames.size;
|
||||
DARRAY_INIT (&lctx->frames, frames);
|
||||
|
@ -355,7 +443,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx)
|
|||
lframe->shadowWrite.dstBinding = 0;
|
||||
lframe->shadowWrite.descriptorCount
|
||||
= min (MaxLights,
|
||||
device->physDev->properties.limits.maxPerStageDescriptorSamplers);
|
||||
device->physDev->properties->limits.maxPerStageDescriptorSamplers);
|
||||
lframe->shadowWrite.pImageInfo = lframe->shadowInfo;
|
||||
}
|
||||
free (shadow_set);
|
||||
|
@ -375,14 +463,16 @@ clear_shadows (vulkan_ctx_t *ctx)
|
|||
dfunc->vkFreeMemory (device->dev, lctx->shadow_memory, 0);
|
||||
lctx->shadow_memory = 0;
|
||||
}
|
||||
for (size_t i = 0; i < lctx->lightviews.size; i++) {
|
||||
dfunc->vkDestroyImageView (device->dev, lctx->lightviews.a[i], 0);
|
||||
for (size_t i = 0; i < lctx->light_renderers.size; i++) {
|
||||
__auto_type lr = &lctx->light_renderers.a[i];
|
||||
dfunc->vkDestroyFramebuffer (device->dev, lr->framebuffer, 0);
|
||||
dfunc->vkDestroyImageView (device->dev, lr->view, 0);
|
||||
}
|
||||
for (size_t i = 0; i < lctx->lightimages.size; i++) {
|
||||
dfunc->vkDestroyImage (device->dev, lctx->lightimages.a[i], 0);
|
||||
for (size_t i = 0; i < lctx->light_images.size; i++) {
|
||||
dfunc->vkDestroyImage (device->dev, lctx->light_images.a[i], 0);
|
||||
}
|
||||
lctx->lightimages.size = 0;
|
||||
lctx->lightviews.size = 0;
|
||||
lctx->light_images.size = 0;
|
||||
lctx->light_renderers.size = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -394,16 +484,20 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx)
|
|||
|
||||
clear_shadows (ctx);
|
||||
|
||||
dfunc->vkDestroyCommandPool (device->dev, lctx->cmdpool, 0);
|
||||
dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_6, 0);
|
||||
dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_4, 0);
|
||||
dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_1, 0);
|
||||
|
||||
for (size_t i = 0; i < lctx->frames.size; i++) {
|
||||
lightingframe_t *lframe = &lctx->frames.a[i];
|
||||
dfunc->vkDestroyBuffer (device->dev, lframe->light_buffer, 0);
|
||||
}
|
||||
dfunc->vkFreeMemory (device->dev, lctx->light_memory, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0);
|
||||
DARRAY_CLEAR (&lctx->lightmats);
|
||||
DARRAY_CLEAR (&lctx->lightimages);
|
||||
DARRAY_CLEAR (&lctx->lightlayers);
|
||||
DARRAY_CLEAR (&lctx->lightviews);
|
||||
DARRAY_CLEAR (&lctx->light_mats);
|
||||
DARRAY_CLEAR (&lctx->light_images);
|
||||
DARRAY_CLEAR (&lctx->light_renderers);
|
||||
free (lctx->frames.a);
|
||||
free (lctx);
|
||||
}
|
||||
|
@ -414,7 +508,7 @@ static void
|
|||
create_light_matrices (lightingctx_t *lctx)
|
||||
{
|
||||
lightingdata_t *ldata = lctx->ldata;
|
||||
DARRAY_RESIZE (&lctx->lightmats, ldata->lights.size);
|
||||
DARRAY_RESIZE (&lctx->light_mats, ldata->lights.size);
|
||||
for (size_t i = 0; i < ldata->lights.size; i++) {
|
||||
light_t *light = &ldata->lights.a[i];
|
||||
mat4f_t view;
|
||||
|
@ -462,7 +556,7 @@ create_light_matrices (lightingctx_t *lctx)
|
|||
QFV_PerspectiveCos (proj, -light->direction[3]);
|
||||
break;
|
||||
}
|
||||
mmulf (lctx->lightmats.a[i], proj, view);
|
||||
mmulf (lctx->light_mats.a[i], proj, view);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -514,30 +608,26 @@ create_map (int size, int layers, int cube, vulkan_ctx_t *ctx)
|
|||
}
|
||||
|
||||
static VkImageView
|
||||
create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx)
|
||||
create_view (const light_renderer_t *lr, int id, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
int layers = 0;
|
||||
VkImageViewType type = 0;
|
||||
const char *viewtype = 0;
|
||||
|
||||
switch (mode) {
|
||||
switch (lr->mode) {
|
||||
case ST_NONE:
|
||||
return 0;
|
||||
case ST_PLANE:
|
||||
layers = 1;
|
||||
type = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewtype = "plane";
|
||||
break;
|
||||
case ST_CASCADE:
|
||||
layers = 4;
|
||||
type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
viewtype = "cascade";
|
||||
break;
|
||||
case ST_CUBE:
|
||||
layers = 6;
|
||||
type = VK_IMAGE_VIEW_TYPE_CUBE;
|
||||
viewtype = "cube";
|
||||
break;
|
||||
|
@ -546,14 +636,14 @@ create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx)
|
|||
VkImageViewCreateInfo createInfo = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 0,
|
||||
0,
|
||||
image, type, VK_FORMAT_X8_D24_UNORM_PACK32,
|
||||
lr->image, type, VK_FORMAT_X8_D24_UNORM_PACK32,
|
||||
{
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
},
|
||||
{ VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, baseLayer, layers }
|
||||
{ VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, lr->layer, lr->numLayers }
|
||||
};
|
||||
|
||||
VkImageView view;
|
||||
|
@ -565,13 +655,33 @@ create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx)
|
|||
return view;
|
||||
}
|
||||
|
||||
static VkFramebuffer
|
||||
create_framebuffer (const light_renderer_t *lr, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
VkFramebuffer framebuffer;
|
||||
VkFramebufferCreateInfo cInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
.renderPass = lr->renderPass,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &lr->view,
|
||||
.width = lr->size,
|
||||
.height = lr->size,
|
||||
.layers = 1,
|
||||
};
|
||||
dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer);
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
static void
|
||||
build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
qfv_physdev_t *physDev = device->physDev;
|
||||
int maxLayers = physDev->properties.limits.maxImageArrayLayers;
|
||||
int maxLayers = physDev->properties->limits.maxImageArrayLayers;
|
||||
lightingdata_t *ldata = lctx->ldata;
|
||||
light_t *lights = ldata->lights.a;
|
||||
int numLights = ldata->lights.size;
|
||||
|
@ -585,126 +695,128 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx)
|
|||
for (int i = 0; i < numLights; i++) {
|
||||
lightMap[i] = i;
|
||||
}
|
||||
DARRAY_RESIZE (&lctx->lightlayers, numLights);
|
||||
heapsort_r (lightMap, numLights, sizeof (int), light_compare, ldata);
|
||||
|
||||
DARRAY_RESIZE (&lctx->light_renderers, numLights);
|
||||
for (int i = 0; i < numLights; i++) {
|
||||
int layers = 1;
|
||||
int shadow = ST_NONE;
|
||||
int li = lightMap[i];
|
||||
__auto_type lr = &lctx->light_renderers.a[li];
|
||||
*lr = (light_renderer_t) {};
|
||||
|
||||
if (!lights[li].position[3]) {
|
||||
shadow = ST_CASCADE;
|
||||
if (!VectorIsZero (lights[li].direction)) {
|
||||
lr->mode = ST_CASCADE;
|
||||
}
|
||||
} else {
|
||||
if (lights[li].direction[3] > -0.5) {
|
||||
shadow = ST_CUBE;
|
||||
lr->mode = ST_CUBE;
|
||||
} else {
|
||||
shadow = ST_PLANE;
|
||||
lr->mode = ST_PLANE;
|
||||
}
|
||||
}
|
||||
if (shadow == ST_CASCADE || shadow == ST_NONE) {
|
||||
if (lr->mode == ST_CASCADE || lr->mode == ST_NONE) {
|
||||
// cascade shadows will be handled separately, and "none" has no
|
||||
// shadow map at all
|
||||
imageMap[li] = -1;
|
||||
continue;
|
||||
}
|
||||
if (shadow == ST_CUBE) {
|
||||
if (lr->mode == ST_CUBE) {
|
||||
layers = 6;
|
||||
}
|
||||
if (size != abs ((int) lights[li].color[3])
|
||||
|| numLayers + layers > maxLayers) {
|
||||
if (numLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 1, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||
numLayers = 0;
|
||||
}
|
||||
size = abs ((int) lights[li].color[3]);
|
||||
}
|
||||
imageMap[li] = lctx->lightimages.size;
|
||||
lctx->lightlayers.a[li] = numLayers;
|
||||
imageMap[li] = lctx->light_images.size;
|
||||
lr->size = size;
|
||||
lr->layer = numLayers;
|
||||
lr->numLayers = layers;
|
||||
numLayers += layers;
|
||||
totalLayers += layers;
|
||||
}
|
||||
if (numLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 1, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||
}
|
||||
|
||||
numLayers = 0;
|
||||
size = 1024;
|
||||
for (int i = 0; i < numLights; i++) {
|
||||
int layers = 4;
|
||||
int shadow = ST_NONE;
|
||||
int li = lightMap[i];
|
||||
__auto_type lr = &lctx->light_renderers.a[li];
|
||||
|
||||
if (!lights[li].position[3]) {
|
||||
shadow = ST_CASCADE;
|
||||
} else {
|
||||
if (lights[li].direction[3] > -0.5) {
|
||||
shadow = ST_CUBE;
|
||||
} else {
|
||||
shadow = ST_PLANE;
|
||||
}
|
||||
}
|
||||
|
||||
if (shadow != ST_CASCADE) {
|
||||
if (lr->mode != ST_CASCADE) {
|
||||
continue;
|
||||
}
|
||||
if (numLayers + layers > maxLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 0, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||
numLayers = 0;
|
||||
}
|
||||
imageMap[li] = lctx->lightimages.size;
|
||||
lctx->lightlayers.a[li] = numLayers;
|
||||
imageMap[li] = lctx->light_images.size;
|
||||
lr->size = size;
|
||||
lr->layer = numLayers;
|
||||
lr->numLayers = layers;
|
||||
numLayers += layers;
|
||||
totalLayers += layers;
|
||||
}
|
||||
if (numLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 0, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lctx->lightimages.size; i++) {
|
||||
memsize += QFV_GetImageSize (device, lctx->lightimages.a[i]);
|
||||
for (size_t i = 0; i < lctx->light_images.size; i++) {
|
||||
memsize += QFV_GetImageSize (device, lctx->light_images.a[i]);
|
||||
}
|
||||
lctx->shadow_memory = QFV_AllocImageMemory (device, lctx->lightimages.a[0],
|
||||
lctx->shadow_memory = QFV_AllocImageMemory (device, lctx->light_images.a[0],
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
memsize, 0);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
||||
lctx->shadow_memory, "memory:shadowmap");
|
||||
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < lctx->lightimages.size; i++) {
|
||||
dfunc->vkBindImageMemory (device->dev, lctx->lightimages.a[i],
|
||||
for (size_t i = 0; i < lctx->light_images.size; i++) {
|
||||
dfunc->vkBindImageMemory (device->dev, lctx->light_images.a[i],
|
||||
lctx->shadow_memory, offset);
|
||||
offset += QFV_GetImageSize (device, lctx->lightimages.a[i]);
|
||||
offset += QFV_GetImageSize (device, lctx->light_images.a[i]);
|
||||
}
|
||||
|
||||
DARRAY_RESIZE (&lctx->lightviews, numLights);
|
||||
for (int i = 0; i < numLights; i++) {
|
||||
int li = lightMap[i];
|
||||
__auto_type lr = &lctx->light_renderers.a[li];
|
||||
|
||||
if (imageMap[li] == -1) {
|
||||
lctx->lightviews.a[li] = 0;
|
||||
continue;
|
||||
}
|
||||
int mode = ST_NONE;
|
||||
|
||||
if (!ldata->lights.a[li].position[3]) {
|
||||
mode = ST_CASCADE;
|
||||
} else {
|
||||
if (ldata->lights.a[li].direction[3] > -0.5) {
|
||||
mode = ST_CUBE;
|
||||
} else {
|
||||
mode = ST_PLANE;
|
||||
}
|
||||
switch (lr->numLayers) {
|
||||
case 6:
|
||||
lr->renderPass = lctx->renderpass_6;
|
||||
break;
|
||||
case 4:
|
||||
lr->renderPass = lctx->renderpass_4;
|
||||
break;
|
||||
case 1:
|
||||
lr->renderPass = lctx->renderpass_1;
|
||||
break;
|
||||
default:
|
||||
Sys_Error ("build_shadow_maps: invalid light layer count: %u",
|
||||
lr->numLayers);
|
||||
}
|
||||
lctx->lightviews.a[li] = create_view (lctx->lightimages.a[imageMap[li]],
|
||||
lctx->lightlayers.a[li],
|
||||
mode, li, ctx);
|
||||
lr->image = lctx->light_images.a[imageMap[li]];
|
||||
lr->view = create_view (lr, li, ctx);
|
||||
lr->framebuffer = create_framebuffer(lr, ctx);
|
||||
}
|
||||
Sys_MaskPrintf (SYS_vulkan, "shadow maps: %d layers in %zd images: %zd\n",
|
||||
totalLayers, lctx->lightimages.size, memsize);
|
||||
Sys_MaskPrintf (SYS_vulkan,
|
||||
"shadow maps: %d layers in %zd images: %zd\n",
|
||||
totalLayers, lctx->light_images.size, memsize);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -48,18 +48,21 @@
|
|||
#include "QF/scene/entity.h"
|
||||
#include "QF/scene/scene.h"
|
||||
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/qf_alias.h"
|
||||
#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"
|
||||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_particles.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_scene.h"
|
||||
#include "QF/Vulkan/qf_sprite.h"
|
||||
//#include "QF/Vulkan/qf_textures.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/swapchain.h"
|
||||
|
||||
#include "mod_internal.h"
|
||||
#include "r_internal.h"
|
||||
|
@ -129,6 +132,7 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame)
|
|||
}
|
||||
Vulkan_DrawWaterSurfaces (rFrame);
|
||||
Vulkan_Bsp_Flush (ctx);
|
||||
Vulkan_RenderEntities (r_ent_queue, rFrame);
|
||||
Vulkan_Scene_Flush (ctx);
|
||||
}
|
||||
|
||||
|
@ -152,3 +156,28 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx)
|
|||
Vulkan_BuildDisplayLists (scene->models, scene->num_models, ctx);
|
||||
Vulkan_LoadLights (scene, ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
main_draw (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
Vulkan_Matrix_Draw (rFrame);
|
||||
Vulkan_RenderView (rFrame);
|
||||
Vulkan_FlushText (rFrame);//FIXME delayed by a frame?
|
||||
Vulkan_Lighting_Draw (rFrame);
|
||||
Vulkan_Compose_Draw (rFrame);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_output_t output = {
|
||||
.extent = ctx->swapchain->extent,
|
||||
.view = ctx->swapchain->imageViews->a[0],
|
||||
.format = ctx->swapchain->format,
|
||||
.view_list = ctx->swapchain->imageViews->a,
|
||||
};
|
||||
__auto_type rp = Vulkan_CreateRenderPass (ctx, "deferred",
|
||||
&output, main_draw);
|
||||
rp->order = QFV_rp_main;
|
||||
DARRAY_APPEND (&ctx->renderPasses, rp);
|
||||
}
|
||||
|
|
|
@ -43,13 +43,13 @@
|
|||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/barrier.h"
|
||||
#include "QF/Vulkan/buffer.h"
|
||||
#include "QF/Vulkan/debug.h"
|
||||
#include "QF/Vulkan/descriptor.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
#include "QF/Vulkan/staging.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
|
|
283
libs/video/renderer/vulkan/vulkan_renderpass.c
Normal file
283
libs/video/renderer/vulkan/vulkan_renderpass.c
Normal file
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
renderpass.c
|
||||
|
||||
Vulkan render pass and frame buffer functions
|
||||
|
||||
Copyright (C) 2020 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/cvar.h"
|
||||
#include "QF/hash.h"
|
||||
#include "QF/plist.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "QF/Vulkan/command.h"
|
||||
#include "QF/Vulkan/debug.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/swapchain.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
|
||||
#include "vid_vulkan.h"
|
||||
#include "vkparse.h"
|
||||
|
||||
static plitem_t *
|
||||
get_rp_item (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name)
|
||||
{
|
||||
if (!rp->renderpassDef) {
|
||||
rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name);
|
||||
}
|
||||
|
||||
plitem_t *item = rp->renderpassDef;
|
||||
if (!item) {
|
||||
Sys_Printf ("error loading %s\n", rp->name);
|
||||
} else if ((item = PL_ObjectForKey (item, name))) {
|
||||
Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
static size_t
|
||||
get_image_size (VkImage image, qfv_device_t *device)
|
||||
{
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
size_t size;
|
||||
size_t align;
|
||||
|
||||
VkMemoryRequirements requirements;
|
||||
dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements);
|
||||
size = requirements.size;
|
||||
align = requirements.alignment - 1;
|
||||
size = (size + align) & ~(align);
|
||||
return size;
|
||||
}
|
||||
|
||||
static void
|
||||
create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
|
||||
plitem_t *item = get_rp_item (ctx, rp, "images");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
__auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef);
|
||||
rp->attachment_images = images;
|
||||
size_t memSize = 0;
|
||||
for (size_t i = 0; i < images->size; i++) {
|
||||
memSize += get_image_size (images->a[i], device);
|
||||
}
|
||||
VkDeviceMemory mem;
|
||||
mem = QFV_AllocImageMemory (device, images->a[0],
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
memSize, 0);
|
||||
rp->attachmentMemory = mem;
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
||||
mem, "memory:framebuffers");
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < images->size; i++) {
|
||||
QFV_BindImageMemory (device, images->a[i], mem, offset);
|
||||
offset += get_image_size (images->a[i], device);
|
||||
}
|
||||
|
||||
item = get_rp_item (ctx, rp, "imageViews");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
__auto_type views = QFV_ParseImageViewSet (ctx, item, rp->renderpassDef);
|
||||
rp->attachment_views = views;
|
||||
|
||||
item = get_rp_item (ctx, rp, "framebuffer");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages,
|
||||
malloc);
|
||||
for (size_t i = 0; i < rp->framebuffers->size; i++) {
|
||||
ctx->output.view = ctx->output.view_list[i];
|
||||
rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item,
|
||||
rp->renderpassDef);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp,
|
||||
qfv_renderframe_t *rFrame)
|
||||
{
|
||||
rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
|
||||
rFrame->vulkan_ctx = ctx;
|
||||
rFrame->renderpass = rp;
|
||||
rFrame->subpassCount = rp->subpassCount;
|
||||
if (rp->subpass_info) {
|
||||
rFrame->subpassInfo = rp->subpass_info->a;
|
||||
}
|
||||
rFrame->subpassCmdSets = malloc (rp->subpassCount
|
||||
* sizeof (qfv_cmdbufferset_t));
|
||||
for (size_t j = 0; j < rp->subpassCount; j++) {
|
||||
DARRAY_INIT (&rFrame->subpassCmdSets[j], 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
if (rp->attachment_views) {
|
||||
for (size_t i = 0; i < rp->attachment_views->size; i++) {
|
||||
dfunc->vkDestroyImageView (device->dev,
|
||||
rp->attachment_views->a[i], 0);
|
||||
}
|
||||
}
|
||||
if (rp->attachment_images) {
|
||||
for (size_t i = 0; i < rp->attachment_images->size; i++) {
|
||||
dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0);
|
||||
}
|
||||
}
|
||||
dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0);
|
||||
|
||||
free (rp->attachment_images);
|
||||
free (rp->attachment_views);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
for (size_t i = 0; i < rp->frames.size; i++) {
|
||||
__auto_type rFrame = &rp->frames.a[i];
|
||||
for (int j = 0; j < rFrame->subpassCount; j++) {
|
||||
DARRAY_CLEAR (&rFrame->subpassCmdSets[j]);
|
||||
}
|
||||
free (rFrame->subpassCmdSets);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
for (size_t i = 0; i < rp->framebuffers->size; i++) {
|
||||
dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0);
|
||||
}
|
||||
free (rp->framebuffers);
|
||||
}
|
||||
|
||||
qfv_renderpass_t *
|
||||
Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name,
|
||||
qfv_output_t *output, qfv_draw_t draw)
|
||||
{
|
||||
plitem_t *item;
|
||||
|
||||
qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t));
|
||||
|
||||
rp->name = name;
|
||||
|
||||
plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass");
|
||||
if (rp_cfg) {
|
||||
hashtab_t *tab = ctx->renderpasses;
|
||||
const char *path;
|
||||
path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name);
|
||||
__auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path);
|
||||
if (renderpass) {
|
||||
rp->renderpass = renderpass;
|
||||
} else {
|
||||
ctx->output = *output;
|
||||
rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg,
|
||||
rp->renderpassDef);
|
||||
QFV_AddHandle (tab, path, (uint64_t) rp->renderpass);
|
||||
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS,
|
||||
rp->renderpass, va (ctx->va_ctx,
|
||||
"renderpass:%s", name));
|
||||
}
|
||||
rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg,
|
||||
"subpasses"));
|
||||
}
|
||||
plitem_t *rp_info = get_rp_item (ctx, rp, "info");
|
||||
if (rp_info) {
|
||||
plitem_t *subpass_info = PL_ObjectForKey (rp_info, "subpass_info");
|
||||
if (subpass_info) {
|
||||
rp->subpass_info = QFV_ParseSubpasses (ctx, subpass_info,
|
||||
rp->renderpassDef);
|
||||
if (rp->subpass_info->size < rp->subpassCount) {
|
||||
Sys_Printf ("warning:%s:%d: insufficient entries in "
|
||||
"subpass_info\n", name, PL_Line (subpass_info));
|
||||
}
|
||||
if (!rp->subpassCount) {
|
||||
rp->subpassCount = rp->subpass_info->size;
|
||||
}
|
||||
}
|
||||
|
||||
plitem_t *color = PL_ObjectForKey (rp_info, "color");
|
||||
if (color) {
|
||||
QFV_ParseRGBA (ctx, (float *)&rp->color, color, rp->renderpassDef);
|
||||
}
|
||||
}
|
||||
|
||||
int width = output->extent.width;
|
||||
int height = output->extent.height;
|
||||
rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 };
|
||||
rp->scissor = (VkRect2D) { {0, 0}, {width, height} };
|
||||
|
||||
DARRAY_INIT (&rp->frames, 4);
|
||||
DARRAY_RESIZE (&rp->frames, ctx->frames.size);
|
||||
for (size_t i = 0; i < rp->frames.size; i++) {
|
||||
init_renderframe (ctx, rp, &rp->frames.a[i]);
|
||||
}
|
||||
|
||||
create_attachements (ctx, rp);
|
||||
|
||||
item = get_rp_item (ctx, rp, "clearValues");
|
||||
rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef);
|
||||
|
||||
rp->draw = draw;
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
PL_Free (renderpass->renderpassDef);
|
||||
|
||||
destroy_attachments (ctx, renderpass);
|
||||
dfunc->vkDestroyRenderPass (device->dev, renderpass->renderpass, 0);
|
||||
destroy_renderframes (ctx, renderpass);
|
||||
if (renderpass->framebuffers) {
|
||||
destroy_framebuffers (ctx, renderpass);
|
||||
}
|
||||
|
||||
DARRAY_CLEAR (&renderpass->frames);
|
||||
free (renderpass->clearValues);
|
||||
free (renderpass);
|
||||
}
|
|
@ -54,6 +54,7 @@
|
|||
#include "QF/scene/entity.h"
|
||||
|
||||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_sprite.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
#include "QF/Vulkan/buffer.h"
|
||||
|
@ -62,7 +63,6 @@
|
|||
#include "QF/Vulkan/descriptor.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
|
|
@ -39,31 +39,27 @@
|
|||
#include "QF/cvar.h"
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/hash.h"
|
||||
#include "QF/heapsort.h"
|
||||
#include "QF/plist.h"
|
||||
#include "QF/va.h"
|
||||
#include "QF/scene/entity.h"
|
||||
#include "QF/Vulkan/capture.h"
|
||||
#include "QF/Vulkan/command.h"
|
||||
#include "QF/Vulkan/debug.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
#include "QF/Vulkan/staging.h"
|
||||
#include "QF/Vulkan/swapchain.h"
|
||||
|
||||
#include "QF/Vulkan/qf_alias.h"
|
||||
#include "QF/Vulkan/qf_bsp.h"
|
||||
#include "QF/Vulkan/qf_compose.h"
|
||||
#include "QF/Vulkan/qf_draw.h"
|
||||
#include "QF/Vulkan/qf_lighting.h"
|
||||
#include "QF/Vulkan/qf_main.h"
|
||||
#include "QF/Vulkan/qf_matrices.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
#include "vkparse.h"
|
||||
|
||||
#include "libs/video/renderer/vulkan/vkparse.hinc"
|
||||
|
||||
static exprsym_t builtin_plist_syms[] = {
|
||||
|
@ -75,6 +71,10 @@ static exprsym_t builtin_plist_syms[] = {
|
|||
.value = (void *)
|
||||
#include "libs/video/renderer/vulkan/deferred.plc"
|
||||
},
|
||||
{ .name = "shadow",
|
||||
.value = (void *)
|
||||
#include "libs/video/renderer/vulkan/shadow.plc"
|
||||
},
|
||||
{ .name = "forward",
|
||||
.value = (void *)
|
||||
#include "libs/video/renderer/vulkan/forward.plc"
|
||||
|
@ -314,8 +314,8 @@ build_configs (vulkan_ctx_t *ctx)
|
|||
cexpr_init_symtab (&builtin_configs, &ectx);
|
||||
}
|
||||
|
||||
static plitem_t *
|
||||
get_builtin_config (vulkan_ctx_t *ctx, const char *name)
|
||||
plitem_t *
|
||||
Vulkan_GetConfig (vulkan_ctx_t *ctx, const char *name)
|
||||
{
|
||||
if (!builtin_configs.tab) {
|
||||
build_configs (ctx);
|
||||
|
@ -350,7 +350,7 @@ static plitem_t *
|
|||
qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name)
|
||||
{
|
||||
if (!ctx->pipelineDef) {
|
||||
ctx->pipelineDef = get_builtin_config (ctx, "qfpipeline");
|
||||
ctx->pipelineDef = Vulkan_GetConfig (ctx, "qfpipeline");
|
||||
}
|
||||
|
||||
plitem_t *item = ctx->pipelineDef;
|
||||
|
@ -362,240 +362,29 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name)
|
|||
return item;
|
||||
}
|
||||
|
||||
static plitem_t *
|
||||
qfv_load_renderpass (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name)
|
||||
static int
|
||||
renderpass_cmp (const void *_a, const void *_b)
|
||||
{
|
||||
if (!rp->renderpassDef) {
|
||||
rp->renderpassDef = get_builtin_config (ctx, "deferred");
|
||||
}
|
||||
|
||||
plitem_t *item = rp->renderpassDef;
|
||||
if (!item || !(item = PL_ObjectForKey (item, name))) {
|
||||
Sys_Printf ("error loading %s\n", name);
|
||||
} else {
|
||||
Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
static size_t
|
||||
get_image_size (VkImage image, qfv_device_t *device)
|
||||
{
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
size_t size;
|
||||
size_t align;
|
||||
|
||||
VkMemoryRequirements requirements;
|
||||
dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements);
|
||||
size = requirements.size;
|
||||
align = requirements.alignment - 1;
|
||||
size = (size + align) & ~(align);
|
||||
return size;
|
||||
}
|
||||
|
||||
static void
|
||||
renderpass_draw (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
Vulkan_Matrix_Draw (rFrame);
|
||||
Vulkan_RenderView (rFrame);
|
||||
Vulkan_FlushText (rFrame);//FIXME delayed by a frame?
|
||||
Vulkan_Lighting_Draw (rFrame);
|
||||
Vulkan_Compose_Draw (rFrame);
|
||||
}
|
||||
|
||||
static void
|
||||
create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
|
||||
plitem_t *item = qfv_load_renderpass (ctx, rp, "images");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
__auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef);
|
||||
rp->attachment_images = images;
|
||||
size_t memSize = 0;
|
||||
for (size_t i = 0; i < images->size; i++) {
|
||||
memSize += get_image_size (images->a[i], device);
|
||||
}
|
||||
VkDeviceMemory mem;
|
||||
mem = QFV_AllocImageMemory (device, images->a[0],
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
memSize, 0);
|
||||
rp->attachmentMemory = mem;
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
||||
mem, "memory:framebuffers");
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < images->size; i++) {
|
||||
QFV_BindImageMemory (device, images->a[i], mem, offset);
|
||||
offset += get_image_size (images->a[i], device);
|
||||
}
|
||||
|
||||
item = qfv_load_renderpass (ctx, rp, "imageViews");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
__auto_type views = QFV_ParseImageViewSet (ctx, item, rp->renderpassDef);
|
||||
rp->attachment_views = views;
|
||||
|
||||
item = qfv_load_renderpass (ctx, rp, "framebuffer");
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages,
|
||||
malloc);
|
||||
for (size_t i = 0; i < rp->framebuffers->size; i++) {
|
||||
ctx->output = (qfv_output_t) {
|
||||
.extent = ctx->swapchain->extent,
|
||||
.view = ctx->swapchain->imageViews->a[i],
|
||||
.format = ctx->swapchain->format,
|
||||
};
|
||||
rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item,
|
||||
rp->renderpassDef);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp,
|
||||
qfv_renderframe_t *rFrame)
|
||||
{
|
||||
// FIXME should not be hard-coded
|
||||
static qfv_subpass_t subpass_info[] = {
|
||||
{ .name = "depth", .color = { 0.5, 0.5, 0.5, 1} },
|
||||
{ .name = "translucent", .color = { 0.25, 0.25, 0.6, 1} },
|
||||
{ .name = "g-buffef", .color = { 0.3, 0.7, 0.3, 1} },
|
||||
{ .name = "lighting", .color = { 0.8, 0.8, 0.8, 1} },
|
||||
{ .name = "compose", .color = { 0.7, 0.3, 0.3, 1} },
|
||||
};
|
||||
|
||||
rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
|
||||
rFrame->vulkan_ctx = ctx;
|
||||
rFrame->renderpass = rp;
|
||||
rFrame->subpassCount = QFV_NumPasses;
|
||||
rFrame->subpassInfo = subpass_info; //FIXME
|
||||
rFrame->subpassCmdSets = malloc (QFV_NumPasses
|
||||
* sizeof (qfv_cmdbufferset_t));
|
||||
for (int j = 0; j < QFV_NumPasses; j++) {
|
||||
DARRAY_INIT (&rFrame->subpassCmdSets[j], 4);
|
||||
}
|
||||
const qfv_renderpass_t *a = _a;
|
||||
const qfv_renderpass_t *b = _b;
|
||||
return a->order - b->order;
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
|
||||
Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx)
|
||||
{
|
||||
const char *name = "renderpass";//FIXME
|
||||
plitem_t *item;
|
||||
Vulkan_Main_CreateRenderPasses (ctx);
|
||||
Vulkan_Lighting_CreateRenderPasses (ctx);
|
||||
|
||||
qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t));
|
||||
|
||||
rp->name = name;
|
||||
rp->color = (vec4f_t) { 0, 1, 0, 1 }; //FIXME
|
||||
|
||||
hashtab_t *tab = ctx->renderpasses;
|
||||
const char *path;
|
||||
path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name);
|
||||
__auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path);
|
||||
if (renderpass) {
|
||||
rp->renderpass = renderpass;
|
||||
} else {
|
||||
ctx->output = (qfv_output_t) {
|
||||
.extent = ctx->swapchain->extent,
|
||||
.view = ctx->swapchain->imageViews->a[0],
|
||||
.format = ctx->swapchain->format,
|
||||
};
|
||||
item = qfv_load_renderpass (ctx, rp, name);
|
||||
rp->renderpass = QFV_ParseRenderPass (ctx, item, rp->renderpassDef);
|
||||
QFV_AddHandle (tab, path, (uint64_t) rp->renderpass);
|
||||
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS,
|
||||
rp->renderpass, va (ctx->va_ctx, "renderpass:%s",
|
||||
name));
|
||||
}
|
||||
|
||||
int width = ctx->window_width;
|
||||
int height = ctx->window_height;
|
||||
rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 };
|
||||
rp->scissor = (VkRect2D) { {0, 0}, {width, height} };
|
||||
|
||||
DARRAY_INIT (&rp->frames, 4);
|
||||
DARRAY_RESIZE (&rp->frames, ctx->frames.size);
|
||||
for (size_t i = 0; i < rp->frames.size; i++) {
|
||||
init_renderframe (ctx, rp, &rp->frames.a[i]);
|
||||
}
|
||||
|
||||
create_attachements (ctx, rp);
|
||||
|
||||
item = qfv_load_renderpass (ctx, rp, "clearValues");
|
||||
rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef);
|
||||
|
||||
rp->draw = renderpass_draw;
|
||||
|
||||
DARRAY_APPEND (&ctx->renderPasses, rp);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
for (size_t i = 0; i < rp->attachment_views->size; i++) {
|
||||
dfunc->vkDestroyImageView (device->dev, rp->attachment_views->a[i], 0);
|
||||
}
|
||||
for (size_t i = 0; i < rp->attachment_images->size; i++) {
|
||||
dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0);
|
||||
}
|
||||
dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0);
|
||||
|
||||
free (rp->attachment_images);
|
||||
free (rp->attachment_views);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
for (size_t i = 0; i < rp->frames.size; i++) {
|
||||
__auto_type rFrame = &rp->frames.a[i];
|
||||
for (int j = 0; j < rFrame->subpassCount; j++) {
|
||||
DARRAY_CLEAR (&rFrame->subpassCmdSets[j]);
|
||||
}
|
||||
free (rFrame->subpassCmdSets);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
for (size_t i = 0; i < rp->framebuffers->size; i++) {
|
||||
dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0);
|
||||
}
|
||||
free (rp->framebuffers);
|
||||
heapsort (ctx->renderPasses.a, ctx->renderPasses.size,
|
||||
sizeof (qfv_renderpass_t *), renderpass_cmp);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
for (size_t i = 0; i < ctx->renderPasses.size; i++) {
|
||||
__auto_type rp = ctx->renderPasses.a[i];
|
||||
|
||||
PL_Free (rp->renderpassDef);
|
||||
|
||||
destroy_attachments (ctx, rp);
|
||||
dfunc->vkDestroyRenderPass (device->dev, rp->renderpass, 0);
|
||||
destroy_renderframes (ctx, rp);
|
||||
destroy_framebuffers (ctx, rp);
|
||||
|
||||
DARRAY_CLEAR (&rp->frames);
|
||||
free (rp->clearValues);
|
||||
free (rp);
|
||||
Vulkan_DestroyRenderPass (ctx, ctx->renderPasses.a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ ruamoko_gui_libgui_a_SOURCES= \
|
|||
ruamoko/gui/View.r
|
||||
ruamoko_gui_libgui_a_dep=$(call qcautodep,$(ruamoko_gui_libgui_a_SOURCES))
|
||||
ruamoko_gui_libgui_a_AR= $(PAK) -cf
|
||||
EXTRA_ruamoko_gui_libgui_a_DEPENDENCIES=pak
|
||||
EXTRA_ruamoko_gui_libgui_a_DEPENDENCIES=$(PAK)
|
||||
include $(ruamoko_gui_libgui_a_dep) # am--include-marker
|
||||
r_depfiles_remade += $(ruamoko_gui_libgui_a_dep)
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ ruamoko_lib_libr_a_SOURCES=\
|
|||
ruamoko/lib/Set.r
|
||||
ruamoko_lib_libr_a_dep=$(call qcautodep,$(ruamoko_lib_libr_a_SOURCES))
|
||||
ruamoko_lib_libr_a_AR=$(PAK) -cf
|
||||
EXTRA_ruamoko_lib_libr_a_DEPENDENCIES=pak
|
||||
EXTRA_ruamoko_lib_libr_a_DEPENDENCIES=$(PAK)
|
||||
include $(ruamoko_lib_libr_a_dep) # am--include-marker
|
||||
r_depfiles_remade += $(ruamoko_lib_libr_a_dep)
|
||||
|
||||
|
@ -83,7 +83,7 @@ ruamoko_lib_libqw_a_SOURCES= \
|
|||
ruamoko/lib/math.r
|
||||
ruamoko_lib_libqw_a_dep=$(call qcautodep,$(ruamoko_lib_libqw_a_src))
|
||||
ruamoko_lib_libqw_a_AR=$(PAK) -cf
|
||||
EXTRA_ruamoko_lib_libqw_a_DEPENDENCIES=pak
|
||||
EXTRA_ruamoko_lib_libqw_a_DEPENDENCIES=$(PAK)
|
||||
include $(ruamoko_lib_libqw_a_dep) # am--include-marker
|
||||
r_depfiles_remade += $(ruamoko_lib_libqw_a_dep)
|
||||
|
||||
|
@ -94,7 +94,7 @@ ruamoko_lib_libnq_a_SOURCES=\
|
|||
ruamoko/lib/math.r
|
||||
ruamoko_lib_libnq_a_dep=$(call qcautodep,$(ruamoko_lib_libnq_a_src))
|
||||
ruamoko_lib_libnq_a_AR=$(PAK) -cf
|
||||
EXTRA_ruamoko_lib_libnq_a_DEPENDENCIES=pak
|
||||
EXTRA_ruamoko_lib_libnq_a_DEPENDENCIES=$(PAK)
|
||||
include $(ruamoko_lib_libnq_a_dep) # am--include-marker
|
||||
r_depfiles_remade += $(ruamoko_lib_libnq_a_dep)
|
||||
|
||||
|
@ -103,7 +103,7 @@ ruamoko_lib_libcsqc_a_SOURCES=\
|
|||
$(ruamoko_lib_common_src)
|
||||
ruamoko_lib_libcsqc_a_dep=$(call qcautodep,$(ruamoko_lib_libcsqc_a_src))
|
||||
ruamoko_lib_libcsqc_a_AR= $(PAK) -cf
|
||||
EXTRA_ruamoko_lib_libcsqc_a_DEPENDENCIES=pak
|
||||
EXTRA_ruamoko_lib_libcsqc_a_DEPENDENCIES=$(PAK)
|
||||
include $(ruamoko_lib_libcsqc_a_dep) # am--include-marker
|
||||
r_depfiles_remade += $(ruamoko_lib_libcsqc_a_dep)
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ ruamoko_qwaq_libui_a_SOURCES= \
|
|||
ruamoko/qwaq/ui/window.r
|
||||
ruamoko_qwaq_libui_a_dep=$(call qcautodep,$(ruamoko_qwaq_libui_a_SOURCES))
|
||||
ruamoko_qwaq_libui_a_AR=$(PAK) -cf
|
||||
EXTRA_ruamoko_qwaq_libui_a_DEPENDENCIES=pak
|
||||
EXTRA_ruamoko_qwaq_libui_a_DEPENDENCIES=$(PAK)
|
||||
include $(ruamoko_qwaq_libui_a_dep) # am--include-marker
|
||||
r_depfiles_remade += $(ruamoko_qwaq_libui_a_dep)
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ ruamoko_scheme_libscheme_a_SOURCES=\
|
|||
ruamoko/scheme/BaseContinuation.r
|
||||
ruamoko_scheme_libscheme_a_dep=$(call qcautodep,$(ruamoko_scheme_libscheme_a_SOURCES))
|
||||
ruamoko_scheme_libscheme_a_AR=$(PAK) -cf
|
||||
EXTRA_ruamoko_scheme_libscheme_a_DEPENDENCIES=pak
|
||||
EXTRA_ruamoko_scheme_libscheme_a_DEPENDENCIES=$(PAK)
|
||||
include $(ruamoko_scheme_libscheme_a_dep) # am--include-marker
|
||||
r_depfiles_remade += $(ruamoko_scheme_libscheme_a_dep)
|
||||
|
||||
|
|
|
@ -253,7 +253,7 @@ class pldata:
|
|||
elif type(item) in [int, float]:
|
||||
self.write_string(str(item))
|
||||
else:
|
||||
raise PListError(0, "unsupported type")
|
||||
raise PListError(0, f"unsupported type {type(item)}")
|
||||
def write(self, item):
|
||||
self.data = []
|
||||
self.write_item(item, 0)
|
||||
|
|
|
@ -25,6 +25,9 @@ from bpy.props import BoolProperty, FloatProperty, StringProperty, EnumProperty
|
|||
from bpy.props import BoolVectorProperty, CollectionProperty, PointerProperty
|
||||
from bpy.props import FloatVectorProperty, IntProperty
|
||||
from mathutils import Vector
|
||||
from math import ceil
|
||||
|
||||
from textwrap import TextWrapper
|
||||
|
||||
from .entityclass import EntityClass
|
||||
|
||||
|
@ -158,23 +161,6 @@ class QFEntpropRemove(bpy.types.Operator):
|
|||
qfentity.fields.remove(qfentity.field_idx)
|
||||
return {'FINISHED'}
|
||||
|
||||
def reflow_text(text, max_width):
|
||||
lines = []
|
||||
for text_line in text.split("\n"):
|
||||
if not text_line:
|
||||
continue
|
||||
words = text_line.split(" ")
|
||||
flowed_line = ""
|
||||
while words:
|
||||
if len(flowed_line) + len(words[0]) > max_width:
|
||||
lines.append(flowed_line)
|
||||
flowed_line = ""
|
||||
flowed_line += (" " if flowed_line else "") + words[0]
|
||||
del words[0]
|
||||
if flowed_line:
|
||||
lines.append(flowed_line)
|
||||
return lines
|
||||
|
||||
class OBJECT_PT_EntityPanel(bpy.types.Panel):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
|
@ -198,9 +184,22 @@ class OBJECT_PT_EntityPanel(bpy.types.Panel):
|
|||
row = layout.row()
|
||||
row.prop(qfentity, "classname")
|
||||
box=layout.box()
|
||||
lines = reflow_text(ec.comment, 40)
|
||||
for l in lines:
|
||||
box.label(text=l)
|
||||
width = int(ceil(context.region.width / 6))
|
||||
mainwrap = TextWrapper(width = width)
|
||||
subwrap = TextWrapper(width = width - 8)
|
||||
for c in ec.comment:
|
||||
clines = mainwrap.wrap(c)
|
||||
for l in clines:
|
||||
box.label(text=l)
|
||||
for f in ec.fields.values():
|
||||
print(f.name)
|
||||
flines = subwrap.wrap(f.comment)
|
||||
box.label(text=f"{f.name}")
|
||||
for l in flines:
|
||||
box.label(text=f" {l}")
|
||||
if hasattr(f, "sounds"):
|
||||
for s in f.sounds:
|
||||
box.label(text=f" {s[0]} {s[1]}")
|
||||
row = layout.row()
|
||||
for c in range(3):
|
||||
col = row.column()
|
||||
|
@ -269,7 +268,7 @@ def set_entity_props(obj, ent):
|
|||
qfe.classname = ent.d["classname"]
|
||||
except TypeError:
|
||||
#FIXME hmm, maybe an enum wasn't the most brilliant idea?
|
||||
qfe.classname = ''
|
||||
qfe.classname = '.'
|
||||
if "spawnflags" in ent.d:
|
||||
flags = int(float(ent.d["spawnflags"]))
|
||||
for i in range(12):
|
||||
|
|
|
@ -20,9 +20,14 @@
|
|||
# <pep8 compliant>
|
||||
|
||||
import os
|
||||
from .script import Script
|
||||
from .qfplist import pldata
|
||||
from . import quakechr
|
||||
try:
|
||||
from .script import Script
|
||||
from .qfplist import pldata
|
||||
from . import quakechr
|
||||
except ImportError:
|
||||
from script import Script
|
||||
from qfplist import pldata
|
||||
import quakechr
|
||||
|
||||
MAX_FLAGS = 8
|
||||
|
||||
|
@ -34,16 +39,46 @@ class EntityClassError(Exception):
|
|||
def entclass_error(self, msg):
|
||||
raise EntityClassError(self.filename, self.line, msg)
|
||||
|
||||
class EntityField:
|
||||
def __init__(self, name, default, comment):
|
||||
self.name = name
|
||||
self.default = default
|
||||
self.comment = comment
|
||||
def to_dictionary(self):
|
||||
d = {}
|
||||
if self.default != None:
|
||||
d["default"] = self.default
|
||||
if self.comment:
|
||||
d["comment"] = self.comment
|
||||
if hasattr(self, "sounds"):
|
||||
d["sounds"] = self.sounds
|
||||
return d
|
||||
@classmethod
|
||||
def from_dictionary(cls, name, d):
|
||||
if "default" in d:
|
||||
default = d["default"]
|
||||
else:
|
||||
default = None
|
||||
if "comment" in d:
|
||||
comment = d["comment"]
|
||||
else:
|
||||
comment = ""
|
||||
field = cls(name, default, comment)
|
||||
if "sounds" in d:
|
||||
field.sounds = d["sounds"]
|
||||
return field
|
||||
|
||||
class EntityClass:
|
||||
def __init__(self, name, color, size, flagnames, comment):
|
||||
def __init__(self, name, color, size, flagnames, comment, fields):
|
||||
self.name = name
|
||||
self.color = color
|
||||
self.size = size
|
||||
self.flagnames = flagnames
|
||||
self.comment = comment
|
||||
self.fields = fields
|
||||
@classmethod
|
||||
def null(cls):
|
||||
return cls('', (1, 1, 1), None, (), "")
|
||||
return cls('', (1, 1, 1), None, (), "", {})
|
||||
@classmethod
|
||||
def from_quaked(cls, text, filename, line = 0):
|
||||
script = Script(filename, text)
|
||||
|
@ -59,8 +94,49 @@ class EntityClass:
|
|||
else:
|
||||
size = None
|
||||
flagnames = ()
|
||||
comment = cls.extract_comment(script)
|
||||
return cls(name, color, size, flagnames, comment)
|
||||
comment = []
|
||||
fields = {}
|
||||
script.quotes = False
|
||||
script.single = ""
|
||||
while script.tokenAvailable(True):
|
||||
line = []
|
||||
while script.tokenAvailable():
|
||||
script.getToken()
|
||||
if script.token[-2:] == "*/":
|
||||
break;
|
||||
line.append(script.token)
|
||||
if line:
|
||||
if ((line[0][0] == '"' and line[0][-1] == '"')
|
||||
or (len(line) > 1 and line[1] == '=')):
|
||||
if line[0][0] == '"':
|
||||
fname = line[0][1:-1]
|
||||
line = line[1:]
|
||||
else:
|
||||
fname = line[0]
|
||||
line = line[2:]
|
||||
default = None
|
||||
for i, t in enumerate(line[:-1]):
|
||||
if t[0] == '(' and line[i + 1] == "default)":
|
||||
default = t[1:]
|
||||
break
|
||||
line = " ".join(line)
|
||||
fields[fname] = EntityField(fname, default, line)
|
||||
line = None
|
||||
elif "sounds" in fields:
|
||||
sounds = fields["sounds"]
|
||||
if not hasattr(sounds, "sounds"):
|
||||
sounds.sounds = []
|
||||
if line[0][-1] == ')':
|
||||
line[0] = line[0][:-1]
|
||||
sounds.sounds.append((line[0], " ".join(line[1:])))
|
||||
line = None
|
||||
else:
|
||||
line = " ".join(line)
|
||||
if line:
|
||||
comment.append(line)
|
||||
if script.token[-2:] == "*/":
|
||||
break;
|
||||
return cls(name, color, size, flagnames, comment, fields)
|
||||
@classmethod
|
||||
def from_dictionary(cls, name, d):
|
||||
if "color" in d:
|
||||
|
@ -81,11 +157,21 @@ class EntityClass:
|
|||
if "comment" in d:
|
||||
comment = d["comment"]
|
||||
else:
|
||||
comment = ""
|
||||
return cls(name, color, size, flagnames, comment)
|
||||
comment = []
|
||||
if "fields" in d:
|
||||
field_dict = d["fields"]
|
||||
fields = {}
|
||||
for f in field_dict:
|
||||
fields[f] = EntityField.from_dictionary(f, field_dict[f])
|
||||
else:
|
||||
fields = {}
|
||||
return cls(name, color, size, flagnames, comment, fields)
|
||||
def to_dictionary(self):
|
||||
fields = {}
|
||||
for f in self.fields:
|
||||
fields[f] = self.fields[f].to_dictionary()
|
||||
d = {"color":self.color, "flagnames":self.flagnames,
|
||||
"comment":self.comment}
|
||||
"comment":self.comment, "fields":fields}
|
||||
if self.size:
|
||||
d["size"] = self.size
|
||||
return d
|
||||
|
@ -93,8 +179,11 @@ class EntityClass:
|
|||
def parse_vector(cls, script):
|
||||
if script.getToken() != "(":
|
||||
script.error("Missing (")
|
||||
v = (float(script.getToken()), float(script.getToken()),
|
||||
float(script.getToken()))
|
||||
s = script.getToken(), script.getToken(), script.getToken()
|
||||
try:
|
||||
v = (float(s[0]), float(s[1]), float(s[2]))
|
||||
except ValueError:
|
||||
v = s
|
||||
if script.getToken() != ")":
|
||||
script.error("Missing )")
|
||||
return v
|
||||
|
@ -118,7 +207,6 @@ class EntityClass:
|
|||
if len(flagnames) < MAX_FLAGS:
|
||||
flagnames.append(script.token)
|
||||
return tuple(flagnames)
|
||||
@classmethod
|
||||
def extract_comment(cls, script):
|
||||
if not script.tokenAvailable(True):
|
||||
return ""
|
||||
|
@ -203,3 +291,35 @@ class EntityClassDict:
|
|||
self.entity_classes = {}
|
||||
for k in ec.keys():
|
||||
self.entity_classes[k] = EntityClass.from_dictionary(k, ec[k])
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
from pprint import pprint
|
||||
from textwrap import TextWrapper
|
||||
|
||||
mainwrap = TextWrapper(width = 70)
|
||||
fieldwrap = TextWrapper(width = 50)
|
||||
|
||||
ecd = EntityClassDict()
|
||||
for fname in sys.argv[1:]:
|
||||
ecd.scan_source(fname)
|
||||
text = ecd.to_plist()
|
||||
print(text)
|
||||
ecd.from_plist(text)
|
||||
for ec in ecd.entity_classes.values():
|
||||
print(f"{ec.name}: {ec.color} {ec.size} {ec.flagnames}")
|
||||
for c in ec.comment:
|
||||
mlines = mainwrap.wrap(c)
|
||||
for m in mlines:
|
||||
print(f" {m}")
|
||||
print()
|
||||
for f in ec.fields.values():
|
||||
print(f" {f.name}: {f.default}")
|
||||
flines = fieldwrap.wrap(f.comment)
|
||||
for l in flines:
|
||||
print(f" {l}")
|
||||
if f.name == "sounds":
|
||||
for s in f.sounds:
|
||||
print(f" {s[0]} {s[1]}")
|
||||
print()
|
||||
print()
|
||||
|
|
|
@ -175,8 +175,8 @@ def process_entity(ent, wads):
|
|||
obj = bpy.data.objects.new(name, mesh)
|
||||
else:
|
||||
obj = bpy.data.objects.new(name, None)
|
||||
obj.empty_draw_type = 'CUBE'
|
||||
obj.empty_draw_size = 8
|
||||
obj.empty_display_type = 'CUBE'
|
||||
obj.empty_display_size = 8
|
||||
obj.show_name = True
|
||||
if "origin" in ent.d:
|
||||
obj.location = parse_vector (ent.d["origin"])
|
||||
|
|
|
@ -26,17 +26,19 @@ class ScriptError(Exception):
|
|||
|
||||
class Script:
|
||||
def __init__(self, filename, text, single="{}()':", quotes=True):
|
||||
self.filename = filename
|
||||
if text[0:3] == "\xef\xbb\xbf":
|
||||
text = text[3:]
|
||||
elif text[0] == u"\ufeff":
|
||||
text = text[1:]
|
||||
self.token = ""
|
||||
self.unget = False
|
||||
self.text = text
|
||||
self.pos = 0
|
||||
self.filename = filename
|
||||
self.line = 1
|
||||
self.no_quote_lines = False
|
||||
self.single = single
|
||||
self.quotes = quotes
|
||||
self.pos = 0
|
||||
self.line = 1
|
||||
self.unget = False
|
||||
def error(self, msg):
|
||||
raise ScriptError(self.filename, self.line, msg)
|
||||
def tokenAvailable(self, crossline=False):
|
||||
|
@ -102,6 +104,9 @@ class Script:
|
|||
self.error("EOF inside quoted string")
|
||||
return None
|
||||
if self.text[self.pos] == "\n":
|
||||
if self.no_quote_lines:
|
||||
self.error("EOL inside quoted string")
|
||||
return None
|
||||
self.line += 1
|
||||
self.pos += 1
|
||||
self.token = self.text[start:self.pos]
|
||||
|
|
|
@ -494,7 +494,7 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n, statement_t *s)
|
|||
set_remove (gn->edges, n->number);
|
||||
}
|
||||
}
|
||||
if (num_params && isdigit (*num_params)) {
|
||||
if (num_params && isdigit ((byte) *num_params)) {
|
||||
for (i = first_param; i < *num_params - '0'; i++) {
|
||||
flowvar_t *var = flowvars[i + 1];
|
||||
def_t *param_def = var->op->def;
|
||||
|
|
|
@ -279,7 +279,10 @@ merge_method_lists (methodlist_t *dst, methodlist_t *src)
|
|||
s->next = 0;
|
||||
if (method_in_list (dst, s)) {
|
||||
debug (0, "dropping duplicate method: %s", s->name);
|
||||
free (s);
|
||||
//FIXME this free is currently erroneous as it remains in
|
||||
//known_methods, but it may also be a leak, thus only
|
||||
//commented out for now.
|
||||
//free (s);
|
||||
} else {
|
||||
// add_method does the duplicate check
|
||||
*dst->tail = s;
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
//the first place, but not at all sure what to do about that)
|
||||
#ifdef _WIN32
|
||||
#define aligned_alloc(al, sz) _aligned_malloc(sz, al)
|
||||
#define free(x) _aligned_free(x)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
|
|
Loading…
Reference in a new issue