diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index 0a5766216..cc20dd27b 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -102,7 +102,7 @@ TA_context* _pvrrc; void SetREP(TA_context* cntx); static void rend_create_renderer(); -void dump_frame(const char* file, TA_context* ctx, u8* vram, u8* vram_ref = NULL) { +static void dump_frame(const char* file, TA_context* ctx, u8* vram, u8* vram_ref = NULL) { FILE* fw = fopen(file, "wb"); //append to it @@ -245,7 +245,8 @@ TA_context* read_frame(const char* file, u8* vram_ref = NULL) { bool dump_frame_switch = false; -bool rend_frame(TA_context* ctx, bool draw_osd) { +static bool rend_frame(TA_context* ctx) +{ if (dump_frame_switch) { char name[32]; sprintf(name, "dcframe-%d", FrameCount); @@ -267,12 +268,7 @@ bool rend_frame(TA_context* ctx, bool draw_osd) { re.Set(); #endif - bool do_swp = proc && renderer->Render(); - - if (do_swp && draw_osd) - renderer->DrawOSD(false); - - return do_swp; + return proc && renderer->Render(); } bool rend_single_frame() @@ -332,7 +328,7 @@ bool rend_single_frame() _pvrrc = DequeueRender(); } while (!_pvrrc); - bool do_swp = rend_frame(_pvrrc, true); + bool do_swp = rend_frame(_pvrrc); swap_pending = settings.rend.DelayFrameSwapping && do_swp && !_pvrrc->rend.isRenderFramebuffer; #if !defined(TARGET_NO_THREADS) diff --git a/core/linux-dist/x11.cpp b/core/linux-dist/x11.cpp index 3246b1a6b..7a98bbe4e 100644 --- a/core/linux-dist/x11.cpp +++ b/core/linux-dist/x11.cpp @@ -476,7 +476,7 @@ void x11_window_destroy() } cfgSaveBool("x11", "fullscreen", x11_fullscreen); XDestroyWindow(x11_disp, x11_win); - x11_win = NULL; + x11_win = (Window)0; } if (x11_disp) { diff --git a/core/rend/TexCache.cpp b/core/rend/TexCache.cpp index c09002782..eeba89898 100644 --- a/core/rend/TexCache.cpp +++ b/core/rend/TexCache.cpp @@ -1,5 +1,3 @@ -#include -#include #ifndef TARGET_NO_OPENMP #include #endif @@ -7,13 +5,13 @@ #include "TexCache.h" #include "hw/pvr/pvr_regs.h" #include "hw/pvr/pvr_mem.h" -#include "hw/pvr/Renderer_if.h" #include "hw/mem/_vmem.h" #include "hw/mem/vmem32.h" #include "hw/sh4/modules/mmu.h" #include "deps/xbrz/xbrz.h" #include #include "CustomTexture.h" +#include u8* vq_codebook; u32 palette_index; @@ -733,40 +731,6 @@ void BaseTextureCacheData::CheckCustomTexture() } } -std::unordered_map> TexCache; - -void CollectCleanup() -{ - vector list; - - u32 TargetFrame = max((u32)120,FrameCount) - 120; - - for (const auto& pair : TexCache) - { - if (pair.second->dirty && pair.second->dirty < TargetFrame) - list.push_back(pair.first); - - if (list.size() > 5) - break; - } - - for (u64 id : list) - { - if (TexCache[id]->Delete()) - TexCache.erase(id); - } -} - -void killtex() -{ - for (auto& pair : TexCache) - pair.second->Delete(); - - TexCache.clear(); - KillTex = false; - INFO_LOG(RENDERER, "Texture cache cleared"); -} - void ReadFramebuffer(PixelBuffer& pb, int& width, int& height) { width = (FB_R_SIZE.fb_x_size + 1) << 1; // in 16-bit words @@ -944,3 +908,147 @@ void rend_text_invl(vram_block* bl) libCore_vramlock_Unlock_block_wb(bl); } + +static FILE* pngfile; + +void png_cstd_read(png_structp png_ptr, png_bytep data, png_size_t length) +{ + if (fread(data, 1, length, pngfile) != length) + png_error(png_ptr, "Truncated read error"); +} + +u8* loadPNGData(const string& fname, int &width, int &height) +{ + const char* filename=fname.c_str(); + FILE* file = fopen(filename, "rb"); + pngfile=file; + + if (!file) + { + EMUERROR("Error opening %s\n", filename); + return NULL; + } + + //header for testing if it is a png + png_byte header[8]; + + //read the header + if (fread(header, 1, 8, file) != 8) + { + fclose(file); + WARN_LOG(RENDERER, "Not a PNG file : %s", filename); + return NULL; + } + + //test if png + int is_png = !png_sig_cmp(header, 0, 8); + if (!is_png) + { + fclose(file); + WARN_LOG(RENDERER, "Not a PNG file : %s", filename); + return NULL; + } + + //create png struct + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL); + if (!png_ptr) + { + fclose(file); + WARN_LOG(RENDERER, "Unable to create PNG struct : %s", filename); + return (NULL); + } + + //create png info struct + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + WARN_LOG(RENDERER, "Unable to create PNG info : %s", filename); + fclose(file); + return (NULL); + } + + //create png info struct + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + WARN_LOG(RENDERER, "Unable to create PNG end info : %s", filename); + fclose(file); + return (NULL); + } + + //png error stuff, not sure libpng man suggests this. + if (setjmp(png_jmpbuf(png_ptr))) + { + fclose(file); + WARN_LOG(RENDERER, "Error during setjmp : %s", filename); + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + return (NULL); + } + + //init png reading + //png_init_io(png_ptr, fp); + png_set_read_fn(png_ptr, NULL, png_cstd_read); + + //let libpng know you already read the first 8 bytes + png_set_sig_bytes(png_ptr, 8); + + // read all the info up to the image data + png_read_info(png_ptr, info_ptr); + + //variables to pass to get info + int bit_depth, color_type; + png_uint_32 twidth, theight; + + // get info about png + png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, + NULL, NULL, NULL); + + //update width and height based on png info + width = twidth; + height = theight; + + // Update the png info struct. + png_read_update_info(png_ptr, info_ptr); + + // Row size in bytes. + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + // Allocate the image_data as a big block, to be given to opengl + png_byte *image_data = new png_byte[rowbytes * height]; + if (!image_data) + { + //clean up memory and close stuff + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + WARN_LOG(RENDERER, "Unable to allocate image_data while loading %s", filename); + fclose(file); + return NULL; + } + + //row_pointers is for pointing to image_data for reading the png with libpng + png_bytep *row_pointers = new png_bytep[height]; + if (!row_pointers) + { + //clean up memory and close stuff + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + delete[] image_data; + WARN_LOG(RENDERER, "Unable to allocate row_pointer while loading %s", filename); + fclose(file); + return NULL; + } + + // set the individual row_pointers to point at the correct offsets of image_data + for (int i = 0; i < height; ++i) + row_pointers[height - 1 - i] = image_data + i * rowbytes; + + //read the png into image_data through row_pointers + png_read_image(png_ptr, row_pointers); + + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + delete[] row_pointers; + fclose(file); + + return image_data; +} diff --git a/core/rend/TexCache.h b/core/rend/TexCache.h index a5176993b..b27778057 100644 --- a/core/rend/TexCache.h +++ b/core/rend/TexCache.h @@ -6,6 +6,7 @@ #include "hw/pvr/pvr_regs.h" #undef ID #include "hw/pvr/ta_structs.h" +#include "hw/pvr/Renderer_if.h" extern u8* vq_codebook; extern u32 palette_index; @@ -706,52 +707,85 @@ struct BaseTextureCacheData virtual ~BaseTextureCacheData() {} }; -extern std::unordered_map> TexCache; -typedef std::unordered_map>::iterator TexCacheIter; - -// Only use TexU and TexV from TSP in the cache key -// TexV : 7, TexU : 7 -const TSP TSPTextureCacheMask = { { 7, 7 } }; -// TexAddr : 0x1FFFFF, Reserved : 0, StrideSel : 0, ScanOrder : 1, PixelFmt : 7, VQ_Comp : 1, MipMapped : 1 -const TCW TCWTextureCacheMask = { { 0x1FFFFF, 0, 0, 1, 7, 1, 1 } }; - -template -BaseTextureCacheData *getTextureCacheData(TSP tsp, TCW tcw, Func factory) +template +class BaseTextureCache { - u64 key = tsp.full & TSPTextureCacheMask.full; - if (tcw.PixelFmt == PixelPal4 || tcw.PixelFmt == PixelPal8) - // Paletted textures have a palette selection that must be part of the key - // We also add the palette type to the key to avoid thrashing the cache - // when the palette type is changed. If the palette type is changed back in the future, - // this texture will stil be available. - key |= ((u64)tcw.full << 32) | ((PAL_RAM_CTRL & 3) << 6); - else - key |= (u64)(tcw.full & TCWTextureCacheMask.full) << 32; - - TexCacheIter it = TexCache.find(key); - - BaseTextureCacheData* texture; - if (it != TexCache.end()) + using TexCacheIter = typename std::unordered_map::iterator; +public: + Texture *getTextureCacheData(TSP tsp, TCW tcw) { - texture = it->second.get(); - // Needed if the texture is updated - texture->tcw.StrideSel = tcw.StrideSel; + u64 key = tsp.full & TSPTextureCacheMask.full; + if (tcw.PixelFmt == PixelPal4 || tcw.PixelFmt == PixelPal8) + // Paletted textures have a palette selection that must be part of the key + // We also add the palette type to the key to avoid thrashing the cache + // when the palette type is changed. If the palette type is changed back in the future, + // this texture will stil be available. + key |= ((u64)tcw.full << 32) | ((PAL_RAM_CTRL & 3) << 6); + else + key |= (u64)(tcw.full & TCWTextureCacheMask.full) << 32; + + TexCacheIter it = cache.find(key); + + Texture* texture; + if (it != cache.end()) + { + texture = &it->second; + // Needed if the texture is updated + texture->tcw.StrideSel = tcw.StrideSel; + } + else //create if not existing + { + texture = &cache[key]; + + texture->tsp = tsp; + texture->tcw = tcw; + } + texture->Lookups++; + + return texture; } - else //create if not existing + + void CollectCleanup() { - texture = factory(); - TexCache[key] = std::unique_ptr(texture); + vector list; - texture->tsp = tsp; - texture->tcw = tcw; + u32 TargetFrame = max((u32)120, FrameCount) - 120; + + for (const auto& pair : cache) + { + if (pair.second.dirty && pair.second.dirty < TargetFrame) + list.push_back(pair.first); + + if (list.size() > 5) + break; + } + + for (u64 id : list) + { + if (cache[id].Delete()) + cache.erase(id); + } } - texture->Lookups++; - return texture; -} + void Clear() + { + for (auto& pair : cache) + pair.second.Delete(); + + cache.clear(); + KillTex = false; + INFO_LOG(RENDERER, "Texture cache cleared"); + } + +private: + std::unordered_map cache; + // Only use TexU and TexV from TSP in the cache key + // TexV : 7, TexU : 7 + const TSP TSPTextureCacheMask = { { 7, 7 } }; + // TexAddr : 0x1FFFFF, Reserved : 0, StrideSel : 0, ScanOrder : 1, PixelFmt : 7, VQ_Comp : 1, MipMapped : 1 + const TCW TCWTextureCacheMask = { { 0x1FFFFF, 0, 0, 1, 7, 1, 1 } }; +}; -void CollectCleanup(); -void killtex(); void rend_text_invl(vram_block* bl); void ReadFramebuffer(PixelBuffer& pb, int& width, int& height); @@ -766,3 +800,4 @@ static inline void MakeFogTexture(u8 *tex_data) tex_data[i + 128] = fog_table[i * 4 + 1]; } } +u8* loadPNGData(const string& fname, int &width, int &height); diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index a933261a6..511c8d8b8 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -1001,9 +1001,7 @@ struct gl4rend : Renderer glcache.DeleteTextures(1, &depthSaveTexId); depthSaveTexId = 0; } - killtex(); - - CollectCleanup(); + TexCache.Clear(); gl_free_osd_resources(); free_output_framebuffer(); @@ -1011,16 +1009,20 @@ struct gl4rend : Renderer } bool Process(TA_context* ctx) override { return ProcessFrame(ctx); } - bool Render() override { return RenderFrame(); } + bool Render() override + { + RenderFrame(); + if (!pvrrc.isRTT) + DrawOSD(false); + + return !pvrrc.isRTT; + } bool RenderLastFrame() override { return !theGLContext.IsSwapBufferPreserved() ? gl4_render_output_framebuffer() : false; } void Present() override { theGLContext.Swap(); } void DrawOSD(bool clear_screen) override { - glBindVertexArray(gl4.vbo.main_vao); - glBindBuffer(GL_ARRAY_BUFFER, gl4.vbo.geometry); glCheck(); - OSD_DRAW(clear_screen); } diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 2deb04823..7b2f95b4c 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -5,6 +5,7 @@ #include "rend/gui.h" #include "wsi/gl_context.h" #include "cfg/cfg.h" +#include "rend/osd.h" #ifdef GLES #ifndef GL_RED @@ -381,13 +382,11 @@ out highp vec4 FragColor; \n\ \n\ in lowp vec4 vtx_base; \n\ in mediump vec2 vtx_uv; \n\ -/* Vertex input*/ \n\ + \n\ uniform sampler2D tex; \n\ void main() \n\ { \n\ - mediump vec2 uv=vtx_uv; \n\ - uv.y=1.0-uv.y; \n\ - gl_FragColor = vtx_base*texture(tex,uv.st); \n\ + gl_FragColor = vtx_base * texture(tex, vtx_uv); \n\ }"; GLCache glcache; @@ -746,7 +745,34 @@ bool CompilePipelineShader( PipelineShader* s) return glIsProgram(s->program)==GL_TRUE; } -GLuint osd_tex; +static void SetupOSDVBO() +{ +#ifndef GLES2 + if (gl.gl_major >= 3) + { + if (gl.OSD_SHADER.vao == 0) + glGenVertexArrays(1, &gl.OSD_SHADER.vao); + glBindVertexArray(gl.OSD_SHADER.vao); + } +#endif + if (gl.OSD_SHADER.geometry == 0) + glGenBuffers(1, &gl.OSD_SHADER.geometry); + glBindBuffer(GL_ARRAY_BUFFER, gl.OSD_SHADER.geometry); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + //setup vertex buffers attrib pointers + glEnableVertexAttribArray(VERTEX_POS_ARRAY); + glVertexAttribPointer(VERTEX_POS_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(OSDVertex), (void*)offsetof(OSDVertex, x)); + + glEnableVertexAttribArray(VERTEX_COL_BASE_ARRAY); + glVertexAttribPointer(VERTEX_COL_BASE_ARRAY, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(OSDVertex), (void*)offsetof(OSDVertex, r)); + + glEnableVertexAttribArray(VERTEX_UV_ARRAY); + glVertexAttribPointer(VERTEX_UV_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(OSDVertex), (void*)offsetof(OSDVertex, u)); + + glDisableVertexAttribArray(VERTEX_COL_OFFS_ARRAY); + glCheck(); +} void gl_load_osd_resources() { @@ -762,19 +788,26 @@ void gl_load_osd_resources() #ifdef __ANDROID__ int w, h; - if (osd_tex == 0) - osd_tex = loadPNG(get_readonly_data_path(DATA_PATH "buttons.png"), w, h); + if (gl.OSD_SHADER.osd_tex == 0) + gl.OSD_SHADER.osd_tex = loadPNG(get_readonly_data_path(DATA_PATH "buttons.png"), w, h); #endif + SetupOSDVBO(); } void gl_free_osd_resources() { glcache.DeleteProgram(gl.OSD_SHADER.program); - if (osd_tex != 0) { - glcache.DeleteTextures(1, &osd_tex); - osd_tex = 0; + if (gl.OSD_SHADER.osd_tex != 0) { + glcache.DeleteTextures(1, &gl.OSD_SHADER.osd_tex); + gl.OSD_SHADER.osd_tex = 0; } + glDeleteBuffers(1, &gl.OSD_SHADER.geometry); + gl.OSD_SHADER.geometry = 0; +#ifndef GLES2 + glDeleteVertexArrays(1, &gl.OSD_SHADER.vao); + gl.OSD_SHADER.vao = 0; +#endif } static void create_modvol_shader() @@ -893,143 +926,23 @@ void UpdateFogTexture(u8 *fog_table, GLenum texture_slot, GLint fog_image_format glActiveTexture(GL_TEXTURE0); } - -extern u16 kcode[4]; -extern u8 rt[4],lt[4]; - -#define VJOY_VISIBLE 14 - -#if defined(__ANDROID__) -extern float vjoy_pos[15][8]; -#else - -float vjoy_pos[15][8]= -{ - {24+0,24+64,64,64}, //LEFT - {24+64,24+0,64,64}, //UP - {24+128,24+64,64,64}, //RIGHT - {24+64,24+128,64,64}, //DOWN - - {440+0,280+64,64,64}, //X - {440+64,280+0,64,64}, //Y - {440+128,280+64,64,64}, //B - {440+64,280+128,64,64}, //A - - {320-32,360+32,64,64}, //Start - - {440,200,90,64}, //LT - {542,200,90,64}, //RT - - {-24,128+224,128,128}, //ANALOG_RING - {96,320,64,64}, //ANALOG_POINT - {320-32,24,64,64}, // FFORWARD - {1} // VJOY_VISIBLE -}; -#endif // !__ANDROID__ - -static List osd_vertices; -static bool osd_vertices_overrun; - -static const float vjoy_sz[2][15] = { - { 64,64,64,64, 64,64,64,64, 64, 90,90, 128, 64, 64 }, - { 64,64,64,64, 64,64,64,64, 64, 64,64, 128, 64, 64 }, -}; - -void HideOSD() -{ - vjoy_pos[VJOY_VISIBLE][0] = 0; -} - -static void DrawButton(float* xy, u32 state) -{ - Vertex vtx; - - vtx.z = 1; - - vtx.col[0]=vtx.col[1]=vtx.col[2]=(0x7F-0x40*state/255)*vjoy_pos[VJOY_VISIBLE][0]; - - vtx.col[3]=0xA0*vjoy_pos[VJOY_VISIBLE][4]; - - vjoy_pos[VJOY_VISIBLE][4]+=(vjoy_pos[VJOY_VISIBLE][0]-vjoy_pos[VJOY_VISIBLE][4])/2; - - - - vtx.x = xy[0]; vtx.y = xy[1]; - vtx.u=xy[4]; vtx.v=xy[5]; - *osd_vertices.Append() = vtx; - - vtx.x = xy[0] + xy[2]; vtx.y = xy[1]; - vtx.u=xy[6]; vtx.v=xy[5]; - *osd_vertices.Append() = vtx; - - vtx.x = xy[0]; vtx.y = xy[1] + xy[3]; - vtx.u=xy[4]; vtx.v=xy[7]; - *osd_vertices.Append() = vtx; - - vtx.x = xy[0] + xy[2]; vtx.y = xy[1] + xy[3]; - vtx.u=xy[6]; vtx.v=xy[7]; - *osd_vertices.Append() = vtx; -} - -static void DrawButton2(float* xy, bool state) { DrawButton(xy,state?0:255); } - -static void osd_gen_vertices() -{ - osd_vertices.Init(ARRAY_SIZE(vjoy_pos) * 4, &osd_vertices_overrun, "OSD vertices"); - DrawButton2(vjoy_pos[0],kcode[0] & DC_DPAD_LEFT); - DrawButton2(vjoy_pos[1],kcode[0] & DC_DPAD_UP); - DrawButton2(vjoy_pos[2],kcode[0] & DC_DPAD_RIGHT); - DrawButton2(vjoy_pos[3],kcode[0] & DC_DPAD_DOWN); - - DrawButton2(vjoy_pos[4],kcode[0] & DC_BTN_X); - DrawButton2(vjoy_pos[5],kcode[0] & DC_BTN_Y); - DrawButton2(vjoy_pos[6],kcode[0] & DC_BTN_B); - DrawButton2(vjoy_pos[7],kcode[0] & DC_BTN_A); - - DrawButton2(vjoy_pos[8],kcode[0] & DC_BTN_START); - - DrawButton(vjoy_pos[9],lt[0]); - - DrawButton(vjoy_pos[10],rt[0]); - - DrawButton2(vjoy_pos[11],1); - DrawButton2(vjoy_pos[12],0); - - DrawButton2(vjoy_pos[13], 0); -} - -#define OSD_TEX_W 512 -#define OSD_TEX_H 256 - void OSD_DRAW(bool clear_screen) { #ifdef __ANDROID__ - if (osd_tex == 0) + if (gl.OSD_SHADER.osd_tex == 0) gl_load_osd_resources(); - if (osd_tex != 0) + if (gl.OSD_SHADER.osd_tex != 0) { - osd_gen_vertices(); + const std::vector& osdVertices = GetOSDVertices(); - float u=0; - float v=0; +#ifndef GLES2 + if (gl.gl_major >= 3) + glBindVertexArray(gl.OSD_SHADER.vao); + else +#endif + SetupOSDVBO(); - for (int i = 0; i < 14; i++) - { - //umin,vmin,umax,vmax - vjoy_pos[i][4]=(u+1)/OSD_TEX_W; - vjoy_pos[i][5]=(v+1)/OSD_TEX_H; - - vjoy_pos[i][6]=((u+vjoy_sz[0][i]-1))/OSD_TEX_W; - vjoy_pos[i][7]=((v+vjoy_sz[1][i]-1))/OSD_TEX_H; - - u+=vjoy_sz[0][i]; - if (u>=OSD_TEX_W) - { - u-=OSD_TEX_W; - v+=vjoy_sz[1][i]; - } - //v+=vjoy_pos[i][3]; - } + glBindBuffer(GL_ARRAY_BUFFER, gl.OSD_SHADER.geometry); verify(glIsProgram(gl.OSD_SHADER.program)); glcache.UseProgram(gl.OSD_SHADER.program); @@ -1044,11 +957,11 @@ void OSD_DRAW(bool clear_screen) glUniform4fv(gl.OSD_SHADER.scale, 1, scale); glActiveTexture(GL_TEXTURE0); - glcache.BindTexture(GL_TEXTURE_2D, osd_tex); + glcache.BindTexture(GL_TEXTURE_2D, gl.OSD_SHADER.osd_tex); glBindFramebuffer(GL_FRAMEBUFFER, 0); - glBufferData(GL_ARRAY_BUFFER, osd_vertices.bytes(), osd_vertices.head(), GL_STREAM_DRAW); glCheck(); + glBufferData(GL_ARRAY_BUFFER, osdVertices.size() * sizeof(OSDVertex), osdVertices.data(), GL_STREAM_DRAW); glCheck(); glcache.Enable(GL_BLEND); glcache.Disable(GL_DEPTH_TEST); @@ -1066,10 +979,12 @@ void OSD_DRAW(bool clear_screen) glcache.ClearColor(0.7f, 0.7f, 0.7f, 1.f); glClear(GL_COLOR_BUFFER_BIT); } - int dfa = osd_vertices.used() / 4; + int dfa = osdVertices.size() / 4; for (int i = 0; i < dfa; i++) glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4); + + glCheck(); } #endif gui_display_osd(); @@ -1080,7 +995,7 @@ bool ProcessFrame(TA_context* ctx) ctx->rend_inuse.Lock(); if (KillTex) - killtex(); + TexCache.Clear(); if (ctx->rend.isRenderFramebuffer) { @@ -1092,7 +1007,7 @@ bool ProcessFrame(TA_context* ctx) if (!ta_parse_vdrc(ctx)) return false; } - CollectCleanup(); + TexCache.CollectCleanup(); if (ctx->rend.Overrun) WARN_LOG(PVR, "ERROR: TA context overrun"); @@ -1575,33 +1490,25 @@ struct glesrend : Renderer void Resize(int w, int h) override { screen_width=w; screen_height=h; } void Term() override { - killtex(); + TexCache.Clear(); gles_term(); } bool Process(TA_context* ctx) override { return ProcessFrame(ctx); } - bool Render() override { return RenderFrame(); } + bool Render() override + { + RenderFrame(); + if (!pvrrc.isRTT) + DrawOSD(false); + + return !pvrrc.isRTT; + } bool RenderLastFrame() override { return !theGLContext.IsSwapBufferPreserved() ? render_output_framebuffer() : false; } void Present() override { theGLContext.Swap(); glViewport(0, 0, screen_width, screen_height); } void DrawOSD(bool clear_screen) override { -#ifndef GLES2 - if (gl.gl_major >= 3) - glBindVertexArray(gl.vbo.vao); -#endif - glBindBuffer(GL_ARRAY_BUFFER, gl.vbo.geometry); - glEnableVertexAttribArray(VERTEX_POS_ARRAY); - glVertexAttribPointer(VERTEX_POS_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex,x)); - - glEnableVertexAttribArray(VERTEX_COL_BASE_ARRAY); - glVertexAttribPointer(VERTEX_COL_BASE_ARRAY, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex,col)); - - glEnableVertexAttribArray(VERTEX_UV_ARRAY); - glVertexAttribPointer(VERTEX_UV_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex,u)); - OSD_DRAW(clear_screen); - glCheck(); } virtual u64 GetTexture(TSP tsp, TCW tcw) override @@ -1611,150 +1518,6 @@ struct glesrend : Renderer }; -FILE* pngfile; - -void png_cstd_read(png_structp png_ptr, png_bytep data, png_size_t length) -{ - if (fread(data, 1, length, pngfile) != length) - png_error(png_ptr, "Truncated read error"); -} - -u8* loadPNGData(const string& fname, int &width, int &height) -{ - const char* filename=fname.c_str(); - FILE* file = fopen(filename, "rb"); - pngfile=file; - - if (!file) - { - EMUERROR("Error opening %s\n", filename); - return NULL; - } - - //header for testing if it is a png - png_byte header[8]; - - //read the header - if (fread(header, 1, 8, file) != 8) - { - fclose(file); - WARN_LOG(RENDERER, "Not a PNG file : %s", filename); - return NULL; - } - - //test if png - int is_png = !png_sig_cmp(header, 0, 8); - if (!is_png) - { - fclose(file); - WARN_LOG(RENDERER, "Not a PNG file : %s", filename); - return NULL; - } - - //create png struct - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, - NULL, NULL); - if (!png_ptr) - { - fclose(file); - WARN_LOG(RENDERER, "Unable to create PNG struct : %s", filename); - return (NULL); - } - - //create png info struct - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); - WARN_LOG(RENDERER, "Unable to create PNG info : %s", filename); - fclose(file); - return (NULL); - } - - //create png info struct - png_infop end_info = png_create_info_struct(png_ptr); - if (!end_info) - { - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); - WARN_LOG(RENDERER, "Unable to create PNG end info : %s", filename); - fclose(file); - return (NULL); - } - - //png error stuff, not sure libpng man suggests this. - if (setjmp(png_jmpbuf(png_ptr))) - { - fclose(file); - WARN_LOG(RENDERER, "Error during setjmp : %s", filename); - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - return (NULL); - } - - //init png reading - //png_init_io(png_ptr, fp); - png_set_read_fn(png_ptr, NULL, png_cstd_read); - - //let libpng know you already read the first 8 bytes - png_set_sig_bytes(png_ptr, 8); - - // read all the info up to the image data - png_read_info(png_ptr, info_ptr); - - //variables to pass to get info - int bit_depth, color_type; - png_uint_32 twidth, theight; - - // get info about png - png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, - NULL, NULL, NULL); - - //update width and height based on png info - width = twidth; - height = theight; - - // Update the png info struct. - png_read_update_info(png_ptr, info_ptr); - - // Row size in bytes. - int rowbytes = png_get_rowbytes(png_ptr, info_ptr); - - // Allocate the image_data as a big block, to be given to opengl - png_byte *image_data = new png_byte[rowbytes * height]; - if (!image_data) - { - //clean up memory and close stuff - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - WARN_LOG(RENDERER, "Unable to allocate image_data while loading %s", filename); - fclose(file); - return NULL; - } - - //row_pointers is for pointing to image_data for reading the png with libpng - png_bytep *row_pointers = new png_bytep[height]; - if (!row_pointers) - { - //clean up memory and close stuff - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - delete[] image_data; - WARN_LOG(RENDERER, "Unable to allocate row_pointer while loading %s", filename); - fclose(file); - return NULL; - } - - // set the individual row_pointers to point at the correct offsets of image_data - for (int i = 0; i < height; ++i) - row_pointers[height - 1 - i] = image_data + i * rowbytes; - - //read the png into image_data through row_pointers - png_read_image(png_ptr, row_pointers); - - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - delete[] row_pointers; - fclose(file); - - return image_data; -} - GLuint loadPNG(const string& fname, int &width, int &height) { png_byte *image_data = loadPNGData(fname, width, height); diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index cece2af63..b02c6932b 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -63,6 +63,9 @@ struct gl_ctx { GLuint program; GLuint scale; + GLuint vao; + GLuint geometry; + GLuint osd_tex; } OSD_SHADER; struct @@ -200,4 +203,9 @@ struct TextureCacheData : BaseTextureCacheData virtual bool Delete() override; }; +class TextureCache : public BaseTextureCache +{ +}; +extern TextureCache TexCache; + extern const u32 Zfunction[8]; diff --git a/core/rend/gles/gltex.cpp b/core/rend/gles/gltex.cpp index 92526880a..d8825d432 100644 --- a/core/rend/gles/gltex.cpp +++ b/core/rend/gles/gltex.cpp @@ -30,6 +30,7 @@ Compression #endif extern u32 decoded_colors[3][65536]; +TextureCache TexCache; static void dumpRtTexture(u32 name, u32 w, u32 h) { char sname[256]; @@ -319,7 +320,7 @@ void ReadRTTBuffer() { for (tsp.TexU = 0; tsp.TexU <= 7 && (8 << tsp.TexU) < w; tsp.TexU++); for (tsp.TexV = 0; tsp.TexV <= 7 && (8 << tsp.TexV) < h; tsp.TexV++); - TextureCacheData *texture_data = static_cast(getTextureCacheData(tsp, tcw, [](){ return (BaseTextureCacheData *)new TextureCacheData(); })); + TextureCacheData *texture_data = TexCache.getTextureCacheData(tsp, tcw); if (texture_data->texID != 0) glcache.DeleteTextures(1, &texture_data->texID); else @@ -345,7 +346,7 @@ u64 gl_GetTexture(TSP tsp, TCW tcw) TexCacheLookups++; //lookup texture - TextureCacheData* tf = static_cast(getTextureCacheData(tsp, tcw, [](){ return (BaseTextureCacheData *)new TextureCacheData(); })); + TextureCacheData* tf = TexCache.getTextureCacheData(tsp, tcw); if (tf->texID == 0) { @@ -380,7 +381,7 @@ text_info raw_GetTexture(TSP tsp, TCW tcw) text_info rv = { 0 }; //lookup texture - TextureCacheData* tf = static_cast(getTextureCacheData(tsp, tcw, [](){ return (BaseTextureCacheData *)new TextureCacheData(); })); + TextureCacheData* tf = TexCache.getTextureCacheData(tsp, tcw); if (tf->pData == nullptr) tf->Create(); diff --git a/core/rend/osd.cpp b/core/rend/osd.cpp new file mode 100644 index 000000000..2734e7f59 --- /dev/null +++ b/core/rend/osd.cpp @@ -0,0 +1,132 @@ +// Personal message to whoever wrote this code originally: please quit programming. Stop making other people's life miserable + +#include "osd.h" +#include "types.h" +#include "input/gamepad.h" + +extern u16 kcode[4]; +extern u8 rt[4], lt[4]; + +#if defined(__ANDROID__) +extern float vjoy_pos[15][8]; +#else + +static float vjoy_pos[15][8]= +{ + {24+0,24+64,64,64}, //LEFT + {24+64,24+0,64,64}, //UP + {24+128,24+64,64,64}, //RIGHT + {24+64,24+128,64,64}, //DOWN + + {440+0,280+64,64,64}, //X + {440+64,280+0,64,64}, //Y + {440+128,280+64,64,64}, //B + {440+64,280+128,64,64}, //A + + {320-32,360+32,64,64}, //Start + + {440,200,90,64}, //LT + {542,200,90,64}, //RT + + {-24,128+224,128,128}, //ANALOG_RING + {96,320,64,64}, //ANALOG_POINT + {320-32,24,64,64}, // FFORWARD + {1} // VJOY_VISIBLE +}; +#endif // !__ANDROID__ + +static const float vjoy_sz[2][15] = { + { 64,64,64,64, 64,64,64,64, 64, 90,90, 128, 64, 64 }, + { 64,64,64,64, 64,64,64,64, 64, 64,64, 128, 64, 64 }, +}; + +static std::vector osdVertices; + +void HideOSD() +{ + vjoy_pos[VJOY_VISIBLE][0] = 0; +} + +static void DrawButton(const float xy[8], u32 state) +{ + OSDVertex vtx; + + vtx.r = vtx.g = vtx.b = (0x7F - 0x40 * state / 255) * vjoy_pos[VJOY_VISIBLE][0]; + vtx.a = 0xA0 * vjoy_pos[VJOY_VISIBLE][4]; + vjoy_pos[VJOY_VISIBLE][4] += (vjoy_pos[VJOY_VISIBLE][0] - vjoy_pos[VJOY_VISIBLE][4]) / 2; + + vtx.x = xy[0]; vtx.y = xy[1]; + vtx.u = xy[4]; vtx.v = xy[5]; + osdVertices.push_back(vtx); + + vtx.x = xy[0] + xy[2]; vtx.y = xy[1]; + vtx.u = xy[6]; vtx.v = xy[5]; + osdVertices.push_back(vtx); + + vtx.x = xy[0]; vtx.y = xy[1] + xy[3]; + vtx.u = xy[4]; vtx.v = xy[7]; + osdVertices.push_back(vtx); + + vtx.x = xy[0] + xy[2]; vtx.y = xy[1] + xy[3]; + vtx.u = xy[6]; vtx.v = xy[7]; + osdVertices.push_back(vtx); +} + +static void DrawButton2(const float xy[8], bool state) +{ + DrawButton(xy, state ? 0 : 255); +} + +const std::vector& GetOSDVertices() +{ + osdVertices.reserve(ARRAY_SIZE(vjoy_pos) * 4); + osdVertices.clear(); + DrawButton2(vjoy_pos[0], kcode[0] & DC_DPAD_LEFT); + DrawButton2(vjoy_pos[1], kcode[0] & DC_DPAD_UP); + DrawButton2(vjoy_pos[2], kcode[0] & DC_DPAD_RIGHT); + DrawButton2(vjoy_pos[3], kcode[0] & DC_DPAD_DOWN); + + DrawButton2(vjoy_pos[4], kcode[0] & DC_BTN_X); + DrawButton2(vjoy_pos[5], kcode[0] & DC_BTN_Y); + DrawButton2(vjoy_pos[6], kcode[0] & DC_BTN_B); + DrawButton2(vjoy_pos[7], kcode[0] & DC_BTN_A); + + DrawButton2(vjoy_pos[8], kcode[0] & DC_BTN_START); + + DrawButton(vjoy_pos[9], lt[0]); + + DrawButton(vjoy_pos[10], rt[0]); + + DrawButton2(vjoy_pos[11], 1); + DrawButton2(vjoy_pos[12], 0); + + DrawButton2(vjoy_pos[13], 0); + + return osdVertices; +} + +static void setVjoyUV() +{ + float u = 0; + float v = 0; + + for (int i = 0; i < VJOY_VISIBLE; i++) + { + //umin, vmin, umax, vmax + vjoy_pos[i][4] = (u + 1) / OSD_TEX_W; + vjoy_pos[i][5] = 1.f - (v + 1) / OSD_TEX_H; + + vjoy_pos[i][6] = (u + vjoy_sz[0][i] - 1) / OSD_TEX_W; + vjoy_pos[i][7] = 1.f - (v + vjoy_sz[1][i] - 1) / OSD_TEX_H; + + u += vjoy_sz[0][i]; + if (u >= OSD_TEX_W) + { + u -= OSD_TEX_W; + v += vjoy_sz[1][i]; + } + } +} + +static OnLoad setVjoyUVOnLoad(&setVjoyUV); + diff --git a/core/rend/osd.h b/core/rend/osd.h new file mode 100644 index 000000000..00a201231 --- /dev/null +++ b/core/rend/osd.h @@ -0,0 +1,15 @@ +#include +#include "types.h" + +#define VJOY_VISIBLE 14 +#define OSD_TEX_W 512 +#define OSD_TEX_H 256 + +struct OSDVertex +{ + float x, y; + float u, v; + u8 r, g, b, a; +}; + +const std::vector& GetOSDVertices(); diff --git a/core/rend/vulkan/buffer.h b/core/rend/vulkan/buffer.h index efe301136..ee40397b5 100644 --- a/core/rend/vulkan/buffer.h +++ b/core/rend/vulkan/buffer.h @@ -36,7 +36,7 @@ struct BufferData void upload(vk::Device const& device, u32 size, const void *data, u32 bufOffset = 0) const { verify((m_propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent) && (m_propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)); - verify(offset + bufOffset + size <= bufferSize); + verify(bufOffset + size <= bufferSize); void* dataPtr = device.mapMemory(sharedDeviceMemory, offset + bufOffset, size); memcpy(dataPtr, data, size); @@ -50,7 +50,7 @@ struct BufferData u32 totalSize = 0; for (int i = 0; i < count; i++) totalSize += sizes[i]; - verify(offset + bufOffset + totalSize <= bufferSize); + verify(bufOffset + totalSize <= bufferSize); void* dataPtr = device.mapMemory(sharedDeviceMemory, offset + bufOffset, totalSize); for (int i = 0; i < count; i++) { @@ -64,7 +64,7 @@ struct BufferData void download(vk::Device const& device, u32 size, void *data, u32 bufOffset = 0) const { verify((m_propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent) && (m_propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)); - verify(offset + bufOffset + size <= bufferSize); + verify(bufOffset + size <= bufferSize); void* dataPtr = device.mapMemory(sharedDeviceMemory, offset + bufOffset, size); memcpy(data, dataPtr, size); diff --git a/core/rend/vulkan/drawer.cpp b/core/rend/vulkan/drawer.cpp index fa7b77b1b..9079b0c5d 100644 --- a/core/rend/vulkan/drawer.cpp +++ b/core/rend/vulkan/drawer.cpp @@ -448,8 +448,6 @@ bool Drawer::Draw(const Texture *fogTexture) if (!is_rtt) gui_display_osd(); - EndRenderPass(); - return !is_rtt; } @@ -477,7 +475,7 @@ vk::CommandBuffer TextureDrawer::BeginRenderPass() heightPow2 *= settings.rend.RenderToTextureUpscale; } - static_cast(pipelineManager.get())->CheckSettingsChange(); + static_cast(pipelineManager)->CheckSettingsChange(); VulkanContext *context = GetContext(); vk::Device device = *context->GetDevice(); @@ -514,11 +512,14 @@ vk::CommandBuffer TextureDrawer::BeginRenderPass() for (tsp.TexU = 0; tsp.TexU <= 7 && (8 << tsp.TexU) < origWidth; tsp.TexU++); for (tsp.TexV = 0; tsp.TexV <= 7 && (8 << tsp.TexV) < origHeight; tsp.TexV++); - texture = static_cast(getTextureCacheData(tsp, tcw, [this](){ - return (BaseTextureCacheData *)new Texture(VulkanContext::Instance()->GetPhysicalDevice(), *VulkanContext::Instance()->GetDevice(), this->texAllocator); - })); + texture = textureCache->getTextureCacheData(tsp, tcw); if (texture->IsNew()) + { texture->Create(); + texture->SetAllocator(texAllocator); + texture->SetPhysicalDevice(GetContext()->GetPhysicalDevice()); + texture->SetDevice(*GetContext()->GetDevice()); + } if (texture->format != vk::Format::eR8G8B8A8Unorm) { texture->extent = vk::Extent2D(widthPow2, heightPow2); diff --git a/core/rend/vulkan/drawer.h b/core/rend/vulkan/drawer.h index f3fbbaaec..980b434c5 100644 --- a/core/rend/vulkan/drawer.h +++ b/core/rend/vulkan/drawer.h @@ -56,17 +56,17 @@ public: } protected: - void Init(SamplerManager *samplerManager, ShaderManager *shaderManager) + void Init(SamplerManager *samplerManager, PipelineManager *pipelineManager) { + this->pipelineManager = pipelineManager; this->samplerManager = samplerManager; - pipelineManager->Init(shaderManager); } virtual DescriptorSets& GetCurrentDescSet() = 0; virtual BufferData *GetMainBuffer(u32 size) = 0; VulkanContext *GetContext() const { return VulkanContext::Instance(); } - std::unique_ptr pipelineManager; + PipelineManager *pipelineManager = nullptr; vk::Rect2D baseScissor; // temp stuff float scale_x = 1.f; @@ -106,9 +106,10 @@ class ScreenDrawer : public Drawer public: void Init(SamplerManager *samplerManager, ShaderManager *shaderManager) { - if (!pipelineManager) - pipelineManager = std::unique_ptr(new PipelineManager()); - Drawer::Init(samplerManager, shaderManager); + if (!screenPipelineManager) + screenPipelineManager = std::unique_ptr(new PipelineManager()); + screenPipelineManager->Init(shaderManager); + Drawer::Init(samplerManager, screenPipelineManager.get()); if (descriptorSets.size() > GetContext()->GetSwapChainSize()) descriptorSets.resize(GetContext()->GetSwapChainSize()); @@ -116,7 +117,7 @@ public: while (descriptorSets.size() < GetContext()->GetSwapChainSize()) { descriptorSets.push_back(DescriptorSets()); - descriptorSets.back().Init(samplerManager, pipelineManager->GetPipelineLayout(), pipelineManager->GetPerFrameDSLayout(), pipelineManager->GetPerPolyDSLayout()); + descriptorSets.back().Init(samplerManager, screenPipelineManager->GetPipelineLayout(), screenPipelineManager->GetPerFrameDSLayout(), screenPipelineManager->GetPerPolyDSLayout()); } } ScreenDrawer() = default; @@ -158,19 +159,20 @@ private: std::vector descriptorSets; std::vector> mainBuffers; + std::unique_ptr screenPipelineManager; }; class TextureDrawer : public Drawer { public: - void Init(SamplerManager *samplerManager, ShaderManager *shaderManager, VulkanAllocator *texAllocator) + void Init(SamplerManager *samplerManager, VulkanAllocator *texAllocator, RttPipelineManager *pipelineManager, TextureCache *textureCache) { - pipelineManager = std::unique_ptr(new RttPipelineManager()); - Drawer::Init(samplerManager, shaderManager); + Drawer::Init(samplerManager, pipelineManager); descriptorSets.Init(samplerManager, pipelineManager->GetPipelineLayout(), pipelineManager->GetPerFrameDSLayout(), pipelineManager->GetPerPolyDSLayout()); fence = GetContext()->GetDevice()->createFenceUnique(vk::FenceCreateInfo()); this->texAllocator = texAllocator; + this->textureCache = textureCache; } void SetCommandPool(CommandPool *commandPool) { this->commandPool = commandPool; } @@ -179,10 +181,10 @@ public: TextureDrawer(TextureDrawer&& other) = default; TextureDrawer& operator=(const TextureDrawer& other) = delete; TextureDrawer& operator=(TextureDrawer&& other) = default; + virtual void EndRenderPass() override; protected: virtual vk::CommandBuffer BeginRenderPass() override; - virtual void EndRenderPass() override; DescriptorSets& GetCurrentDescSet() override { return descriptorSets; } virtual BufferData* GetMainBuffer(u32 size) override @@ -216,4 +218,5 @@ private: std::unique_ptr mainBuffer; CommandPool *commandPool = nullptr; VulkanAllocator *texAllocator = nullptr; + TextureCache *textureCache = nullptr; }; diff --git a/core/rend/vulkan/pipeline.cpp b/core/rend/vulkan/pipeline.cpp index 74a7af2c3..ac9f30814 100644 --- a/core/rend/vulkan/pipeline.cpp +++ b/core/rend/vulkan/pipeline.cpp @@ -20,6 +20,7 @@ */ #include "pipeline.h" #include "hw/pvr/Renderer_if.h" +#include "rend/osd.h" static const vk::CompareOp depthOps[] = { @@ -379,9 +380,17 @@ void QuadPipeline::CreatePipeline() vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo; // Color flags and blending - vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState; - pipelineColorBlendAttachmentState.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG - | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA; + vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState( + true, // blendEnable + vk::BlendFactor::eConstantAlpha, // srcColorBlendFactor + vk::BlendFactor::eOneMinusConstantAlpha, // dstColorBlendFactor + vk::BlendOp::eAdd, // colorBlendOp + vk::BlendFactor::eConstantAlpha, // srcAlphaBlendFactor + vk::BlendFactor::eOneMinusConstantAlpha, // dstAlphaBlendFactor + vk::BlendOp::eAdd, // alphaBlendOp + vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG + | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA + ); vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo ( vk::PipelineColorBlendStateCreateFlags(), // flags @@ -392,8 +401,9 @@ void QuadPipeline::CreatePipeline() { { 1.0f, 1.0f, 1.0f, 1.0f } } // blendConstants ); - vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; - vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates); + vk::DynamicState dynamicStates[] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor, vk::DynamicState::eBlendConstants }; + vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), ARRAY_SIZE(dynamicStates), + dynamicStates); vk::PipelineShaderStageCreateInfo stages[] = { { vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eVertex, shaderManager->GetQuadVertexShader(), "main" }, @@ -419,3 +429,88 @@ void QuadPipeline::CreatePipeline() pipeline = GetContext()->GetDevice()->createGraphicsPipelineUnique(GetContext()->GetPipelineCache(), graphicsPipelineCreateInfo); } + +void OSDPipeline::CreatePipeline() +{ + // Vertex input state + static const vk::VertexInputBindingDescription vertexBindingDescriptions[] = + { + { 0, sizeof(OSDVertex) }, + }; + static const vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[] = + { + vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32Sfloat, offsetof(OSDVertex, x)), // pos + vk::VertexInputAttributeDescription(1, 0, vk::Format::eR8G8B8A8Uint, offsetof(OSDVertex, r)), // color + vk::VertexInputAttributeDescription(2, 0, vk::Format::eR32G32Sfloat, offsetof(OSDVertex, u)), // tex coord + }; + vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo( + vk::PipelineVertexInputStateCreateFlags(), + ARRAY_SIZE(vertexBindingDescriptions), + vertexBindingDescriptions, + ARRAY_SIZE(vertexInputAttributeDescriptions), + vertexInputAttributeDescriptions); + + // Input assembly state + vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(vk::PipelineInputAssemblyStateCreateFlags(), vk::PrimitiveTopology::eTriangleStrip); + + // Viewport and scissor states + vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(vk::PipelineViewportStateCreateFlags(), 1, nullptr, 1, nullptr); + + // Rasterization and multisample states + vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo; + pipelineRasterizationStateCreateInfo.lineWidth = 1.0; + vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo; + + // Depth and stencil + vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo; + + // Color flags and blending + vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState( + true, // blendEnable + vk::BlendFactor::eSrcAlpha, // srcColorBlendFactor + vk::BlendFactor::eOneMinusSrcAlpha, // dstColorBlendFactor + vk::BlendOp::eAdd, // colorBlendOp + vk::BlendFactor::eSrcAlpha, // srcAlphaBlendFactor + vk::BlendFactor::eOneMinusSrcAlpha, // dstAlphaBlendFactor + vk::BlendOp::eAdd, // alphaBlendOp + vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG + | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA + ); + vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo + ( + vk::PipelineColorBlendStateCreateFlags(), // flags + false, // logicOpEnable + vk::LogicOp::eNoOp, // logicOp + 1, // attachmentCount + &pipelineColorBlendAttachmentState, // pAttachments + { { 1.0f, 1.0f, 1.0f, 1.0f } } // blendConstants + ); + + vk::DynamicState dynamicStates[] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; + vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), ARRAY_SIZE(dynamicStates), + dynamicStates); + + vk::PipelineShaderStageCreateInfo stages[] = { + { vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eVertex, shaderManager->GetOSDVertexShader(), "main" }, + { vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, shaderManager->GetOSDFragmentShader(), "main" }, + }; + vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo + ( + vk::PipelineCreateFlags(), // flags + 2, // stageCount + stages, // pStages + &vertexInputStateCreateInfo, // pVertexInputState + &pipelineInputAssemblyStateCreateInfo, // pInputAssemblyState + nullptr, // pTessellationState + &pipelineViewportStateCreateInfo, // pViewportState + &pipelineRasterizationStateCreateInfo, // pRasterizationState + &pipelineMultisampleStateCreateInfo, // pMultisampleState + &pipelineDepthStencilStateCreateInfo, // pDepthStencilState + &pipelineColorBlendStateCreateInfo, // pColorBlendState + &pipelineDynamicStateCreateInfo, // pDynamicState + *pipelineLayout, // layout + renderPass // renderPass + ); + + pipeline = GetContext()->GetDevice()->createGraphicsPipelineUnique(GetContext()->GetPipelineCache(), graphicsPipelineCreateInfo); +} diff --git a/core/rend/vulkan/pipeline.h b/core/rend/vulkan/pipeline.h index daeae465e..56a5c7ab5 100644 --- a/core/rend/vulkan/pipeline.h +++ b/core/rend/vulkan/pipeline.h @@ -304,7 +304,7 @@ public: descSetLayout = GetContext()->GetDevice()->createDescriptorSetLayoutUnique( vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), ARRAY_SIZE(bindings), bindings)); pipelineLayout = GetContext()->GetDevice()->createPipelineLayoutUnique( - vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descSetLayout.get(), 0, nullptr)); + vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descSetLayout.get())); } if (!sampler) { @@ -360,5 +360,69 @@ private: vk::UniquePipelineLayout pipelineLayout; vk::UniqueDescriptorSetLayout descSetLayout; ShaderManager *shaderManager; - SamplerManager *samplerManager; +}; + +class OSDPipeline +{ +public: + void Init(ShaderManager *shaderManager, vk::ImageView imageView) + { + this->shaderManager = shaderManager; + if (!pipelineLayout) + { + vk::DescriptorSetLayoutBinding bindings[] = { + { 0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment },// texture + }; + descSetLayout = GetContext()->GetDevice()->createDescriptorSetLayoutUnique( + vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), ARRAY_SIZE(bindings), bindings)); + pipelineLayout = GetContext()->GetDevice()->createPipelineLayoutUnique( + vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descSetLayout.get())); + } + if (!sampler) + { + sampler = VulkanContext::Instance()->GetDevice()->createSamplerUnique( + vk::SamplerCreateInfo(vk::SamplerCreateFlags(), vk::Filter::eLinear, vk::Filter::eLinear, + vk::SamplerMipmapMode::eLinear, vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, + vk::SamplerAddressMode::eClampToEdge, 0.0f, false, 16.0f, false, + vk::CompareOp::eNever, 0.0f, 0.0f, vk::BorderColor::eFloatOpaqueBlack)); + } + if (GetContext()->GetRenderPass() != renderPass) + { + renderPass = GetContext()->GetRenderPass(); + pipeline.reset(); + } + if (!descriptorSet) + { + descriptorSet = std::move(GetContext()->GetDevice()->allocateDescriptorSetsUnique( + vk::DescriptorSetAllocateInfo(GetContext()->GetDescriptorPool(), 1, &descSetLayout.get())).front()); + } + vk::DescriptorImageInfo imageInfo(*sampler, imageView, vk::ImageLayout::eShaderReadOnlyOptimal); + std::vector writeDescriptorSets; + writeDescriptorSets.push_back(vk::WriteDescriptorSet(*descriptorSet, 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr)); + GetContext()->GetDevice()->updateDescriptorSets(writeDescriptorSets, nullptr); + } + + vk::Pipeline GetPipeline() + { + if (!pipeline) + CreatePipeline(); + return *pipeline; + } + + void BindDescriptorSets(vk::CommandBuffer cmdBuffer) const + { + cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, nullptr); + } + +private: + VulkanContext *GetContext() const { return VulkanContext::Instance(); } + void CreatePipeline(); + + vk::RenderPass renderPass; + vk::UniquePipeline pipeline; + vk::UniqueSampler sampler; + vk::UniqueDescriptorSet descriptorSet; + vk::UniquePipelineLayout pipelineLayout; + vk::UniqueDescriptorSetLayout descSetLayout; + ShaderManager *shaderManager; }; diff --git a/core/rend/vulkan/shaders.cpp b/core/rend/vulkan/shaders.cpp index 6d912d660..a2d447c90 100644 --- a/core/rend/vulkan/shaders.cpp +++ b/core/rend/vulkan/shaders.cpp @@ -324,6 +324,41 @@ void main() } )"; +static const char OSDVertexShaderSource[] = R"( +#version 400 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec4 inPos; +layout (location = 1) in uvec4 inColor; +layout (location = 2) in vec2 inUV; +layout (location = 0) out lowp vec4 outColor; +layout (location = 1) out mediump vec2 outUV; + +void main() +{ + outColor = inColor / 255.0; + outUV = inUV; + gl_Position = inPos; +} +)"; + +static const char OSDFragmentShaderSource[] = R"( +#version 400 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (binding = 0) uniform sampler2D tex; +layout (location = 0) in lowp vec4 inColor; +layout (location = 1) in mediump vec2 inUV; +layout (location = 0) out vec4 FragColor; + +void main() +{ + FragColor = inColor * texture(tex, inUV); +} +)"; + static const TBuiltInResource DefaultTBuiltInResource = { /* .MaxLights = */ 32, /* .MaxClipPlanes = */ 6, @@ -540,3 +575,13 @@ vk::UniqueShaderModule ShaderManager::compileQuadFragmentShader() { return createShaderModule(VulkanContext::Instance()->GetDevice(), vk::ShaderStageFlagBits::eFragment, QuadFragmentShaderSource); } + +vk::UniqueShaderModule ShaderManager::compileOSDVertexShader() +{ + return createShaderModule(VulkanContext::Instance()->GetDevice(), vk::ShaderStageFlagBits::eVertex, OSDVertexShaderSource); +} + +vk::UniqueShaderModule ShaderManager::compileOSDFragmentShader() +{ + return createShaderModule(VulkanContext::Instance()->GetDevice(), vk::ShaderStageFlagBits::eFragment, OSDFragmentShaderSource); +} diff --git a/core/rend/vulkan/shaders.h b/core/rend/vulkan/shaders.h index 6360365e5..6e5deea10 100644 --- a/core/rend/vulkan/shaders.h +++ b/core/rend/vulkan/shaders.h @@ -111,6 +111,18 @@ public: quadFragmentShader = compileQuadFragmentShader(); return *quadFragmentShader; } + vk::ShaderModule GetOSDVertexShader() + { + if (!osdVertexShader) + osdVertexShader = compileOSDVertexShader(); + return *osdVertexShader; + } + vk::ShaderModule GetOSDFragmentShader() + { + if (!osdFragmentShader) + osdFragmentShader = compileOSDFragmentShader(); + return *osdFragmentShader; + } private: template @@ -128,6 +140,8 @@ private: vk::UniqueShaderModule compileModVolFragmentShader(); vk::UniqueShaderModule compileQuadVertexShader(); vk::UniqueShaderModule compileQuadFragmentShader(); + vk::UniqueShaderModule compileOSDVertexShader(); + vk::UniqueShaderModule compileOSDFragmentShader(); std::map vertexShaders; std::map fragmentShaders; @@ -135,4 +149,6 @@ private: vk::UniqueShaderModule modVolShader; vk::UniqueShaderModule quadVertexShader; vk::UniqueShaderModule quadFragmentShader; + vk::UniqueShaderModule osdVertexShader; + vk::UniqueShaderModule osdFragmentShader; }; diff --git a/core/rend/vulkan/texture.cpp b/core/rend/vulkan/texture.cpp index 8b46fa98e..9b6212c79 100644 --- a/core/rend/vulkan/texture.cpp +++ b/core/rend/vulkan/texture.cpp @@ -235,6 +235,7 @@ void Texture::CreateImage(vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk: void Texture::SetImage(u32 srcSize, void *srcData, bool isNew) { + verify((bool)commandBuffer); commandBuffer.begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit)); if (!isNew && !needsStaging) diff --git a/core/rend/vulkan/texture.h b/core/rend/vulkan/texture.h index f3de8a44c..f41f23240 100644 --- a/core/rend/vulkan/texture.h +++ b/core/rend/vulkan/texture.h @@ -29,9 +29,6 @@ void setImageLayout(vk::CommandBuffer const& commandBuffer, vk::Image image, vk: struct Texture : BaseTextureCacheData { - Texture(vk::PhysicalDevice physicalDevice, vk::Device device, VulkanAllocator *allocator = nullptr) - : physicalDevice(physicalDevice), device(device), format(vk::Format::eUndefined), allocator(allocator) - {} ~Texture() override { imageView.reset(); @@ -47,6 +44,10 @@ struct Texture : BaseTextureCacheData void SetCommandBuffer(vk::CommandBuffer commandBuffer) { this->commandBuffer = commandBuffer; } virtual bool Force32BitTexture(TextureType type) override { return !VulkanContext::Instance()->IsFormatSupported(type); } + void SetAllocator(VulkanAllocator *allocator) { this->allocator = allocator; } + void SetPhysicalDevice(vk::PhysicalDevice physicalDevice) { this->physicalDevice = physicalDevice; } + void SetDevice(vk::Device device) { this->device = device; } + private: void Init(u32 width, u32 height, vk::Format format); void SetImage(u32 size, void *data, bool isNew); @@ -54,7 +55,7 @@ private: vk::MemoryPropertyFlags memoryProperties, vk::ImageAspectFlags aspectMask); void GenerateMipmaps(); - vk::Format format; + vk::Format format = vk::Format::eUndefined; vk::Extent2D extent; u32 mipmapLevels = 1; bool needsStaging = false; @@ -67,7 +68,7 @@ private: vk::PhysicalDevice physicalDevice; vk::Device device; - VulkanAllocator *allocator; + VulkanAllocator *allocator = nullptr; vk::DeviceMemory sharedDeviceMemory; u32 memoryType = 0; vk::DeviceSize memoryOffset = 0; @@ -129,3 +130,7 @@ private: vk::PhysicalDevice physicalDevice; vk::Device device; }; + +class TextureCache : public BaseTextureCache +{ +}; diff --git a/core/rend/vulkan/vulkan_renderer.cpp b/core/rend/vulkan/vulkan_renderer.cpp index 9c462c72d..b89135251 100644 --- a/core/rend/vulkan/vulkan_renderer.cpp +++ b/core/rend/vulkan/vulkan_renderer.cpp @@ -26,7 +26,8 @@ #include "commandpool.h" #include "drawer.h" #include "shaders.h" -#include "../gui.h" +#include "rend/gui.h" +#include "rend/osd.h" extern bool ProcessFrame(TA_context* ctx); @@ -41,14 +42,55 @@ public: // FIXME this might be called after initial init texAllocator.SetChunkSize(16 * 1024 * 1024); - while (textureDrawer.size() < 2) - textureDrawer.emplace_back(); - textureDrawer[0].Init(&samplerManager, &shaderManager, &texAllocator); - textureDrawer[0].SetCommandPool(&texCommandPool); - textureDrawer[1].Init(&samplerManager, &shaderManager, &texAllocator); - textureDrawer[1].SetCommandPool(&texCommandPool); + rttPipelineManager.Init(&shaderManager); + if (textureDrawer.size() > GetContext()->GetSwapChainSize()) + textureDrawer.resize(GetContext()->GetSwapChainSize()); + else + { + while (textureDrawer.size() < GetContext()->GetSwapChainSize()) + textureDrawer.emplace_back(); + } + for (auto& drawer : textureDrawer) + { + drawer.Init(&samplerManager, &texAllocator, &rttPipelineManager, &textureCache); + drawer.SetCommandPool(&texCommandPool); + } + screenDrawer.Init(&samplerManager, &shaderManager); quadPipeline.Init(&shaderManager); +#ifdef __ANDROID__ + if (!vjoyTexture) + { + int w, h; + u8 *image_data = loadPNGData(get_readonly_data_path(DATA_PATH "buttons.png"), w, h); + if (image_data == nullptr) + { + WARN_LOG(RENDERER, "Cannot load buttons.png image"); + } + else + { + vjoyTexture = std::unique_ptr(new Texture()); + vjoyTexture->tex_type = TextureType::_8888; + vjoyTexture->tcw.full = 0; + vjoyTexture->tsp.full = 0; + vjoyTexture->SetAllocator(&texAllocator); + vjoyTexture->SetPhysicalDevice(GetContext()->GetPhysicalDevice()); + vjoyTexture->SetDevice(*GetContext()->GetDevice()); + vjoyTexture->SetCommandBuffer(texCommandPool.Allocate()); + vjoyTexture->UploadToGPU(OSD_TEX_W, OSD_TEX_H, image_data); + vjoyTexture->SetCommandBuffer(nullptr); + delete [] image_data; + osdPipeline.Init(&shaderManager, vjoyTexture->GetImageView()); + } + } + if (!osdBuffer) + { + osdBuffer = std::unique_ptr(new BufferData(GetContext()->GetPhysicalDevice(), GetContext()->GetDevice().get(), + sizeof(OSDVertex) * VJOY_VISIBLE * 4, + vk::BufferUsageFlagBits::eVertexBuffer, &texAllocator)); + } +#endif + return true; } @@ -58,13 +100,14 @@ public: texCommandPool.Init(); screenDrawer.Init(&samplerManager, &shaderManager); quadPipeline.Init(&shaderManager); + osdPipeline.Init(&shaderManager, vjoyTexture->GetImageView()); } void Term() override { DEBUG_LOG(RENDERER, "VulkanRenderer::Term"); GetContext()->WaitIdle(); - killtex(); + textureCache.Clear(); fogTexture = nullptr; texCommandPool.Term(); shaderManager.Term(); @@ -86,10 +129,13 @@ public: std::unique_ptr& curTexture = framebufferTextures[GetContext()->GetCurrentImageIndex()]; if (!curTexture) { - curTexture = std::unique_ptr(new Texture(GetContext()->GetPhysicalDevice(), *GetContext()->GetDevice(), &texAllocator)); + curTexture = std::unique_ptr(new Texture()); curTexture->tex_type = TextureType::_8888; curTexture->tcw.full = 0; curTexture->tsp.full = 0; + curTexture->SetAllocator(&texAllocator); + curTexture->SetPhysicalDevice(GetContext()->GetPhysicalDevice()); + curTexture->SetDevice(*GetContext()->GetDevice()); } curTexture->SetCommandBuffer(texCommandPool.Allocate()); curTexture->UploadToGPU(width, height, (u8*)pb.data()); @@ -117,6 +163,8 @@ public: quadPipeline.SetTexture(curTexture.get()); quadPipeline.BindDescriptorSets(cmdBuffer); + float blendConstants[4] = { 1.0, 1.0, 1.0, 1.0 }; + cmdBuffer.setBlendConstants(blendConstants); // FIXME scaling, stretching... vk::Viewport viewport(ds2s_offs_x, 0.f, screen_width - ds2s_offs_x * 2, (float)screen_height); cmdBuffer.setViewport(0, 1, &viewport); @@ -138,7 +186,19 @@ public: return RenderFramebuffer(); } - bool result = ProcessFrame(ctx); + ctx->rend_inuse.Lock(); + + if (KillTex) + textureCache.Clear(); + + bool result = ta_parse_vdrc(ctx); + + textureCache.CollectCleanup(); + + if (ctx->rend.Overrun) + WARN_LOG(PVR, "ERROR: TA context overrun"); + + result = result && !ctx->rend.Overrun; if (result) CheckFogTexture(); @@ -151,6 +211,51 @@ public: void DrawOSD(bool clear_screen) override { + if (!vjoyTexture) + return; + if (clear_screen) + { + GetContext()->NewFrame(); + GetContext()->BeginRenderPass(); + } + const float screen_stretching = settings.rend.ScreenStretching / 100.f; + float dc2s_scale_h, ds2s_offs_x; + if (settings.rend.Rotate90) + { + dc2s_scale_h = screen_height / 640.0f; + ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0f * screen_stretching) / 2; + } + else + { + dc2s_scale_h = screen_height / 480.0f; + ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0f * screen_stretching) / 2; + } + std::vector osdVertices = GetOSDVertices(); + const float x1 = 2.0f / (screen_width / dc2s_scale_h /* FIXME * scale_x */) * screen_stretching; + const float y1 = 2.0f / 480 /* FIXME dc_height */; + const float x2 = 1 - 2 * ds2s_offs_x / screen_width; + const float y2 = 1; + for (OSDVertex& vtx : osdVertices) + { + vtx.x = vtx.x * x1 - x2; + vtx.y = vtx.y * y1 - y2; + } + + const vk::CommandBuffer cmdBuffer = GetContext()->GetCurrentCommandBuffer(); + cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, osdPipeline.GetPipeline()); + + osdPipeline.BindDescriptorSets(cmdBuffer); + const vk::Viewport viewport(0, 0, (float)screen_width, (float)screen_height, 0, 1.f); + cmdBuffer.setViewport(0, 1, &viewport); + const vk::Rect2D scissor({ 0, 0 }, { (u32)screen_width, (u32)screen_height }); + cmdBuffer.setScissor(0, 1, &scissor); + osdBuffer->upload(*GetContext()->GetDevice(), osdVertices.size() * sizeof(OSDVertex), osdVertices.data()); + const vk::DeviceSize zero = 0; + cmdBuffer.bindVertexBuffers(0, 1, &osdBuffer->buffer.get(), &zero); + for (int i = 0; i < osdVertices.size(); i += 4) + cmdBuffer.draw(4, 1, i, 0); + if (clear_screen) + GetContext()->EndFrame(); } bool Render() override @@ -158,14 +263,18 @@ public: if (pvrrc.isRenderFramebuffer) return true; + Drawer *drawer; if (pvrrc.isRTT) - { - textureDrawer[curTextureDrawer].Draw(fogTexture.get()); - curTextureDrawer ^= 1; - return false; - } + drawer = &textureDrawer[GetContext()->GetCurrentImageIndex()]; else - return screenDrawer.Draw(fogTexture.get()); + drawer = &screenDrawer; + + drawer->Draw(fogTexture.get()); + if (!pvrrc.isRTT) + DrawOSD(false); + drawer->EndRenderPass(); + + return !pvrrc.isRTT; } void Present() override @@ -175,12 +284,15 @@ public: virtual u64 GetTexture(TSP tsp, TCW tcw) override { - Texture* tf = static_cast(getTextureCacheData(tsp, tcw, [this](){ - return (BaseTextureCacheData *)new Texture(VulkanContext::Instance()->GetPhysicalDevice(), *VulkanContext::Instance()->GetDevice(), &this->texAllocator); - })); + Texture* tf = textureCache.getTextureCacheData(tsp, tcw); if (tf->IsNew()) + { tf->Create(); + tf->SetAllocator(&texAllocator); + tf->SetPhysicalDevice(GetContext()->GetPhysicalDevice()); + tf->SetDevice(*GetContext()->GetDevice()); + } //update if needed if (tf->NeedsUpdate()) @@ -202,7 +314,10 @@ private: { if (!fogTexture) { - fogTexture = std::unique_ptr(new Texture(GetContext()->GetPhysicalDevice(), *GetContext()->GetDevice())); + fogTexture = std::unique_ptr(new Texture()); + fogTexture->SetAllocator(&texAllocator); + fogTexture->SetPhysicalDevice(GetContext()->GetPhysicalDevice()); + fogTexture->SetDevice(*GetContext()->GetDevice()); fogTexture->tex_type = TextureType::_8; fog_needs_update = true; } @@ -224,11 +339,15 @@ private: SamplerManager samplerManager; ShaderManager shaderManager; ScreenDrawer screenDrawer; - std::vector textureDrawer; // FIXME should be a singleton - int curTextureDrawer = 0; + RttPipelineManager rttPipelineManager; + std::vector textureDrawer; VulkanAllocator texAllocator; std::vector> framebufferTextures; QuadPipeline quadPipeline; + OSDPipeline osdPipeline; + std::unique_ptr vjoyTexture; + std::unique_ptr osdBuffer; + TextureCache textureCache; }; Renderer* rend_Vulkan() diff --git a/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj b/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj index 9f6e844c7..d6736d46f 100644 --- a/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj +++ b/shell/apple/emulator-osx/reicast-osx.xcodeproj/project.pbxproj @@ -258,6 +258,7 @@ AE8C274221122E2500D4D8F4 /* License.txt in Resources */ = {isa = PBXBuildFile; fileRef = AE8C273C21122E2500D4D8F4 /* License.txt */; }; AE8C274321122E2500D4D8F4 /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE8C273D21122E2500D4D8F4 /* xbrz.cpp */; }; AE90679B235B6F6400CE473C /* gl_context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE90679A235B6F6400CE473C /* gl_context.cpp */; }; + AE90679D235DF80400CE473C /* osd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE90679C235DF80400CE473C /* osd.cpp */; }; AED73BAE22FC0E9600ECDB64 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = AED73BAD22FC0E9600ECDB64 /* README.md */; }; AED73DC42303E19200ECDB64 /* sdl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AED73DC02303E19100ECDB64 /* sdl.cpp */; }; AED73DC72303E57C00ECDB64 /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AED73DC62303E57C00ECDB64 /* libSDL2.a */; }; @@ -850,6 +851,7 @@ AE8C273F21122E2500D4D8F4 /* xbrz_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbrz_config.h; sourceTree = ""; }; AE8C274021122E2500D4D8F4 /* xbrz_tools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbrz_tools.h; sourceTree = ""; }; AE90679A235B6F6400CE473C /* gl_context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gl_context.cpp; sourceTree = ""; }; + AE90679C235DF80400CE473C /* osd.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = osd.cpp; sourceTree = ""; }; AED73BAD22FC0E9600ECDB64 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../../../core/README.md; sourceTree = ""; }; AED73DC02303E19100ECDB64 /* sdl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sdl.cpp; sourceTree = ""; }; AED73DC12303E19100ECDB64 /* sdl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sdl.h; sourceTree = ""; }; @@ -1858,6 +1860,7 @@ AEE62769220D7B5500EC7E89 /* gui.h */, AEE6279222247C0A00EC7E89 /* gui_util.cpp */, AEE6279322247C0A00EC7E89 /* gui_util.h */, + AE90679C235DF80400CE473C /* osd.cpp */, 84B7BEA21B72720200F9733F /* rend.h */, AED73EAD2348E49900ECDB64 /* sorter.cpp */, AED73EBD2348E49900ECDB64 /* sorter.h */, @@ -2826,6 +2829,7 @@ 84B7BF201B72720200F9733F /* uncompr.c in Sources */, AE649C2A218C553A00EF4A81 /* LzFind.c in Sources */, 84B7BF2A1B72720200F9733F /* arm7.cpp in Sources */, + AE90679D235DF80400CE473C /* osd.cpp in Sources */, 84B7BF0D1B72720200F9733F /* zip_source_zip.c in Sources */, 84B7BEF51B72720200F9733F /* zip_fopen.c in Sources */, 84B7BF551B72720200F9733F /* sh4_mem.cpp in Sources */,