diff --git a/Common/Vulkan/VulkanImage.h b/Common/Vulkan/VulkanImage.h index 8aca750357..c7d6b61f68 100644 --- a/Common/Vulkan/VulkanImage.h +++ b/Common/Vulkan/VulkanImage.h @@ -37,11 +37,19 @@ public: int GetNumMips() const { return numMips_; } void Destroy(); + // Used in image copies, etc. + VkImage GetImage() const { return image; } + + // Used for sampling, generally. VkImageView GetImageView() const { return view; } + int32_t GetWidth() const { return tex_width; } + int32_t GetHeight() const { return tex_height; } + private: void CreateMappableImage(); void Wipe(); + VulkanContext *vulkan_; VkImage image; VkDeviceMemory mem; @@ -51,7 +59,7 @@ private: VkImage mappableImage; VkDeviceMemory mappableMemory; VkMemoryRequirements mem_reqs; - bool needStaging; VulkanDeviceAllocator *allocator_; size_t offset_; + bool needStaging; }; diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 4456e3461c..899c9a0062 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -175,7 +175,6 @@ public: virtual void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) = 0; virtual void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes) = 0; - virtual void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) = 0; virtual void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) = 0; virtual void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) = 0; diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index 9ea5b6b035..3db9030bdd 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -55,7 +55,6 @@ public: transformDraw_ = td; } - virtual void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override; virtual void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override; virtual void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) override; @@ -109,6 +108,7 @@ protected: virtual void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; private: + void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height); void CompileDraw2DProgram(); void DestroyDraw2DProgram(); diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 751364deea..20cbaf14fb 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -75,7 +75,6 @@ public: transformDraw_ = td; } - void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override; void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override; void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) override; @@ -137,6 +136,7 @@ protected: virtual void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; private: + void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height); void UpdatePostShaderUniforms(int bufferWidth, int bufferHeight, int renderWidth, int renderHeight); void CompileDraw2DProgram(); void DestroyDraw2DProgram(); diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 9004a135e0..4ca7faab3c 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -555,6 +555,28 @@ void DrawEngineVulkan::DirtyAllUBOs() { gstate_c.textureChanged = TEXCHANGE_UPDATED; } +//void DrawEngineVulkan::ApplyDrawStateLate() { + /* + // At this point, we know if the vertices are full alpha or not. + // TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)? + if (!gstate.isModeClear()) { + // TODO: Test texture? + + textureCache_->ApplyTexture(); + + if (fboTexNeedBind_) { + // Note that this is positions, not UVs, that we need the copy from. + framebufferManager_->BindFramebufferColor(1, nullptr, BINDFBCOLOR_MAY_COPY); + // If we are rendering at a higher resolution, linear is probably best for the dest color. + pD3Ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + pD3Ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + fboTexBound_ = true; + fboTexNeedBind_ = false; + } + } + */ +//} + // The inline wrapper in the header checks for numDrawCalls == 0d void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) { gpuStats.numFlushes++; diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index 74c1c94ec0..65c424f94a 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -93,105 +93,6 @@ void FramebufferManagerVulkan::ClearBuffer(bool keepState) { void FramebufferManagerVulkan::DisableState() { } -void FramebufferManagerVulkan::SetNumExtraFBOs(int num) { - /* - for (size_t i = 0; i < extraFBOs_.size(); i++) { - fbo_destroy(extraFBOs_[i]); - } - extraFBOs_.clear(); - for (int i = 0; i < num; i++) { - // No depth/stencil for post processing - FBO *fbo_vk = fbo_create(renderWidth_, renderHeight_, 1, false, FBO_8888); - extraFBOs_.push_back(fbo_vk); - - // The new FBO is still bound after creation, but let's bind it anyway. - fbo_bind_as_render_target(fbo_vk); - ClearBuffer(); - } - - currentRenderVfb_ = 0; - fbo_unbind(); - */ -} - -void FramebufferManagerVulkan::CompileDraw2DProgram() { - /* - if (!draw2dprogram_) { - std::string errorString; - draw2dprogram_ = glsl_create_source(basic_vs, tex_fs, &errorString); - if (!draw2dprogram_) { - ERROR_LOG_REPORT(G3D, "Failed to compile draw2dprogram! This shouldn't happen.\n%s", errorString.c_str()); - } else { - glsl_bind(draw2dprogram_); - glUniform1i(draw2dprogram_->sampler0, 0); - } - - plainColorProgram_ = glsl_create_source(color_vs, color_fs, &errorString); - if (!plainColorProgram_) { - ERROR_LOG_REPORT(G3D, "Failed to compile plainColorProgram! This shouldn't happen.\n%s", errorString.c_str()); - } else { - glsl_bind(plainColorProgram_); - plainColorLoc_ = glsl_uniform_loc(plainColorProgram_, "u_color"); - } - - SetNumExtraFBOs(0); - const ShaderInfo *shaderInfo = 0; - if (g_Config.sPostShaderName != "Off") { - shaderInfo = GetPostShaderInfo(g_Config.sPostShaderName); - } - - if (shaderInfo) { - postShaderAtOutputResolution_ = shaderInfo->outputResolution; - postShaderProgram_ = glsl_create(shaderInfo->vertexShaderFile.c_str(), shaderInfo->fragmentShaderFile.c_str(), &errorString); - if (!postShaderProgram_) { - // DO NOT turn this into a report, as it will pollute our logs with all kinds of - // user shader experiments. - ERROR_LOG(G3D, "Failed to build post-processing program from %s and %s!\n%s", shaderInfo->vertexShaderFile.c_str(), shaderInfo->fragmentShaderFile.c_str(), errorString.c_str()); - // let's show the first line of the error string as an OSM. - std::set blacklistedLines; - // These aren't useful to show, skip to the first interesting line. - blacklistedLines.insert("Fragment shader failed to compile with the following errors:"); - blacklistedLines.insert("Vertex shader failed to compile with the following errors:"); - blacklistedLines.insert("Compile failed."); - blacklistedLines.insert(""); - - std::string firstLine; - size_t start = 0; - for (size_t i = 0; i < errorString.size(); i++) { - if (errorString[i] == '\n') { - firstLine = errorString.substr(start, i - start); - if (blacklistedLines.find(firstLine) == blacklistedLines.end()) { - break; - } - start = i + 1; - firstLine.clear(); - } - } - if (!firstLine.empty()) { - osm.Show("Post-shader error: " + firstLine + "...", 10.0f, 0xFF3090FF); - } else { - osm.Show("Post-shader error, see log for details", 10.0f, 0xFF3090FF); - } - usePostShader_ = false; - } else { - glsl_bind(postShaderProgram_); - glUniform1i(postShaderProgram_->sampler0, 0); - SetNumExtraFBOs(1); - deltaLoc_ = glsl_uniform_loc(postShaderProgram_, "u_texelDelta"); - pixelDeltaLoc_ = glsl_uniform_loc(postShaderProgram_, "u_pixelDelta"); - timeLoc_ = glsl_uniform_loc(postShaderProgram_, "u_time"); - usePostShader_ = true; - } - } else { - postShaderProgram_ = nullptr; - usePostShader_ = false; - } - - glsl_unbind(); - } - */ -} - void FramebufferManagerVulkan::UpdatePostShaderUniforms(int bufferWidth, int bufferHeight, int renderWidth, int renderHeight) { float u_delta = 1.0f / renderWidth; float v_delta = 1.0f / renderHeight; @@ -214,19 +115,6 @@ void FramebufferManagerVulkan::UpdatePostShaderUniforms(int bufferWidth, int buf memcpy(postUniforms_.time, time, 4 * sizeof(float)); } -void FramebufferManagerVulkan::DestroyDraw2DProgram() { - /* - if (draw2dprogram_) { - glsl_destroy(draw2dprogram_); - draw2dprogram_ = nullptr; - } - if (postShaderProgram_) { - glsl_destroy(postShaderProgram_); - postShaderProgram_ = nullptr; - } - */ -} - FramebufferManagerVulkan::FramebufferManagerVulkan(VulkanContext *vulkan) : vulkan_(vulkan), drawPixelsTex_(0), @@ -262,33 +150,19 @@ void FramebufferManagerVulkan::Init() { FramebufferManagerCommon::Init(); // Workaround for upscaling shaders where we force x1 resolution without saving it resized_ = true; - CompileDraw2DProgram(); } void FramebufferManagerVulkan::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) { - /* - if (drawPixelsTex_ && (drawPixelsTexFormat_ != srcPixelFormat || drawPixelsTexW_ != width || drawPixelsTexH_ != height)) { - glDeleteTextures(1, &drawPixelsTex_); - drawPixelsTex_ = 0; + if (drawPixelsTex_ && (drawPixelsTexFormat_ != srcPixelFormat || drawPixelsTex_->GetWidth() != width || drawPixelsTex_->GetHeight() != height)) { + delete drawPixelsTex_; + drawPixelsTex_ = nullptr; } if (!drawPixelsTex_) { - drawPixelsTex_ = textureCache_->AllocTextureName(); - drawPixelsTexW_ = width; - drawPixelsTexH_ = height; - + drawPixelsTex_ = new VulkanTexture(vulkan_); + drawPixelsTex_->CreateDirect(width, height, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); // Initialize backbuffer texture for DrawPixels - glBindTexture(GL_TEXTURE_2D, drawPixelsTex_); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); drawPixelsTexFormat_ = srcPixelFormat; - } else { - glBindTexture(GL_TEXTURE_2D, drawPixelsTex_); } // TODO: We can just change the texture format and flip some bits around instead of this. @@ -342,11 +216,15 @@ void FramebufferManagerVulkan::MakePixelTexture(const u8 *srcPixels, GEBufferFor } } } - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, useConvBuf ? convBuf_ : srcPixels); - */ + + /*VkBuffer buffer; + size_t offset = drawEngine_-> + drawPixelsTex_->UploadMip(0, width, height, )*/ + drawPixelsTex_->EndCreate(); } void FramebufferManagerVulkan::DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) { + MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height); /* float v0 = 0.0f, v1 = 1.0f; if (useBufferedRendering_ && vfb && vfb->fbo_vk) { @@ -361,17 +239,14 @@ void FramebufferManagerVulkan::DrawPixels(VirtualFramebuffer *vfb, int dstX, int glViewport(x, y, w, h); } - MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height); - DrawActiveTexture(0, dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, v0, 1.0f, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); textureCache_->ForgetLastTexture(); */ } void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) { - /* MakePixelTexture(srcPixels, srcPixelFormat, srcStride, 512, 272); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, g_Config.iTexFiltering == TEX_FILTER_NEAREST ? GL_NEAREST : GL_LINEAR); + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, g_Config.iTexFiltering == TEX_FILTER_NEAREST ? GL_NEAREST : GL_LINEAR); struct CardboardSettings cardboardSettings; GetCardboardSettings(&cardboardSettings); @@ -383,13 +258,8 @@ void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBu int uvRotation = (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, uvRotation); if (applyPostShader) { - // Make sure we've compiled the shader. - if (!postShaderProgram_) { - CompileDraw2DProgram(); - } // Might've changed if the shader was just changed to Off. if (usePostShader_) { - glsl_bind(postShaderProgram_); UpdatePostShaderUniforms(480, 272, renderWidth_, renderHeight_); } } @@ -399,9 +269,11 @@ void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBu // We are drawing directly to the back buffer. std::swap(v0, v1); + VkPipeline postShaderProgram_ = VK_NULL_HANDLE; + if (cardboardSettings.enabled) { // Left Eye Image - glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); + // glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); if (applyPostShader && usePostShader_ && useBufferedRendering_) { DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); } else { @@ -409,7 +281,7 @@ void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBu } // Right Eye Image - glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); + // glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); if (applyPostShader && usePostShader_ && useBufferedRendering_) { DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); } else { @@ -417,19 +289,17 @@ void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBu } } else { // Fullscreen Image - glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); + // glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); if (applyPostShader && usePostShader_ && useBufferedRendering_) { DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation); } else { DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); } } - */ } // x, y, w, h are relative coordinates against destW/destH, which is not very intuitive. void FramebufferManagerVulkan::DrawActiveTexture(VulkanTexture *texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, VkPipeline pipeline, int uvRotation) { - /* float texCoords[8] = { u0,v0, u1,v0, @@ -437,7 +307,7 @@ void FramebufferManagerVulkan::DrawActiveTexture(VulkanTexture *texture, float x u0,v1, }; - static const GLubyte indices[4] = { 0,1,3,2 }; + static const uint16_t indices[4] = { 0,1,3,2 }; if (uvRotation != ROTATION_LOCKED_HORIZONTAL) { float temp[8]; @@ -455,7 +325,7 @@ void FramebufferManagerVulkan::DrawActiveTexture(VulkanTexture *texture, float x if (texture) { // Previously had NVDrawTexture fallback here but wasn't worth it. - glBindTexture(GL_TEXTURE_2D, texture); + // glBindTexture(GL_TEXTURE_2D, texture); } float pos[12] = { @@ -472,15 +342,12 @@ void FramebufferManagerVulkan::DrawActiveTexture(VulkanTexture *texture, float x pos[i * 3 + 1] = pos[i * 3 + 1] * invDestH - 1.0f; } - if (!program) { - if (!draw2dprogram_) { - CompileDraw2DProgram(); - } - - program = draw2dprogram_; - } + //if (!program) { + // program = draw2dprogram_; + //} // Upscaling postshaders doesn't look well with linear + /* if (postShaderIsUpscalingFilter_) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -488,14 +355,14 @@ void FramebufferManagerVulkan::DrawActiveTexture(VulkanTexture *texture, float x glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, g_Config.iBufFilter == SCALE_NEAREST ? GL_NEAREST : GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, g_Config.iBufFilter == SCALE_NEAREST ? GL_NEAREST : GL_LINEAR); } + */ - if (program != postShaderProgram_) { - shaderManager_->DirtyLastShader(); // dirty lastShader_ - glsl_bind(program); - } + //if (program != postShaderProgram_) { + // shaderManager_->DirtyLastShader(); // dirty lastShader_ + // glsl_bind(program); + //} - glEnableVertexAttribArray(program->a_position); - glEnableVertexAttribArray(program->a_texcoord0); + /* if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { transformDraw_->BindBuffer(pos, sizeof(pos), texCoords, sizeof(texCoords)); transformDraw_->BindElementBuffer(indices, sizeof(indices)); @@ -509,10 +376,6 @@ void FramebufferManagerVulkan::DrawActiveTexture(VulkanTexture *texture, float x glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, texCoords); glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices); } - glDisableVertexAttribArray(program->a_position); - glDisableVertexAttribArray(program->a_texcoord0); - - glsl_unbind(); */ } @@ -537,15 +400,7 @@ void FramebufferManagerVulkan::DestroyFramebuf(VirtualFramebuffer *v) { } void FramebufferManagerVulkan::RebindFramebuffer() { - /* - if (currentRenderVfb_ && currentRenderVfb_->fbo_vk) { - ImagcurrentRenderVfb_->fbo_vk->GetColorImageView(); - } else { - fbo_unbind(); - } - if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE) - glstate.viewport.restore(); - */ + // Switch command buffer? } void FramebufferManagerVulkan::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force) { @@ -631,12 +486,6 @@ void FramebufferManagerVulkan::NotifyRenderFramebufferCreated(VirtualFramebuffer textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED); - // Some AMD drivers crash if we don't clear the buffer first? - /* - glDisable(GL_DITHER); // why? - ClearBuffer(); - */ - // ugly... if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) { shaderManager_->DirtyUniform(DIRTY_PROJMATRIX); @@ -723,6 +572,7 @@ void FramebufferManagerVulkan::ReformatFramebufferFrom(VirtualFramebuffer *vfb, if (!useBufferedRendering_ || !vfb->fbo_vk) { return; } + /* fbo_bind_as_render_target(vfb->fbo); @@ -736,14 +586,7 @@ void FramebufferManagerVulkan::ReformatFramebufferFrom(VirtualFramebuffer *vfb, // to exactly reproduce in 4444 and 8888 formats. if (old == GE_FORMAT_565) { - glstate.scissorTest.disable(); - glstate.depthWrite.set(GL_FALSE); - glstate.colorMask.set(false, false, false, true); - glstate.stencilFunc.set(GL_ALWAYS, 0, 0); - glstate.stencilMask.set(0xFF); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClearStencil(0); - glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + // TODO: Clear to black, set stencil to 0, don't touch depth (or maybe zap depth). } RebindFramebuffer(); @@ -751,32 +594,23 @@ void FramebufferManagerVulkan::ReformatFramebufferFrom(VirtualFramebuffer *vfb, } void FramebufferManagerVulkan::BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) { - /* if (src->z_address == dst->z_address && src->z_stride != 0 && dst->z_stride != 0 && src->renderWidth == dst->renderWidth && src->renderHeight == dst->renderHeight) { - if (gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT)) { - // Only use NV if ARB isn't supported. - bool useNV = !gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT); + // TODO: Let's only do this if not clearing depth. - // Let's only do this if not clearing depth. - fbo_bind_for_read(src->fbo); - glstate.scissorTest.force(false); + VkImageCopy region = {}; + region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + region.extent = { dst->renderWidth, dst->renderHeight, 1 }; + region.extent.depth = 1; + // vkCmdCopyImage(curCmd_, src->fbo_vk->GetDepthStencil()->GetImage(), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + // dst->fbo_vk->GetDepthStencil()->GetImage(), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1, ®ion); - if (useNV) { -#if defined(USING_GLES2) && defined(ANDROID) // We only support this extension on Android, it's not even available on PC. - glBlitFramebufferNV(0, 0, src->renderWidth, src->renderHeight, 0, 0, dst->renderWidth, dst->renderHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST); -#endif // defined(USING_GLES2) && defined(ANDROID) - } else { - glBlitFramebuffer(0, 0, src->renderWidth, src->renderHeight, 0, 0, dst->renderWidth, dst->renderHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST); - } - // If we set dst->depthUpdated here, our optimization above would be pointless. - - glstate.scissorTest.restore(); - } - }*/ + // If we set dst->depthUpdated here, our optimization above would be pointless. + } } VulkanFBO *FramebufferManagerVulkan::GetTempFBO(u16 w, u16 h, VulkanFBOColorDepth depth) { @@ -800,23 +634,18 @@ VulkanFBO *FramebufferManagerVulkan::GetTempFBO(u16 w, u16 h, VulkanFBOColorDept return fbo_vk; } +// This function signature will need to change. Only used for shader blending, doing it later. void FramebufferManagerVulkan::BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags) { if (framebuffer == NULL) { framebuffer = currentRenderVfb_; } - /* - if (stage != GL_TEXTURE0) { - glActiveTexture(stage); - } - if (!framebuffer->fbo_vk || !useBufferedRendering_) { - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE; return; } + /* // currentRenderVfb_ will always be set when this is called, except from the GE debugger. // Let's just not bother with the copy in that case. bool skipCopy = (flags & BINDFBCOLOR_MAY_COPY) == 0; @@ -1006,8 +835,7 @@ void FramebufferManagerVulkan::CopyDisplayToOutput() { // We should not be in a renderpass here so can just copy. - /* - GLuint colorTexture = fbo_get_color_texture(vfb->fbo_vk); + // GLuint colorTexture = fbo_get_color_texture(vfb->fbo_vk); int uvRotation = (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; @@ -1023,24 +851,22 @@ void FramebufferManagerVulkan::CopyDisplayToOutput() { float v1 = (272.0f + offsetY) / (float)vfb->bufferHeight; if (!usePostShader_) { - // We are doing the DrawActiveTexture call directly to the backbuffer here. Hence, we must - // flip V. - std::swap(v0, v1); if (cardboardSettings.enabled) { // Left Eye Image - glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + // glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); + // DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); // Right Eye Image - glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + // glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); + // DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); } else { // Fullscreen Image - glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); + // glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); + // DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); } - } else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) { + } else if (usePostShader_ && !postShaderAtOutputResolution_) { // An additional pass, post-processing shader to the extra FBO. + /* fbo_bind_as_render_target(extraFBOs_[0]); int fbo_w, fbo_h; fbo_get_dimensions(extraFBOs_[0], &fbo_w, &fbo_h); @@ -1051,63 +877,43 @@ void FramebufferManagerVulkan::CopyDisplayToOutput() { DrawActiveTexture(colorTexture, 0, 0, fbo_w, fbo_h, fbo_w, fbo_h, 0.0f, 0.0f, 1.0f, 1.0f, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); fbo_unbind(); - + */ // Use the extra FBO, with applied post-processing shader, as a texture. // fbo_bind_color_as_texture(extraFBOs_[0], 0); - if (extraFBOs_.size() == 0) { - ERROR_LOG(G3D, "WTF?"); - return; - } - colorTexture = fbo_get_color_texture(extraFBOs_[0]); - // We are doing the DrawActiveTexture call directly to the backbuffer after here. Hence, we must - // flip V. - std::swap(v0, v1); + // colorTexture = fbo_get_color_texture(extraFBOs_[0]); if (g_Config.bEnableCardboard) { // Left Eye Image - glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + // glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); + // DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); // Right Eye Image - glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + // glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); + // DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); } else { // Fullscreen Image - glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); - } - - if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) { - fbo_bind_as_render_target(extraFBOs_[0]); - GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT }; - glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments); + // glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); + // DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); } } else { - // We are doing the DrawActiveTexture call directly to the backbuffer here. Hence, we must - // flip V. - std::swap(v0, v1); - - shaderManager_->DirtyLastShader(); // dirty lastShader_ - glsl_bind(postShaderProgram_); + // shaderManager_->DirtyLastShader(); // dirty lastShader_ + // glsl_bind(postShaderProgram_); UpdatePostShaderUniforms(vfb->bufferWidth, vfb->bufferHeight, vfb->renderWidth, vfb->renderHeight); if (g_Config.bEnableCardboard) { // Left Eye Image - glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + // glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); + // DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); // Right Eye Image - glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + // glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); + // DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); } else { // Fullscreen Image - glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation); + // glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); + // DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation); } } - - glBindTexture(GL_TEXTURE_2D, 0); - */ } } @@ -1227,15 +1033,14 @@ void FramebufferManagerVulkan::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb } void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) { - /* if (!dst->fbo || !src->fbo || !useBufferedRendering_) { // This can happen if they recently switched from non-buffered. - fbo_unbind(); return; } - bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT); - bool useNV = useBlit && !gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT); + // NOTE: There may be cases (like within a renderpass) where we want to + // not use a blit. + bool useBlit = true; float srcXFactor = useBlit ? (float)src->renderWidth / (float)src->bufferWidth : 1.0f; float srcYFactor = useBlit ? (float)src->renderHeight / (float)src->bufferHeight : 1.0f; @@ -1265,95 +1070,40 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX return; } - if (gstate_c.Supports(GPU_SUPPORTS_ANY_COPY_IMAGE)) { - // glBlitFramebuffer can clip, but glCopyImageSubData is more restricted. - // In case the src goes outside, we just skip the optimization in that case. - const bool sameSize = dstX2 - dstX1 == srcX2 - srcX1 && dstY2 - dstY1 == srcY2 - srcY1; - const bool sameDepth = dst->colorDepth == src->colorDepth; - const bool srcInsideBounds = srcX2 <= src->renderWidth && srcY2 <= src->renderHeight; - const bool dstInsideBounds = dstX2 <= dst->renderWidth && dstY2 <= dst->renderHeight; - const bool xOverlap = src == dst && srcX2 > dstX1 && srcX1 < dstX2; - const bool yOverlap = src == dst && srcY2 > dstY1 && srcY1 < dstY2; - if (sameSize && sameDepth && srcInsideBounds && dstInsideBounds && !(xOverlap && yOverlap)) { -#if defined(USING_GLES2) -#ifndef IOS - glCopyImageSubDataOES( - fbo_get_color_texture(src->fbo), GL_TEXTURE_2D, 0, srcX1, srcY1, 0, - fbo_get_color_texture(dst->fbo), GL_TEXTURE_2D, 0, dstX1, dstY1, 0, - dstX2 - dstX1, dstY2 - dstY1, 1); - return; -#endif -#else - if (gl_extensions.ARB_copy_image) { - glCopyImageSubData( - fbo_get_color_texture(src->fbo), GL_TEXTURE_2D, 0, srcX1, srcY1, 0, - fbo_get_color_texture(dst->fbo), GL_TEXTURE_2D, 0, dstX1, dstY1, 0, - dstX2 - dstX1, dstY2 - dstY1, 1); - return; - } else if (gl_extensions.NV_copy_image) { - // Older, pre GL 4.x NVIDIA cards. - glCopyImageSubDataNV( - fbo_get_color_texture(src->fbo), GL_TEXTURE_2D, 0, srcX1, srcY1, 0, - fbo_get_color_texture(dst->fbo), GL_TEXTURE_2D, 0, dstX1, dstY1, 0, - dstX2 - dstX1, dstY2 - dstY1, 1); - return; - } -#endif - } + // glBlitFramebuffer can clip, but glCopyImageSubData is more restricted. + // In case the src goes outside, we just skip the optimization in that case. + const bool sameSize = dstX2 - dstX1 == srcX2 - srcX1 && dstY2 - dstY1 == srcY2 - srcY1; + const bool sameDepth = dst->colorDepth == src->colorDepth; + const bool srcInsideBounds = srcX2 <= src->renderWidth && srcY2 <= src->renderHeight; + const bool dstInsideBounds = dstX2 <= dst->renderWidth && dstY2 <= dst->renderHeight; + const bool xOverlap = src == dst && srcX2 > dstX1 && srcX1 < dstX2; + const bool yOverlap = src == dst && srcY2 > dstY1 && srcY1 < dstY2; + if (sameSize && sameDepth && srcInsideBounds && dstInsideBounds && !(xOverlap && yOverlap)) { + VkImageCopy region = {}; + region.extent = { (uint32_t)(dstX2 - dstX1), (uint32_t)(dstY2 - dstY1), 1 }; + /* + glCopyImageSubDataOES( + fbo_get_color_texture(src->fbo), GL_TEXTURE_2D, 0, srcX1, srcY1, 0, + fbo_get_color_texture(dst->fbo), GL_TEXTURE_2D, 0, dstX1, dstY1, 0, + dstX2 - dstX1, dstY2 - dstY1, 1); + */ + return; } - fbo_bind_as_render_target(dst->fbo); - glstate.scissorTest.force(false); + // fbo_bind_as_render_target(dst->fbo); if (useBlit) { - fbo_bind_for_read(src->fbo); - if (!useNV) { - glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } else { -#if defined(USING_GLES2) && defined(ANDROID) // We only support this extension on Android, it's not even available on PC. - glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, GL_COLOR_BUFFER_BIT, GL_NEAREST); -#endif // defined(USING_GLES2) && defined(ANDROID) - } - - fbo_unbind_read(); + // fbo_bind_for_read(src->fbo); + //glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, GL_COLOR_BUFFER_BIT, GL_NEAREST); } else { - fbo_bind_color_as_texture(src->fbo, 0); - - // Make sure our 2D drawing program is ready. Compiles only if not already compiled. - CompileDraw2DProgram(); - - glstate.viewport.force(0, 0, dst->renderWidth, dst->renderHeight); - glstate.blend.force(false); - glstate.cullFace.force(false); - glstate.depthTest.force(false); - glstate.stencilTest.force(false); -#if !defined(USING_GLES2) - glstate.colorLogicOp.force(false); -#endif - glstate.colorMask.force(true, true, true, true); - glstate.stencilMask.force(0xFF); + // fbo_bind_color_as_texture(src->fbo, 0); // The first four coordinates are relative to the 6th and 7th arguments of DrawActiveTexture. // Should maybe revamp that interface. float srcW = src->bufferWidth; float srcH = src->bufferHeight; - DrawActiveTexture(0, dstX1, dstY1, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, draw2dprogram_, ROTATION_LOCKED_HORIZONTAL); - glBindTexture(GL_TEXTURE_2D, 0); - textureCache_->ForgetLastTexture(); - glstate.viewport.restore(); - glstate.blend.restore(); - glstate.cullFace.restore(); - glstate.depthTest.restore(); - glstate.stencilTest.restore(); -#if !defined(USING_GLES2) - glstate.colorLogicOp.restore(); -#endif - glstate.colorMask.restore(); - glstate.stencilMask.restore(); + // DrawActiveTexture(0, dstX1, dstY1, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, draw2dprogram_, ROTATION_LOCKED_HORIZONTAL); } - - glstate.scissorTest.restore(); - */ } // TODO: SSE/NEON @@ -1443,13 +1193,13 @@ static void LogReadPixelsError(GLenum error) { } #endif +// One frame behind, but no stalling. void FramebufferManagerVulkan::PackFramebufferAsync_(VirtualFramebuffer *vfb) { - /* const int MAX_PBO = 2; - GLubyte *packed = 0; - bool unbind = false; + uint8_t *packed = 0; const u8 nextPBO = (currentPBO_ + 1) % MAX_PBO; - const bool useCPU = gstate_c.Supports(GPU_PREFER_CPU_DOWNLOAD); + + bool useCPU = false; // We'll prepare two PBOs to switch between readying and reading if (!pixelBufObj_) { @@ -1459,137 +1209,97 @@ void FramebufferManagerVulkan::PackFramebufferAsync_(VirtualFramebuffer *vfb) { return; } - GLuint pbos[MAX_PBO]; - glGenBuffers(MAX_PBO, pbos); + // GLuint pbos[MAX_PBO]; + // glGenBuffers(MAX_PBO, pbos); - pixelBufObj_ = new AsyncPBO[MAX_PBO]; + pixelBufObj_ = new AsyncPBOVulkan[MAX_PBO]; for (int i = 0; i < MAX_PBO; i++) { - pixelBufObj_[i].handle = pbos[i]; + // TODO + // pixelBufObj_[i].handle = pbos[i]; pixelBufObj_[i].maxSize = 0; pixelBufObj_[i].reading = false; } } // Receive previously requested data from a PBO - AsyncPBO &pbo = pixelBufObj_[nextPBO]; + AsyncPBOVulkan &pbo = pixelBufObj_[nextPBO]; if (pbo.reading) { - glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo.handle); -#ifdef USING_GLES2 - // Not on desktop GL 2.x... - packed = (GLubyte *)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, pbo.size, GL_MAP_READ_BIT); -#else - packed = (GLubyte *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); -#endif + // glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo.handle); + // packed = (GLubyte *)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, pbo.size, GL_MAP_READ_BIT); if (packed) { DEBUG_LOG(SCEGE, "Reading PBO to memory , bufSize = %u, packed = %p, fb_address = %08x, stride = %u, pbo = %u", pbo.size, packed, pbo.fb_address, pbo.stride, nextPBO); - if (useCPU || (UseBGRA8888() && pbo.format == GE_FORMAT_8888)) { - u8 *dst = Memory::GetPointer(pbo.fb_address); - ConvertFromRGBA8888(dst, packed, pbo.stride, pbo.stride, pbo.stride, pbo.height, pbo.format); - } else { - // We don't need to convert, GPU already did (or should have) - Memory::MemcpyUnchecked(pbo.fb_address, packed, pbo.size); - } + // We don't need to convert, GPU already did (or should have) + // (vulkan: hopefully) + Memory::MemcpyUnchecked(pbo.fb_address, packed, pbo.size); pbo.reading = false; } - glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - unbind = true; + // glUnmapBuffer(GL_PIXEL_PACK_BUFFER); } - + // Order packing/readback of the framebuffer if (vfb) { - int pixelType, pixelSize, pixelFormat, align; - - bool reverseOrder = gstate_c.Supports(GPU_PREFER_REVERSE_COLOR_ORDER); + // int pixelType, pixelFormat; + int pixelSize, align; switch (vfb->format) { - // GL_UNSIGNED_INT_8_8_8_8 returns A B G R (little-endian, tested in Nvidia card/x86 PC) - // GL_UNSIGNED_BYTE returns R G B A in consecutive bytes ("big-endian"/not treated as 32-bit value) - // We want R G B A, so we use *_REV for 16-bit formats and GL_UNSIGNED_BYTE for 32-bit case GE_FORMAT_4444: // 16 bit RGBA -#ifdef USING_GLES2 - pixelType = GL_UNSIGNED_SHORT_4_4_4_4; -#else - pixelType = (reverseOrder ? GL_UNSIGNED_SHORT_4_4_4_4_REV : GL_UNSIGNED_SHORT_4_4_4_4); -#endif - pixelFormat = GL_RGBA; + // pixelType = GL_UNSIGNED_SHORT_4_4_4_4; + // pixelFormat = GL_RGBA; pixelSize = 2; align = 2; break; case GE_FORMAT_5551: // 16 bit RGBA -#ifdef USING_GLES2 - pixelType = GL_UNSIGNED_SHORT_5_5_5_1; -#else - pixelType = (reverseOrder ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_SHORT_5_5_5_1); -#endif - pixelFormat = GL_RGBA; + // pixelType = GL_UNSIGNED_SHORT_5_5_5_1; + // pixelFormat = GL_RGBA; pixelSize = 2; align = 2; break; case GE_FORMAT_565: // 16 bit RGB -#ifdef USING_GLES2 - pixelType = GL_UNSIGNED_SHORT_5_6_5; -#else - pixelType = (reverseOrder ? GL_UNSIGNED_SHORT_5_6_5_REV : GL_UNSIGNED_SHORT_5_6_5); -#endif - pixelFormat = GL_RGB; + // pixelType = GL_UNSIGNED_SHORT_5_6_5; + // pixelFormat = GL_RGB; pixelSize = 2; align = 2; break; case GE_FORMAT_8888: // 32 bit RGBA default: - pixelType = GL_UNSIGNED_BYTE; - pixelFormat = UseBGRA8888() ? GL_BGRA_EXT : GL_RGBA; + // pixelType = GL_UNSIGNED_BYTE; + // pixelFormat = UseBGRA8888() ? GL_BGRA_EXT : GL_RGBA; pixelSize = 4; align = 4; break; } // If using the CPU, we need 4 bytes per pixel always. - u32 bufSize = vfb->fb_stride * vfb->height * (useCPU ? 4 : pixelSize); + u32 bufSize = vfb->fb_stride * vfb->height * 4 * (useCPU ? 4 : pixelSize); u32 fb_address = (0x04000000) | vfb->fb_address; if (vfb->fbo) { - fbo_bind_for_read(vfb->fbo); + // fbo_bind_for_read(vfb->fbo); } else { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferAsync_: vfb->fbo == 0"); - fbo_unbind_read(); + // fbo_unbind_read(); return; } - GLenum fbStatus; - fbStatus = (GLenum)fbo_check_framebuffer_status(vfb->fbo); - - if (fbStatus != GL_FRAMEBUFFER_COMPLETE) { - ERROR_LOG(SCEGE, "Incomplete source framebuffer, aborting read"); - fbo_unbind_read(); - return; - } - - glBindBuffer(GL_PIXEL_PACK_BUFFER, pixelBufObj_[currentPBO_].handle); - + // glBindBuffer(GL_PIXEL_PACK_BUFFER, pixelBufObj_[currentPBO_].handle); if (pixelBufObj_[currentPBO_].maxSize < bufSize) { // We reserve a buffer big enough to fit all those pixels - glBufferData(GL_PIXEL_PACK_BUFFER, bufSize, NULL, GL_DYNAMIC_READ); + // glBufferData(GL_PIXEL_PACK_BUFFER, bufSize, NULL, GL_DYNAMIC_READ); pixelBufObj_[currentPBO_].maxSize = bufSize; } if (useCPU) { // If converting pixel formats on the CPU we'll always request RGBA8888 - glPixelStorei(GL_PACK_ALIGNMENT, 4); - SafeGLReadPixels(0, 0, vfb->fb_stride, vfb->height, UseBGRA8888() ? GL_BGRA_EXT : GL_RGBA, GL_UNSIGNED_BYTE, 0); + // SafeGLReadPixels(0, 0, vfb->fb_stride, vfb->height, UseBGRA8888() ? GL_BGRA_EXT : GL_RGBA, GL_UNSIGNED_BYTE, 0); } else { // Otherwise we'll directly request the format we need and let the GPU sort it out - glPixelStorei(GL_PACK_ALIGNMENT, align); - SafeGLReadPixels(0, 0, vfb->fb_stride, vfb->height, pixelFormat, pixelType, 0); + // SafeGLReadPixels(0, 0, vfb->fb_stride, vfb->height, pixelFormat, pixelType, 0); } - fbo_unbind_read(); - unbind = true; - pixelBufObj_[currentPBO_].fb_address = fb_address; pixelBufObj_[currentPBO_].size = bufSize; pixelBufObj_[currentPBO_].stride = vfb->fb_stride; @@ -1599,78 +1309,10 @@ void FramebufferManagerVulkan::PackFramebufferAsync_(VirtualFramebuffer *vfb) { } currentPBO_ = nextPBO; - - if (unbind) { - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - } - */ } void FramebufferManagerVulkan::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h) { - /* - if (vfb->fbo) { - fbo_bind_for_read(vfb->fbo); - } else { - ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferSync_: vfb->fbo == 0"); - fbo_unbind_read(); - return; - } - // Pixel size always 4 here because we always request RGBA8888 - size_t bufSize = vfb->fb_stride * std::max(vfb->height, (u16)h) * 4; - u32 fb_address = (0x04000000) | vfb->fb_address; - - GLubyte *packed = 0; - - bool convert = vfb->format != GE_FORMAT_8888 || UseBGRA8888(); - const int dstBpp = vfb->format == GE_FORMAT_8888 ? 4 : 2; - const int packWidth = x + w < vfb->width ? x + w : vfb->width; - - if (!convert) { - packed = (GLubyte *)Memory::GetPointer(fb_address); - } else { // End result may be 16-bit but we are reading 32-bit, so there may not be enough space at fb_address - u32 neededSize = (u32)bufSize * sizeof(GLubyte); - if (!convBuf_ || convBufSize_ < neededSize) { - delete[] convBuf_; - convBuf_ = new u8[neededSize]; - convBufSize_ = neededSize; - } - packed = convBuf_; - } - - if (packed) { - DEBUG_LOG(SCEGE, "Reading framebuffer to mem, bufSize = %u, packed = %p, fb_address = %08x", - (u32)bufSize, packed, fb_address); - - glPixelStorei(GL_PACK_ALIGNMENT, 4); - GLenum glfmt = GL_RGBA; - if (UseBGRA8888()) { - glfmt = GL_BGRA_EXT; - } - - int byteOffset = y * vfb->fb_stride * 4; - SafeGLReadPixels(0, y, h == 1 ? packWidth : vfb->fb_stride, h, glfmt, GL_UNSIGNED_BYTE, packed + byteOffset); - - if (convert) { - int dstByteOffset = y * vfb->fb_stride * dstBpp; - ConvertFromRGBA8888(Memory::GetPointer(fb_address + dstByteOffset), packed + byteOffset, vfb->fb_stride, vfb->fb_stride, packWidth, h, vfb->format); - } - } - - if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) { -#ifdef USING_GLES2 - // GLES3 doesn't support using GL_READ_FRAMEBUFFER here. - fbo_bind_as_render_target(vfb->fbo); - const GLenum target = GL_FRAMEBUFFER; -#else - const GLenum target = GL_READ_FRAMEBUFFER; -#endif - GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT }; - glInvalidateFramebuffer(target, 3, attachments); - } - - fbo_unbind_read(); - */ } #ifdef _WIN32 @@ -1682,9 +1324,6 @@ void FramebufferManagerVulkan::EndFrame() { // TODO: Only do this if the new size actually changed the renderwidth/height. DestroyAllFBOs(); - // Probably not necessary - //glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); - // Check if postprocessing shader is doing upscaling as it requires native resolution const ShaderInfo *shaderInfo = 0; if (g_Config.sPostShaderName != "Off") { @@ -1725,7 +1364,6 @@ void FramebufferManagerVulkan::EndFrame() { } #endif ClearBuffer(); - DestroyDraw2DProgram(); } // We flush to memory last requested framebuffer, if any. @@ -1736,7 +1374,6 @@ void FramebufferManagerVulkan::EndFrame() { void FramebufferManagerVulkan::DeviceLost() { DestroyAllFBOs(); - DestroyDraw2DProgram(); resized_ = false; } @@ -1892,7 +1529,6 @@ bool FramebufferManagerVulkan::GetDisplayFramebuffer(GPUDebugBuffer &buffer) { bool FramebufferManagerVulkan::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) { // TODO: Doing this synchronously will require stalling the pipeline. Maybe better // to do it callback-style? - /* VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { vfb = GetVFBAt(fb_address); @@ -1904,12 +1540,8 @@ bool FramebufferManagerVulkan::GetDepthbuffer(u32 fb_address, int fb_stride, u32 return true; } + /* buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_FLOAT, false); - if (vfb->fbo_vk) - fbo_bind_for_read(vfb->fbo_vk); - if (gl_extensions.GLES3 || !gl_extensions.IsGLES) - glReadBuffer(GL_COLOR_ATTACHMENT0); - glPixelStorei(GL_PACK_ALIGNMENT, 4); SafeGLReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_DEPTH_COMPONENT, GL_FLOAT, buffer.GetData()); */ return false; @@ -1918,7 +1550,6 @@ bool FramebufferManagerVulkan::GetDepthbuffer(u32 fb_address, int fb_stride, u32 bool FramebufferManagerVulkan::GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) { // TODO: Doing this synchronously will require stalling the pipeline. Maybe better // to do it callback-style? - /* VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { vfb = GetVFBAt(fb_address); @@ -1931,12 +1562,8 @@ bool FramebufferManagerVulkan::GetStencilbuffer(u32 fb_address, int fb_stride, G return true; } + /* buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_8BIT, false); - if (vfb->fbo_vk) - fbo_bind_for_read(vfb->fbo_vk); - if (gl_extensions.GLES3 || !gl_extensions.IsGLES) - glReadBuffer(GL_COLOR_ATTACHMENT0); - glPixelStorei(GL_PACK_ALIGNMENT, 2); SafeGLReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buffer.GetData()); return true; diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index 0b93fabef0..ba2f49a31a 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -43,6 +43,12 @@ struct PostShaderUniforms { float time[4]; }; +static const char *ub_post_shader = +R"( vec2 texelDelta; + vec2 pixelDelta; + vec4 time; +)"; + // Simple struct for asynchronous PBO readbacks // TODO: Probably will need a complete redesign. struct AsyncPBOVulkan { @@ -81,7 +87,6 @@ public: transformDraw_ = td; } - void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override; void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override; void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) override; @@ -144,13 +149,10 @@ protected: private: + void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height); void UpdatePostShaderUniforms(int bufferWidth, int bufferHeight, int renderWidth, int renderHeight); - void CompileDraw2DProgram(); - void DestroyDraw2DProgram(); - void SetNumExtraFBOs(int num); - - void PackFramebufferAsync_(VirtualFramebuffer *vfb); // Not used under ES currently + void PackFramebufferAsync_(VirtualFramebuffer *vfb); void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h); VulkanContext *vulkan_; @@ -166,9 +168,6 @@ private: VulkanTexture *drawPixelsTex_; GEBufferFormat drawPixelsTexFormat_; - int drawPixelsTexW_; - int drawPixelsTexH_; - u8 *convBuf_; u32 convBufSize_; @@ -176,9 +175,6 @@ private: ShaderManagerVulkan *shaderManager_; DrawEngineVulkan *transformDraw_; - // Used by post-processing shader - std::vector extraFBOs_; - bool resized_; struct TempFBO { diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index 092f387739..c0850dd4cf 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -326,25 +326,3 @@ void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerV shaderManager->DirtyUniform(DIRTY_DEPTHRANGE); } } - -//void DrawEngineVulkan::ApplyDrawStateLate() { - /* - // At this point, we know if the vertices are full alpha or not. - // TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)? - if (!gstate.isModeClear()) { - // TODO: Test texture? - - textureCache_->ApplyTexture(); - - if (fboTexNeedBind_) { - // Note that this is positions, not UVs, that we need the copy from. - framebufferManager_->BindFramebufferColor(1, nullptr, BINDFBCOLOR_MAY_COPY); - // If we are rendering at a higher resolution, linear is probably best for the dest color. - pD3Ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - pD3Ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - fboTexBound_ = true; - fboTexNeedBind_ = false; - } - } - */ -//} diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index a978e4523f..b9caf70458 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -643,48 +643,6 @@ inline u32 TextureCacheVulkan::GetCurrentClutHash() { return clutHash_; } -// #define DEBUG_TEXTURES - -#ifdef DEBUG_TEXTURES -bool SetDebugTexture() { - static const int highlightFrames = 30; - - static int numTextures = 0; - static int lastFrames = 0; - static int mostTextures = 1; - - if (lastFrames != gpuStats.numFlips) { - mostTextures = std::max(mostTextures, numTextures); - numTextures = 0; - lastFrames = gpuStats.numFlips; - } - - static GLuint solidTexture = 0; - - bool changed = false; - if (((gpuStats.numFlips / highlightFrames) % mostTextures) == numTextures) { - if (gpuStats.numFlips % highlightFrames == 0) { - NOTICE_LOG(G3D, "Highlighting texture # %d / %d", numTextures, mostTextures); - } - static const u32 solidTextureData[] = { 0x99AA99FF }; - - if (solidTexture == 0) { - glGenTextures(1, &solidTexture); - glBindTexture(GL_TEXTURE_2D, solidTexture); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, solidTextureData); - } else { - glBindTexture(GL_TEXTURE_2D, solidTexture); - } - changed = true; - } - - ++numTextures; - return changed; -} -#endif - void TextureCacheVulkan::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) { _dbg_assert_msg_(G3D, framebuffer != nullptr, "Framebuffer must not be null."); @@ -858,51 +816,6 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(VkCommandBuffer cmd, TexCacheEn shaderManager_->DirtyLastShader(); - /* - glUseProgram(depal->program); - - // Restore will rebind all of the state below. - if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - transformDraw_->BindBuffer(pos, sizeof(pos), uv, sizeof(uv)); - transformDraw_->BindElementBuffer(indices, sizeof(indices)); - } else { - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - glEnableVertexAttribArray(depal->a_position); - glEnableVertexAttribArray(depal->a_texcoord0); - - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, clutTexture); - glActiveTexture(GL_TEXTURE0); - - framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer, BINDFBCOLOR_SKIP_COPY); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glstate.blend.force(false); - glstate.colorMask.force(true, true, true, true); - glstate.scissorTest.force(false); - glstate.cullFace.force(false); - glstate.depthTest.force(false); - glstate.stencilTest.force(false); -#if !defined(USING_GLES2) - glstate.colorLogicOp.force(false); -#endif - glViewport(0, 0, framebuffer->renderWidth, framebuffer->renderHeight); - - if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - glVertexAttribPointer(depal->a_position, 3, GL_FLOAT, GL_FALSE, 12, 0); - glVertexAttribPointer(depal->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, (void *)sizeof(pos)); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0); - } else { - glVertexAttribPointer(depal->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos); - glVertexAttribPointer(depal->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, uv); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices); - } - glDisableVertexAttribArray(depal->a_position); - glDisableVertexAttribArray(depal->a_texcoord0); - */ //depalFBO->EndPass(cmd); //depalFBO->TransitionToTexture(cmd); //imageView = depalFBO->GetColorImageView();