From aa3ab6e9ba753d70302fd2bc782511e0f2aa461f Mon Sep 17 00:00:00 2001 From: xproger Date: Wed, 17 Jun 2020 04:44:07 +0300 Subject: [PATCH] add pipeline states and render passes logic --- src/cache.h | 141 +++++------ src/controller.h | 7 +- src/core.h | 392 +++++++++++++++++++++++------ src/game.h | 1 - src/gapi/gl.h | 124 ++++++++- src/gapi/vk.h | 445 ++++++++++++++++++++++++++++++++- src/inventory.h | 45 ++-- src/level.h | 174 ++++++------- src/objects.h | 9 +- src/platform/nix/main.cpp | 64 +++-- src/shaders/shadow_entity.hlsl | 2 + src/ui.h | 38 ++- 12 files changed, 1119 insertions(+), 323 deletions(-) diff --git a/src/cache.h b/src/cache.h index 6605252..8539bc8 100644 --- a/src/cache.h +++ b/src/cache.h @@ -16,8 +16,7 @@ struct ShaderCache { enum Effect { FX_NONE = 0, FX_UNDERWATER = 1, FX_ALPHA_TEST = 2 }; Shader *shaders[Core::passMAX][Shader::MAX][(FX_UNDERWATER | FX_ALPHA_TEST) + 1]; - PSO *pso[Core::passMAX][Shader::MAX][(FX_UNDERWATER | FX_ALPHA_TEST) + 1][bmMAX]; - + ShaderCache() { memset(shaders, 0, sizeof(shaders)); @@ -47,82 +46,69 @@ struct ShaderCache { delete shaders[pass][type][fx]; } - #define rsBase (RS_COLOR_WRITE | RS_DEPTH_TEST | RS_DEPTH_WRITE | RS_CULL_FRONT) - #define rsBlend (RS_BLEND_ALPHA | RS_BLEND_ADD) - #define rsFull (rsBase | rsBlend) - #define rsShadow (RS_DEPTH_TEST | RS_DEPTH_WRITE | RS_CULL_BACK) - void prepareCompose(int fx) { - compile(Core::passCompose, Shader::MIRROR, fx, rsBase); + compile(Core::passCompose, Shader::MIRROR, fx); - compile(Core::passCompose, Shader::ROOM, fx, rsFull); - compile(Core::passCompose, Shader::ROOM, fx, rsFull | RS_DISCARD); - compile(Core::passCompose, Shader::ROOM, fx | FX_UNDERWATER, rsFull); - compile(Core::passCompose, Shader::ROOM, fx | FX_UNDERWATER, rsFull | RS_DISCARD); + compile(Core::passCompose, Shader::ROOM, fx); + compile(Core::passCompose, Shader::ROOM, fx | FX_ALPHA_TEST); + compile(Core::passCompose, Shader::ROOM, fx | FX_UNDERWATER); + compile(Core::passCompose, Shader::ROOM, fx | FX_UNDERWATER | FX_ALPHA_TEST); - compile(Core::passCompose, Shader::ENTITY, fx, rsFull); - compile(Core::passCompose, Shader::ENTITY, fx, rsFull | RS_DISCARD); - compile(Core::passCompose, Shader::ENTITY, fx | FX_UNDERWATER, rsFull); - compile(Core::passCompose, Shader::ENTITY, fx | FX_UNDERWATER, rsFull | RS_DISCARD); + compile(Core::passCompose, Shader::ENTITY, fx); + compile(Core::passCompose, Shader::ENTITY, fx | FX_ALPHA_TEST); + compile(Core::passCompose, Shader::ENTITY, fx | FX_UNDERWATER); + compile(Core::passCompose, Shader::ENTITY, fx | FX_UNDERWATER | FX_ALPHA_TEST); - compile(Core::passCompose, Shader::SPRITE, fx, rsFull | RS_DISCARD); - compile(Core::passCompose, Shader::SPRITE, fx | FX_UNDERWATER, rsFull | RS_DISCARD); + compile(Core::passCompose, Shader::SPRITE, fx | FX_ALPHA_TEST); + compile(Core::passCompose, Shader::SPRITE, fx | FX_UNDERWATER | FX_ALPHA_TEST); - compile(Core::passCompose, Shader::FLASH, fx, rsFull | RS_BLEND_MULT); // spot shadow + compile(Core::passCompose, Shader::FLASH, fx); // spot shadow } void prepareAmbient(int fx) { - compile(Core::passAmbient, Shader::ROOM, fx, rsFull); - compile(Core::passAmbient, Shader::ROOM, fx, rsFull | RS_DISCARD); - compile(Core::passAmbient, Shader::SPRITE, fx, rsFull | RS_DISCARD); + compile(Core::passAmbient, Shader::ROOM, fx); + compile(Core::passAmbient, Shader::ROOM, fx | FX_ALPHA_TEST); + compile(Core::passAmbient, Shader::SPRITE, fx | FX_ALPHA_TEST); } void prepareShadows(int fx) { - compile(Core::passShadow, Shader::MIRROR, fx, rsShadow); - compile(Core::passShadow, Shader::ENTITY, fx, rsShadow); - compile(Core::passShadow, Shader::ENTITY, fx, rsShadow | RS_DISCARD); + compile(Core::passShadow, Shader::MIRROR, fx); + compile(Core::passShadow, Shader::ENTITY, fx); + compile(Core::passShadow, Shader::ENTITY, fx | FX_ALPHA_TEST); } void prepareSky(int fx) { - compile(Core::passSky, Shader::DEFAULT, fx, rsBase); + compile(Core::passSky, Shader::DEFAULT, fx); if (Core::support.tex3D) { - compile(Core::passSky, Shader::SKY_CLOUDS, fx, rsBase); - compile(Core::passSky, Shader::SKY_CLOUDS_AZURE, fx, rsBase); + compile(Core::passSky, Shader::SKY_CLOUDS, fx); + compile(Core::passSky, Shader::SKY_CLOUDS_AZURE, fx); } } void prepareWater(int fx) { - compile(Core::passWater, Shader::WATER_MASK, fx, RS_COLOR_WRITE_A | RS_DEPTH_TEST); - compile(Core::passWater, Shader::WATER_SIMULATE, fx, RS_COLOR_WRITE); - compile(Core::passWater, Shader::WATER_DROP, fx, RS_COLOR_WRITE); - compile(Core::passWater, Shader::WATER_RAYS, fx, RS_COLOR_WRITE | RS_DEPTH_TEST); + compile(Core::passWater, Shader::WATER_MASK, fx); + compile(Core::passWater, Shader::WATER_SIMULATE, fx); + compile(Core::passWater, Shader::WATER_DROP, fx); + compile(Core::passWater, Shader::WATER_RAYS, fx); if (Core::support.derivatives) { - compile(Core::passWater, Shader::WATER_CAUSTICS, fx, RS_COLOR_WRITE); + compile(Core::passWater, Shader::WATER_CAUSTICS, fx); } - compile(Core::passWater, Shader::WATER_COMPOSE, fx, RS_COLOR_WRITE | RS_DEPTH_TEST); + compile(Core::passWater, Shader::WATER_COMPOSE, fx); } void prepareFilter(int fx) { - compile(Core::passFilter, Shader::FILTER_UPSCALE, fx, RS_COLOR_WRITE); - compile(Core::passFilter, Shader::FILTER_DOWNSAMPLE, fx, RS_COLOR_WRITE); - compile(Core::passFilter, Shader::FILTER_GRAYSCALE, fx, RS_COLOR_WRITE); - compile(Core::passFilter, Shader::FILTER_BLUR, fx, RS_COLOR_WRITE); - compile(Core::passFilter, Shader::FILTER_ANAGLYPH, fx, RS_COLOR_WRITE); + compile(Core::passFilter, Shader::FILTER_UPSCALE, fx); + compile(Core::passFilter, Shader::FILTER_DOWNSAMPLE, fx); + compile(Core::passFilter, Shader::FILTER_GRAYSCALE, fx); + compile(Core::passFilter, Shader::FILTER_BLUR, fx); + compile(Core::passFilter, Shader::FILTER_ANAGLYPH, fx); } void prepareGUI(int fx) { - compile(Core::passGUI, Shader::DEFAULT, fx, RS_COLOR_WRITE | RS_BLEND_ALPHA); + compile(Core::passGUI, Shader::DEFAULT, fx); } - #undef rsBase - #undef rsBlend - #undef rsFull - #undef rsShadow - - Shader* compile(Core::Pass pass, Shader::Type type, int fx, uint32 rs) { - if (rs & RS_DISCARD) - fx |= FX_ALPHA_TEST; - + Shader* compile(Core::Pass pass, Shader::Type type, int fx) { #ifndef FFP if (shaders[pass][type][fx]) return shaders[pass][type][fx]; @@ -196,7 +182,7 @@ struct ShaderCache { shader->setup(); } - Core::setAlphaTest((fx & FX_ALPHA_TEST) != 0); + //Core::setAlphaTest((fx & FX_ALPHA_TEST) != 0); } }; @@ -259,7 +245,7 @@ struct AmbientCache { } void renderAmbient(int room, int sector, vec4 *colors) { - PROFILE_MARKER("PASS_AMBIENT"); + PROFILE_MARKER("ambient"); TR::Room &r = level->rooms[room]; TR::Room::Sector &s = r.sectors[sector]; @@ -274,8 +260,6 @@ struct AmbientCache { game->renderEnvironment(room, pos, textures, 4); // second pass - downsample it - Core::setDepthTest(false); - mat4 mProj, mView; mView.identity(); mProj = GAPI::ortho(-1, +1, -1, +1, 0, 1); @@ -291,20 +275,22 @@ struct AmbientCache { for (int j = 0; j < 6; j++) { Texture *src = textures[j * 4 + i - 1]; Texture *dst = textures[j * 4 + i]; - Core::setTarget(dst, NULL, RT_STORE_COLOR); - Core::validateRenderState(); + + Core::beginRenderPass(RP_FILTER, RenderTarget(dst, 0, 0), RenderTarget(NULL, 0, 0)); + Core::setPipelineState(PS_FILTER_DOWNSAMPLE); + src->bind(sDiffuse); game->getMesh()->renderQuad(); + + Core::endRenderPass(); } } // get result color from 1x1 textures for (int j = 0; j < 6; j++) { - Core::setTarget(textures[j * 4 + 3], NULL, RT_LOAD_COLOR); - colors[j] = Core::copyPixel(0, 0); + colors[j] = Core::copyPixel(textures[j * 4 + 3], 0, 0); } - Core::setDepthTest(true); Core::setClearColor(vec4(0, 0, 0, 0)); } @@ -671,7 +657,7 @@ struct WaterCache { vec4 rPosScale[2] = { vec4(0.0f), vec4(1.0f) }; Core::active.shader->setParam(uPosScale, rPosScale[0], 2); Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, s.x / item.data[0]->width, s.y / item.data[0]->height)); - + #if 0 for (int i = 0; i < dropCount; i++) { Drop &drop = drops[i]; @@ -689,6 +675,7 @@ struct WaterCache { item.data[0]->unbind(sNormal); swap(item.data[0], item.data[1]); } + #endif } void step(Item &item) { @@ -700,7 +687,7 @@ struct WaterCache { Core::active.shader->setParam(uParam, vec4(0.995f, 1.0f, randf() * 0.5f, Core::params.x)); Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, s.x / item.data[0]->width, s.y / item.data[0]->height)); Core::active.shader->setParam(uRoomSize, vec4(1.0f / item.mask->origWidth, 1.0f / item.mask->origHeight, float(item.mask->origWidth) / item.mask->width, float(item.mask->origHeight) / item.mask->height)); - +#if 0 while (item.timer >= SIMULATE_TIMESTEP) { // water step Core::setTarget(item.data[1], NULL, RT_STORE_COLOR); @@ -734,6 +721,7 @@ struct WaterCache { item.data[0]->bind(sNormal); game->getMesh()->renderPlane(); item.data[0]->unbind(sNormal); + #endif } void renderRays() { @@ -761,7 +749,7 @@ struct WaterCache { Core::active.shader->setParam(uPosScale, rPosScale[0], 2); Core::active.shader->setParam(uParam, vec4(level->rooms[item.to].getOffset(), 0.35f)); - +#if 0 Core::setBlendMode(bmAdd); Core::setCullMode(cmBack); Core::setDepthWrite(false); @@ -769,6 +757,7 @@ struct WaterCache { Core::setDepthWrite(true); Core::setCullMode(cmFront); Core::setBlendMode(bmNone); + #endif } } @@ -778,12 +767,12 @@ struct WaterCache { // mask underwater geometry by zero alpha game->setShader(Core::passWater, Shader::WATER_MASK); Core::active.shader->setParam(uTexParam, vec4(1.0f)); - +#if 0 Core::setColorWrite(false, false, false, true); Core::setDepthWrite(false); Core::setCullMode(cmNone); Core::setBlendMode(bmNone); - +#endif for (int i = 0; i < count; i++) { Item &item = items[i]; if (!item.visible) continue; @@ -793,10 +782,11 @@ struct WaterCache { game->getMesh()->renderQuad(); } - +#if 0 Core::setColorWrite(true, true, true, true); Core::setDepthWrite(true); Core::setCullMode(cmFront); +#endif } @@ -805,7 +795,6 @@ struct WaterCache { int h = Core::viewportDef.w; // get refraction texture if (!refract || w != refract->origWidth || h != refract->origHeight) { - PROFILE_MARKER("WATER_REFRACT_INIT"); delete refract; refract = new Texture(w, h, 1, FMT_RGBA, OPT_TARGET); #ifdef USE_SCREEN_TEX @@ -817,7 +806,7 @@ struct WaterCache { } void copyScreenToRefraction() { - PROFILE_MARKER("WATER_REFRACT_COPY"); + PROFILE_MARKER("water_copy_refraction"); // get refraction texture int x, y; if (!screen) { @@ -826,7 +815,7 @@ struct WaterCache { } else { x = y = 0; } - +#if 0 if (screen) { Core::setTarget(refract, NULL, RT_LOAD_DEPTH | RT_STORE_COLOR | RT_STORE_DEPTH); Core::validateRenderState(); @@ -840,11 +829,13 @@ struct WaterCache { } else { Core::copyTarget(refract, 0, 0, x, y, Core::viewportDef.z, Core::viewportDef.w); // copy framebuffer into refraction texture } +#endif } void simulate() { - PROFILE_MARKER("WATER_SIMULATE"); + PROFILE_MARKER("water_simulate"); // simulate water + #if 0 Core::setDepthTest(false); Core::setBlendMode(bmNone); for (int i = 0; i < count; i++) { @@ -861,18 +852,19 @@ struct WaterCache { } } Core::setDepthTest(true); + #endif } void renderReflection() { if (!visible) return; - PROFILE_MARKER("WATER_REFLECT"); + PROFILE_MARKER("water_reflection"); for (int i = 0; i < count; i++) { Item &item = items[i]; if (item.visible && item.blank) item.init(game); } - +#if 0 // render mirror reflection Core::setTarget(reflect, NULL, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR); Camera *camera = (Camera*)game->getCamera(); @@ -928,11 +920,12 @@ struct WaterCache { camera->reflectPlane = NULL; camera->setup(true); +#endif } void compose() { if (!visible) return; - PROFILE_MARKER("WATER_COMPOSE"); + PROFILE_MARKER("water_compose"); for (int i = 0; i < count; i++) { Item &item = items[i]; if (!item.visible) continue; @@ -953,6 +946,7 @@ struct WaterCache { reflect->bind(sReflect); item.mask->bind(sMask); item.data[0]->bind(sNormal); +#if 0 Core::setCullMode(cmNone); Core::setBlendMode(bmAlpha); #ifdef WATER_USE_GRID @@ -966,6 +960,7 @@ struct WaterCache { #endif Core::setCullMode(cmFront); Core::setBlendMode(bmNone); +#endif } dropCount = 0; } @@ -1010,14 +1005,14 @@ struct WaterCache { vertices[2].texCoord = short4(32767, 0, 0, 0); vertices[3].texCoord = short4( 0, 0, 0, 0); } - +#if 0 Core::setDepthTest(false); Core::setBlendMode(bmNone); game->getMesh()->renderBuffer(indices, COUNT(indices), vertices, COUNT(vertices)); Core::setDepthTest(true); - +#endif tex->unbind(sDiffuse); } diff --git a/src/controller.h b/src/controller.h index 7b134de..fda7df2 100644 --- a/src/controller.h +++ b/src/controller.h @@ -78,7 +78,7 @@ struct IGame { virtual void setupBinding() {} virtual void getVisibleRooms(RoomDesc *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) {} virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0, Core::Pass pass = Core::passAmbient) {} - virtual void renderModelFull(int modelIndex, bool underwater, Basis *joints) {} + virtual void renderModelFull(int modelIndex, Basis *joints) {} virtual void renderCompose(int roomIndex) {} virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, RoomDesc *roomsList = NULL) {} virtual void renderGame(bool showUI, bool invBG) {} @@ -1385,9 +1385,6 @@ struct Controller { } void renderShadow(MeshBuilder *mesh) { - if (Core::pass != Core::passCompose || level->isCutsceneLevel()) - return; - Box boxL = getBoundingBoxLocal(); Box boxA = boxL * getMatrix(); @@ -1422,9 +1419,7 @@ struct Controller { float lum = 1.0f - alpha; Core::setMaterial(lum, lum, lum, alpha); - Core::setDepthWrite(false); mesh->renderShadowBlob(); - Core::setDepthWrite(true); } void updateJoints() { diff --git a/src/core.h b/src/core.h index d15f153..2589b54 100644 --- a/src/core.h +++ b/src/core.h @@ -78,6 +78,7 @@ #elif __linux__ #define _OS_LINUX 1 #define _GAPI_GL 1 + //#define _GAPI_VULKAN 1 #elif __APPLE__ #define _GAPI_GL 1 #include "TargetConditionals.h" @@ -217,16 +218,6 @@ struct KeySet { KeySet(InputKey key, JoyKey joy) : key(key), joy(joy) {} }; -enum RenderTargetOp { - RT_CLEAR_COLOR = 0x0001, - RT_LOAD_COLOR = 0x0002, - RT_STORE_COLOR = 0x0004, - - RT_CLEAR_DEPTH = 0x0008, - RT_LOAD_DEPTH = 0x0010, - RT_STORE_DEPTH = 0x0020, -}; - namespace Core { struct Mutex { @@ -425,28 +416,6 @@ namespace GAPI { struct Texture; } -enum RenderState { - RS_TARGET = 1 << 0, - RS_VIEWPORT = 1 << 1, - RS_SCISSOR = 1 << 2, - RS_DEPTH_TEST = 1 << 3, - RS_DEPTH_WRITE = 1 << 4, - RS_COLOR_WRITE_R = 1 << 5, - RS_COLOR_WRITE_G = 1 << 6, - RS_COLOR_WRITE_B = 1 << 7, - RS_COLOR_WRITE_A = 1 << 8, - RS_COLOR_WRITE = RS_COLOR_WRITE_R | RS_COLOR_WRITE_G | RS_COLOR_WRITE_B | RS_COLOR_WRITE_A, - RS_CULL_BACK = 1 << 9, - RS_CULL_FRONT = 1 << 10, - RS_CULL = RS_CULL_BACK | RS_CULL_FRONT, - RS_BLEND_ALPHA = 1 << 11, - RS_BLEND_ADD = 1 << 12, - RS_BLEND_MULT = 1 << 13, - RS_BLEND_PREMULT = 1 << 14, - RS_BLEND = RS_BLEND_ALPHA | RS_BLEND_ADD | RS_BLEND_MULT | RS_BLEND_PREMULT, - RS_DISCARD = 1 << 15, -}; - // Texture image format enum TexFormat { FMT_LUMINANCE, @@ -460,7 +429,7 @@ enum TexFormat { FMT_MAX, }; -// Texture options +// Texture options // TODO rename to TO_ enum TexOption { OPT_REPEAT = 0x0001, OPT_CUBEMAP = 0x0002, @@ -475,22 +444,13 @@ enum TexOption { OPT_VRAM_3DS = 0x0400, }; -// Pipeline State Object -struct PSO { - void *data; - void *shader; - vec4 clearColor; - TexFormat colorFormat; - TexFormat depthFormat; - uint32 renderState; -}; - #if !defined(FFP) && (defined(_OS_WIN) || defined(_OS_LINUX) || defined(_OS_MAC) || defined(_OS_WEB)) typedef uint32 Index; #else typedef uint16 Index; #endif +// TODO move to mesh.h struct Edge { Index a, b; @@ -606,6 +566,89 @@ const char *UniformName[uMAX] = { SHADER_UNIFORMS(DECL_STR) }; enum CullMode { cmNone, cmBack, cmFront, cmMAX }; enum BlendMode { bmNone, bmAlpha, bmAdd, bmMult, bmPremult, bmMAX }; +enum RenderPassType { + RP_MAIN, + RP_SHADOW, + RP_FILTER, + RP_WATER_PROCESS, + RP_WATER_CAUSTICS, + RP_MAX +}; + +enum PipelineStateType { +// RP_SHADOW + PS_ENTITY_SHADOW, + PS_ENTITY_SHADOW_ALPHA, +// RP_MAIN + PS_GUI, + PS_ROOM, + PS_ROOM_ALPHA, + PS_ROOM_ADD, + PS_ROOM_UNDERWATER, + PS_ROOM_UNDERWATER_ALPHA, + PS_ROOM_UNDERWATER_ADD, + PS_AMBIENT, + PS_AMBIENT_ALPHA, + PS_AMBIENT_ADD, + PS_AMBIENT_UNDERWATER, + PS_AMBIENT_UNDERWATER_ALPHA, + PS_AMBIENT_UNDERWATER_ADD, + PS_ENTITY, + PS_ENTITY_ALPHA, + PS_ENTITY_ADD, + PS_ENTITY_UNDERWATER, + PS_ENTITY_UNDERWATER_ALPHA, + PS_ENTITY_UNDERWATER_ADD, + PS_ENTITY_MIRROR, + PS_FLASH, + PS_BLOB, + PS_SPRITE, + PS_SPRITE_UNDERWATER, + PS_SKY, + PS_SKY_CLOUDS, + PS_SKY_CLOUDS_AZURE, + PS_WATER_COMPOSE, + PS_WATER_MASK, + PS_WATER_RAYS, +// RP_WATER_PROCESS + PS_WATER_DROP, + PS_WATER_CALC, +// RP_WATER_CAUSTICS + PS_WATER_CAUSTICS, +// RP_FILTER + PS_FILTER_UPSCALE, + PS_FILTER_DOWNSAMPLE, + PS_FILTER_GRAYSCALE, + PS_FILTER_BLUR, + PS_FILTER_ANAGLYPH, + + PS_MAX, +}; + +enum RenderPassOpt { + RO_COLOR_CLEAR = (1 << 0), + RO_COLOR_LOAD = (1 << 1), + RO_COLOR_STORE = (1 << 2), + RO_DEPTH_CLEAR = (1 << 3), + RO_DEPTH_LOAD = (1 << 4), + RO_DEPTH_STORE = (1 << 5), +}; + +enum PipelineStateOpt { + PO_DEPTH_TEST = (1 << 0), + PO_DEPTH_WRITE = (1 << 1), + PO_COLOR_WRITE_R = (1 << 2), + PO_COLOR_WRITE_G = (1 << 3), + PO_COLOR_WRITE_B = (1 << 4), + PO_COLOR_WRITE_A = (1 << 5), + PO_COLOR_WRITE = PO_COLOR_WRITE_R | PO_COLOR_WRITE_G | PO_COLOR_WRITE_B | PO_COLOR_WRITE_A, + PO_CULL_BACK = (1 << 6), + PO_CULL_FRONT = (1 << 7), + PO_BLEND_ALPHA = (1 << 8), + PO_BLEND_ADD = (1 << 9), + PO_BLEND_MULT = (1 << 10), +}; + namespace Core { float eye; Texture *eyeTex[2]; @@ -635,7 +678,9 @@ namespace Core { int32 renderState; struct Active { - const PSO *pso; + RenderPassType rp; + PipelineStateType ps; + GAPI::Shader *shader; GAPI::Texture *textures[8]; GAPI::Texture *target; @@ -725,8 +770,26 @@ namespace Core { #include "shader.h" #include "video.h" +struct RenderTarget { + Texture *target; + int face; + int mip; + + RenderTarget(Texture *target, int face = 0, int mip = 0) : target(target), face(face), mip(mip) {} +}; + namespace Core { + GAPI::RenderPass* renderPasses[RP_MAX]; + GAPI::PipelineState* pipelineStates[PS_MAX]; + + #define MAX_CACHED_TARGETS 32 + + struct CachedTarget { + Texture *tex; + bool acquired; + } cachedTargets[MAX_CACHED_TARGETS]; + static const char *version = __DATE__; static int defLang = 0; @@ -744,26 +807,132 @@ namespace Core { delete stream; perlinTex = new Texture(PERLIN_TEX_SIZE, PERLIN_TEX_SIZE, PERLIN_TEX_SIZE, FMT_LUMINANCE, OPT_REPEAT | OPT_VOLUME, perlinData); - /*/ - uint8 *pdata = new uint8[SQR(PERLIN_TEX_SIZE) * 4]; - int offset = 0; - for (int k = 0; k < PERLIN_TEX_SIZE; k++) { - int j = 0; - for (int i = 0; i < SQR(PERLIN_TEX_SIZE); i++) { - pdata[j + 0] = pdata[j + 1] = pdata[j + 2] = perlinData[offset + i]; - pdata[j + 3] = 255; - j += 4; - } - char buf[256]; - sprintf(buf, "noise/perlin_%03d", k); - Texture::SaveBMP(buf, (char*)pdata, PERLIN_TEX_SIZE, PERLIN_TEX_SIZE); - offset += PERLIN_TEX_SIZE * PERLIN_TEX_SIZE; - } - delete[] pdata; - */ + delete[] perlinData; } + void initRenderPasses() { + memset(renderPasses, 0, sizeof(renderPasses)); + + renderPasses[RP_MAIN] = new GAPI::RenderPass(FMT_RGBA, FMT_DEPTH, RO_COLOR_CLEAR | RO_COLOR_STORE | RO_DEPTH_CLEAR); + renderPasses[RP_SHADOW] = new GAPI::RenderPass(FMT_MAX, FMT_SHADOW, RO_DEPTH_CLEAR | RO_DEPTH_STORE); + renderPasses[RP_FILTER] = new GAPI::RenderPass(FMT_RGBA, FMT_MAX, RO_COLOR_STORE); + renderPasses[RP_WATER_PROCESS] = new GAPI::RenderPass(FMT_RG_HALF, FMT_MAX, RO_COLOR_STORE); + renderPasses[RP_WATER_CAUSTICS] = new GAPI::RenderPass(FMT_RGBA, FMT_MAX, RO_COLOR_CLEAR | RO_COLOR_STORE); + } + + void initPipelineStates() { + memset(pipelineStates, 0, sizeof(pipelineStates)); + + Shader *gui; + Shader *shadow, *shadow_a; + Shader *room, *room_a, *room_u, *room_ua; + Shader *ambient, *ambient_a, *ambient_u, *ambient_ua; + Shader *entity, *entity_a, *entity_u, *entity_ua, *entity_mirror; + Shader *flash, *blob; + Shader *sprite, *sprite_u; + Shader *sky, *sky_clouds, *sky_clouds_azure; + Shader *water_compose, *water_mask, *water_rays, *water_drop, *water_calc, *water_caustics; + Shader *filter_upscale, *filter_downsample, *filter_grayscale, *filter_blur, *filter_anaglyph; + + pipelineStates[PS_WATER_RAYS] = new GAPI::PipelineState(renderPasses[RP_MAIN], gui, + PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA); + + pipelineStates[PS_ENTITY_SHADOW] = new GAPI::PipelineState(renderPasses[RP_SHADOW], shadow, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_CULL_BACK); + pipelineStates[PS_ENTITY_SHADOW_ALPHA] = new GAPI::PipelineState(renderPasses[RP_SHADOW], shadow_a, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_CULL_BACK); + + pipelineStates[PS_ROOM] = new GAPI::PipelineState(renderPasses[RP_MAIN], room, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_ROOM_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], room_a, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA); + pipelineStates[PS_ROOM_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], room, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD); + + pipelineStates[PS_ROOM_UNDERWATER] = new GAPI::PipelineState(renderPasses[RP_MAIN], room_u, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_ROOM_UNDERWATER_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], room_ua, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA); + pipelineStates[PS_ROOM_UNDERWATER_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], room_u, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD); + + pipelineStates[PS_AMBIENT] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_AMBIENT_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient_a, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA); + pipelineStates[PS_AMBIENT_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD); + + pipelineStates[PS_AMBIENT_UNDERWATER] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient_u, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_AMBIENT_UNDERWATER_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient_ua, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA); + pipelineStates[PS_AMBIENT_UNDERWATER_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient_u, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD); + + pipelineStates[PS_ENTITY] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_ENTITY_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity_a, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA); + pipelineStates[PS_ENTITY_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD); + + pipelineStates[PS_ENTITY_UNDERWATER] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity_u, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_ENTITY_UNDERWATER_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity_ua, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA); + pipelineStates[PS_ENTITY_UNDERWATER_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity_u, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD); + + pipelineStates[PS_ENTITY_MIRROR] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity_mirror, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK); + + pipelineStates[PS_FLASH] = new GAPI::PipelineState(renderPasses[RP_MAIN], flash, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD); + + pipelineStates[PS_BLOB] = new GAPI::PipelineState(renderPasses[RP_MAIN], blob, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_MULT); + + pipelineStates[PS_SPRITE] = new GAPI::PipelineState(renderPasses[RP_MAIN], sprite, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA); + pipelineStates[PS_SPRITE_UNDERWATER] = new GAPI::PipelineState(renderPasses[RP_MAIN], sprite_u, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA); + + pipelineStates[PS_SKY] = new GAPI::PipelineState(renderPasses[RP_MAIN], sky, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_SKY_CLOUDS] = new GAPI::PipelineState(renderPasses[RP_MAIN], sky_clouds, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_SKY_CLOUDS_AZURE] = new GAPI::PipelineState(renderPasses[RP_MAIN], sky_clouds_azure, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK); + + pipelineStates[PS_WATER_COMPOSE] = new GAPI::PipelineState(renderPasses[RP_MAIN], water_compose, + PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE); + pipelineStates[PS_WATER_MASK] = new GAPI::PipelineState(renderPasses[RP_MAIN], water_mask, + PO_DEPTH_TEST | PO_COLOR_WRITE_A); + pipelineStates[PS_WATER_RAYS] = new GAPI::PipelineState(renderPasses[RP_MAIN], water_mask, + PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_FRONT | PO_BLEND_ADD); + + pipelineStates[PS_WATER_DROP] = new GAPI::PipelineState(renderPasses[RP_WATER_PROCESS], water_drop, + PO_COLOR_WRITE_R | PO_COLOR_WRITE_G | PO_CULL_BACK); + pipelineStates[PS_WATER_CALC] = new GAPI::PipelineState(renderPasses[RP_WATER_PROCESS], water_calc, + PO_COLOR_WRITE_R | PO_COLOR_WRITE_G | PO_CULL_BACK); + + pipelineStates[PS_WATER_CAUSTICS] = new GAPI::PipelineState(renderPasses[RP_WATER_CAUSTICS], water_caustics, + PO_COLOR_WRITE | PO_BLEND_ADD); + + pipelineStates[PS_FILTER_UPSCALE] = new GAPI::PipelineState(renderPasses[RP_FILTER], filter_upscale, + PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA); + pipelineStates[PS_FILTER_DOWNSAMPLE] = new GAPI::PipelineState(renderPasses[RP_FILTER], filter_downsample, + PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_FILTER_GRAYSCALE] = new GAPI::PipelineState(renderPasses[RP_FILTER], filter_grayscale, + PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_FILTER_BLUR] = new GAPI::PipelineState(renderPasses[RP_FILTER], filter_blur, + PO_COLOR_WRITE | PO_CULL_BACK); + pipelineStates[PS_FILTER_ANAGLYPH] = new GAPI::PipelineState(renderPasses[RP_FILTER], filter_anaglyph, + PO_COLOR_WRITE | PO_CULL_BACK); + } + void init() { LOG("OpenLara (%s)\n", version); @@ -788,6 +957,9 @@ namespace Core { GAPI::init(); + initRenderPasses(); + initPipelineStates(); + #ifdef _OS_3DS Core::eyeTex[0] = new Texture(Core::width, Core::height, 1, TexFormat::FMT_RGB16, OPT_TARGET | OPT_PROXY); Core::eyeTex[1] = new Texture(Core::width, Core::height, 1, TexFormat::FMT_RGB16, OPT_TARGET | OPT_PROXY); @@ -999,6 +1171,38 @@ namespace Core { Sound::deinit(); } + Texture* acquireTarget(int width, int height, TexFormat fmt) { + for (int i = 0; i < MAX_CACHED_TARGETS; i++) { + CachedTarget &ct = cachedTargets[i]; + + if (ct.tex == NULL) { + ct.acquired = true; + ct.tex = new Texture(width, height, 1, fmt, OPT_TARGET | OPT_NEAREST); + break; + } + + if (!ct.acquired && ct.tex->origWidth == width && ct.tex->origHeight == height && ct.tex->fmt == fmt) { + ct.acquired = true; + return ct.tex; + } + } + + ASSERT(false); + return NULL; + } + + void releaseTarget(Texture *target) { + for (int i = 0; i < MAX_CACHED_TARGETS; i++) { + CachedTarget &ct = cachedTargets[i]; + if (ct.tex == target) { + ASSERT(ct.acquired); + ct.acquired = false; + return; + } + } + ASSERT(false); + } + void setVSync(bool enable) { GAPI::setVSync((Core::settings.detail.vsync = enable)); } @@ -1018,6 +1222,27 @@ namespace Core { return true; } + void beginRenderPass(RenderPassType rp, const RenderTarget &color, const RenderTarget &depth) { + active.rp = rp; + + ASSERT(renderPasses[active.rp]); + renderPasses[active.rp]->begin(color.target, color.face, color.mip, depth.target); + } + + void endRenderPass() { + ASSERT(active.rp < RP_MAX); + ASSERT(renderPasses[active.rp]); + renderPasses[active.rp]->end(); + active.rp = RP_MAX; + } + + void setPipelineState(PipelineStateType ps) { + active.ps = ps; + + ASSERT(pipelineStates[ps]); + pipelineStates[ps]->bind(); + } +/* void validateRenderState() { int32 mask = renderState ^ active.renderState; if (!mask) return; @@ -1086,14 +1311,14 @@ namespace Core { active.renderState = renderState; } - +*/ void setClearColor(const vec4 &color) { GAPI::setClearColor(color); } void setViewport(const short4 &v) { viewport = v; - renderState |= RS_VIEWPORT; + GAPI::setViewport(v); } void setViewport(int x, int y, int width, int height) { @@ -1102,9 +1327,9 @@ namespace Core { void setScissor(const short4 &s) { scissor = s; - renderState |= RS_SCISSOR; + GAPI::setScissor(s); } - +/* void setCullMode(CullMode mode) { renderState &= ~RS_CULL; switch (mode) { @@ -1172,7 +1397,7 @@ namespace Core { reqTarget.face = face; renderState |= RS_TARGET; } - +*/ void setBasis(Basis *basis, int count) { Core::active.basis = basis; Core::active.basisCount = count; @@ -1218,43 +1443,48 @@ namespace Core { } void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) { - validateRenderState(); + //validateRenderState(); GAPI::copyTarget(dst, xOffset, yOffset, x, y, width, height); } - vec4 copyPixel(int x, int y) { // GPU sync! - validateRenderState(); - return GAPI::copyPixel(x, y); + vec4 copyPixel(Texture *texture, int x, int y) { // GPU sync! + //validateRenderState(); + return GAPI::copyPixel(texture, x, y); } void reset() { + } + + bool beginFrame() { + Core::stats.start(); + if (!GAPI::beginFrame()) { + return false; + } + GAPI::resetState(); memset(&active, 0, sizeof(active)); renderState = 0; + active.rp = RP_MAX; + active.ps = PS_MAX; + setViewport(Core::x, Core::y, Core::width, Core::height); viewportDef = viewport; scissor = viewport; - + /* setCullMode(cmFront); setBlendMode(bmAlpha); setDepthTest(true); setDepthWrite(true); setColorWrite(true, true, true, true); validateRenderState(); - } - - bool beginFrame() { - Core::stats.start(); - return GAPI::beginFrame(); + */ + return true; } void endFrame() { - if (active.target != defaultTarget) { - GAPI::setTarget(NULL, NULL, 0); - validateRenderState(); - } + ASSERT(active.rp == RP_MAX); GAPI::endFrame(); Core::stats.stop(); } @@ -1268,7 +1498,7 @@ namespace Core { } void DIP(GAPI::Mesh *mesh, const MeshRange &range) { - validateRenderState(); + //validateRenderState(); mesh->bind(range); GAPI::DIP(mesh, range); diff --git a/src/game.h b/src/game.h index f909888..90cfc38 100644 --- a/src/game.h +++ b/src/game.h @@ -309,7 +309,6 @@ namespace Game { bool frameBegin() { if (Core::settings.version == SETTINGS_READING) return false; - Core::reset(); if (Core::beginFrame()) { level->renderPrepare(); return true; diff --git a/src/gapi/gl.h b/src/gapi/gl.h index 360d316..3d7a899 100644 --- a/src/gapi/gl.h +++ b/src/gapi/gl.h @@ -493,6 +493,21 @@ namespace GAPI { char GLSL_HEADER_VERT[512]; char GLSL_HEADER_FRAG[512]; + GLuint FBO, defaultFBO; + struct RenderTargetCacheItem { + GLuint ID; + int width; + int height; + }; + Array rtCache[2]; + + uint32 m_alphaTest; + uint32 m_depthTest; + uint32 m_depthWrite; + uint32 m_colorMask; + uint32 m_cullMode; + uint32 m_blendMode; + // Shader #ifndef FFP const char SHADER_COMPOSE[] = @@ -550,7 +565,16 @@ namespace GAPI { #ifdef FFP void init(Core::Pass pass, int type, int *def, int defCount) {} void deinit() {} - void bind() {} + void bind() { + if (alphaTest != m_alphaTest) { + if (opt & PO_ALPHA_TEST) { + glEnable(GL_ALPHA_TEST); + } else { + glDisable(GL_ALPHA_TEST); + } + m_alphaTest = alphaTest; + } + } void validate() {} void setParam(UniformType uType, const vec4 &value, int count = 1) {} void setParam(UniformType uType, const mat4 &value, int count = 1) {} @@ -1131,13 +1155,92 @@ namespace GAPI { }; - GLuint FBO, defaultFBO; - struct RenderTargetCacheItem { - GLuint ID; - int width; - int height; +// RenderPass + struct RenderPass { + TexFormat colorFmt; + TexFormat depthFmt; + uint32 opt; + + RenderPass(TexFormat colorFmt, TexFormat depthFmt, uint32 opt) : colorFmt(colorFmt), depthFmt(depthFmt), opt(opt) {} + + void begin(Texture *color, int face, int mip, Texture *depth) { + //setRenderTarget + } + + void end() {} + }; + + +// PipelineState + struct PipelineState { + RenderPass *renderPass; + Shader *shader; + uint32 opt; + + PipelineState(RenderPass *renderPass, Shader *shader, uint32 opt) : renderPass(renderPass), shader(shader), opt(opt) {} + + void bind() { + shader->bind(); + + uint32 depthTest = opt & PO_DEPTH_TEST; + if (depthTest != m_depthTest) { + if (depthTest) { + glEnable(GL_DEPTH_TEST); + } else { + glDisable(GL_DEPTH_TEST); + } + m_depthTest = depthTest; + } + + uint32 depthWrite = opt & PO_DEPTH_WRITE; + if (depthWrite != m_depthWrite) { + glDepthMask(depthWrite != 0); + m_depthWrite = depthWrite; + } + + uint32 colorMask = opt & (PO_COLOR_WRITE_R | PO_COLOR_WRITE_G | PO_COLOR_WRITE_B | PO_COLOR_WRITE_A); + if (colorMask != m_colorMask) { + glColorMask((opt & PO_COLOR_WRITE_R), + (opt & PO_COLOR_WRITE_G), + (opt & PO_COLOR_WRITE_B), + (opt & PO_COLOR_WRITE_A)); + m_colorMask = colorMask; + } + + uint32 cullMode = opt & (PO_CULL_BACK | PO_CULL_FRONT); + if (cullMode != m_cullMode) { + if (opt & PO_CULL_BACK) { + glCullFace(GL_BACK); + } else if (opt & PO_CULL_FRONT) { + glCullFace(GL_FRONT); + } else { + glDisable(GL_CULL_FACE); + } + if (!m_cullMode) { + glEnable(GL_CULL_FACE); + } + m_cullMode = cullMode; + } + + uint32 blendMode = opt & (PO_BLEND_ALPHA | PO_BLEND_ADD | PO_BLEND_MULT); + if (blendMode != m_blendMode) { + if (opt & PO_BLEND_ALPHA) { + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else if (opt & PO_BLEND_ADD) { + glBlendFunc(GL_ONE, GL_ONE); + } else if (opt & PO_BLEND_MULT) { + glBlendFunc(GL_DST_COLOR, GL_ZERO); + } else { + glDisable(GL_BLEND); + } + + if (!m_blendMode) { + glEnable(GL_BLEND); + } + m_blendMode = blendMode; + } + } }; - Array rtCache[2]; bool extSupport(const char *str, const char *ext) { if (!str) return false; @@ -1594,7 +1697,7 @@ namespace GAPI { void setScissor(const short4 &s) { glScissor(s.x, s.y, s.z, s.w); } - +/* void setDepthTest(bool enable) { if (enable) glEnable(GL_DEPTH_TEST); @@ -1641,7 +1744,7 @@ namespace GAPI { } glEnable(GL_BLEND); } - +*/ void setViewProj(const mat4 &mView, const mat4 &mProj) { #ifdef FFP glMatrixMode(GL_PROJECTION); @@ -1710,7 +1813,8 @@ namespace GAPI { glDrawElements(GL_TRIANGLES, range.iCount, sizeof(Index) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, mesh->iBuffer + range.iStart); } - vec4 copyPixel(int x, int y) { + vec4 copyPixel(Texture *texture, int x, int y) { + // TODO setTarget ubyte4 c; glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &c); return vec4(float(c.x), float(c.y), float(c.z), float(c.w)) * (1.0f / 255.0f); diff --git a/src/gapi/vk.h b/src/gapi/vk.h index 369439e..af2b68e 100644 --- a/src/gapi/vk.h +++ b/src/gapi/vk.h @@ -1,6 +1,449 @@ #ifndef H_GAPI_VK #define H_GAPI_VK -// TODO +#include "core.h" +#include + +#if defined(_DEBUG) || defined(PROFILE) + struct Marker { + Marker(const char *title) { + // + } + + ~Marker() { + // + } + + static void setLabel(void *object, const char *label) { + // TODO: use Windows 10 SDK + } + }; + + #define PROFILE_MARKER(title) Marker marker##__LINE__(title) + #define PROFILE_LABEL(id, child, label) Marker::setLabel(child, label) + #define PROFILE_TIMING(time) +#else + #define PROFILE_MARKER(title) + #define PROFILE_LABEL(id, child, label) + #define PROFILE_TIMING(time) +#endif + +#define VK_INIT(s) memset(&s, 0, sizeof(s)) +#define VK_INIT_STRUCT(s,t) VK_INIT(s); s.sType = t +#define VK_CHECK(x) { VkResult r = (x); if (r != VK_SUCCESS) { LOG("! %s = %d\n", #x, (int)r); ASSERT(r != VK_SUCCESS); } } + +namespace GAPI { + using namespace Core; + + typedef ::Vertex Vertex; + + enum { + smpDefault, + smpPoint, + smpPointWrap, + smpLinear, + smpLinearWrap, + smpCmp, + smpMAX + }; + + VkDevice device; + VkInstance instance; + + CullMode cullMode; + BlendMode blendMode; + vec4 clearColor; + VkSampler samplers[smpMAX]; + +// Shader + //#include "shaders/vulkan/shaders.h" + + static const int bindings[uMAX] = { + 0, // uParam + 1, // uTexParam + 2, // uViewProj + 6, // uBasis + 70, // uLightProj + 74, // uMaterial + 75, // uAmbient + 81, // uFogParams + 82, // uViewPos + 83, // uLightPos + 87, // uLightColor + 91, // uRoomSize + 92, // uPosScale + 98, // uContacts + }; + + struct Shader { + VkShaderModule VS; + VkShaderModule PS; + + Shader() : VS(VK_NULL_HANDLE), PS(VK_NULL_HANDLE) {} + + void init(Core::Pass pass, int type, int *def, int defCount) { + // + } + + void deinit() { + vkDestroyShaderModule(device, VS, NULL); + vkDestroyShaderModule(device, PS, NULL); + } + + void bind() { + // + } + + void setParam(UniformType uType, float *value, int count) { + // + } + + void setParam(UniformType uType, const vec4 &value, int count = 1) { + setParam(uType, (float*)&value, count); + } + + void setParam(UniformType uType, const mat4 &value, int count = 1) { + setParam(uType, (float*)&value, count * 4); + } + }; + +// Texture + struct Texture { + VkImage image; + VkImageView imageView; + + int width, height, depth, origWidth, origHeight, origDepth; + TexFormat fmt; + uint32 opt; + + Texture(int width, int height, int depth, uint32 opt) : image(VK_NULL_HANDLE), imageView(VK_NULL_HANDLE), width(width), height(height), depth(depth), origWidth(width), origHeight(height), origDepth(depth), fmt(FMT_RGBA), opt(opt) { + // + } + + void init(void *data) { + ASSERT((opt & OPT_PROXY) == 0); + + bool mipmaps = (opt & OPT_MIPMAPS) != 0; + bool isDepth = fmt == FMT_DEPTH || fmt == FMT_SHADOW; + bool isCube = (opt & OPT_CUBEMAP) != 0; + bool isVolume = (opt & OPT_VOLUME) != 0; + bool isTarget = (opt & OPT_TARGET) != 0; + bool isDynamic = (opt & OPT_DYNAMIC) != 0; + + static const struct FormatDesc { + int bpp; + VkFormat format; + } formats[FMT_MAX] = { + { 8, VK_FORMAT_R8_UNORM }, + { 32, VK_FORMAT_R8G8B8A8_UNORM }, + { 16, VK_FORMAT_B5G6R5_UNORM_PACK16 }, + { 16, VK_FORMAT_B5G5R5A1_UNORM_PACK16 }, + { 64, VK_FORMAT_R32G32_SFLOAT }, + { 32, VK_FORMAT_R16G16_SFLOAT }, + { 16, VK_FORMAT_R16_UNORM }, + { 16, VK_FORMAT_R16_UNORM }, + }; + + // + } + + void deinit() { + vkDestroyImage(device, image, NULL); + vkDestroyImageView(device, imageView, NULL); + } + + void generateMipMap() { + // + } + + void update(void *data) { + // + } + + void bind(int sampler) { + if (opt & OPT_PROXY) return; + // + } + + void unbind(int sampler) { + // + } + + void setFilterQuality(int value) { + // + } + }; + +// Mesh + struct Mesh { + VkBuffer IB; + VkBuffer VB; + + int iCount; + int vCount; + bool dynamic; + + Mesh(bool dynamic) : IB(VK_NULL_HANDLE), VB(VK_NULL_HANDLE), dynamic(dynamic) { + // + } + + void init(Index *indices, int iCount, ::Vertex *vertices, int vCount, int aCount) { + this->iCount = iCount; + this->vCount = vCount; + ASSERT(sizeof(GAPI::Vertex) == sizeof(::Vertex)); + // + } + + void deinit() { + vkDestroyBuffer(device, IB, NULL); + vkDestroyBuffer(device, VB, NULL); + } + + void update(Index *indices, int iCount, ::Vertex *vertices, int vCount) { + ASSERT(sizeof(GAPI::Vertex) == sizeof(::Vertex)); + + if (indices && iCount) { + // + } + + if (vertices && vCount) { + // + } + } + + void bind(const MeshRange &range) const { + // + } + + void initNextRange(MeshRange &range, int &aIndex) const { + range.aIndex = -1; + } + }; + +// GLuint FBO, defaultFBO; + struct RenderTargetCache { + int count; + struct Item { + int width; + int height; + } items[MAX_RENDER_BUFFERS]; + } rtCache; + + void deinitSamplers() { + for (int i = 0; i < COUNT(samplers); i++) { + //vkDestroySampler(device, samplers[i], NULL); + } + } + + VkSampler initSampler(bool filter, bool aniso, bool wrap, bool cmp) { + VkSamplerCreateInfo createInfo; + VK_INIT_STRUCT(createInfo, VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); + + if (aniso && (Core::support.maxAniso > 0)) { + createInfo.maxAnisotropy = min(int(Core::support.maxAniso), 8); + } else { + createInfo.maxAnisotropy = 1; + } + + createInfo.anisotropyEnable = (createInfo.maxAnisotropy > 1) ? VK_TRUE : VK_FALSE; + + if (filter) { + createInfo.minFilter = VK_FILTER_LINEAR; + createInfo.magFilter = VK_FILTER_LINEAR; + createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + } else { + createInfo.minFilter = VK_FILTER_LINEAR; + createInfo.magFilter = VK_FILTER_LINEAR; + createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + } + + if (cmp) { + createInfo.compareEnable = VK_TRUE; + createInfo.compareOp = VK_COMPARE_OP_LESS; + createInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + } + + createInfo.addressModeU = + createInfo.addressModeV = + createInfo.addressModeW = cmp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER : (wrap ? VK_SAMPLER_ADDRESS_MODE_REPEAT : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); + createInfo.minLod = 0.0f; + createInfo.maxLod = 0.0f; + + VkSampler sampler = VK_NULL_HANDLE; + //VK_CHECK(vkCreateSampler(device, &createInfo, NULL, &sampler)); + return sampler; + } + + void initSamplers() { + deinitSamplers(); + samplers[smpDefault] = initSampler(true, true, false, false); // TODO settings dependent + samplers[smpPoint] = initSampler(false, false, false, false); + samplers[smpPointWrap] = initSampler(false, false, true, false); + samplers[smpLinear] = initSampler(true, false, false, false); + samplers[smpLinearWrap] = initSampler(true, false, true, false); + samplers[smpCmp] = initSampler(true, false, false, true); + } + + void init() { + memset(&rtCache, 0, sizeof(rtCache)); + memset(samplers, 0, sizeof(samplers)); + + /* TODO + D3DADAPTER_IDENTIFIER9 adapterInfo; + D3D->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &adapterInfo); + LOG("Vendor : %s\n", adapterInfo.Description); + LOG("Renderer : Direct3D 9.0c\n"); + */ + + support.maxAniso = 8; + support.maxVectors = 16; + support.shaderBinary = true; + support.VAO = false; // SHADOW_COLOR + support.depthTexture = true; + support.shadowSampler = true; + support.discardFrame = false; + support.texNPOT = true; + support.texRG = true; + support.texBorder = true; + support.colorFloat = true; + support.colorHalf = true; + support.texFloatLinear = true; + support.texFloat = true; + support.texHalfLinear = true; + support.texHalf = true; + support.tex3D = true; + + // init samplers + memset(samplers, 0, sizeof(samplers)); + initSamplers(); + } + + void resetDevice() { + rtCache.count = 0; + } + + void deinit() { + resetDevice(); + + deinitSamplers(); + } + + inline mat4::ProjRange getProjRange() { + return mat4::PROJ_ZERO_POS; + } + + mat4 ortho(float l, float r, float b, float t, float znear, float zfar) { + mat4 m; + m.ortho(getProjRange(), l, r, b, t, znear, zfar); + return m; + } + + mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) { + mat4 m; + m.perspective(getProjRange(), fov, aspect, znear, zfar, eye); + return m; + } + + bool beginFrame() { + return true; + } + + void endFrame() { + // + } + + void resetState() { + // + } + + void cacheRenderTarget(VkImageView **RTV, VkImageView **DSV, int width, int height) { + ASSERT((RTV != NULL) ^ (DSV != NULL)); + + int index = -1; + for (int i = 0; i < rtCache.count; i++) + if (rtCache.items[i].width == width && rtCache.items[i].height == height) { + index = i; + break; + } + + ASSERT(rtCache.count < MAX_RENDER_BUFFERS); + + if (index == -1) { + index = rtCache.count++; + rtCache.items[index].width = width; + rtCache.items[index].height = height; + } + + // + } + + void bindTarget(Texture *target, int face) { + // + } + + void discardTarget(bool color, bool depth) {} + + void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) { + // + } + + void setVSync(bool enable) {} + void waitVBlank() {} + + void clear(bool color, bool depth) { + // + } + + void setClearColor(const vec4 &color) { + clearColor = color; + } + + void setViewport(const short4 &v) { + // + } + + void setScissor(const short4 &s) { + // + } + + void setDepthTest(bool enable) { + // + } + + void setDepthWrite(bool enable) { + // + } + + void setColorWrite(bool r, bool g, bool b, bool a) { + // + } + + void setAlphaTest(bool enable) {} + + void setCullMode(int rsMask) { + // + } + + void setBlendMode(int rsMask) { + // + } + + void setViewProj(const mat4 &mView, const mat4 &mProj) {} + + void updateLights(vec4 *lightPos, vec4 *lightColor, int count) { + //if (active.shader) { + // active.shader->setParam(uLightColor, lightColor[0], count); + // active.shader->setParam(uLightPos, lightPos[0], count); + //} + } + + void DIP(Mesh *mesh, const MeshRange &range) { + // + } + + vec4 copyPixel(int x, int y) { + return vec4(0.0f); + } +} #endif \ No newline at end of file diff --git a/src/inventory.h b/src/inventory.h index dec19cb..c7ed537 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -571,7 +571,7 @@ struct Inventory { joints[1].rotate(quat(vec3(0.0f, 1.0f, 0.0f), -params.x)); } - game->renderModelFull(desc.model, false, joints); + game->renderModelFull(desc.model, joints); } void choose() { @@ -1424,31 +1424,36 @@ struct Inventory { game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false); float s = 1.0f / INV_BG_SIZE; // vertical - Core::setTarget(tmp, NULL, RT_STORE_COLOR); - Core::validateRenderState(); + Core::beginRenderPass(RP_FILTER, RenderTarget(tmp), RenderTarget(NULL)); + Core::setPipelineState(PS_FILTER_BLUR); Core::active.shader->setParam(uParam, vec4(0, s, 0, s)); texInOut->bind(sDiffuse); game->getMesh()->renderQuad(); + Core::endRenderPass(); + // horizontal - Core::setTarget(texInOut, NULL, RT_STORE_COLOR); - Core::validateRenderState(); + Core::beginRenderPass(RP_FILTER, RenderTarget(texInOut), RenderTarget(NULL)); + Core::setPipelineState(PS_FILTER_BLUR); game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false); Core::active.shader->setParam(uParam, vec4(s, 0, 0, s)); tmp->bind(sDiffuse); game->getMesh()->renderQuad(); + Core::endRenderPass(); } void grayscale(Texture *texIn, Texture *texOut) { #ifdef FFP return; // TODO #endif + Core::beginRenderPass(RP_FILTER, RenderTarget(texOut), RenderTarget(NULL)); + Core::setPipelineState(PS_FILTER_GRAYSCALE); + float s = 1.0f / INV_BG_SIZE; - game->setShader(Core::passFilter, Shader::FILTER_GRAYSCALE, false, false); - Core::setTarget(texOut, NULL, RT_STORE_COLOR); - Core::validateRenderState(); Core::active.shader->setParam(uParam, vec4(0.75f, 0.75f, 1.0f, s)); texIn->bind(sDiffuse); game->getMesh()->renderQuad(); + + Core::endRenderPass(); } void prepareBackground() { @@ -1469,9 +1474,6 @@ struct Inventory { game->renderGame(false, true); - Core::setDepthTest(false); - Core::setBlendMode(bmNone); - int viewsCount = (Core::settings.detail.stereo == Core::Settings::STEREO_OFF) ? 1 : 2; mat4 mProj, mView; @@ -1489,8 +1491,6 @@ struct Inventory { #ifdef _OS_3DS GAPI::rotate90 = true; #endif - - Core::setDepthTest(true); } float getEyeOffset() { @@ -1828,9 +1828,9 @@ struct Inventory { } else { background[0]->bind(sDiffuse); } - +#if 0 Core::setBlendMode(alpha < 255 ? bmAlpha : bmNone); - +#endif mat4 mProj, mView; mView.identity(); mProj = GAPI::ortho(-1, +1, -1, +1, 0, 1); @@ -1890,18 +1890,19 @@ struct Inventory { game->setShader(Core::passFilter, Shader::FILTER_UPSCALE, false, false); Core::active.shader->setParam(uParam, vec4(float(Core::active.textures[sDiffuse]->width), float(Core::active.textures[sDiffuse]->height), 0.0f, 0.0f)); - +#if 0 Core::setBlendMode(phaseRing < 1.0f ? bmAlpha : bmNone); +#endif game->getMesh()->renderBuffer(indices, COUNT(indices), vertices, COUNT(vertices)); } void renderBackground(int view) { if (!isActive() && titleTimer == 0.0f) return; - +#if 0 Core::setDepthTest(false); Core::setDepthWrite(false); - +#endif uint8 alpha; if (!isActive() && titleTimer > 0.0f && titleTimer < 1.0f) alpha = uint8(titleTimer * 255); @@ -1924,10 +1925,11 @@ struct Inventory { else renderTitleBG(1.0f, sy, alpha); } - +#if 0 Core::setBlendMode(bmPremult); Core::setDepthTest(true); Core::setDepthWrite(true); +#endif } void setupCamera(float aspect, bool ui = false) { @@ -1969,7 +1971,9 @@ struct Inventory { void render(float aspect) { if (video) { +#if 0 Core::setDepthTest(false); +#endif video->render(); Texture *tmp = background[0]; @@ -1992,8 +1996,9 @@ struct Inventory { renderTitleBG(1.0f, sy, clamp(int((video->stepTimer / video->step) * 255), 0, 255), 1.0f, ch); background[0] = tmp; - +#if 0 Core::setDepthTest(true); +#endif return; } diff --git a/src/level.h b/src/level.h index e536820..670bbde 100644 --- a/src/level.h +++ b/src/level.h @@ -513,7 +513,7 @@ struct Level : IGame { virtual void setRoomParams(int roomIndex, Shader::Type type, float diffuse, float ambient, float specular, float alpha, bool alphaTest = false) { if (Core::pass == Core::passShadow) { - setShader(Core::pass, type, false, alphaTest); + Core::setPipelineState(alphaTest ? PS_ENTITY_SHADOW_ALPHA : PS_ENTITY_SHADOW); return; } @@ -621,7 +621,7 @@ struct Level : IGame { GAPI::rotate90 = false; #endif - PROFILE_MARKER("ENVIRONMENT"); + PROFILE_MARKER("environment"); setupBinding(); float tmpEye = Core::eye; Core::Pass tmpPass = Core::pass; @@ -630,18 +630,30 @@ struct Level : IGame { int16 rIndex = roomIndex; level.getSector(rIndex, pos); // fix room index for overlapped blocks + Texture *depthTex = Core::acquireTarget(targets[0]->width, targets[0]->height, FMT_DEPTH); + // render level into cube faces or texture images for (int i = 0; i < 6; i++) { setupCubeCamera(pos, i); Core::pass = pass; + + int index, face; + if (targets[0]->opt & OPT_CUBEMAP) { - Core::setTarget(targets[0], NULL, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR, i); + index = 0; + face = i; } else { - Core::setTarget(targets[i * stride], NULL, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR); + index = i * stride; + face = 0; } + + Core::beginRenderPass(RP_MAIN, RenderTarget(targets[index], face, 0), RenderTarget(depthTex)); renderView(rIndex, false, false); + Core::endRenderPass(); } + Core::releaseTarget(depthTex); + #ifdef _OS_3DS GAPI::rotate90 = true; #endif @@ -650,39 +662,19 @@ struct Level : IGame { Core::eye = tmpEye; } - virtual void renderModelFull(int modelIndex, bool underwater, Basis *joints) { + virtual void renderModelFull(int modelIndex, Basis *joints) { vec4 ambient[6] = { vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0) }; - // opaque - Core::setBlendMode(bmPremult); // inventory items has fade-out/in alpha - mesh->transparent = 0; - setShader(Core::passCompose, Shader::ENTITY, underwater, false); + Core::setPipelineState(PS_ENTITY_ALPHA); // inventory items has fade-out/in alpha Core::setBasis(joints, level.models[modelIndex].mCount); Core::active.shader->setParam(uMaterial, Core::active.material); Core::active.shader->setParam(uAmbient, ambient[0], 6); Core::updateLights(); - mesh->renderModel(modelIndex, underwater); - // transparent - mesh->transparent = 1; - setShader(Core::passCompose, Shader::ENTITY, underwater, true); - Core::setBasis(joints, level.models[modelIndex].mCount); - Core::active.shader->setParam(uMaterial, Core::active.material); - Core::active.shader->setParam(uAmbient, ambient[0], 6); - Core::updateLights(); - mesh->renderModel(modelIndex, underwater); - // additive - Core::setBlendMode(bmAdd); - Core::setDepthWrite(false); - mesh->transparent = 2; - setShader(Core::passCompose, Shader::ENTITY, underwater, false); - Core::setBasis(joints, level.models[modelIndex].mCount); - Core::active.shader->setParam(uMaterial, Core::active.material); - Core::active.shader->setParam(uAmbient, ambient[0], 6); - Core::updateLights(); - mesh->renderModel(modelIndex, underwater); - Core::setDepthWrite(true); - Core::setBlendMode(bmNone); - mesh->transparent = 0; + + for (int i = 0; i < 0; i++) { + mesh->transparent = i; + mesh->renderModel(modelIndex, false); + } } virtual void setEffect(Controller *controller, TR::Effect::Type effect) { @@ -1811,29 +1803,29 @@ struct Level : IGame { #endif ASSERT(mesh->transparent == 0); - Shader::Type type; + PipelineStateType type; TR::SkyParams skyParams; if (level.version & TR::VER_TR1) { if (Core::settings.detail.lighting < Core::Settings::HIGH || !Core::support.tex3D || !TR::getSkyParams(level.id, skyParams)) return; - type = Shader::SKY_CLOUDS_AZURE; + type = PS_SKY_CLOUDS_AZURE; } else { // TR2, TR3 if (level.extra.sky == -1) return; if (Core::settings.detail.lighting < Core::Settings::HIGH || !Core::support.tex3D) { - type = Shader::DEFAULT; + type = PS_SKY; } else { - type = Shader::SKY_CLOUDS; + type = PS_SKY_CLOUDS; if (!TR::getSkyParams(level.id, skyParams)) { - type = Shader::DEFAULT; + type = PS_SKY; } } } - if (type != Shader::DEFAULT && !Core::perlinTex) { - type = Shader::DEFAULT; + if (type != PS_SKY && !Core::perlinTex) { + type = PS_SKY; if (level.version & TR::VER_TR1) { return; } @@ -1846,9 +1838,9 @@ struct Level : IGame { Core::mView.setPos(vec3(0)); Core::setViewProj(Core::mView, Core::mProj); - setShader(Core::passSky, type, false, false); + Core::setPipelineState(type); - if (type != Shader::DEFAULT) { + if (type != PS_SKY) { float time = Core::params.x; if (time > SKY_TIME_PERIOD) { time /= SKY_TIME_PERIOD; @@ -1864,9 +1856,7 @@ struct Level : IGame { } if (level.version & TR::VER_TR1) { - Core::setCullMode(cmNone); - mesh->renderBox(); - Core::setCullMode(cmFront); + mesh->renderBox(); // TODO renderBoxInv } else { Basis b; Core::setBasis(&b, 1); // unused @@ -1932,7 +1922,7 @@ struct Level : IGame { } void renderRooms(RoomDesc *roomsList, int roomsCount, int transp) { - PROFILE_MARKER("ROOMS"); + PROFILE_MARKER("rooms"); if (Core::pass == Core::passShadow) return; @@ -1942,12 +1932,6 @@ struct Level : IGame { Core::mModel.identity(); - switch (transp) { - case 0 : Core::setBlendMode(bmNone); break; - case 1 : Core::setBlendMode(bmPremult); break; - case 2 : Core::setBlendMode(bmAdd); Core::setDepthWrite(false); break; - } - int i = 0; int end = roomsCount; int dir = 1; @@ -1991,13 +1975,9 @@ struct Level : IGame { i += dir; } - Core::setDepthWrite(true); - if (transp == 1) { atlasSprites->bind(sDiffuse); - Core::setBlendMode(bmPremult); - #ifdef MERGE_SPRITES basis.rot = Core::mViewInv.getRot(); #else @@ -2025,7 +2005,6 @@ struct Level : IGame { } Core::setScissor(vp); - Core::setBlendMode(bmNone); } void renderEntity(const TR::Entity &entity) { @@ -2338,7 +2317,7 @@ struct Level : IGame { } { - PROFILE_MARKER("ENTITY_SPRITES"); + PROFILE_MARKER("sprites"); if (mesh->dynICount) { atlasSprites->bind(sDiffuse); @@ -2365,36 +2344,27 @@ struct Level : IGame { if (Core::pass == Core::passAmbient) // TODO allow static entities return; - PROFILE_MARKER("ENTITIES"); + PROFILE_MARKER("objects"); - if (transp == 0) { - Core::setBlendMode(bmNone); - renderEntitiesTransp(transp); - } - - if (transp == 1) { - Core::setBlendMode(bmPremult); - renderEntitiesTransp(transp); - - #ifndef FFP - Core::whiteTex->bind(sDiffuse); - Core::setBlendMode(bmMult); - for (int i = 0; i < level.entitiesCount; i++) { - TR::Entity &entity = level.entities[i]; - Controller *controller = (Controller*)entity.controller; - if (controller && controller->flags.rendered && controller->getEntity().castShadow()) - controller->renderShadow(mesh); - } - Core::setBlendMode(bmNone); - #endif - } - - if (transp == 2) { - Core::setDepthWrite(false); - Core::setBlendMode(bmAdd); - renderEntitiesTransp(transp); - Core::setDepthWrite(true); + renderEntitiesTransp(transp); + } + + void renderBlobs() { + PROFILE_MARKER("blobs"); + + if (Core::pass != Core::passCompose || level.isCutsceneLevel()) + return; + + #ifndef FFP + Core::setPipelineState(PS_BLOB); + Core::whiteTex->bind(sDiffuse); + for (int i = 0; i < level.entitiesCount; i++) { + TR::Entity &entity = level.entities[i]; + Controller *controller = (Controller*)entity.controller; + if (controller && controller->flags.rendered && controller->getEntity().castShadow()) + controller->renderShadow(mesh); } + #endif } virtual vec4 projectPoint(const vec4 &p) { @@ -2447,25 +2417,27 @@ struct Level : IGame { if ((a.w > 0.0f) ^ (b.w > 0.0f)) { - if (a.x < 0.0f && b.x < 0.0f) + if (a.x < 0.0f && b.x < 0.0f) { clipPort.x = -1.0f; - else + } else { if (a.x > 0.0f && b.x > 0.0f) clipPort.z = 1.0f; else { clipPort.x = -1.0f; clipPort.z = 1.0f; } + } - if (a.y < 0.0f && b.y < 0.0f) + if (a.y < 0.0f && b.y < 0.0f) { clipPort.y = -1.0f; - else + } else { if (a.y > 0.0f && b.y > 0.0f) clipPort.w = 1.0f; else { clipPort.y = -1.0f; clipPort.w = 1.0f; } + } } } @@ -2530,8 +2502,8 @@ struct Level : IGame { } virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, RoomDesc *roomsList = NULL) { - PROFILE_MARKER("VIEW"); - + PROFILE_MARKER("view"); +#if 0 if (water && waterCache) waterCache->reset(); @@ -2590,8 +2562,12 @@ struct Level : IGame { } Texture *screen = NULL; + Texture *depthTex = NULL; + if (water) { screen = (waterCache && waterCache->visible) ? waterCache->getScreenTex() : NULL; + + Core::beginrenderPass(RP_SCENE, RenderTarget(screen), RenderTarget()); Core::setTarget(screen, NULL, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR | (screen ? RT_STORE_DEPTH : 0)); // render to screen texture (FUCK YOU iOS!) or back buffer Core::validateRenderState(); setupBinding(); @@ -2601,6 +2577,7 @@ struct Level : IGame { renderOpaque(roomsList, roomsCount); renderTransparent(roomsList, roomsCount); + renderBlobs(); if (camera->isUnderwater()) renderAdditive(roomsList, roomsCount); @@ -2639,6 +2616,7 @@ struct Level : IGame { } Core::pass = pass; +#endif } void setupCubeCamera(const vec3 &pos, int face) { @@ -2804,7 +2782,7 @@ struct Level : IGame { } */ void renderShadows(int roomIndex, Texture *shadowMap) { - PROFILE_MARKER("PASS_SHADOW"); + PROFILE_MARKER("shadows"); if (Core::settings.detail.shadows == Core::Settings::LOW) return; @@ -2816,12 +2794,14 @@ struct Level : IGame { Core::pass = Core::passShadow; shadowMap->unbind(sShadow); + +#if 0 bool colorShadow = shadowMap->fmt == FMT_RGBA ? true : false; if (colorShadow) Core::setClearColor(vec4(1.0f)); Core::setTarget(shadowMap, NULL, RT_CLEAR_DEPTH | (colorShadow ? (RT_CLEAR_COLOR | RT_STORE_COLOR) : RT_STORE_DEPTH)); //Core::setCullMode(cmBack); - Core::validateRenderState(); + //Core::validateRenderState(); /* if (Core::settings.detail.shadows > Core::Settings::MEDIUM) { // per-object shadow map (atlas) @@ -2847,7 +2827,7 @@ struct Level : IGame { Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_CLEAR_COLOR | RT_STORE_COLOR | RT_STORE_DEPTH); Core::validateRenderState(); #endif - +#endif Core::eye = oldEye; } @@ -3265,7 +3245,7 @@ struct Level : IGame { } else { renderEye(int(Core::eye), showUI, invBG); } - +#if 0 #ifndef _OS_3DS if (!invBG && Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH) { mat4 mProj, mView; @@ -3309,7 +3289,7 @@ struct Level : IGame { Core::setDepthTest(true); Core::setDepthWrite(true); } - +#endif // TODO render all UI with native resolution here } @@ -3381,7 +3361,7 @@ struct Level : IGame { setDefaultTarget(eye, view, false); - Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_STORE_COLOR); + //Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_STORE_COLOR); float aspect = setViewport(view, eye); @@ -3422,6 +3402,7 @@ struct Level : IGame { } void render() { +#if 0 if (isEnded && !inventory->video) { Core::setTarget(NULL, NULL, RT_CLEAR_COLOR | RT_STORE_COLOR); UI::begin(float(Core::width) / float(Core::height)); @@ -3430,6 +3411,7 @@ struct Level : IGame { UI::end(); return; } +#endif renderGame(true, false); } diff --git a/src/objects.h b/src/objects.h index 1af31c6..f769239 100644 --- a/src/objects.h +++ b/src/objects.h @@ -292,9 +292,11 @@ struct MuzzleFlash : Controller { game->setShader(Core::pass, Shader::FLASH, false, false); Core::setMaterial(lum * alpha, 0.0f, 0.0f, alpha); Core::setBasis(&b, 1); + #if 0 Core::setDepthWrite(false); mesh->renderModel(level->extra.muzzleFlash); Core::setDepthWrite(true); + #endif } }; @@ -1315,16 +1317,17 @@ struct Lightning : Controller { game->setShader(Core::pass, Shader::FLASH, false, false); Core::setMaterial(0.0f, 0.0f, 0.0f, 1.0f); Core::setBasis(&b, 1); - +#if 0 Core::setCullMode(cmNone); Core::setBlendMode(bmAdd); Core::setDepthWrite(false); - +#endif renderPolyline(vec3(0.0f), target - b.pos, 64.0f, 512.0f, 1); - +#if 0 Core::setDepthWrite(true); Core::setBlendMode(bmNone); Core::setCullMode(cmFront); +#endif } }; diff --git a/src/platform/nix/main.cpp b/src/platform/nix/main.cpp index 7592edf..a741901 100644 --- a/src/platform/nix/main.cpp +++ b/src/platform/nix/main.cpp @@ -14,7 +14,7 @@ #include "game.h" -#define WND_TITLE "OpenLara" +#define WND_TITLE "OpenLara" // timing unsigned int startTime; @@ -399,25 +399,39 @@ int main(int argc, char **argv) { home = getpwuid(getuid())->pw_dir; strcat(cacheDir, home); strcat(cacheDir, "/.openlara/"); - +int i = 0; +i = i / i; struct stat st = {0}; if (stat(cacheDir, &st) == -1 && mkdir(cacheDir, 0777) == -1) cacheDir[0] = 0; strcpy(saveDir, cacheDir); - static int XGLAttr[] = { - GLX_RGBA, - GLX_DOUBLEBUFFER, - GLX_DEPTH_SIZE, 24, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - 0 - }; - Display *dpy = XOpenDisplay(NULL); - XVisualInfo *vis = glXChooseVisual(dpy, XDefaultScreen(dpy), XGLAttr); + XVisualInfo *vis = NULL; + + #ifdef _GAPI_GL + static int XGLAttr[] = { + GLX_RGBA, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 24, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + 0 + }; + + vis = glXChooseVisual(dpy, XDefaultScreen(dpy), XGLAttr); + + GLXContext ctx = glXCreateContext(dpy, vis, NULL, true); + #elif _GAPI_VULKAN + XVisualInfo visTpl; + memset(&visTpl, 0, sizeof(visTpl)); + visTpl.screen = DefaultScreen(dpy); + + int visCount = 0; + vis = XGetVisualInfo(dpy, 2, &visTpl, &visCount); + #endif XSetWindowAttributes attr; attr.colormap = XCreateColormap(dpy, RootWindow(dpy, vis->screen), vis->visual, AllocNone); @@ -432,8 +446,11 @@ int main(int argc, char **argv) { CWColormap | CWBorderPixel | CWEventMask, &attr); XStoreName(dpy, wnd, WND_TITLE); - GLXContext ctx = glXCreateContext(dpy, vis, NULL, true); - glXMakeCurrent(dpy, wnd, ctx); + #ifdef _GAPI_GL + glXMakeCurrent(dpy, wnd, ctx); + #endif + + XSync(dpy, false); XMapWindow(dpy, wnd); Atom WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", 0); @@ -462,7 +479,11 @@ int main(int argc, char **argv) { if (updated) { Game::render(); Core::waitVBlank(); - glXSwapBuffers(dpy, wnd); + #ifdef _GAPI_GL + glXSwapBuffers(dpy, wnd); + #elif _GAPI_VULKAN + + #endif } } }; @@ -471,7 +492,12 @@ int main(int argc, char **argv) { sndFree(); Game::deinit(); - glXMakeCurrent(dpy, 0, 0); - XCloseDisplay(dpy); + #ifdef _GAPI_GL + glXMakeCurrent(dpy, 0, 0); + XCloseDisplay(dpy); + #elif _GAPI_VULKAN + + #endif + return 0; } diff --git a/src/shaders/shadow_entity.hlsl b/src/shaders/shadow_entity.hlsl index 9561c31..9dea87c 100644 --- a/src/shaders/shadow_entity.hlsl +++ b/src/shaders/shadow_entity.hlsl @@ -1,5 +1,7 @@ #include "common.hlsl" +// ALPHA_TEST, SHADOW_DEPTH + struct VS_OUTPUT { float4 pos : POSITION; float4 texCoord : TEXCOORD0; diff --git a/src/ui.h b/src/ui.h index 5d08e04..2a5279d 100644 --- a/src/ui.h +++ b/src/ui.h @@ -47,7 +47,7 @@ namespace UI { int advGlyphsStart; - #define RU_MAP "" "i~" + #define RU_MAP "�������������������������������������������" "i~" #define RU_GLYPH_COUNT (COUNT(RU_MAP) - 1) #define RU_GLYPH_START 102 #define RU_GLYPH_UPPERCASE 20 @@ -62,9 +62,9 @@ namespace UI { 5, 5, 5, 11, 9, 7, 8, 6, 0, 7, 7, 3, 8, 8, 13, 7, 9, 4, 12, 12, 7, 5, 7, 7, 7, 7, 7, 7, 7, 7, 16, 14, 14, 14, 16, 16, 16, 16, 16, 12, 14, 8, 8, 8, 8, 8, 8, 8, // cyrillic - 11, 11, 11, 13, 10, 13, 11, 11, 12, 12, 11, 9, 13, 13, 10, 13, // - 9, 11, 12, 11, 10, 9, 8, 10, 11, 9, 10, 10, 11, 9, 10, 12, // - 10, 10, 9, 11, 12, 9, 11, 8, 9, 13, 9, // + 11, 11, 11, 13, 10, 13, 11, 11, 12, 12, 11, 9, 13, 13, 10, 13, // ���������������� + 9, 11, 12, 11, 10, 9, 8, 10, 11, 9, 10, 10, 11, 9, 10, 12, // ���������������� + 10, 10, 9, 11, 12, 9, 11, 8, 9, 13, 9, // ����������� // additional latin (i~) 5, 10 }; @@ -82,10 +82,11 @@ namespace UI { enum Align { aLeft, aRight, aCenter, aCenterV }; inline int charRemap(char c) { +#if 0 if (isCyrillic(c)) { - return char_map[RU_GLYPH_START + (c - '')]; + return char_map[RU_GLYPH_START + (c - 'А')]; } - +#endif if (c < 11) return c + 81; if (c < 16) @@ -118,11 +119,11 @@ namespace UI { int h = upperCase(idx) ? 13 : 9; int o = 0; char c = RU_MAP[i]; - - if (c == '' || c == '' || c == '~') h = 14; - if (c == '' || c == '' || c == '' || c == '') { o = 1; h++; } - if (c == '') { o = 2; h += 2; } - +#if 0 + if (c == 'б' || c == 'д' || c == '~') h = 14; + if (c == 'Ц' || c == 'Щ' || c == 'ц' || c == 'щ') { o = 1; h++; } + if (c == 'ф') { o = 2; h += 2; } +#endif *glyphSprite++ = TR::TextureInfo(TR::TEX_TYPE_SPRITE, 0, -h + o, w, o, (i % 16) * 16, (i / 16) * 16 + (16 - h), w, h); } // append japanese glyphs @@ -273,10 +274,13 @@ namespace UI { Core::mProj = GAPI::ortho(0.0f, width, height, 0.0f, -128.0f, 127.0f); Core::setViewProj(Core::mView, Core::mProj); + Core::setPipelineState(PS_GUI); + #if 0 Core::setDepthTest(false); Core::setDepthWrite(false); Core::setBlendMode(bmPremult); Core::setCullMode(cmNone); + #endif game->setupBinding(); game->setShader(Core::passGUI, Shader::DEFAULT); @@ -291,10 +295,12 @@ namespace UI { void end() { game->getMesh()->dynEnd(); + #if 0 Core::setCullMode(cmFront); Core::setBlendMode(bmNone); Core::setDepthTest(true); Core::setDepthWrite(true); + #endif } enum ShadeType { @@ -667,9 +673,12 @@ namespace UI { Core::whiteTex->bind(sDiffuse); + Core::setPipelineState(PS_GUI); + #if 0 Core::setDepthTest(false); Core::setBlendMode(bmPremult); Core::setCullMode(cmNone); + #endif Core::mViewProj = GAPI::ortho(0.0f, float(Core::width), float(Core::height), 0.0f, 0.0f, 1.0f); @@ -691,9 +700,11 @@ namespace UI { if (Input::btnEnable[i]) renderControl(Input::btnPos[i], Input::btnRadius, Input::btn == i); + #if 0 Core::setCullMode(cmFront); Core::setBlendMode(bmNone); Core::setDepthTest(true); + #endif } void renderBar(CommonTexType type, const vec2 &pos, const vec2 &size, float value, uint32 fgColor = 0xFFFFFFFF, uint32 bgColor = 0x80000000, uint32 brColor1 = 0xFF4C504C, uint32 brColor2 = 0xFF748474, uint32 fgColor2 = 0) { @@ -801,7 +812,7 @@ namespace UI { setupInventoryShading(lightOffset); Basis joints[MAX_JOINTS]; - +#if 0 Core::setDepthTest(true); Core::setDepthWrite(true); @@ -834,7 +845,7 @@ namespace UI { Core::setMaterial(1.0f, 0.0f, 0.0f, alpha); - game->renderModelFull(item.modelIndex - 1, false, joints); + game->renderModelFull(item.modelIndex - 1, joints); } Core::setDepthTest(false); @@ -846,6 +857,7 @@ namespace UI { Core::setBlendMode(bmPremult); Core::setCullMode(cmNone); Core::setMaterial(1, 1, 1, 1); + #endif } };