vulkan: copy provoking vertex. crash when rtt2vram. rtt vram stride

setImageLayout was missing TransferSrcOptimal as source layout
Vulkan needs the first vertex to be the provoking vertex so copy 3rd on
1st when flat shading.
VRAM stride was incorrect (RTT to VRAM)
This commit is contained in:
Flyinghead 2019-12-10 12:51:10 +01:00
parent 637ad3b214
commit 066093553f
5 changed files with 63 additions and 43 deletions

View File

@ -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<PolyParam>& 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<u32> 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;
}

View File

@ -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)
{

View File

@ -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<u32> 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;
}

View File

@ -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<vk::UniqueShaderModule> trModVolShaders;
// vk::UniqueShaderModule quadVertexShader;
// vk::UniqueShaderModule quadFragmentShader;
// vk::UniqueShaderModule osdVertexShader;
// vk::UniqueShaderModule osdFragmentShader;
vk::UniqueShaderModule finalVertexShader;
vk::UniqueShaderModule finalAutosortShader;

View File

@ -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);