1 /* 2 This file is part of Warzone 2100. 3 Copyright (C) 2017-2020 Warzone 2100 Project 4 5 Warzone 2100 is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 Warzone 2100 is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with Warzone 2100; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 #pragma once 21 22 #include <memory> 23 #include <string> 24 #include <map> 25 #include <vector> 26 #include <tuple> 27 #include <functional> 28 29 #include "lib/framework/frame.h" 30 #include "screen.h" 31 #include "pietypes.h" 32 33 #include <glm/glm.hpp> 34 35 namespace gfx_api 36 { 37 // Must be implemented by backend (ex. SDL) 38 class backend_Null_Impl; // see: gfx_api_null.h 39 class backend_OpenGL_Impl; // see: gfx_api_gl.h 40 #if defined(WZ_VULKAN_ENABLED) 41 class backend_Vulkan_Impl; // see: gfx_api_vk.h 42 #endif 43 class backend_Impl_Factory 44 { 45 public: ~backend_Impl_Factory()46 virtual ~backend_Impl_Factory() {}; 47 virtual std::unique_ptr<backend_Null_Impl> createNullBackendImpl() const = 0; 48 virtual std::unique_ptr<backend_OpenGL_Impl> createOpenGLBackendImpl() const = 0; 49 #if defined(WZ_VULKAN_ENABLED) 50 virtual std::unique_ptr<backend_Vulkan_Impl> createVulkanBackendImpl() const = 0; 51 #endif 52 }; 53 // 54 } 55 56 namespace gfx_api 57 { 58 enum class backend_type 59 { 60 null_backend, 61 opengl_backend, 62 vulkan_backend 63 }; 64 } 65 66 namespace gfx_api 67 { 68 #ifdef GL_ONLY 69 using gfxFloat = GLfloat; 70 using gfxByte = GLbyte; 71 using gfxUByte = GLubyte; 72 #else 73 using gfxFloat = float; 74 using gfxByte = char; 75 using gfxUByte = unsigned char; 76 #endif 77 78 enum class pixel_format 79 { 80 invalid, 81 FORMAT_RGBA8_UNORM_PACK8, 82 FORMAT_BGRA8_UNORM_PACK8, 83 FORMAT_RGB8_UNORM_PACK8, 84 }; 85 86 struct texture 87 { ~texturetexture88 virtual ~texture() {}; 89 virtual void bind() = 0; 90 virtual void upload(const size_t& mip_level, const size_t& offset_x, const size_t& offset_y, const size_t& width, const size_t& height, const pixel_format& buffer_format, const void* data) = 0; 91 virtual void upload_and_generate_mipmaps(const size_t& offset_x, const size_t& offset_y, const size_t& width, const size_t& height, const pixel_format& buffer_format, const void* data) = 0; 92 virtual unsigned id() = 0; 93 94 texture( const texture& other ) = delete; // non construction-copyable 95 texture& operator=( const texture& ) = delete; // non copyable texturetexture96 texture() {}; 97 }; 98 99 // An abstract base that manages a single gfx buffer 100 struct buffer 101 { 102 enum class usage 103 { 104 vertex_buffer, 105 index_buffer, 106 }; 107 static const size_t USAGE_COUNT = 2; 108 109 // Create a new data store for the buffer. Any existing data store will be deleted. 110 // The new data store is created with the specified `size` in bytes. 111 // If `data` is not NULL, the data store is initialized with `size` bytes of data from the pointer. 112 // - If data is NULL, a data store of the specified `size` is still created, but its contents may be uninitialized (and thus undefined). 113 // 114 // NOTE: A single buffer instance should only be uploaded / updated *once per frame*. 115 // Buffer uploads / updates may be re-ordered to occur before the processing of *any* draw calls in a frame, 116 // hence re-using a single buffer instance for different data may lead to anything using that buffer (in that frame) 117 // seeing only the last-written data in the buffer. 118 // (i.e. Don't re-use a buffer instance for different data in the same frame - use separate buffer instances.) 119 virtual void upload(const size_t& size, const void* data) = 0; 120 121 enum class update_flag { 122 // Default behavior 123 none, 124 125 // This flag disables asserts caused by multiple updates to a single buffer instance in a single frame 126 // *ONLY* use if you are certain the updates are non-overlapping 127 non_overlapping_updates_promise 128 }; 129 130 // Update `size` bytes in the existing data store, from the `start` offset, using the data at `data`. 131 // - The `start` offset must be within the range of the existing data store (0 to buffer_size - 1, inclusive). 132 // - The `size` of the data specified (+ the offset) must not attempt to write past the end of the existing data store. 133 // - A data store must be allocated before it can be updated - call `upload` on a `buffer` instance before `update`. 134 // 135 // NOTE: A single buffer instance should only be uploaded / updated *once per frame*. 136 // Buffer uploads / updates may be re-ordered to occur before the processing of *any* draw calls in a frame, 137 // hence re-using a single buffer instance for different data may lead to anything using that buffer (in that frame) 138 // seeing only the last-written data in the buffer. 139 // (i.e. Don't re-use a buffer instance for different data in the same frame - use separate buffer instances.) 140 virtual void update(const size_t& start, const size_t& size, const void* data, const update_flag flag = update_flag::none) = 0; 141 142 virtual void bind() = 0; 143 ~bufferbuffer144 virtual ~buffer() {}; 145 146 buffer( const buffer& other ) = delete; // non construction-copyable 147 buffer& operator=( const buffer& ) = delete; // non copyable bufferbuffer148 buffer() {}; 149 }; 150 151 enum class primitive_type 152 { 153 lines, 154 line_strip, 155 triangles, 156 triangle_strip, 157 // NOTE: Do *NOT* support triangle_fan, for portability reasons 158 }; 159 160 enum class index_type 161 { 162 u16, 163 u32, 164 }; 165 166 enum class polygon_offset 167 { 168 enabled, 169 disabled, 170 }; 171 172 enum class stencil_mode 173 { 174 stencil_shadow_silhouette, 175 stencil_shadow_quad, 176 stencil_disabled, 177 }; 178 179 enum class cull_mode 180 { 181 back, 182 none, 183 }; 184 185 struct state_description 186 { 187 const REND_MODE blend_state; 188 const DEPTH_MODE depth_mode; 189 const uint8_t output_mask; 190 const bool offset; 191 const stencil_mode stencil; 192 const cull_mode cull; 193 state_descriptionstate_description194 constexpr state_description(REND_MODE _blend_state, DEPTH_MODE _depth_mode, uint8_t _output_mask, polygon_offset _polygon_offset, stencil_mode _stencil, cull_mode _cull) : 195 blend_state(_blend_state), depth_mode(_depth_mode), output_mask(_output_mask), offset(_polygon_offset == polygon_offset::enabled), stencil(_stencil), cull(_cull) {} 196 }; 197 198 enum class vertex_attribute_type 199 { 200 float2, 201 float3, 202 float4, 203 u8x4_norm, 204 }; 205 206 struct vertex_buffer_input 207 { 208 const std::size_t id; 209 const vertex_attribute_type type; 210 const std::size_t offset; 211 vertex_buffer_inputvertex_buffer_input212 constexpr vertex_buffer_input(std::size_t _id, vertex_attribute_type _type, std::size_t _offset) 213 : id(_id), type(_type), offset(_offset) 214 {} 215 }; 216 217 struct vertex_buffer 218 { 219 const std::size_t stride; 220 const std::vector<vertex_buffer_input> attributes; vertex_buffervertex_buffer221 vertex_buffer(std::size_t _stride, std::vector<vertex_buffer_input>&& _attributes) 222 : stride(_stride), attributes(std::forward<std::vector<vertex_buffer_input>>(_attributes)) 223 {} 224 }; 225 226 enum class sampler_type 227 { 228 bilinear, 229 bilinear_repeat, 230 anisotropic, 231 nearest_clamped, 232 anisotropic_repeat, 233 }; 234 235 struct texture_input 236 { 237 const std::size_t id; 238 const sampler_type sampler; 239 texture_inputtexture_input240 constexpr texture_input(std::size_t _id, sampler_type _sampler) 241 : id(_id), sampler(_sampler) 242 {} 243 }; 244 245 struct pipeline_state_object 246 { ~pipeline_state_objectpipeline_state_object247 virtual ~pipeline_state_object() {} 248 }; 249 250 struct context 251 { 252 enum class buffer_storage_hint 253 { 254 static_draw, 255 stream_draw, 256 dynamic_draw, 257 }; 258 259 enum class context_value 260 { 261 MAX_ELEMENTS_VERTICES, 262 MAX_ELEMENTS_INDICES, 263 MAX_TEXTURE_SIZE, 264 MAX_SAMPLES, // max antialiasing 265 }; 266 267 enum class swap_interval_mode 268 { 269 adaptive_vsync = -1, 270 immediate = 0, 271 vsync = 1, 272 }; 273 static const swap_interval_mode min_swap_interval_mode = swap_interval_mode::adaptive_vsync; 274 static const swap_interval_mode max_swap_interval_mode = swap_interval_mode::vsync; 275 ~contextcontext276 virtual ~context() {}; 277 virtual texture* create_texture(const size_t& mipmap_count, const size_t& width, const size_t& height, const pixel_format& internal_format, const std::string& filename = "") = 0; 278 virtual buffer* create_buffer_object(const buffer::usage&, const buffer_storage_hint& = buffer_storage_hint::static_draw) = 0; 279 virtual pipeline_state_object* build_pipeline(const state_description&, 280 const SHADER_MODE&, 281 const gfx_api::primitive_type& primitive, 282 const std::vector<gfx_api::texture_input>& texture_desc, 283 const std::vector<vertex_buffer>& attribute_descriptions) = 0; 284 virtual void bind_pipeline(pipeline_state_object*, bool notextures) = 0; 285 virtual void bind_index_buffer(buffer&, const index_type&) = 0; 286 virtual void unbind_index_buffer(buffer&) = 0; 287 virtual void bind_vertex_buffers(const std::size_t& first, const std::vector<std::tuple<gfx_api::buffer*, std::size_t>>& vertex_buffers_offset) = 0; 288 virtual void unbind_vertex_buffers(const std::size_t& first, const std::vector<std::tuple<gfx_api::buffer*, std::size_t>>& vertex_buffers_offset) = 0; 289 virtual void disable_all_vertex_buffers() = 0; 290 virtual void bind_streamed_vertex_buffers(const void* data, const std::size_t size) = 0; 291 virtual void bind_textures(const std::vector<texture_input>& attribute_descriptions, const std::vector<texture*>& textures) = 0; 292 virtual void set_constants(const void* buffer, const std::size_t& size) = 0; 293 virtual void draw(const std::size_t& offset, const std::size_t&, const primitive_type&) = 0; 294 virtual void draw_elements(const std::size_t& offset, const std::size_t&, const primitive_type&, const index_type&) = 0; 295 virtual void set_polygon_offset(const float& offset, const float& slope) = 0; 296 virtual void set_depth_range(const float& min, const float& max) = 0; 297 virtual int32_t get_context_value(const context_value property) = 0; 298 static context& get(); 299 static bool initialize(const gfx_api::backend_Impl_Factory& impl, int32_t antialiasing, swap_interval_mode mode, gfx_api::backend_type backend); 300 virtual void flip(int clearMode) = 0; 301 virtual void debugStringMarker(const char *str) = 0; 302 virtual void debugSceneBegin(const char *descr) = 0; 303 virtual void debugSceneEnd(const char *descr) = 0; 304 virtual bool debugPerfAvailable() = 0; 305 virtual bool debugPerfStart(size_t sample) = 0; 306 virtual void debugPerfStop() = 0; 307 virtual void debugPerfBegin(PERF_POINT pp, const char *descr) = 0; 308 virtual void debugPerfEnd(PERF_POINT pp) = 0; 309 virtual uint64_t debugGetPerfValue(PERF_POINT pp) = 0; 310 virtual std::map<std::string, std::string> getBackendGameInfo() = 0; 311 virtual const std::string& getFormattedRendererInfoString() const = 0; 312 virtual bool getScreenshot(std::function<void (std::unique_ptr<iV_Image>)> callback) = 0; 313 virtual void handleWindowSizeChange(unsigned int oldWidth, unsigned int oldHeight, unsigned int newWidth, unsigned int newHeight) = 0; 314 virtual void shutdown() = 0; 315 virtual const size_t& current_FrameNum() const = 0; 316 virtual bool setSwapInterval(swap_interval_mode mode) = 0; 317 virtual swap_interval_mode getSwapInterval() const = 0; 318 private: 319 virtual bool _initialize(const backend_Impl_Factory& impl, int32_t antialiasing, swap_interval_mode mode) = 0; 320 }; 321 322 template<std::size_t id, vertex_attribute_type type, std::size_t offset> 323 struct vertex_attribute_description 324 { get_descvertex_attribute_description325 static vertex_buffer_input get_desc() 326 { 327 return vertex_buffer_input{id, type, offset}; 328 } 329 }; 330 331 /** 332 * A struct templated by a tuple. 333 * Describes a buffer input. 334 * input_description describes the various vertex attributes fetched from this buffer. 335 */ 336 template<std::size_t stride, typename... input_description> 337 struct vertex_buffer_description 338 { get_descvertex_buffer_description339 static vertex_buffer get_desc() 340 { 341 return { stride, { input_description::get_desc()...} }; 342 } 343 }; 344 345 template<std::size_t texture_unit, sampler_type sampler> 346 struct texture_description 347 { get_desctexture_description348 static texture_input get_desc() 349 { 350 return texture_input{ texture_unit, sampler }; 351 } 352 }; 353 354 template<REND_MODE render_mode, DEPTH_MODE depth_mode, uint8_t output_mask, polygon_offset offset, stencil_mode stencil, cull_mode cull> 355 struct rasterizer_state 356 { getrasterizer_state357 static state_description get() 358 { 359 return state_description{ render_mode, depth_mode, output_mask, offset, stencil, cull }; 360 } 361 }; 362 363 template<SHADER_MODE T> 364 struct constant_buffer_type {}; 365 366 template<typename rasterizer, primitive_type primitive, index_type index, typename vertex_buffer_inputs, typename texture_inputs, SHADER_MODE shader> 367 struct pipeline_state_helper 368 { 369 using texture_tuple = texture_inputs; 370 getpipeline_state_helper371 static pipeline_state_helper<rasterizer, primitive, index, vertex_buffer_inputs, texture_inputs, shader>& get() 372 { 373 static pipeline_state_helper < rasterizer, primitive, index, vertex_buffer_inputs, texture_inputs, shader> object; 374 return object; 375 } 376 bindpipeline_state_helper377 void bind() 378 { 379 gfx_api::context::get().bind_pipeline(pso, std::tuple_size<texture_inputs>::value == 0); 380 } 381 382 template<typename... Args> bind_vertex_bufferspipeline_state_helper383 void bind_vertex_buffers(Args&&... args) 384 { 385 static_assert(sizeof...(args) == std::tuple_size<vertex_buffer_inputs>::value, "Wrong number of vertex buffer"); 386 gfx_api::context::get().bind_vertex_buffers(0, { std::make_tuple(args, 0)... }); 387 } 388 389 template<typename... Args> unbind_vertex_bufferspipeline_state_helper390 void unbind_vertex_buffers(Args&&... args) 391 { 392 static_assert(sizeof...(args) == std::tuple_size<vertex_buffer_inputs>::value, "Wrong number of vertex buffer"); 393 gfx_api::context::get().unbind_vertex_buffers(0, { std::make_tuple(args, 0)... }); 394 } 395 396 template<typename...Args> bind_texturespipeline_state_helper397 void bind_textures(Args&&... args) 398 { 399 static_assert(sizeof...(args) == std::tuple_size<texture_inputs>::value, "Wrong number of textures"); 400 gfx_api::context::get().bind_textures(untuple<texture_input>(texture_inputs{}), { args... }); 401 } 402 bind_constantspipeline_state_helper403 void bind_constants(const constant_buffer_type<shader>& data) 404 { 405 // Vulkan: Many platforms have a maxUniformBufferRange of 64k 406 // - see: https://vulkan.gpuinfo.org/displaydevicelimit.php?name=maxUniformBufferRange 407 static_assert(sizeof(constant_buffer_type<shader>) <= 65536, "Constant buffer size exceeds 64k"); 408 409 gfx_api::context::get().set_constants(static_cast<const void*>(&data), sizeof(constant_buffer_type<shader>)); 410 } 411 drawpipeline_state_helper412 void draw(const std::size_t& count, const std::size_t& offset) 413 { 414 context::get().draw(offset, count, primitive); 415 } 416 draw_elementspipeline_state_helper417 void draw_elements(const std::size_t& count, const std::size_t& offset) 418 { 419 context::get().draw_elements(offset, count, primitive, index); 420 } 421 private: 422 pipeline_state_object* pso; pipeline_state_helperpipeline_state_helper423 pipeline_state_helper() 424 { 425 pso = gfx_api::context::get().build_pipeline(rasterizer::get(), shader, primitive, untuple<texture_input>(texture_inputs{}), untuple<vertex_buffer>(vertex_buffer_inputs{})); 426 } 427 428 // // Requires C++14 (+) 429 // template<typename...Args> 430 // auto untuple(const std::tuple<Args...>&) 431 // { 432 // auto type_holder = { Args::get_desc()... }; 433 // using output_type = decltype(type_holder); 434 // return std::vector<typename output_type::value_type>(type_holder); 435 // } 436 // 437 // std::vector<gfx_api::texture_input> untuple(const std::tuple<>&) 438 // { 439 // return std::vector<gfx_api::texture_input>{}; 440 // } 441 442 // C++11, but requires specifying Output type 443 template<typename Output, typename...Args> untuplepipeline_state_helper444 std::vector<Output> untuple(const std::tuple<Args...>&) 445 { 446 return std::vector<Output>({ Args::get_desc()... }); 447 } 448 }; 449 450 constexpr std::size_t position = 0; 451 constexpr std::size_t texcoord = 1; 452 constexpr std::size_t color = 2; 453 constexpr std::size_t normal = 3; 454 constexpr std::size_t tangent = 4; 455 456 using notexture = std::tuple<>; 457 458 // NOTE: Be very careful changing these constant_buffer_type structs; 459 // they must match std140 layout rules (see: the Vulkan shaders) 460 template<> 461 struct constant_buffer_type<SHADER_BUTTON> 462 { 463 glm::vec4 colour; 464 glm::vec4 teamcolour; 465 float shaderStretch; 466 int tcmask; 467 int fogEnabled; 468 int normalMap; 469 int specularMap; 470 int ecmState; 471 int alphaTest; 472 float timeState; 473 glm::mat4 ModelViewMatrix; 474 glm::mat4 ModelViewProjectionMatrix; 475 glm::mat4 NormalMatrix; 476 glm::vec4 sunPos; 477 glm::vec4 sceneColor; 478 glm::vec4 ambient; 479 glm::vec4 diffuse; 480 glm::vec4 specular; 481 glm::vec4 fogColour; 482 float fogEnd; 483 float fogBegin; 484 int hasTangents; 485 }; 486 487 template<> 488 struct constant_buffer_type<SHADER_COMPONENT> 489 { 490 glm::vec4 colour; 491 glm::vec4 teamcolour; 492 float shaderStretch; 493 int tcmask; 494 int fogEnabled; 495 int normalMap; 496 int specularMap; 497 int ecmState; 498 int alphaTest; 499 float timeState; 500 glm::mat4 ModelViewMatrix; 501 glm::mat4 ModelViewProjectionMatrix; 502 glm::mat4 NormalMatrix; 503 glm::vec4 sunPos; 504 glm::vec4 sceneColor; 505 glm::vec4 ambient; 506 glm::vec4 diffuse; 507 glm::vec4 specular; 508 glm::vec4 fogColour; 509 float fogEnd; 510 float fogBegin; 511 int hasTangents; 512 }; 513 514 template<> 515 struct constant_buffer_type<SHADER_NOLIGHT> 516 { 517 glm::vec4 colour; 518 glm::vec4 teamcolour; 519 float shaderStretch; 520 int tcmask; 521 int fogEnabled; 522 int normalMap; 523 int specularMap; 524 int ecmState; 525 int alphaTest; 526 float timeState; 527 glm::mat4 ModelViewMatrix; 528 glm::mat4 ModelViewProjectionMatrix; 529 glm::mat4 NormalMatrix; 530 glm::vec4 sunPos; 531 glm::vec4 sceneColor; 532 glm::vec4 ambient; 533 glm::vec4 diffuse; 534 glm::vec4 specular; 535 glm::vec4 fogColour; 536 float fogEnd; 537 float fogBegin; 538 int hasTangents; 539 }; 540 541 template<REND_MODE render_mode, SHADER_MODE shader> 542 using Draw3DShape = typename gfx_api::pipeline_state_helper<rasterizer_state<render_mode, DEPTH_CMP_LEQ_WRT_ON, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangles, index_type::u16, 543 std::tuple< 544 vertex_buffer_description<12, vertex_attribute_description<position, gfx_api::vertex_attribute_type::float3, 0>>, 545 vertex_buffer_description<12, vertex_attribute_description<normal, gfx_api::vertex_attribute_type::float3, 0>>, 546 vertex_buffer_description<8, vertex_attribute_description<texcoord, gfx_api::vertex_attribute_type::float2, 0>>, 547 vertex_buffer_description<16, vertex_attribute_description<tangent, gfx_api::vertex_attribute_type::float4, 0>> 548 >, 549 std::tuple< 550 texture_description<0, sampler_type::anisotropic>, // diffuse 551 texture_description<1, sampler_type::bilinear>, // team color mask 552 texture_description<2, sampler_type::anisotropic>, // normal map 553 texture_description<3, sampler_type::anisotropic> // specular map 554 >, shader>; 555 556 using Draw3DButtonPSO = Draw3DShape<REND_OPAQUE, SHADER_BUTTON>; 557 using Draw3DShapeOpaque = Draw3DShape<REND_OPAQUE, SHADER_COMPONENT>; 558 using Draw3DShapeAlpha = Draw3DShape<REND_ALPHA, SHADER_COMPONENT>; 559 using Draw3DShapePremul = Draw3DShape<REND_PREMULTIPLIED, SHADER_COMPONENT>; 560 using Draw3DShapeAdditive = Draw3DShape<REND_ADDITIVE, SHADER_COMPONENT>; 561 using Draw3DShapeNoLightOpaque = Draw3DShape<REND_OPAQUE, SHADER_NOLIGHT>; 562 using Draw3DShapeNoLightAlpha = Draw3DShape<REND_ALPHA, SHADER_NOLIGHT>; 563 using Draw3DShapeNoLightPremul = Draw3DShape<REND_PREMULTIPLIED, SHADER_NOLIGHT>; 564 using Draw3DShapeNoLightAdditive = Draw3DShape<REND_ADDITIVE, SHADER_NOLIGHT>; 565 566 template<> 567 struct constant_buffer_type<SHADER_GENERIC_COLOR> 568 { 569 glm::mat4 transform_matrix; 570 glm::vec2 unused; 571 glm::vec2 unused2; 572 glm::vec4 colour; 573 }; 574 575 using TransColouredTrianglePSO = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_ADDITIVE, DEPTH_CMP_LEQ_WRT_ON, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangle_strip, index_type::u16, 576 std::tuple< 577 vertex_buffer_description<12, vertex_attribute_description<position, gfx_api::vertex_attribute_type::float3, 0>> 578 >, notexture, SHADER_GENERIC_COLOR>; 579 using DrawStencilShadow = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_OPAQUE, DEPTH_CMP_LEQ_WRT_OFF, 0, polygon_offset::disabled, stencil_mode::stencil_shadow_silhouette, cull_mode::none>, primitive_type::triangles, index_type::u16, 580 std::tuple< 581 vertex_buffer_description<12, vertex_attribute_description<position, gfx_api::vertex_attribute_type::float3, 0>> 582 >, notexture, SHADER_GENERIC_COLOR>; 583 584 template<> 585 struct constant_buffer_type<SHADER_TERRAIN_DEPTH> 586 { 587 glm::mat4 transform_matrix; 588 glm::vec4 paramX; 589 glm::vec4 paramY; 590 glm::vec4 paramXLight; 591 glm::vec4 paramYLight; 592 glm::mat4 unused; 593 glm::mat4 texture_matrix; 594 glm::vec4 fog_colour; 595 int fog_enabled; 596 float fog_begin; 597 float fog_end; 598 int texture0; 599 int texture1; 600 }; 601 602 using TerrainDepth = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_OPAQUE, DEPTH_CMP_LEQ_WRT_ON, 0, polygon_offset::enabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangles, index_type::u32, 603 std::tuple< 604 vertex_buffer_description<12, vertex_attribute_description<position, gfx_api::vertex_attribute_type::float3, 0>> 605 >, notexture, SHADER_TERRAIN_DEPTH>; 606 607 template<> 608 struct constant_buffer_type<SHADER_TERRAIN> 609 { 610 glm::mat4 transform_matrix; 611 glm::vec4 paramX; 612 glm::vec4 paramY; 613 glm::vec4 paramXLight; 614 glm::vec4 paramYLight; 615 glm::mat4 unused; 616 glm::mat4 texture_matrix; 617 glm::vec4 fog_colour; 618 int fog_enabled; 619 float fog_begin; 620 float fog_end; 621 int texture0; 622 int texture1; 623 }; 624 625 using TerrainLayer = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_ADDITIVE, DEPTH_CMP_LEQ_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangles, index_type::u32, 626 std::tuple< 627 vertex_buffer_description<12, vertex_attribute_description<position, gfx_api::vertex_attribute_type::float3, 0>>, 628 vertex_buffer_description<4, vertex_attribute_description<color, gfx_api::vertex_attribute_type::u8x4_norm, 0>> 629 >, std::tuple<texture_description<0, sampler_type::anisotropic_repeat>, texture_description<1, sampler_type::bilinear>>, SHADER_TERRAIN>; 630 631 template<> 632 struct constant_buffer_type<SHADER_DECALS> 633 { 634 glm::mat4 transform_matrix; 635 glm::mat4 texture_matrix; 636 glm::vec4 param1; 637 glm::vec4 param2; 638 glm::vec4 fog_colour; 639 int fog_enabled; 640 float fog_begin; 641 float fog_end; 642 int texture0; 643 int texture1; 644 }; 645 646 using TerrainDecals = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_ALPHA, DEPTH_CMP_LEQ_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangles, index_type::u16, 647 std::tuple< 648 vertex_buffer_description<sizeof(glm::vec3) + sizeof(glm::vec2), 649 vertex_attribute_description<position, gfx_api::vertex_attribute_type::float3, 0>, 650 vertex_attribute_description<texcoord, gfx_api::vertex_attribute_type::float2, sizeof(glm::vec3)> 651 > 652 >, std::tuple<texture_description<0, sampler_type::anisotropic>, texture_description<1, sampler_type::bilinear>>, SHADER_DECALS>; 653 654 template<> 655 struct constant_buffer_type<SHADER_WATER> 656 { 657 glm::mat4 transform_matrix; 658 glm::vec4 param1; 659 glm::vec4 param2; 660 glm::vec4 param3; 661 glm::vec4 param4; 662 glm::mat4 translation; 663 glm::mat4 texture_matrix; 664 glm::vec4 fog_colour; 665 int fog_enabled; 666 float fog_begin; 667 float fog_end; 668 int texture0; 669 int texture1; 670 }; 671 672 using WaterPSO = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_MULTIPLICATIVE, DEPTH_CMP_LEQ_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangles, index_type::u32, 673 std::tuple< 674 vertex_buffer_description<12, vertex_attribute_description<position, gfx_api::vertex_attribute_type::float3, 0>> 675 >, std::tuple<texture_description<0, sampler_type::anisotropic_repeat>, texture_description<1, sampler_type::anisotropic_repeat>>, SHADER_WATER>; 676 677 using gfx_tc = vertex_buffer_description<8, vertex_attribute_description<texcoord, gfx_api::vertex_attribute_type::float2, 0>>; 678 using gfx_colour = vertex_buffer_description<4, vertex_attribute_description<color, gfx_api::vertex_attribute_type::u8x4_norm, 0>>; 679 using gfx_vtx2 = vertex_buffer_description<8, vertex_attribute_description<position, gfx_api::vertex_attribute_type::float2, 0>>; 680 using gfx_vtx3 = vertex_buffer_description<12, vertex_attribute_description<position, gfx_api::vertex_attribute_type::float3, 0>>; 681 682 template<> 683 struct constant_buffer_type<SHADER_GFX_TEXT> 684 { 685 glm::mat4 transform_matrix; 686 glm::vec2 offset; 687 glm::vec2 size; 688 glm::vec4 color; 689 int texture; 690 }; 691 692 template<> 693 struct constant_buffer_type<SHADER_GFX_COLOUR> 694 { 695 glm::mat4 transform_matrix; 696 // glm::vec2 offset; 697 // glm::vec2 size; 698 // glm::vec4 color; 699 // int texture; 700 }; 701 702 template<REND_MODE rm, DEPTH_MODE dm, primitive_type primitive, typename VTX, typename Second, SHADER_MODE shader, typename texture> 703 using GFX = typename gfx_api::pipeline_state_helper<rasterizer_state<rm, dm, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive, index_type::u16, std::tuple<VTX, Second>, texture, shader>; 704 using VideoPSO = GFX<REND_OPAQUE, DEPTH_CMP_ALWAYS_WRT_OFF, primitive_type::triangle_strip, gfx_vtx2, gfx_tc, SHADER_GFX_TEXT, std::tuple<texture_description<0, gfx_api::sampler_type::bilinear>>>; 705 using BackDropPSO = GFX<REND_OPAQUE, DEPTH_CMP_ALWAYS_WRT_OFF, primitive_type::triangle_strip, gfx_vtx2, gfx_tc, SHADER_GFX_TEXT, std::tuple<texture_description<0, gfx_api::sampler_type::nearest_clamped>>>; 706 using SkyboxPSO = GFX<REND_ALPHA, DEPTH_CMP_LEQ_WRT_OFF, primitive_type::triangles, gfx_vtx3, gfx_tc, SHADER_GFX_TEXT, std::tuple<texture_description<0, gfx_api::sampler_type::bilinear_repeat>>>; 707 using RadarPSO = GFX<REND_ALPHA, DEPTH_CMP_ALWAYS_WRT_OFF, primitive_type::triangle_strip, gfx_vtx2, gfx_tc, SHADER_GFX_TEXT, std::tuple<texture_description<0, gfx_api::sampler_type::nearest_clamped>>>; 708 using RadarViewInsideFillPSO = GFX<REND_ALPHA, DEPTH_CMP_ALWAYS_WRT_OFF, primitive_type::triangle_strip, gfx_vtx2, gfx_colour, SHADER_GFX_COLOUR, notexture>; 709 using RadarViewOutlinePSO = GFX<REND_ALPHA, DEPTH_CMP_ALWAYS_WRT_OFF, primitive_type::line_strip, gfx_vtx2, gfx_colour, SHADER_GFX_COLOUR, notexture>; 710 711 template<> 712 struct constant_buffer_type<SHADER_TEXT> 713 { 714 glm::mat4 transform_matrix; 715 glm::vec2 offset; 716 glm::vec2 size; 717 glm::vec4 color; 718 int texture; 719 }; 720 721 using DrawImageTextPSO = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_TEXT, DEPTH_CMP_ALWAYS_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::none>, primitive_type::triangle_strip, index_type::u16, 722 std::tuple< 723 vertex_buffer_description<4, vertex_attribute_description<position, gfx_api::vertex_attribute_type::u8x4_norm, 0>> 724 >, 725 std::tuple<texture_description<0, sampler_type::bilinear>>, SHADER_TEXT>; 726 727 template<> 728 struct constant_buffer_type<SHADER_RECT> 729 { 730 glm::mat4 transform_matrix; 731 glm::vec2 offset; 732 glm::vec2 size; 733 glm::vec4 colour; 734 }; 735 736 using ShadowBox2DPSO = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_OPAQUE, DEPTH_CMP_ALWAYS_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangle_strip, index_type::u16, 737 std::tuple< 738 vertex_buffer_description<4, vertex_attribute_description<position, gfx_api::vertex_attribute_type::u8x4_norm, 0>> 739 >, notexture, SHADER_RECT>; 740 using UniTransBoxPSO = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_ALPHA, DEPTH_CMP_ALWAYS_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangle_strip, index_type::u16, 741 std::tuple< 742 vertex_buffer_description<4, vertex_attribute_description<position, gfx_api::vertex_attribute_type::u8x4_norm, 0>> 743 >, notexture, SHADER_RECT>; 744 745 template<> 746 struct constant_buffer_type<SHADER_TEXRECT> 747 { 748 glm::mat4 transform_matrix; 749 glm::vec2 offset; 750 glm::vec2 size; 751 glm::vec4 color; 752 int texture; 753 }; 754 755 using DrawImagePSO = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_ALPHA, DEPTH_CMP_ALWAYS_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangle_strip, index_type::u16, 756 std::tuple< 757 vertex_buffer_description<4, vertex_attribute_description<position, gfx_api::vertex_attribute_type::u8x4_norm, 0>> 758 >, std::tuple<texture_description<0, sampler_type::bilinear>>, SHADER_TEXRECT>; 759 760 using DrawImageAnisotropicPSO = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_ALPHA, DEPTH_CMP_ALWAYS_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangle_strip, index_type::u16, 761 std::tuple< 762 vertex_buffer_description<4, vertex_attribute_description<position, gfx_api::vertex_attribute_type::u8x4_norm, 0>> 763 >, std::tuple<texture_description<0, sampler_type::anisotropic>>, SHADER_TEXRECT>; 764 765 using BoxFillPSO = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_OPAQUE, DEPTH_CMP_ALWAYS_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::triangle_strip, index_type::u16, 766 std::tuple< 767 vertex_buffer_description<4, vertex_attribute_description<position, gfx_api::vertex_attribute_type::u8x4_norm, 0>> 768 >, notexture, SHADER_RECT>; 769 using BoxFillAlphaPSO = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_ALPHA, DEPTH_CMP_ALWAYS_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_shadow_quad, cull_mode::back>, primitive_type::triangle_strip, index_type::u16, 770 std::tuple< 771 vertex_buffer_description<4, vertex_attribute_description<position, gfx_api::vertex_attribute_type::u8x4_norm, 0>> 772 >, notexture, SHADER_RECT>; 773 774 template<> 775 struct constant_buffer_type<SHADER_LINE> 776 { 777 glm::mat4 mat; 778 glm::vec2 p0; 779 glm::vec2 p1; 780 glm::vec4 colour; 781 }; 782 783 using LinePSO = typename gfx_api::pipeline_state_helper<rasterizer_state<REND_ALPHA, DEPTH_CMP_ALWAYS_WRT_OFF, 255, polygon_offset::disabled, stencil_mode::stencil_disabled, cull_mode::back>, primitive_type::lines, index_type::u16, 784 std::tuple< 785 vertex_buffer_description<4, vertex_attribute_description<position, gfx_api::vertex_attribute_type::u8x4_norm, 0>> 786 >, notexture, SHADER_LINE>; 787 } 788 789 static inline int to_int(gfx_api::context::swap_interval_mode mode) 790 { 791 return static_cast<int>(mode); 792 } 793 794 static inline gfx_api::context::swap_interval_mode to_swap_mode(int value) 795 { 796 switch (value) { 797 case static_cast<int>(gfx_api::context::swap_interval_mode::immediate): 798 return gfx_api::context::swap_interval_mode::immediate; 799 case static_cast<int>(gfx_api::context::swap_interval_mode::vsync): 800 return gfx_api::context::swap_interval_mode::vsync; 801 case static_cast<int>(gfx_api::context::swap_interval_mode::adaptive_vsync): 802 return gfx_api::context::swap_interval_mode::adaptive_vsync; 803 default: 804 debug(LOG_WARNING, "Invalid vsync value (%d); defaulting to vsync ON", value); 805 } 806 return gfx_api::context::swap_interval_mode::vsync; 807 } 808