diff --git a/core/rend/vulkan/drawer.cpp b/core/rend/vulkan/drawer.cpp index 100f5d80b..1201ec63d 100644 --- a/core/rend/vulkan/drawer.cpp +++ b/core/rend/vulkan/drawer.cpp @@ -152,6 +152,33 @@ void BaseDrawer::SetBaseScissor() currentScissor = { 0, 0, 0, 0 }; } +// Vulkan uses the color values of the first vertex for flat shaded triangle strips. +// On Dreamcast the last vertex is the provoking one so we must copy it onto the first. +void BaseDrawer::SetProvokingVertices() +{ + auto setProvokingVertex = [](const List& list) { + for (int i = 0; i < list.used(); i++) + { + const PolyParam& pp = list.head()[i]; + if (!pp.pcw.Gouraud && pp.count > 2) + { + for (int i = 0; i < pp.count - 2; i++) + { + Vertex *vertex = &pvrrc.verts.head()[pvrrc.idx.head()[pp.first + i]]; + Vertex *lastVertex = &pvrrc.verts.head()[pvrrc.idx.head()[pp.first + i + 2]]; + memcpy(vertex->col, lastVertex->col, 4); + memcpy(vertex->spc, lastVertex->spc, 4); + memcpy(vertex->col1, lastVertex->col1, 4); + memcpy(vertex->spc1, lastVertex->spc1, 4); + } + } + } + }; + setProvokingVertex(pvrrc.global_param_op); + setProvokingVertex(pvrrc.global_param_pt); + setProvokingVertex(pvrrc.global_param_tr); +} + void Drawer::DrawPoly(const vk::CommandBuffer& cmdBuffer, u32 listType, bool sortTriangles, const PolyParam& poly, u32 first, u32 count) { vk::Rect2D scissorRect; @@ -331,6 +358,8 @@ bool Drawer::Draw(const Texture *fogTexture) vk::CommandBuffer cmdBuffer = BeginRenderPass(); + SetProvokingVertices(); + // Upload vertex and index buffers UploadMainBuffer(vtxUniforms, fragUniforms); @@ -530,10 +559,18 @@ void TextureDrawer::EndRenderPass() { currentCommandBuffer.endRenderPass(); + u32 clippedWidth = pvrrc.fb_X_CLIP.max - pvrrc.fb_X_CLIP.min + 1; + u32 clippedHeight = pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1; + + u32 stride = FB_W_LINESTRIDE.stride * 8; + if (clippedWidth * 2 > stride) + // Happens for Virtua Tennis + clippedWidth = stride / 2; + if (settings.rend.RenderToTextureBuffer) { - vk::BufferImageCopy copyRegion(0, width, height, vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), vk::Offset3D(0, 0, 0), - vk::Extent3D(vk::Extent2D(width, height), 1)); + vk::BufferImageCopy copyRegion(0, clippedWidth, clippedHeight, vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), vk::Offset3D(0, 0, 0), + vk::Extent3D(vk::Extent2D(clippedWidth, clippedHeight), 1)); currentCommandBuffer.copyImageToBuffer(colorAttachment->GetImage(), vk::ImageLayout::eTransferSrcOptimal, *colorAttachment->GetBufferData()->buffer, copyRegion); @@ -561,9 +598,9 @@ void TextureDrawer::EndRenderPass() u16 *dst = (u16 *)&vram[textureAddr]; PixelBuffer tmpBuf; - tmpBuf.init(width, height); - colorAttachment->GetBufferData()->download(width * height * 4, tmpBuf.data()); - WriteTextureToVRam(width, height, (u8 *)tmpBuf.data(), dst); + tmpBuf.init(clippedWidth, clippedHeight); + colorAttachment->GetBufferData()->download(clippedWidth * clippedHeight * 4, tmpBuf.data()); + WriteTextureToVRam(clippedWidth, clippedHeight, (u8 *)tmpBuf.data(), dst); return; } diff --git a/core/rend/vulkan/drawer.h b/core/rend/vulkan/drawer.h index f93ce4f98..f9ccb0fc5 100644 --- a/core/rend/vulkan/drawer.h +++ b/core/rend/vulkan/drawer.h @@ -46,6 +46,7 @@ protected: VulkanContext *GetContext() const { return VulkanContext::Instance(); } TileClipping SetTileClip(u32 val, vk::Rect2D& clipRect); void SetBaseScissor(); + void SetProvokingVertices(); u32 align(vk::DeviceSize offset, u32 alignment) { diff --git a/core/rend/vulkan/oit/oit_drawer.cpp b/core/rend/vulkan/oit/oit_drawer.cpp index b6e164059..0da70a8c5 100644 --- a/core/rend/vulkan/oit/oit_drawer.cpp +++ b/core/rend/vulkan/oit/oit_drawer.cpp @@ -258,6 +258,8 @@ bool OITDrawer::Draw(const Texture *fogTexture) oitBuffers->OnNewFrame(cmdBuffer); + SetProvokingVertices(); + // Upload vertex and index buffers UploadMainBuffer(vtxUniforms, fragUniforms); @@ -578,11 +580,19 @@ void OITTextureDrawer::EndFrame() { currentCommandBuffer.endRenderPass(); + u32 clippedWidth = pvrrc.fb_X_CLIP.max - pvrrc.fb_X_CLIP.min + 1; + u32 clippedHeight = pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1; + + u32 stride = FB_W_LINESTRIDE.stride * 8; + if (clippedWidth * 2 > stride) + // Happens for Virtua Tennis + clippedWidth = stride / 2; + if (settings.rend.RenderToTextureBuffer) { - vk::BufferImageCopy copyRegion(0, viewport.extent.width, viewport.extent.height, + vk::BufferImageCopy copyRegion(0, clippedWidth, clippedHeight, vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), vk::Offset3D(0, 0, 0), - vk::Extent3D(viewport.extent, 1)); + vk::Extent3D(clippedWidth, clippedHeight, 1)); currentCommandBuffer.copyImageToBuffer(colorAttachment->GetImage(), vk::ImageLayout::eTransferSrcOptimal, *colorAttachment->GetBufferData()->buffer, copyRegion); @@ -611,9 +621,9 @@ void OITTextureDrawer::EndFrame() u16 *dst = (u16 *)&vram[textureAddr]; PixelBuffer tmpBuf; - tmpBuf.init(viewport.extent.width, viewport.extent.height); - colorAttachment->GetBufferData()->download(viewport.extent.width * viewport.extent.height * 4, tmpBuf.data()); - WriteTextureToVRam(viewport.extent.width, viewport.extent.height, (u8 *)tmpBuf.data(), dst); + tmpBuf.init(clippedWidth, clippedHeight); + colorAttachment->GetBufferData()->download(clippedWidth * clippedHeight * 4, tmpBuf.data()); + WriteTextureToVRam(clippedWidth, clippedHeight, (u8 *)tmpBuf.data(), dst); return; } diff --git a/core/rend/vulkan/oit/oit_shaders.h b/core/rend/vulkan/oit/oit_shaders.h index 80581fcfb..1d560398f 100644 --- a/core/rend/vulkan/oit/oit_shaders.h +++ b/core/rend/vulkan/oit/oit_shaders.h @@ -80,30 +80,6 @@ public: compileTrModVolFragmentShader(mode); return *trModVolShaders[(size_t)mode]; } -// vk::ShaderModule GetQuadVertexShader() -// { -// if (!quadVertexShader) -// quadVertexShader = compileQuadVertexShader(); -// return *quadVertexShader; -// } -// vk::ShaderModule GetQuadFragmentShader() -// { -// if (!quadFragmentShader) -// quadFragmentShader = compileQuadFragmentShader(); -// return *quadFragmentShader; -// } -// vk::ShaderModule GetOSDVertexShader() -// { -// if (!osdVertexShader) -// osdVertexShader = compileOSDVertexShader(); -// return *osdVertexShader; -// } -// vk::ShaderModule GetOSDFragmentShader() -// { -// if (!osdFragmentShader) -// osdFragmentShader = compileOSDFragmentShader(); -// return *osdFragmentShader; -// } vk::ShaderModule GetFinalShader(bool autosort) { @@ -148,10 +124,6 @@ private: vk::UniqueShaderModule compileModVolVertexShader(); vk::UniqueShaderModule compileModVolFragmentShader(); void compileTrModVolFragmentShader(ModVolMode mode); -// vk::UniqueShaderModule compileQuadVertexShader(); -// vk::UniqueShaderModule compileQuadFragmentShader(); -// vk::UniqueShaderModule compileOSDVertexShader(); -// vk::UniqueShaderModule compileOSDFragmentShader(); vk::UniqueShaderModule compileFinalShader(bool autosort); vk::UniqueShaderModule compileFinalVertexShader(); vk::UniqueShaderModule compileClearShader(); @@ -161,10 +133,6 @@ private: vk::UniqueShaderModule modVolVertexShader; vk::UniqueShaderModule modVolShader; std::vector trModVolShaders; -// vk::UniqueShaderModule quadVertexShader; -// vk::UniqueShaderModule quadFragmentShader; -// vk::UniqueShaderModule osdVertexShader; -// vk::UniqueShaderModule osdFragmentShader; vk::UniqueShaderModule finalVertexShader; vk::UniqueShaderModule finalAutosortShader; diff --git a/core/rend/vulkan/texture.cpp b/core/rend/vulkan/texture.cpp index 60f870a1a..2e4038632 100644 --- a/core/rend/vulkan/texture.cpp +++ b/core/rend/vulkan/texture.cpp @@ -30,6 +30,9 @@ void setImageLayout(vk::CommandBuffer const& commandBuffer, vk::Image image, vk: case vk::ImageLayout::eTransferDstOptimal: sourceAccessMask = vk::AccessFlagBits::eTransferWrite; break; + case vk::ImageLayout::eTransferSrcOptimal: + sourceAccessMask = vk::AccessFlagBits::eTransferRead; + break; case vk::ImageLayout::ePreinitialized: sourceAccessMask = vk::AccessFlagBits::eHostWrite; break; @@ -52,6 +55,7 @@ void setImageLayout(vk::CommandBuffer const& commandBuffer, vk::Image image, vk: sourceStage = vk::PipelineStageFlagBits::eHost; break; case vk::ImageLayout::eTransferDstOptimal: + case vk::ImageLayout::eTransferSrcOptimal: sourceStage = vk::PipelineStageFlagBits::eTransfer; break; case vk::ImageLayout::eUndefined: @@ -176,7 +180,7 @@ void Texture::Init(u32 width, u32 height, vk::Format format) this->extent = vk::Extent2D(width, height); this->format = format; mipmapLevels = 1; - if (tcw.MipMapped) + if (tcw.MipMapped && settings.rend.UseMipmaps) mipmapLevels += floor(log2(std::max(width, height))); vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(format);