Vulkan: Don't try to overlap proj with proj_through, will need a different approach.

Also, assorted bugfixes.
This commit is contained in:
Henrik Rydgard 2016-01-24 17:30:26 +01:00
parent 5f71b5b3ec
commit 1677697735
9 changed files with 28 additions and 17 deletions

View File

@ -494,6 +494,8 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
uint32_t vbOffset = 0; uint32_t vbOffset = 0;
if (useHWTransform) { if (useHWTransform) {
// We don't detect clears in this path, so here we can switch framebuffers if necessary.
int vertexCount = 0; int vertexCount = 0;
int maxIndex = 0; int maxIndex = 0;
bool useElements = true; bool useElements = true;
@ -529,7 +531,7 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
vkCmdSetBlendConstants(cmd_, bc); vkCmdSetBlendConstants(cmd_, bc);
shaderManager_->UpdateUniforms(); shaderManager_->UpdateUniforms();
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform); shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, pipelineKey, dec_, vshader->GetModule(), fshader->GetModule(), true); VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, pipelineKey, dec_, vshader, fshader, true);
vkCmdBindPipeline(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); // TODO: Avoid if same as last draw. vkCmdBindPipeline(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); // TODO: Avoid if same as last draw.
if (pipeline->uniformBlocks & UB_VS_FS_BASE) { if (pipeline->uniformBlocks & UB_VS_FS_BASE) {
@ -548,11 +550,11 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
}; };
vkCmdBindDescriptorSets(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &ds, 3, dynamicUBOOffsets); vkCmdBindDescriptorSets(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &ds, 3, dynamicUBOOffsets);
vbOffset = (uint32_t)frame->pushData->Push(decoded, vertexCount * dec_->GetDecVtxFmt().stride); vbOffset = (uint32_t)frame->pushData->PushAligned(decoded, vertexCount * dec_->GetDecVtxFmt().stride, 16);
VkDeviceSize offsets[1] = { vbOffset }; VkDeviceSize offsets[1] = { vbOffset };
if (useElements) { if (useElements) {
ibOffset = (uint32_t)frame->pushData->Push(decIndex, 2 * indexGen.VertexCount()); ibOffset = (uint32_t)frame->pushData->PushAligned(decIndex, 2 * indexGen.VertexCount(), 16);
// TODO: Avoid rebinding vertex/index buffers if the vertex size stays the same by using the offset arguments // TODO: Avoid rebinding vertex/index buffers if the vertex size stays the same by using the offset arguments
// Might want to separate vertices out into a different push buffer in that case. // Might want to separate vertices out into a different push buffer in that case.
vkCmdBindVertexBuffers(cmd_, 0, 1, buf, offsets); vkCmdBindVertexBuffers(cmd_, 0, 1, buf, offsets);
@ -591,6 +593,9 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(), dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(),
maxIndex, framebufferManager_, textureCache_, transformed, transformedExpanded, drawBuffer, numTrans, drawIndexed, &result, 1.0f); maxIndex, framebufferManager_, textureCache_, transformed, transformedExpanded, drawBuffer, numTrans, drawIndexed, &result, 1.0f);
// Only here, where we know whether to clear or to draw primitives, should we actually set the current framebuffer! Because that gives use the opportunity
// to use a "pre-clear" render pass, for high efficiency on tilers.
if (result.action == SW_DRAW_PRIMITIVES) { if (result.action == SW_DRAW_PRIMITIVES) {
VulkanPipelineRasterStateKey pipelineKey; VulkanPipelineRasterStateKey pipelineKey;
VulkanDynamicState dynState; VulkanDynamicState dynState;
@ -614,7 +619,7 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
vkCmdSetBlendConstants(cmd_, bc); vkCmdSetBlendConstants(cmd_, bc);
shaderManager_->UpdateUniforms(); shaderManager_->UpdateUniforms();
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform); shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, pipelineKey, dec_, vshader->GetModule(), fshader->GetModule(), false); VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, pipelineKey, dec_, vshader, fshader, false);
vkCmdBindPipeline(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); // TODO: Avoid if same as last draw. vkCmdBindPipeline(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); // TODO: Avoid if same as last draw.
if (pipeline->uniformBlocks & UB_VS_FS_BASE) { if (pipeline->uniformBlocks & UB_VS_FS_BASE) {

View File

@ -320,7 +320,7 @@ static const CommandTableEntry commandTable[] = {
{ GE_CMD_BOUNDINGBOX, FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_BoundingBox }, // + FLUSHBEFORE when we implement... or not, do we need to? { GE_CMD_BOUNDINGBOX, FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_BoundingBox }, // + FLUSHBEFORE when we implement... or not, do we need to?
// Changing the vertex type requires us to flush. // Changing the vertex type requires us to flush.
{ GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, DIRTY_PROJMATRIX, &GPU_Vulkan::Execute_VertexType }, { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPU_Vulkan::Execute_VertexType },
{ GE_CMD_BEZIER, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_Bezier }, { GE_CMD_BEZIER, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_Bezier },
{ GE_CMD_SPLINE, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_Spline }, { GE_CMD_SPLINE, FLAG_FLUSHBEFORE | FLAG_EXECUTE, 0, &GPU_Vulkan::Execute_Spline },

View File

@ -4,6 +4,7 @@
#include "Common/StringUtils.h" #include "Common/StringUtils.h"
#include "GPU/Vulkan/VulkanUtil.h" #include "GPU/Vulkan/VulkanUtil.h"
#include "GPU/Vulkan/PipelineManagerVulkan.h" #include "GPU/Vulkan/PipelineManagerVulkan.h"
#include "GPU/Vulkan/ShaderManagerVulkan.h"
// #include "GPU/Vulkan/" // #include "GPU/Vulkan/"
#include "thin3d/VulkanContext.h" #include "thin3d/VulkanContext.h"
@ -285,12 +286,12 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
return vulkanPipeline; return vulkanPipeline;
} }
VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layout, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VkShaderModule vShader, VkShaderModule fShader, bool useHwTransform) { VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layout, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform) {
VulkanPipelineKey key; VulkanPipelineKey key;
key.raster = rasterKey; key.raster = rasterKey;
key.useHWTransform = useHwTransform; key.useHWTransform = useHwTransform;
key.vShader = vShader; key.vShader = vs->GetModule();
key.fShader = fShader; key.fShader = fs->GetModule();
key.vtxDec = vtxDec; key.vtxDec = vtxDec;
auto iter = pipelines_.find(key); auto iter = pipelines_.find(key);
if (iter != pipelines_.end()) { if (iter != pipelines_.end()) {
@ -299,7 +300,7 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layo
VulkanPipeline *pipeline = CreateVulkanPipeline( VulkanPipeline *pipeline = CreateVulkanPipeline(
vulkan_->GetDevice(), pipelineCache_, layout, vulkan_->GetSurfaceRenderPass(), vulkan_->GetDevice(), pipelineCache_, layout, vulkan_->GetSurfaceRenderPass(),
rasterKey, vtxDec, vShader, fShader, useHwTransform); rasterKey, vtxDec, key.vShader, key.fShader, useHwTransform);
pipelines_[key] = pipeline; pipelines_[key] = pipeline;
return pipeline; return pipeline;
} }

View File

@ -74,13 +74,15 @@ struct VulkanPipeline {
}; };
class VulkanContext; class VulkanContext;
class VulkanVertexShader;
class VulkanFragmentShader;
class PipelineManagerVulkan { class PipelineManagerVulkan {
public: public:
PipelineManagerVulkan(VulkanContext *ctx); PipelineManagerVulkan(VulkanContext *ctx);
~PipelineManagerVulkan(); ~PipelineManagerVulkan();
VulkanPipeline *GetOrCreatePipeline(VkPipelineLayout layout, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VkShaderModule vShader, VkShaderModule fShader, bool useHwTransform); VulkanPipeline *GetOrCreatePipeline(VkPipelineLayout layout, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform);
int GetNumPipelines() const { return (int)pipelines_.size(); } int GetNumPipelines() const { return (int)pipelines_.size(); }
void Clear(); void Clear();

View File

@ -249,7 +249,7 @@ void ShaderManagerVulkan::BaseUpdateUniforms(int dirtyUniforms) {
Matrix4x4 proj_through; Matrix4x4 proj_through;
proj_through.setOrtho(0.0f, gstate_c.curRTWidth, 0, gstate_c.curRTHeight, 0, 1); proj_through.setOrtho(0.0f, gstate_c.curRTWidth, 0, gstate_c.curRTHeight, 0, 1);
ConvertProjMatrixToVulkanThrough(proj_through); ConvertProjMatrixToVulkanThrough(proj_through);
CopyMatrix4x4(ub_base.proj, proj_through.getReadPtr()); CopyMatrix4x4(ub_base.proj_through, proj_through.getReadPtr());
} else { } else {
Matrix4x4 flippedMatrix; Matrix4x4 flippedMatrix;
memcpy(&flippedMatrix, gstate.projMatrix, 16 * sizeof(float)); memcpy(&flippedMatrix, gstate.projMatrix, 16 * sizeof(float));

View File

@ -34,7 +34,7 @@ void ConvertProjMatrixToVulkan(Matrix4x4 & in);
// Pretty much full. Will need more bits for more fine grained dirty tracking for lights. // Pretty much full. Will need more bits for more fine grained dirty tracking for lights.
enum { enum {
DIRTY_PROJMATRIX = (1 << 0), DIRTY_PROJMATRIX = (1 << 0),
// 1 << 1 is free DIRTY_PROJTHROUGHMATRIX = (1 << 1),
DIRTY_FOGCOLOR = (1 << 2), DIRTY_FOGCOLOR = (1 << 2),
DIRTY_FOGCOEF = (1 << 3), DIRTY_FOGCOEF = (1 << 3),
DIRTY_TEXENV = (1 << 4), DIRTY_TEXENV = (1 << 4),
@ -82,8 +82,10 @@ enum {
DIRTY_ALL = 0xFFFFFFFF DIRTY_ALL = 0xFFFFFFFF
}; };
// TODO: Split into two structs, one for software transform and one for hardware transform, to save space.
struct UB_VS_FS_Base { struct UB_VS_FS_Base {
float proj[16]; float proj[16];
float proj_through[16];
float view[16]; float view[16];
float world[16]; float world[16];
float tex[16]; // not that common, may want to break out float tex[16]; // not that common, may want to break out
@ -104,7 +106,8 @@ struct UB_VS_FS_Base {
}; };
static const char *ub_baseStr = static const char *ub_baseStr =
R"( mat4 proj_mtx; R"( mat4 proj_mtx;
mat4 proj_through_mtx;
mat4 view_mtx; mat4 view_mtx;
mat4 world_mtx; mat4 world_mtx;
mat4 tex_mtx; mat4 tex_mtx;

View File

@ -172,13 +172,13 @@ void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerV
key.depthCompareOp = VK_COMPARE_OP_ALWAYS; key.depthCompareOp = VK_COMPARE_OP_ALWAYS;
key.depthWriteEnable = gstate.isClearModeDepthMask(); key.depthWriteEnable = gstate.isClearModeDepthMask();
if (gstate.isClearModeDepthMask()) { if (gstate.isClearModeDepthMask()) {
// framebufferManager_->SetDepthUpdated(); fbManager.SetDepthUpdated();
} }
// Color Test // Color Test
bool colorMask = gstate.isClearModeColorMask(); bool colorMask = gstate.isClearModeColorMask();
bool alphaMask = gstate.isClearModeAlphaMask(); bool alphaMask = gstate.isClearModeAlphaMask();
key.colorWriteMask = (colorMask ? (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_A_BIT) : 0) | (alphaMask ? VK_COLOR_COMPONENT_A_BIT : 0); key.colorWriteMask = (colorMask ? (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT) : 0) | (alphaMask ? VK_COLOR_COMPONENT_A_BIT : 0);
GenericStencilFuncState stencilState; GenericStencilFuncState stencilState;
ConvertStencilFuncState(stencilState); ConvertStencilFuncState(stencilState);

View File

@ -34,7 +34,7 @@ struct VulkanPipelineRasterStateKey {
unsigned int blendOpAlpha : 3; // VkBlendOp unsigned int blendOpAlpha : 3; // VkBlendOp
bool logicOpEnable : 1; bool logicOpEnable : 1;
unsigned int logicOp : 4; // VkLogicOp unsigned int logicOp : 4; // VkLogicOp
int colorWriteMask : 4; unsigned int colorWriteMask : 4;
// Depth/Stencil // Depth/Stencil
bool depthTestEnable : 1; bool depthTestEnable : 1;

View File

@ -242,7 +242,7 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer) {
WRITE(p, " v_fogdepth = position.w;\n"); WRITE(p, " v_fogdepth = position.w;\n");
} }
if (isModeThrough) { if (isModeThrough) {
WRITE(p, " gl_Position = base.proj_mtx * vec4(position.xyz, 1.0);\n"); WRITE(p, " gl_Position = base.proj_through_mtx * vec4(position.xyz, 1.0);\n");
} else { } else {
// The viewport is used in this case, so need to compensate for that. // The viewport is used in this case, so need to compensate for that.
if (gstate_c.Supports(GPU_ROUND_DEPTH_TO_16BIT)) { if (gstate_c.Supports(GPU_ROUND_DEPTH_TO_16BIT)) {